Visual studio How to set output path dependant of

2019-08-20 11:28发布

I want to configure my main output path to something like

C:\Company\UpdaterLauncher\Worker\Version

Where version is my AssemblyInfo.Version in string.

So a new folder each time I decide to change the assembly version.

I know I can change output all time.. But it's annoying.

Is this possible to use something like "C:\Company\UpdaterLauncher\Worker\{AssemblyVersion}" for visual output path to interprete it and build where I want?

I looked a bit in documentation and didn't found anything like this...

1条回答
等我变得足够好
2楼-- · 2019-08-20 11:51

Which way do you build the project? By msbuild command-line or within VS IDE?

First direction: Let's read the assembly version number before the build starts, then pass it to outputpath property.

I've written a script trying to read the version before the build starts. But not completely work:(

E.g: Using a class library project as the example.

Right-click the project and choose edit the xx.csproj, add the script (From In property to FourthNum property) into the PropertyGroup:

  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{DAB28A16-73AD-4EC5-9F8D-E58CE3EC84BE}</ProjectGuid>
    ......
    <In>$([System.IO.File]::ReadAllText('$(MSBuildProjectDirectory)\properties\AssemblyInfo.cs'))</In>
    <Pattern>\[assembly: AssemblyVersion\(.(\d+)\.(\d+)\.(\d+).(\d+)</Pattern>
    <FirstNum>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern),System.Text.RegularExpressions.RegexOptions.Multiline).Groups[1].Value)</FirstNum>
    <SecondNum>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern),System.Text.RegularExpressions.RegexOptions.Multiline).Groups[2].Value)</SecondNum>
    <ThirdNum>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern),System.Text.RegularExpressions.RegexOptions.Multiline).Groups[3].Value)</ThirdNum>
    <FourthNum>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern),System.Text.RegularExpressions.RegexOptions.Multiline).Groups[4].Value)</FourthNum>
  </PropertyGroup>

It will read the assembly version number from AssemblyInfo.cs. If I have an assembly whose assembly version is 3.13.8.5. Then the FirstNum=3, SecondNum=13 ...

And set the outputpath as: <OutputPath>C:\Company\UpdaterLauncher\Worker\$(FirstNum).$(SecondNum).$(ThirdNum).$(FourthNum)</OutputPath>

Reload the project and build it. You can find the build output there C:\Company\UpdaterLauncher\Worker\3.13.8.5.

Note:

1.In this way, since we will build it in both debug and release mode. We need to set the outputpath value in both propertygroup for debug and release.(2 places)

2.Since we only define the output depending on version, the debug output and release will all locates in same folder. So I think the <OutputPath> would be better like:

<OutputPath>C:\Company\UpdaterLauncher\Worker\$(FirstNum).$(SecondNum).$(ThirdNum).$(FourthNum)\$(Configuration)</OutputPath>

3.This script won't work immediately after you change the version in VS IDE.

Via Command-line: It works well, every time we change the version number and build it, the output is correct.

Within VS IDE: Every time after we change the version, it needs us to unload and reload the project file by right-clicking the project, then it will work. So I say it isn't that perfect.(I would think this issue has something to do with when and how the VS loads the project file)

Second Direction: The build output actually is copy the related assemblies to output folder. So we can copy or move the output content to the directory after the build we want by copy or move task.

We can check this issue, using GetAssemblyIdentity to get the info after the build.

Using the way above to get version number, name it $(MyVersion). Then use a after-build target to copy the output to the specified folder.

<Target Name="CopyToSpecificFolder" AfterTargets="build">
    <GetAssemblyIdentity
        AssemblyFiles="$(OutputPath)$(AssemblyName).dll">
      <Output
          TaskParameter="Assemblies"
          ItemName="MyAssemblyIdentities"/>
    </GetAssemblyIdentity>
    <PropertyGroup>
      <MyVersion>%(MyAssemblyIdentities.Version)</MyVersion>
    </PropertyGroup>
    <ItemGroup>
      <Out Include="$(OutputPath)*.*" />
      </ItemGroup>
    <Copy DestinationFolder="C:\Company\UpdaterLauncher\Worker\$(MyVersion)" SourceFiles="@(Out)"/>
  </Target>

Add this script into the xx.csproj file. In the bottom of it like:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  ......

  <Target Name="CopyToSpecificFolder" AfterTargets="build">
    ......
  </Target>
</Project>

It works well in whether VS IDE or by command-line. And it's for class project, if you're developing a .exe project, change the $(AssemblyName).dll to $(AssemblyName).exe.

查看更多
登录 后发表回答