AjaxMin task has been declared or used incorrectly, or failed during construction - asp.net-mvc-4

I'm trying to add Microsoft's AjaxMin to VS2012 project and I'm not really sure what I'm doing. I think I'm missing something obvious.
I copied the code from the tutorial here (http://ajaxmin.codeplex.com/wikipage?title=AjaxMinTask)
And I've tried adding the reference to my project so my code looks like this:
<UsingTask TaskName="AjaxMin" AssemblyFile="$(MSBuildProjectDirectory)\Build\AjaxMinTask.dll" />
<Target Name="AfterBuild" >
<ItemGroup>
<JS Include="**\*.js" Exclude="**\*.min.js;Scripts\*.js" />
</ItemGroup>
<ItemGroup>
<CSS Include="**\*.css" Exclude="**\*.min.css" />
</ItemGroup>
<AjaxMin JsSourceFiles="#(JS)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".min.js" CssSourceFiles="#(CSS)" CssSourceExtensionPattern="\.css$" CssTargetExtension=".min.css" />
</Target>
This is at the bottom of my .csproj file where there was already a commented out AfterBuild section. I get errors saying JS, CSS, AjaxMin are invalid child elements. When I try to build the project I get an error, I'm not sure what I am missing. I created a folder in the project called Build and added the AjaxMinTask.dll. I don't know if there's any additional thing i need to do to make sure it is referenced properly.
I've also tried using the Import node instead of the UsingTask
<Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\AjaxMin.tasks" />
And I think AjaxMin is installed correctly because I can run it from command line.

In your .csproj, the end of the document (I've included the last closing element ) should look something like this:
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\MicrosoftAjax\AjaxMin.tasks" />
<Target Name="AfterBuild" AfterTargets="CopyAllFilesToSingleFolderForPackage" Condition="'$(Configuration)'=='Release'">
<ItemGroup>
<JS Include="scripts\*.js" Exclude="scripts\*.min.js;" />
</ItemGroup>
<ItemGroup>
<CSS Include="css\main.css" />
</ItemGroup>
<AjaxMin Switches="-global:jQuery,$" JsSourceFiles="#(JS)" JsCombinedFileName="scripts\combined.min.js" CssSourceFiles="#(CSS)" CssSourceExtensionPattern="\.css$" CssTargetExtension=".min.css" />
</Target>
</Project>
As I am using Windows 7 64-bit, you will see the path of Import... includes (MSBuildExtensionsPath32). If you are using Windows 32-bit, then you do not need the 32 at the end. Other then that, your code should work.
Disregard the JS, CSS, AjaxMin childelements error. But you should not get a built error. If you could post your built error, it would be useful.
Also, the code above combines multiple JS files, just added for fun.

Related

C# Source Generator should refresh/delete emited files

I created a Source Generator to extend (partial) classes which fulfill certain criteria. To check and view the generated code I enabled the emission of these files by adding the following to my project:
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
This works as long as I don't do refactoring - like renaming a class. Because for every class a file is generated but not removed when I rename the "source" class.
So I added the following code to clean all generated files (on clean and rebuild)
<Target Name="CleanSourceGeneratedFiles" AfterTargets="Clean">
<RemoveDir Directories="Generated" />
</Target>
However then every second rebuild fails with:
Error CS2001 Source file 'xyz.generated.cs' could not be found.
So I'm looking for another way to keep my generated sources up to date, where the project not only compiles every second try.
Try this. It works for me.
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
<Target Name="CleanSourceGeneratedFiles" BeforeTargets="BeforeBuild" DependsOnTargets="$(BeforeBuildDependsOn)">
<RemoveDir Directories="Generated" />
</Target>
<ItemGroup>
<Compile Remove="Generated\**" />
<Content Include="Generated\**" />
</ItemGroup>

How to include a local DLL reference in to a nuget package when calling msbuild pack?

We have several projects that need to include a few static DLL. Therefore the project files include code like this:
<ItemGroup>
<Reference Include="..\_Solutions\dependencies\abc123.dll" />
<Reference Include="..\_Solutions\dependencies\def456.dll" />
<Reference Include="System.Web" />
</ItemGroup>
Expected:
We expected that the two dlls; abc123.dll and def456.dll would befound in the nupkg file.
Actual:
However, the nupkg doesn't include the abc123.dll nor the def456.dll files.
One can always include custom content in the nuget-package. Like this:
<ItemGroup>
<Content Include="$(OutputPath)\ReferencedLib.dll">
<Pack>true</Pack>
<PackagePath>lib\$(TargetFramework)</PackagePath>
</Content>
</ItemGroup>
If you target multiple frameworks:
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard1.6</TargetFrameworks>
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);IncludeReferencedProjectInPackage</TargetsForTfmSpecificContentInPackage>
</PropertyGroup>
<Target Name="IncludeReferencedProjectInPackage" Condition="'$(IncludeBuildOutput)' != 'false'">
<ItemGroup>
<TfmSpecificPackageFile Include="$(OutputPath)\ReferencedLib.dll" PackagePath="lib/$(TargetFramework)" />
</ItemGroup>
</Target>
How to include a local DLL reference in to a nuget package when calling msbuild pack?
According the issue on the GitHub, this is currently not directly supported by NuGet.
The workaround I suggest is using the .nuspec file:
NuGet allows you to disable the automatic generation of the resulting
.nuspec file and automatic collection of files by setting the
property in your project, along with a
property that allows you to pass replacement tokens for parsing the
.nuspec file.
See Martin`s answer for details.

How to generate files during build using msbuild

Does anyone know how to modify a csproj file in a way to generate code files during build without actually referencing the files?
A process like :
create file,
dynamically reference temporary file during build
compiled assembly has additional members, depending on the files created during build
The purpose of this is to create a way of generating code files using roslyn instead of using t4 templates, which are very awkward to use once you're trying to do something depending on attributes.
Hence i am planning on providing a way to use a special csharp file (for full syntax support) to generate files programatically based on the contents of that special file.
I've spent a couple of weeks looking into resources on the internet (with the topic msbuild), but until now it seems i didn't use the right keywords.
This one has been the most insightful one to me yet:
https://www.simple-talk.com/dotnet/.net-tools/extending-msbuild/
My guess is, that the correct build target for my purpose should be "BeforeCompile" in order to somehow populate the build process with custom code files.
Does anyone have experience with my issue, or is aware of any particular resources which deal with the task?
Solution i got it working with:
<UsingTask TaskName="DynamicCodeGenerator.DynamicFileGeneratorTask" AssemblyFile="..\DynamicCodeGenerator\bin\Debug\DynamicCodeGenerator.dll" />
<Target Name="DynamicCodeGeneratorTarget" BeforeTargets="BeforeBuild;BeforeRebuild">
<DynamicFileGeneratorTask>
<Output ItemName="Generated" TaskParameter="GeneratedFilePaths" />
</DynamicFileGeneratorTask>
<ItemGroup>
<Compile Include="#(Generated)" />
<FileWrites Include="#(Generated)" />
<!-- For clean to work properly -->
</ItemGroup>
</Target>
Unfortunately i did not get it to work with a propertygroup override as suggested
Update: This link is interesting too: https://github.com/firstfloorsoftware/xcc/blob/master/FirstFloor.Xcc/Targets/Xcc.targets
Generating the code file can be achieved by msbuild task or msbuild inline task. It is up to you to generate the proper code. One thing that you must care of is creating output item parameter in order to append it to the #(Compile) item. You can use $(IntDir) location to locate your newly generated file, and add them to the #(FileWrites) item group in order for Clean target work properly.
When you finish writing your task, you must use it in your project like this:
<UsingTask TaskName="TaskTypeFullName" AssemblyFile="YourAssembly.dll"/>
<PropertyGroup>
<!-- Here you need to experiment with [Build/Compile/SomeOther]DependsOn property -->
<BuildDependsOn>
MyCodeGenerator;
$(BuildDependsOn)
</BuildDependsOn>
</PropertyGroup>
<Target Name="MyCodeGenerator">
<YourTaskName>
<Output ItemName="Generated" TaskParameter="GeneratedFiles" />
</YourTaskName>
<ItemGroup>
<Compile Include="#(Generated)" />
<FileWrites Include="#(Generated)" /> <!-- For clean to work properly -->
</ItemGroup>
</Target>
I wanted to use a bash script to generate code for a project using dotnet core on Linux. Here is what worked for me. And thanks #stukselbax, I built this off of your answer.
<Target Name="GenerateProtocolBuffers" BeforeTargets="BeforeBuild;BeforeRebuild">
<Exec Command="./generatecode.sh" Outputs="proto/*.cs">
<Output ItemName="Generated" TaskParameter="Outputs" />
</Exec>
<ItemGroup>
<Compile Include="#(Generated)" />
<FileWrites Include="#(Generated)" />
</ItemGroup>
</Target>
Note that the script I'm using to generate the code is called generatecode.sh. Replace this with your own.

Using XmlUpdate to set Version information from an Assembly

Using MSBuild and MSBuild Community Tasks I am trying to do something very simple:
Get version information from an assembly.
Update a .nuspec file with that version information.
My MSBuild target looks like this:
<Target Name="Package">
<GetAssemblyIdentity AssemblyFiles="%(PackageDir.FullPath)\MyAssembly.dll">
<Output TaskParameter="Assemblies" ItemName="AssemblyIdentity" />
</GetAssemblyIdentity>
<XmlUpdate
Prefix="nu"
Namespace="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"
XmlFileName="%(PackageDir.FullPath)\MyAssembly.nuspec"
XPath="/nu:package/nu:metadata/nu:version"
Value="%(AssemblyIdentity.Version)" />
</Target>
The problem I'm having is that the NuGetPack task runs TWICE: The first time, the Assembly version is missing but the paths are correct, the second time the Assembly version is correct but the paths are missing!
Here is the output:
Updating Xml Document "D:\MyProject\package\MyAssembly.nuspec".
1 node(s) selected for update.
XmlUpdate Wrote: "".
Updating Xml Document "\MyAssembly.nuspec".
D:\MyProject\MyProject.build(64,9): error : Could not find file
'D:\MyAssembly.nuspec'.
Done Building Project "D:\MyProject\MyProject.build" (Package target(s)
) -- FAILED.
I also tried using the NuGetPack task, but got similar results. Help is greatly appreciated!
I seem to have solved it, though I'm still not sure why the code in my original question does not work.
Instead of specifying paths via concatenation (e.g. AssemblyFiles="%(PackageDir.FullPath)\MyAssembly.dll") I put each path into its own item:
<ItemGroup>
...
<PackageVersionAssembly Include=".\build-artifacts\package\MyAssembly.dll"/>
<NuSpecFile Include=".\build-artifacts\package\MyAssembly.nuspec"/>
...
</ItemGroup>
I made the same change in the task and made the same change to references to the .nuspec file.
The new Package target looks like this:
<Target Name="Package">
<GetAssemblyIdentity AssemblyFiles="#(PackageVersionAssembly)">
<Output TaskParameter="Assemblies" ItemName="AssemblyIdentity" />
</GetAssemblyIdentity>
<XmlUpdate
Prefix="nu"
Namespace="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"
XmlFileName="#(NuSpecFile)"
XPath="/nu:package/nu:metadata/nu:version"
Value="%(AssemblyIdentity.Version)" />
</Target>
I hope this helps others!

Trying to include a transformed App.config in a XAP file

I have a Silverlight project with multiple configuration files, and am using the transformation approach shown here:
App.Config Transformation for projects which are not Web Projects in Visual Studio 2010?
This approach doesn't work as-is for Silverlight projects though. I've re-written the MSBuild project to look like this:
<ItemGroup>
<None Include="App.config" />
<None Include="App.QABuild.config">
<DependentUpon>App.config</DependentUpon>
</None>
</ItemGroup>
....
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="BeforeCompile" Condition="Exists('App.$(Configuration).config')">
<!-- Generate transformed app config in the output directory -->
<Message Importance="high" Text="Transforming 'App.$(Configuration).config' to output config file..." />
<TransformXml Source="App.config" Destination="$(OutputPath)App.config" Transform="App.$(Configuration).config" />
<ItemGroup>
<Content Include="$(OutputPath)App.config" />
</ItemGroup>
</Target>
<Target Name="BeforeCompile" Condition="!Exists('App.$(Configuration).config')">
<Message Importance="high" Text="Using default 'App.config' as output config file..." />
<Copy SourceFiles="App.config" DestinationFiles="$(OutputPath)App.config" />
<ItemGroup>
<Content Include="$(OutputPath)App.config" />
</ItemGroup>
</Target>
This code generates the correct output file for the correct configuration, however it is never included in the XAP file, even though I am putting the output config into the Content item group. All I need to happen is for the output config to get included in the output XAP but I can't get this to happen.
Can anyone tell me what I'm doing wrong? I'm not an MSBuild expert by any means!
Found the solution by digging into the Silverlight 4 targets. Turns out the XAP packager target actually takes an item called XapFilesInputCollection, which is where the input files come from. The Content item looks likes it is copied to this item before my target runs, so modifying the Content item afterwards is the wrong approach.
All I did was add the transformed files directly to the XapFilesInputCollection item and it worked as I expected.