Setting Visual Studio to automatically minifying using Ajax Minifier - visual-studio-2010

I use VS 2010 I would like at the pressing of Build Button have all CSS and .JS files minified.
Following this article all is working great for JS... adding some extra code for the CSS (pasted below) I'm not able to Minifying the CSS. What I'm doing wrong here?
Thanks for your time.
<Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\ajaxmin.tasks" />
<Target Name="AfterBuild">
<ItemGroup>
<JS Include="**\*.js" Exclude="**\*.min.js;Scripts\*.js" />
<JS Include="**\*.css" Exclude="**\*.min.css;Scripts\*.css" />
</ItemGroup>
<AjaxMin SourceFiles="#(JS)" SourceExtensionPattern="\.js$" TargetExtension=".min.js" />
<AjaxMin SourceFiles="#(CSS)" SourceExtensionPattern="\.css$" TargetExtension=".min.css" />
</Target>

I found out the solution to my problem, more resource here
Unable to run Ajax Minifier as post-build in Visual Studio
http://ajaxmin.codeplex.com/wikipage?title=AjaxMinTask
Also very interesting:
http://www.codeproject.com/Articles/81317/Automatically-compress-embedded-JavaScript-resourc.aspx?msg=3802401&display=Mobile
<Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\ajaxmin.tasks" />
<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>

On my project file I used "UsingTask" instead of "Import" and it's working:
<UsingTask TaskName="AjaxMin" AssemblyFile="$(MSBuildProjectDirectory)\..\..\packages\AjaxMin.5.14.5506.26202\tools\net40\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>

Related

Building web project causes web config to be updated setting 'environmentVariable' to 'Development'

Time back I created a .net core with react SPA project from a template, ever since I have been unable to identify what is causing the web.config to be update each time I build.
Well, to be precise it is updated only adding back the environment variables tags, setting the environment to Development.
Can anyone please tell me how to prevent this?
<environmentVariables>
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
</environmentVariables>
Here is the csproj file content:
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
<IsPackable>false</IsPackable>
<SpaRoot>ClientApp\</SpaRoot>
<DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OData" Version="8.0.12" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="6.0.13" />
<PackageReference Include="Minded" Version="0.1.3" />
[...]
<ItemGroup>
<!-- Don't publish the SPA source files, but do show them in the project files list -->
<Content Remove="$(SpaRoot)**" />
<None Remove="$(SpaRoot)**" />
<None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
</ItemGroup>
<ItemGroup>
<Folder Include="ClientApp\src\components\" />
</ItemGroup>
<Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
<!-- Ensure Node.js is installed -->
<Exec Command="node --version" ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
<Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
</Target>
<Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
<!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
<Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm run build" />
<!-- Include the newly-built files in the publish output -->
<ItemGroup>
<DistFiles Include="$(SpaRoot)build\**" />
<ResolvedFileToPublish Include="#(DistFiles->'%(FullPath)')" Exclude="#(ResolvedFileToPublish)">
<RelativePath>%(DistFiles.Identity)</RelativePath>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</ResolvedFileToPublish>
</ItemGroup>
</Target>

How to publish file from subfolder to main application folder?

I have a WinForms NET4.8 desktop app that I publish using ClickOnce. I have a dll file in a project subfolder that I need published to the same directory as the main app. I have the following in my csproj file:
<PropertyGroup>
<UnreferencedDlls>lib\twaindsm.dll</UnreferencedDlls>
</PropertyGroup>
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
</PropertyGroup>
<Target Name="AfterBuild">
<Message Text="Copying unreferenced DLLs to bin" Importance="High" />
<CreateItem Include="$(UnreferencedDlls)">
<Output TaskParameter="Include" ItemName="_UnReferencedDLLs" />
</CreateItem>
<Copy SourceFiles="#(_UnReferencedDLLs)" DestinationFolder="$(OutputPath)\%(RecursiveDir)" SkipUnchangedFiles="true" />
</Target>
<Target Name="CustomCollectFiles">
<Message Text="Publishing unreferenced DLLs" Importance="High" />
<ItemGroup>
<_CustomFiles Include="$(UnreferencedDlls)" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>$(OutputPath)\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
The file is published to the subfolder.
I change this line:
<DestinationRelativePath>$(OutputPath)\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
to:
<DestinationRelativePath>$(OutputPath)\%(Filename)%(Extension)</DestinationRelativePath>
But it still doesn't work.
How can I force the file to be published to the same folder as the app?
I don't know if it can help you: %(RecursiveDir)
If the Include attribute contains the wildcard **, this metadata
specifies the part of the path that replaces the wildcard.
Maybe you can try to change the path of the dll. I put it into ProjectDir\lib\Debug\ and here is my code:
<PropertyGroup>
<UnreferencedDlls>lib\**\ClassLibrary1.dll</UnreferencedDlls>
</PropertyGroup>
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
</PropertyGroup>
<Target Name="AfterBuild">
<Message Text="Copying unreferenced DLLs to bin" Importance="High" />
<CreateItem Include="$(UnreferencedDlls)">
<Output TaskParameter="Include" ItemName="_UnReferencedDLLs" />
</CreateItem>
<Copy SourceFiles="#(_UnReferencedDLLs)" DestinationFolder="bin\%(RecursiveDir)" SkipUnchangedFiles="true" />
</Target>
<Target Name="CustomCollectFiles">
<Message Text="Publishing unreferenced DLLs" Importance="High" />
<ItemGroup>
<_CustomFiles Include="$(UnreferencedDlls)" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>bin\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
You can also refer to this page hope it can help you.

AjaxMin not running on CopyAllFilesToSingleFolderForPackage when using MSDeploy to remote server

I'm trying to get my JS and CSS files to be automatically minified when publishing our Web App, but it only seems to work on a File System publish not a web deploy; using the target CopyAllFilesToSingleFolderForPackage in a .pubxml file.
I've tried running on different targets but the same result.
<UsingTask TaskName="AjaxMin" AssemblyFile="$(MSBuildProjectDirectory)\lib\AjaxMinTask.dll" />
<Target Name="CompressJsAndCss" AfterTargets="CopyAllFilesToSingleFolderForPackage">
<ItemGroup>
<JS Include="$(_PackageTempDir)\**\*.js" Exclude="$(_PackageTempDir)\**\*.min.js" />
<CSS Include="$(_PackageTempDir)\**\*.css" Exclude="$(_PackageTempDir)\**\*.min.css" />
</ItemGroup>
<Message Text="Compressing JavaScript and CSS files in $(PublishDir)..." Importance="high" />
<AjaxMin JsKnownGlobalNames="jQuery,$" JsSourceFiles="#(JS)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".js" CssSourceFiles="#(CSS)" CssSourceExtensionPattern="\.css$" CssTargetExtension=".css" />
</Target>
I'd expect it to minify the files in the temporary package folder, but nothing happens.
So I've managed to solve the problem.
I had to find the right target and folders to do this on:
<UsingTask TaskName="AjaxMin" AssemblyFile="$(MSBuildProjectDirectory)\lib\AjaxMinTask.dll" />
<Target Name="CompressJsAndCss" AfterTargets="CopyAllFilesToSingleFolderForAspNetCompileMerge">
<ItemGroup>
<JS Include="$(IntermediateOutputPath)\AspnetCompileMerge\Source\**\*.js" Exclude="$(IntermediateOutputPath)\AspnetCompileMerge\Source\**\*.min.js" />
<CSS Include="$(IntermediateOutputPath)\AspnetCompileMerge\Source\**\*.css" Exclude="$(IntermediateOutputPath)\AspnetCompileMerge\Source\**\*.min.css" />
</ItemGroup>
<Message Text="Compressing JavaScript and CSS files in $(IntermediateOutputPath)..." Importance="high" />
<AjaxMin JsKnownGlobalNames="jQuery,$" JsSourceFiles="#(JS)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".js" CssSourceFiles="#(CSS)" CssSourceExtensionPattern="\.css$" CssTargetExtension=".css" />
</Target>
Now after the first copy, it will minify the files and use those going forward

Is there an indexer available in MSBuild ItemGroups?

I'm using this stack overflow answer to return the built assembly's #(Version) as an ItemGroup for use in the post-build event.
However, I want to have Major and Minor separately, as I only want vMajor.Minor in the post build. To do this, I'd like to index inside the Include attribute.
The following works, but will break if the Major or Minor numbers go over 9 (single digits only):
<Target Name="PostBuildMacros">
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="Targets" />
</GetAssemblyIdentity>
<ItemGroup>
<Version Include="#(Targets->'%(Version)')" />
<Major Include="#(Version->Substring(0,1))" />
<Minor Include="#(Version->Substring(2,1))" />
</ItemGroup>
</Target>
<PropertyGroup>
<PostBuildEventDependsOn>
$(PostBuildEventDependsOn);
PostBuildMacros;
</PostBuildEventDependsOn>
<PostBuildEvent>
if $(ConfigurationName) == Release copy /y $(TargetPath) $(SolutionDir)..\Builds\$(TargetName)_v#(Major).#(Minor)$(TargetExt)
</PostBuildEvent>
</PropertyGroup>
What I'm looking for is something more along the lines of:
<Major Include="#(Version->Split('.')[0])" />
<Minor Include="#(Version->Split('.')[1])" />
or, only if an indexer is really not possible,
<Major Include="#(Targets->Version->Major)" />
<Minor Include="#(Targets->Version->Minor)" />
<Major Include="#(Targets->'%(Version)'->'%(Major)')" />
<Minor Include="#(Targets->'%(Version)'->'%(Minor)')" />
<Major Include="#(Targets->'%(Version.Major)')" />
<Minor Include="#(Targets->'%(Version.Minor)')" />
What options, if any, do I have to index an array or otherwise pick apart a version number like 1.0.2838.24877 into 1 and 0?
Edit
This now works, by first using a <PropertyGroup> I can utilitize Split('.')[n] like in this post, but the $(Major) Properties ($()) are not available in the Post-Build event (why not? Am I missing something?). This would be more elegant if I could just directly use $(Major) in the post-build.
<Target Name="PostBuildMacros">
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="Targets" />
</GetAssemblyIdentity>
<PropertyGroup>
<Version>#(Targets->'%(Version)')</Version>
<Major>$(Version.Split('.')[0])</Major>
<Minor>$(Version.Split('.')[1])</Minor>
<Build>$(Version.Split('.')[2])</Build>
<Revision>$(Version.Split('.')[3])</Revision>
</PropertyGroup>
<ItemGroup>
<Version Include="$(Version)" />
<Major Include="$(Major)" />
<Minor Include="$(Minor)" />
<Build Include="$(Build)" />
<Revision Include="$(Revision)" />
</ItemGroup>
<Message Text="Version: #(Version)" />
<Message Text="Major.Minor.Build.Revision: #(Major).#(Minor).#(Build).#(Revision)" />
</Target>
<PropertyGroup>
<PostBuildEventDependsOn>
$(PostBuildEventDependsOn);
PostBuildMacros;
</PostBuildEventDependsOn>
<PostBuildEvent>
if $(ConfigurationName) == Release copy /y $(TargetPath) $(SolutionDir)..\Builds\$(TargetName)_v#(Major).#(Minor)$(TargetExt)
</PostBuildEvent>
</PropertyGroup>
Why are ItemGroups #() available and PropertyGroups $() not?
This is the best I've come to, with little understanding of what else would be available or how to use indexers within ItemGroups.
<Target Name="PostBuildMacros">
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="Targets" />
</GetAssemblyIdentity>
<PropertyGroup>
<Version>#(Targets->'%(Version)')</Version>
</PropertyGroup>
<ItemGroup>
<Version Include="$(Version)" />
<Major Include="$(Version.Split('.')[0])" />
<Minor Include="$(Version.Split('.')[1])" />
<Build Include="$(Version.Split('.')[2])" />
<Revision Include="$(Version.Split('.')[3])" />
</ItemGroup>
<Message Text="Version: #(Version)" />
<Message Text="Major.Minor.Build.Revision: #(Major).#(Minor).#(Build).#(Revision)" />
</Target>
<PropertyGroup>
<PostBuildEventDependsOn>
$(PostBuildEventDependsOn);
PostBuildMacros;
</PostBuildEventDependsOn>
<PostBuildEvent>
if $(ConfigurationName) == Release copy /y $(TargetPath) $(SolutionDir)..\Builds\$(TargetName)_v#(Major).#(Minor)$(TargetExt)
</PostBuildEvent>
</PropertyGroup>
I would like to be able to accomplish this without the <PropertyGroup> section, if possible.

My app.config did not transform the value

In my windows service application, I want to debug it by my configuration. Originally I used slowcheetah, however it just did not work. So I wanted to manually to transform it.
There is a method to do it.
In the project file, I have
<ItemGroup>
<Content Include="App.config" />
<Content Include="App.Debug.config">
<DependentUpon>App.config</DependentUpon>
</Content>
<Content Include="App.TestDebug.config">
<DependentUpon>App.config</DependentUpon>
</Content>
<Content Include="App.Release.config">
<DependentUpon>App.config</DependentUpon>
</Content>
<None Include="packages.config">
</None>
</ItemGroup>
Also I have
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterCompile" Condition="exists('app.$(Configuration).config')">
<!-- Generate transformed app config in the intermediate directory -->
<TransformXml Source="app.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="app.$(Configuration).config" />
<!-- Force build process to use the transformed configuration file from now on. -->
<ItemGroup>
<AppConfigWithTargetPath Remove="app.config" />
<AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
<TargetPath>$(TargetFileName).config</TargetPath>
</AppConfigWithTargetPath>
</ItemGroup>
</Target>
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
In App.TestDebug.config, the value is:
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings>
<add key="veserver" value="xx.xx.xx.221" xdt:Transform="Replace" xdt:Locator="Match(key)"/>
In App.Debug.config, the value is:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="veserver" value="xx.xx.xx.221" />
In App.config, the value is:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<add key="veserver" value="xx.xx.xx.222" />
Now I debug it with
App.TestDebug.config
In the C# code ConfigurationManager.AppSettings["veserver"] is still
xx.xx.xx.222
Which means that it didn't transform the value. It is supposed to be
xx.xx.xx.221
Why?
Find a solution by myself.
<ItemGroup>
<Content Include="App.config" />
<None Include="App.Debug.config">
<DependentUpon>App.config</DependentUpon>
</None>
<None Include="App.TestDebug.config">
<DependentUpon>App.config</DependentUpon>
</None>
<None Include="App.Release.config">
<DependentUpon>App.config</DependentUpon>
</None>
<None Include="packages.config">
</None>
Change
Content
to
None
.

Resources