NLog produces the following log filename MyMachine_MyExe_1.0.0.0.log. It includes the assembly version, but not the git's commit id which can be seen in dll's Product version property below.
Is there a way, either via NLog.config or programmatically to include the git's commit id in the log's filename?
NLog.config
<variable name="callsite" value="${callsite:includeNamespace=false:className=true:methodName=true}"/>
<variable name="baseLogDir" value="logs" />
<variable name="baseLogFilename" value="${machinename}_${processname}_${assembly-version}" />
<variable name="debugTraceLayout" value="${longdate}|${level:uppercase=true}|${callsite}|${message}" />
<targets>
<target
xsi:type="Console"
name="console"
layout="${longdate}|${level:uppercase=true}|${message}" />
<target xsi:type="File"
name="fileInfo"
fileName="${baseLogDir}/${baseLogFilename}.log"
layout="${longdate}|${level:uppercase=true}|${message}"
archiveFileName="${baseLogDir}/archive/${baseLogFilename}_{#}.log"
archiveNumbering="Date"
archiveOldFileOnStartup="true"
archiveDateFormat="yyyyMMdd_HHmmss" />
MyProject.csproj
<Project Sdk="Microsoft.NET.Sdk">
<Target Name="SetSourceRevisionId" BeforeTargets="InitializeSourceControlInformation">
<Exec Command="git describe --long --always --dirty --exclude=* --abbrev=8" ConsoleToMSBuild="True" IgnoreExitCode="False">
<Output PropertyName="SourceRevisionId" TaskParameter="ConsoleOutput" />
</Exec>
</Target>
</Project>
MyLibrary.dll Properties
I would define additional assembly attributes in your msbuild project;
<Project Sdk="Microsoft.NET.Sdk">
<Target Name="SetSourceRevisionId" BeforeTargets="InitializeSourceControlInformation">
<Exec ...></Exec>
<ItemGroup>
<AssemblyMetadata Include="SourceRevisionId" Value="$(SourceRevisionId)" />
</ItemGroup>
</Target>
</Project>
Which I believe you can use to define NLog's Global Diagnostic Context (GDC)
GlobalDiagnosticsContext.Set(
"SourceRevisionId",
typeof(Program).Assembly
.GetCustomAttributes<AssemblyMetadataAttribute>()
.Where(a => a.Key == "SourceRevisionId")
.Single()
.Value
);
And define the output filename;
fileName="${baseLogDir}/${gdc:item=SourceRevisionId}.log"
Related
I have project A that need to insert a TextId.cs before build. And, there is project B. TextId.cs would generated after project B is compiled and executed.
Now I'd like to integrate the compile and execute in Directory.Build.targets in project A. It is not worked as I expect. TextId.cs will generate but the build would still failed as no TextId.cs if I set BeforeTargets="BeforeBuild" as below.
Anyone knows that which target is OK? or, any other solution?
<Project>
<ItemGroup>
<ProjectReferences Include="c:\code\textidfilegenerator\*.*proj" />
</ItemGroup>
<Target Name="BuildOtherProjects">
<Message Importance="High" Text="-----------------------" />
<MSBuild
Projects="#(ProjectReferences)"
Targets="Build">
</MSBuild>
</Target>
<Target Name="CopyText" DependsOnTargets="BuildOtherProjects" BeforeTargets="BeforeBuild">
<Message Importance="High" Text="**********************" />
<Exec Command="C:\Code\TextIdFileGenerator\bin\Debug\net6.0\TextIdFileGenerator.exe C:\Code\Sys1500TestDriver\TextProvider\TextIds.cs" IgnoreExitCode="true"/>
</Target>
</Project>
Before you will dive into the comments below, go through these docs:
MSBuild reserved and well-known properties
Common MSBuild project properties
<Project>
<ItemGroup>
<ProjectReferences Include="c:\code\textidfilegenerator\*.*proj" /> <!--you should use relative path like <ProjectReference Include="../**/*.csproj or absolute with MSBuild well-known properties" />-->
</ItemGroup>
<Target Name="BuildOtherProjects"> <!--you don't need this target if you have project reference-->
<Message Importance="High" Text="-----------------------" />
<MSBuild
Projects="#(ProjectReferences)"
Targets="Build">
</MSBuild>
</Target>
<Target Name="CopyText" DependsOnTargets="BuildOtherProjects" BeforeTargets="BeforeBuild"><!-- 'BeforeBuild' will not work because TextIdFileGenerator.exe needs to be created before you will do anything with it so you should use 'AfterTargets="Build"'-->
<Message Importance="High" Text="**********************" />
<Exec Command="C:\Code\TextIdFileGenerator\bin\Debug\net6.0\TextIdFileGenerator.exe C:\Code\Sys1500TestDriver\TextProvider\TextIds.cs" IgnoreExitCode="true"/><!-- again, you should use relative paths or absolute ones with combination of MSBuildProjectDirectory and OutDir -->
</Target>
</Project>
I'm upgrading a project from AspNet Mvc 4 to AspNet Core Mvc 2.2; I am attempting to migrate the msbuild build.proj file to set the version and other attributes for the projects that create dll's; everything is working except the GenerateAssemblyInfo task. Is there a new way to do this in netcoreapp2.2?
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="GetRevisionInfo" BeforeTargets="Build">
<GitPendingChanges ContinueOnError="WarnAndContinue">
<Output TaskParameter="HasPendingChanges" PropertyName="HasPendingChanges" />
</GitPendingChanges>
<!--This will throw git Error 128 if there are no Tags -->
<GitDescribe SoftErrorMode="true" Lightweight="true" ContinueOnError="WarnAndContinue">
<Output TaskParameter="Tag" PropertyName="Tag" />
<Output TaskParameter="CommitCount" PropertyName="CommitCount" />
<Output TaskParameter="CommitHash" PropertyName="CommitHash" />
</GitDescribe>
<GitBranch ContinueOnError="WarnAndContinue">
<Output TaskParameter="Branch" PropertyName="Branch" />
</GitBranch>
<PropertyGroup>
<ShortCommitHash Condition="'$(CommitHash)' != ''">$(CommitHash.Substring(0,6))</ShortCommitHash>
<ReleaseType Condition="'$(CommitCount)' != '' AND '$(CommitCount)' != '0'">Beta</ReleaseType>
<ReleaseType Condition="'$(Branch)' != '' AND '$(Branch)' != 'master'">Alpha</ReleaseType>
</PropertyGroup>
</Target>
<!-- Error out if this is a release and our working copy has uncommitted changes -->
<Target Name="CheckRelease" AfterTargets="GetRevisionInfo" Condition="'$(Configuration)' == 'Release'">
<Error Text="Cannot build a Release Version when there are uncommitted changes, commit or revert all changes." Condition="'$(CommitHash)' != '' AND '$(HasPendingChanges)' == 'True'" />
</Target>
<!-- Generates AssemblyInfo file using Git Describe -->
<Target Name="GenerateAssemblyInfo" AfterTargets="CheckRelease" Condition="'$(CommitHash)' != ''">
<Time>
<Output TaskParameter="Year" PropertyName="Year" />
</Time>
<AssemblyInfo
CodeLanguage="CS"
OutputFile="$(MSBuildProjectDirectory)\Properties\AssemblyInfo.cs"
AssemblyProduct="$(MSBuildProjectName) $(ReleaseType)"
AssemblyCompany="xxx xxx xxx, LLC"
AssemblyCopyright="Copyright © $(Year) xxx xxx xxx, LLC. All rights reserved."
AssemblyConfiguration="$(Configuration)-$(Platform)"
AssemblyVersion="$(Tag).$(CommitCount)"
AssemblyFileVersion="$(Tag).$(CommitCount)"
AssemblyInformationalVersion ="$(Tag)-$(CommitCount)-$(ShortCommitHash) $(ReleaseType)"
AssemblyTitle="$(Tag)-$(CommitCount)-$(CommitHash)"/>
</Target>
<!-- copy framework files to libraries -->
<Target Name="CopyLibraries" Condition="'$(MSBuildProjectName)' == 'BaseApplication'" AfterTargets="Build">
<CreateItem Include="$(TargetDir)xxx.*">
<Output TaskParameter="Include" PropertyName="CopyFiles" />
</CreateItem>
<Copy SourceFiles="$(CopyFiles)" DestinationFolder="$(MSBuildProjectDirectory)\..\libraries\xxx\$(Configuration)"/>
</Target>
<Target Name="CopyKendoUI" AfterTargets="AfterBuild">
<ItemGroup>
<KendoFiles Include="
$(TargetDir)kendo.mvc.*;
$(TargetDir)\**\Kendo.Mvc.resources.*;" />
</ItemGroup>
<Copy SourceFiles="#(KendoFiles)" DestinationFolder="$(MSBuildProjectDirectory)\..\libraries\kendoui\$(Configuration)\%(RecursiveDir)"/>
</Target>
</Project>
There were a few things preventing this from working in Visual Studio 2019 using .Net Core;
The name of the target cannot be "GenerateAssemblyInfo", if this is the name of the target, it just gets ignored, no error, warning, or message, the target just doesn't run...
In the csproj file for the project that the msbuild project is imported in, you need to add false, I added this right below the
You have to manually create the Properties folder if you set the OutputFile to be in that folder.
Below is the working build.proj file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="GetRevisionInfo" BeforeTargets="Build">
<GitPendingChanges ContinueOnError="WarnAndContinue">
<Output TaskParameter="HasPendingChanges" PropertyName="HasPendingChanges" />
</GitPendingChanges>
<!--This will throw git Error 128 if there are no Tags -->
<GitDescribe SoftErrorMode="true" Lightweight="true" ContinueOnError="WarnAndContinue">
<Output TaskParameter="Tag" PropertyName="Tag" />
<Output TaskParameter="CommitCount" PropertyName="CommitCount" />
<Output TaskParameter="CommitHash" PropertyName="CommitHash" />
</GitDescribe>
<GitBranch ContinueOnError="WarnAndContinue">
<Output TaskParameter="Branch" PropertyName="Branch" />
</GitBranch>
<PropertyGroup>
<ShortCommitHash Condition="'$(CommitHash)' != ''">$(CommitHash.Substring(0,6))</ShortCommitHash>
<ReleaseType Condition="'$(CommitCount)' != '' AND '$(CommitCount)' != '0'">Beta</ReleaseType>
<ReleaseType Condition="'$(Branch)' != '' AND '$(Branch)' != 'master'">Alpha</ReleaseType>
</PropertyGroup>
</Target>
<!-- Error out if this is a release and our working copy has uncommitted changes -->
<Target Name="CheckRelease" AfterTargets="GetRevisionInfo" Condition="'$(Configuration)' == 'Release'">
<Error Text="Cannot build a Release Version when there are uncommitted changes, commit or revert all changes." Condition="'$(CommitHash)' != '' AND '$(HasPendingChanges)' == 'True'" />
</Target>
<!-- Generates AssemblyInfo file using Git Describe -->
<Target Name="GenerateAssemblyInfo" AfterTargets="CheckRelease" Condition="'$(CommitHash)' != ''">
<Time>
<Output TaskParameter="Year" PropertyName="Year" />
</Time>
<AssemblyInfo
CodeLanguage="CS"
OutputFile="$(MSBuildProjectDirectory)\Properties\AssemblyInfo.cs"
AssemblyProduct="$(MSBuildProjectName) $(ReleaseType)"
AssemblyCompany="xxx xxx xxx, LLC"
AssemblyCopyright="Copyright © $(Year) xxx xxx xxx, LLC. All rights reserved."
AssemblyConfiguration="$(Configuration)-$(Platform)"
AssemblyVersion="$(Tag).$(CommitCount)"
AssemblyFileVersion="$(Tag).$(CommitCount)"
AssemblyInformationalVersion ="$(Tag)-$(CommitCount)-$(ShortCommitHash) $(ReleaseType)"
AssemblyTitle="$(Tag)-$(CommitCount)-$(CommitHash)"/>
</Target>
<!-- copy framework files to libraries -->
<Target Name="CopyLibraries" Condition="'$(MSBuildProjectName)' == 'BaseApplication'" AfterTargets="Build">
<CreateItem Include="$(TargetDir)xxx.*">
<Output TaskParameter="Include" PropertyName="CopyFiles" />
</CreateItem>
<Copy SourceFiles="$(CopyFiles)" DestinationFolder="$(MSBuildProjectDirectory)\..\libraries\xxx\$(Configuration)"/>
</Target>
<Target Name="CopyKendoUI" AfterTargets="AfterBuild">
<ItemGroup>
<KendoFiles Include="
$(TargetDir)kendo.mvc.*;
$(TargetDir)\**\Kendo.Mvc.resources.*;" />
</ItemGroup>
<Copy SourceFiles="#(KendoFiles)" DestinationFolder="$(MSBuildProjectDirectory)\..\libraries\kendoui\$(Configuration)\%(RecursiveDir)"/>
</Target>
</Project>
And the MyProject.csproj file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MSBuildTasks" Version="1.5.0.235">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Http.Abstractions">
<HintPath>C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.http.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Abstractions.dll</HintPath>
</Reference>
</ItemGroup>
<Import Project="../.build/build.proj" />
</Project
In my company, we have some projects using .NET Framework (4.5.1) and one project using .NET Core.
Currently, all the .NET Framework projects are built with MSBuild.exe (version 12) and i would like to update the build to use MSBuild 15 so i would be able to build both .NET Framework and .NET Core projects in the same build.
Currently, the build compiles successfully when i'm building only my .NET Core project. But i wish to publish it, and the build result is not my desired outcome as it doesn't publish it correctly (the build results in the folders: bin, Properties, Views, wwwroot, and the configuration files).
I dont know what im doing wrong here, i have searched the web for a couple of days and still wasnt able to figure out what i did wrong. Please advice.
Note: to be able to build in the first place, i had to add to my .NET Core's project .csproj file the following lines so it wont fail while building:
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets" Condition="true" />
The command line to execute the build
"C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild" DailyBuild.proj /t:DailyBuild /p:VersionNumber=15
DailyBuild.proj
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SourcesPath>$(MSBuildProjectDirectory)\..\..\</SourcesPath>
<CSCleanProperties>BuildType=Clean;Configuration=Release;IsFormalBuild=true</CSCleanProperties>
<CSBuildProperties>BuildType=ReBuild;Configuration=Release;PauseBuildOnError=false;PublishWebSites=true;VersionName=Prod-$(VersionNumber)</CSBuildProperties>
</PropertyGroup>
<Target Name="DailyBuildWithClean">
<MSBuild Projects="$(MSBuildProjectDirectory)\Make2.proj" Targets="Clean" Properties="$(CSCleanProperties)"/>
<MSBuild Projects="$(MSBuildProjectDirectory)\Make2.proj" Properties="$(CSCleanProperties)"/>
<MSBuild Projects="$(MSBuildProjectDirectory)\Make2.proj" Targets="FormalBuild" Properties="$(CSBuildProperties)"/>
</Target>
<Target Name="DailyBuild">
<MSBuild Projects="$(MSBuildProjectDirectory)\Make2.proj" Targets="SW;PreparePackFolder" Properties="$(CSBuildProperties)"/>
</Target>
</Project>
Make2.proj
<Project DefaultTargets="SW" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" InitialTargets="CreateProperties;Clean">
<ItemGroup>
<SourcesPathItem Include='$(MSBuildProjectDirectory)\..\..\' />
</ItemGroup>
<PropertyGroup>
<MSBuildCommunityTasksPath>$(MSBuildProjectDirectory)\MSBuild.Community.Tasks.v1.4.0.88</MSBuildCommunityTasksPath>
</PropertyGroup>
<Import Project="$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.Targets" />
<PropertyGroup>
<Configuration>Debug</Configuration>
<Platform>x86</Platform>
<CSConfiguration>$(Configuration)</CSConfiguration>
<BuildType Condition=" '$(BuildType)' == '' ">Build</BuildType>
<PauseBuildOnError>true</PauseBuildOnError>
<PublishWebSites>false</PublishWebSites>
<IsFormalBuild>false</IsFormalBuild>
<VersionName>Prod</VersionName>
</PropertyGroup>
<Target Name="CreateProperties" >
<CreateProperty Value="%(SourcesPathItem.Fullpath)Src\">
<Output PropertyName="SourcesPath" TaskParameter="Value"/>
</CreateProperty>
<CreateProperty Value="%(SourcesPathItem.Fullpath)Artifacts\">
<Output PropertyName="MainArtifactsFolder" TaskParameter="Value"/>
</CreateProperty>
<CreateProperty Value="%(SourcesPathItem.Fullpath)Packages\">
<Output PropertyName="PackageFolder" TaskParameter="Value"/>
</CreateProperty>
<CreateProperty Value="%(SourcesPathItem.Fullpath)Artifacts\DeployedArtifacts\">
<Output PropertyName="DeployedPackageFolder" TaskParameter="Value"/>
</CreateProperty>
<CreateProperty Value="%(SourcesPathItem.Fullpath)Src\Util\InspectorWebService\InspectorWebService\Publish\">
<Output PropertyName="InspectorWebServicePublishPath" TaskParameter="Value"/>
</CreateProperty>
</Target>
<PropertyGroup>
<CSPlatformIndependentProjectProperties>Configuration=$(CSConfiguration);Platform=AnyCPU</CSPlatformIndependentProjectProperties>
<CSPlatformSpecificProjectProperties>Configuration=$(CSConfiguration);Platform=$(Platform)</CSPlatformSpecificProjectProperties>
<VCConfiguration>Configuration=$(CSConfiguration);Platform=Win32</VCConfiguration>
</PropertyGroup>
<Target Name="InspectorWebService">
<RemoveDir Directories="$(InspectorWebServicePublishPath)"/>
<MSBuild Projects="$(SourcesPath)Util\InspectorWebService\InspectorWebService\InspectorWebService.csproj" Targets="$(BuildType)" Properties="$(CSPlatformIndependentProjectProperties)"/>
<MSBuild Condition=" '$(BuildType)' != 'Clean' And '$(PublishWebSites)' == 'true' " Projects="$(SourcesPath)Util\InspectorWebService\InspectorWebService\InspectorWebService.csproj"
Targets="ResolveReferences;_WPPCopyWebApplication" Properties="WebProjectOutputDir=$(InspectorWebServicePublishPath);BuildingProject=true" />
</Target>
<PropertyGroup>
<AllProcessesTargets>
InspectorWebService;
</AllProcessesTargets>
</PropertyGroup>
<Target Name="SW">
<CallTarget Targets="$(AllProcessesTargets)" RunEachTargetSeparately="false"/>
<OnError ExecuteTargets="PauseBuild"/>
</Target>
<Target Name="FormalBuild">
<CallTarget Targets="SW;PreparePackFolder;Pack"/>
<OnError ExecuteTargets="ErrorHandler"/>
</Target>
<Target Name="PreparePackFolder">
<RemoveDir Directories="$(MainArtifactsFolder)" />
<MakeDir Directories="$(MainArtifactsFolder)" />
<MSBuild Projects="$(MSBuildProjectFile)" Targets="PreparePackFolderInternal" Properties="ArtifactFormat=Old;MixedArtifiactFolder=$(MainArtifactsFolder)MixedArtifacts\"/>
<MSBuild Projects="$(MSBuildProjectFile)" Targets="PreparePackFolderInternal" Properties="ArtifactFormat=New;MixedArtifiactFolder=$(MainArtifactsFolder)DeployedArtifacts\"/>
</Target>
<Target Name="PreparePackFolderInternal">
<CallTarget Targets="PrepareInspectorWebServiceToPack;PrepareOtherFolders"/>
</Target>
<Target Name="CopyDefaultFiles">
<Exec Condition=" '$(ArtifactFormat)' == 'Old'" Command="xcopy "$(CompleteBinFolder)*.*" "$(MixedArtifiactFolder)$(ComponenetName)\Binaries" /I /Y /D /E /F"/>
<Exec Condition=" '$(ArtifactFormat)' == 'New'" Command="xcopy "$(CompleteBinFolder)*.*" "$(MixedArtifiactFolder)$(ComponenetName)" /I /Y /D /E /F"/>
<ItemGroup>
<GeneralConfigFiles Include="$(MixedArtifiactFolder)$(ComponenetName)\Binaries\*.config"/>
<PDBFiles Include="$(MixedArtifiactFolder)$(ComponenetName)\**\*.pdb"/>
</ItemGroup>
<Move Condition=" '$(ArtifactFormat)' == 'Old'" SourceFiles="#(GeneralConfigFiles)" DestinationFolder="$(MixedArtifiactFolder)$(ComponenetName)\Configurations"/>
<Move Condition=" '$(ArtifactFormat)' == 'New'" SourceFiles="#(PDBFiles)" DestinationFolder="$(MainArtifactsFolder)PDBs\$(ComponenetName)"/>
<Delete Condition=" '$(ArtifactFormat)' == 'Old'" Files="#(PDBFiles)"/>
</Target>
<Target Name="PrepareInspectorWebServiceToPack" Condition=" '$(BuildType)' != 'Clean' ">
<MSBuild Projects="$(MSBuildProjectFile)" Targets="CopyDefaultFiles" Properties="CompleteBinFolder=$(InspectorWebServicePublishPath);ComponenetName=InspectorWebService"/>
</Target>
<Target Name="PrepareOtherFolders">
<Exec Command="xcopy "$(SourcesPath)..\Certificates\*.*" "$(MixedArtifiactFolder)Certificates" /I /Y /D /E /F"/>
<Exec Command="xcopy "$(SourcesPath)\Resources\CCI\*.*" "$(DeployedPackageFolder)CCI\Configuration\" /I /Y /D /E /F"/>
</Target>
<Target Name="Pack" Condition=" '$(BuildType)' != 'Clean' ">
<RemoveDir Directories="$(PackageFolder)" />
<MakeDir Directories="$(PackageFolder)" />
<ItemGroup>
<InspectorWebServiceFilesForZip Include="$(DeployedPackageFolder)InspectorWebService\**\*.*" Exclude="$(DeployedPackageFolder)InspectorWebService\**\*.pdb" />
</ItemGroup>
<Zip ZipFileName="$(PackageFolder)$(VersionName)-InspectorWebService.zip" WorkingDirectory="$(DeployedPackageFolder)InspectorWebService" Files="#(InspectorWebServiceFilesForZip)" ZipLevel="9" ParallelCompression="false" />
<ItemGroup>
<AllZipFiles Include="$(DeployedPackageFolder)\**\*.*" Exclude="$(DeployedPackageFolder)\**\*.pdb" />
</ItemGroup>
<Zip ZipFileName="$(PackageFolder)$(VersionName)-!All.zip" WorkingDirectory="$(DeployedPackageFolder)" Files="#(AllZipFiles)" ZipLevel="9" ParallelCompression="false" />
<ItemGroup>
<AllPDBFiles Include="$(MainArtifactsFolder)PDBs\**\*.pdb"/>
</ItemGroup>
<Zip ZipFileName="$(PackageFolder)$(VersionName)-!PDBForAll.zip" WorkingDirectory="$(MainArtifactsFolder)PDBs" Files="#(AllPDBFiles)" ZipLevel="9" ParallelCompression="false" />
</Target>
<Target Name="Clean" Condition=" '$(BuildType)' == 'Clean' ">
<RemoveDir Directories="$(InspectorWebServicePublishPath)"/>
<RemoveDir Directories="$(PackageFolder)"/>
<RemoveDir Directories="$(MixedArtifiactFolder)"/>
</Target>
<Target Name="PauseBuild" Condition=" '$(PauseBuildOnError)' == 'true' ">
<Prompt Text="Press any key to continue ..." />
</Target>
<Target Name="ErrorHandler">
</Target>
</Project>
I have an application which I want to publish with ClickOnce via command line. I have a test and a live version. It should be allowed to have both installed at the same time, which means that I need to change the assemble name (and preferably also the product name) for one of the builds. I would like to do this in the build settings.
I have managed to make some build settings, which works fine, but I cannot figure out how to change the assembly and product name, for just one of them.
I have added the following code to my .csproj file, which I call with the command msbuild /target:Test or msbuild /target:Live. But where do I implement the assembly and product name change?
<PropertyGroup>
<ProjLocation>$(ProjectDir)</ProjLocation>
<ProjLocationReleaseDir>$(ProjLocation)\bin\Debug</ProjLocationReleaseDir>
<ProjPublishLocation>$(ProjLocationReleaseDir)\app.publish</ProjPublishLocation>
<DeploymentFolder>C:\MyProjects\Software\Publish\</DeploymentFolder>
</PropertyGroup>
<!-- Build settings for live version -->
<Target Name="Live" DependsOnTargets="Clean">
<MSBuild Projects="$(ProjLocation)\$(ProjectName).csproj"
Properties="$(DefaultBuildProperties)"
Targets="Publish"/>
<ItemGroup>
<SetupFiles Include="$(ProjPublishLocation)\*.*"/>
<UpdateFiles Include="$(ProjPublishLocation)\Application Files\**\*.*"/>
</ItemGroup>
<Copy SourceFiles="#(SetupFiles)" DestinationFolder="$(DeploymentFolder)\Live\" />
<Copy SourceFiles="#(UpdateFiles)" DestinationFolder="$(DeploymentFolder)\Live\Application Files\%(RecursiveDir)"/>
</Target>
<!-- Build settings for test version -->
<Target Name="Test" DependsOnTargets="Clean">
<MSBuild Projects="$(ProjLocation)\$(ProjectName).csproj"
Properties="$(DefaultBuildProperties)"
Targets="Publish"/>
<ItemGroup>
<SetupFiles Include="$(ProjPublishLocation)\*.*"/>
<UpdateFiles Include="$(ProjPublishLocation)\Application Files\**\*.*"/>
</ItemGroup>
<Copy SourceFiles="#(SetupFiles)" DestinationFolder="$(DeploymentFolder)\Public Test\" />
<Copy SourceFiles="#(UpdateFiles)" DestinationFolder="$(DeploymentFolder)\Public Test\Application Files\%(RecursiveDir)"/>
</Target>
You can add "AssemblyName" property to the PropertyGroup. like this:
<PropertyGroup>
<AssemblyName>YourAppName</AssemblyName>
</PropertyGroup>
or you can use the MSBuild command line switch. like this :
msbuild /property:AssemblyName=YourAppName
I had almost the same task (need to distinguish between Staging and Production) and I solved it with the following MSBuild-Target:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- call "nuget restore Deployment\packages.config" before executing this script -->
<Import Project="..\packages\MSBuildTasks.1.5.0.235\build\MSBuildTasks.targets" />
<PropertyGroup>
<Configuration>Release</Configuration>
<ClientProject>..\MyProject\MyProject.vbproj</ClientProject>
<ClientPublishDir Condition="$(Environment) == 'Staging'">\\deployment-staging\MyProject\</ClientPublishDir>
<ClientPublishDir Condition="$(Environment) == 'Production'">\\deployment\MyProject\</ClientPublishDir>
</PropertyGroup>
<ItemGroup>
<ClientModifiedAppConfig Include="$(ClientProject)\..\App.$(Environment).config" />
</ItemGroup>
<Target Name="DeployClient">
<Error Condition="$(Environment) == ''" Text="The Property 'Environment' has not been set." />
<Error Condition="$(Environment) != 'Staging' AND $(Environment) != 'Production'" Text="The Property 'Environment' has not been set properly. Valid values are 'Staging' and 'Production'." />
<!-- Sets different assembly names for INT and PRD applications. Due to this, both INT and PRD applications with the
same version number can be installed on the same system. -->
<XmlUpdate Condition="$(Environment) == 'Staging'" Prefix="n" Namespace="http://schemas.microsoft.com/developer/msbuild/2003" XmlFileName="$(ClientProject)" Xpath="/n:Project/n:PropertyGroup/n:AssemblyName" Value="MyProjectStaging" />
<XmlUpdate Condition="$(Environment) == 'Staging'" Prefix="n" Namespace="http://schemas.microsoft.com/developer/msbuild/2003" XmlFileName="$(ClientProject)" Xpath="/n:Project/n:PropertyGroup/n:ProductName" Value="MyProject Staging" />
<XmlUpdate Condition="$(Environment) == 'Production'" Prefix="n" Namespace="http://schemas.microsoft.com/developer/msbuild/2003" XmlFileName="$(ClientProject)" Xpath="/n:Project/n:PropertyGroup/n:AssemblyName" Value="MyProject" />
<XmlUpdate Condition="$(Environment) == 'Production'" Prefix="n" Namespace="http://schemas.microsoft.com/developer/msbuild/2003" XmlFileName="$(ClientProject)" Xpath="/n:Project/n:PropertyGroup/n:ProductName" Value="MyProject" />
<!-- Overwrites the original App.config with the environment-dependent App.config.
Reason: ClickOnce only uses App.config and does not apply transformations, as it is done in Web Projects. -->
<Copy
SourceFiles="#(ClientModifiedAppConfig)"
DestinationFiles="$(ClientProject)\..\App.config"
OverwriteReadOnlyFiles="true"
/>
<!-- Publish -->
<MSBuild
Projects="$(ClientProject)"
Targets="Publish"
Properties="
PublishDir=$(ClientPublishDir);
Configuration=$(Configuration);
Platform=x86" />
</Target>
</Project>
To make this work, you have to restore the NuGet package MSBuildTasks.
Finally, all I have to call is msbuild Deployment.targets /t:DeployClient /p:Environment=Staging
Hope that helps!
I currently create my first MSBuild-script.
I've a tag "Folders" that findes all Directories in a given root path:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Target Name="Build">
<PropertyGroup>
<RootFolder>tmp</RootFolder>
</PropertyGroup>
<ItemGroup>
<Folders Include="$([System.IO.Directory]::GetDirectories("$(RootFolder)"))"/>
</ItemGroup>
<Message Text="#(Folders -> '%(FullPath)\Bin\Debug\%(Filename)%(Extension).dll', ';')"/>
</Target>
</Project>
That works perfect.
My problem is that I only need directories where the specified file exists.
I tried a condition like that
Condition="$([System.IO.File]::Exists("%(FullPath)\\Bin\\Debug\\%(Filename)%(Extension).dll"))"
for the folder tag.
This script runs without any error but my list is empty.
Why?
Are there any other solutions to check for a file?
I used this solution because it uses C# and I'm a C#-developer.
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Target Name="Build">
<PropertyGroup>
<RootFolders>tmp</RootFolders>
</PropertyGroup>
<GetFiles rootFolders="$(RootFolders)">
<Output PropertyName="Files" TaskParameter="Files" />
</GetFiles>
<Message Text="$(Files)" />
</Target>
<UsingTask
TaskName="GetFiles"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<rootFolders ParameterType="System.String" Required="true" />
<files ParameterType="System.String" Output="true" />
</ParameterGroup>
<Task>
<Using Namespace="System" />
<Using Namespace="System.IO" />
<Using Namespace="System.Linq" />
<Code Type="Fragment" Language="cs">
<![CDATA[
Func<string, string> BuildFilePath = path => path + #"\Bin\Debug\" + Path.GetFileName(path) + ".dll";
var dirs = Directory.GetDirectories(rootFolders).Where(x => File.Exists(BuildFilePath(x)));
files = string.Join("\n", dirs.Select(BuildFilePath));
]]>
</Code>
</Task>
</UsingTask>
</Project>
AFAIK, the thing is Condition is executed and checked for the whole declaration of Items (i.e. <Folders ..> tag).
I think, you need to loop through the collection (e.g. using target/task batching) and check the file to exist in every single folder folder in the collection. Then if the file exists - include it in the new <FoldersFiletered> items collection.
NB: I don't have time to test the code now, but this is the idea roughly:
<Target Name="FilterFolders"
Inputs="#(Folders)"
Outputs="%(FullPath)">
<ItemGroup>
<FoldersFiltered Include="#(Folders->'%(FullPath)')"
Condition="$([System.IO.File]::Exists("#(Folders->'%(FullPath)'\\Bin\\Debug\\YourFile.dll"))" />
</ItemGroup>
</Target>