清单文件的 dependentAssembly/assemblyIdentity 元素中的版本号

Version number in manifest file's dependentAssembly/assemblyIdentity element

我正在使用一个包含非托管客户端 DLL 和托管 COM 服务器 DLL 的应用程序(这本身就是一个挑战:),现在我想知道什么是保持版本号同步的最佳方法。由于我们同时构建客户端和服务器,并且我们尝试在每次构建时保持所有文件的版本号同步,所以看起来我需要一个过程来编辑客户端和服务器上的所有清单文件在完整构建发生之前结束我所有独立的 COM 引用。有没有更简单的方法?

示例(客户端清单):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
   <assemblyIdentity type="win32" name="globals" version="1.0.0.0" />
   <dependency>
      <dependentAssembly>
         <assemblyIdentity type="win32" name="SoftBrands.FourthShift.FSCulture" version="8.0.0.999" publicKeyToken="541b4aff0f04b60a" />
      </dependentAssembly>
   </dependency>
</assembly>

服务器清单:

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <assemblyIdentity type="win32" name="SoftBrands.FourthShift.FSCulture" version="8.0.0.999" publicKeyToken="541b4aff0f04b60a" />
   <clrClass   clsid="{23D4FF3D-EEDF-4F68-AD65-749958EE3B2A}"
               name="SoftBrands.FourthShift.FSCulture.FSCulture"
               tlbid="{8D480B22-D603-309F-9A26-EA9E9B020207}">
   </clrClass>
</asmv1:assembly>

我可以进行全局搜索并在 version="8.0.0.999" 上替换每个构建的当前版本,但我怀疑可能有更好的方法。

最好的办法是在编译之前利用自定义 MSBuild 任务来操作项目工件。

该任务应接受三个属性。一个 属性 用于客户端清单,另一个 属性 用于服务器清单,第三个 属性 用于版本。

这是目标文件在 MSBuild 中的样子。

Manifests.targets

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <!-- Import Tasks -->
  <!-- Be sure to sue the full namespace of the task to import -->
  <UsingTask TaskName="Full.Namespace.To.UpdateManifestsTask" AssemblyFile="$(MSBuildThisFileDirectory)\MyCustomTasks.dll" />
  <!-- Define the location of the client and server manifest files -->
  <PropertyGroup>
    <ClientManifest><!-- Location of the client manifest --></ClientManifest>
    <ServerManifest><!-- Location of the server manifest --></ServerManifest>
  </PropertyGroup>
  <!-- Define Generate App Config Target -->
  <Target Name="UpdateManifests">
    <UpdateManifests ClientManifest="$(ClientManifest)" ServerManifest="$(ServerManifest)" Version="$(Version)" />
  </Target>
  <!-- Define Before Build Target -->
  <!-- This will ensure the above target gets executed prior to compilation -->
  <Target Name="BeforeBuild">
    <CallTarget Targets="UpdateManifests;" />
  </Target>
</Project>

这是自定义任务的样子 -

UpdateManifestsTask.cs

public class UpdateManifestsTask : Task
{
    public ITaskItem ClientManifest { get; set; }
    public ITaskItem ServerManifest { get; set; }
    public ITaskItem Version { get; set; }

    public override bool Execute()
    {
        var newVersion = string.Format("name=\"SoftBrands.FourthShift.FSCulture\" version=\"{0}\"", this.Version.ItemSpec);
        var clientFile = File.ReadAllText(this.ClientManifest.ItemSpec);
        clientFile = Regex.Replace(clientFile, "name=\"SoftBrands.FourthShift.FSCulture\" version=\"\d*\.\d*\.\d*\.\d*\"", newVersion);
        File.WriteAllText(this.ClientManifest.ItemSpec, clientFile);
        var serverFile = File.ReadAllText(this.ClientManifest.ItemSpec);
        serverFile = Regex.Replace(clientFile, "name=\"SoftBrands.FourthShift.FSCulture\" version=\"\d*\.\d*\.\d*\.\d*\"", newVersion);
        File.WriteAllText(this.ServerManifest.ItemSpec, serverFile);

        return true;
    }
}

RegEx 有点草率,因为这是一个快速而肮脏的示例,但这实际上是您执行此类操作的方式。

务必添加对 MSBuild 库的引用。

http://blogs.msdn.com/b/msbuild/archive/2006/01/21/515834.aspx

如果您不想构建自定义任务,您可以编写一个小型控制台应用程序来执行相同的操作,但我认为自定义任务更简洁。

如果您决定使用控制台应用程序路线,您可以利用项目文件中的 BeforeBuild 和 AfterBuild 事件。

  <Target Name="BeforeBuild">
      <!-- Invoke console app -->
  </Target>
  <Target Name="AfterBuild">
  </Target>