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

时间:2015-12-07 17:57:56

标签: c# .net com manifest

我正在使用一个包含未受管理的客户端DLL和托管COM服务器DLL的应用程序(这本身就是一个挑战:Managed Reg-Free COM Server Won't Activate),现在我想知道什么是最好的方式保持版本号同步。由于我们正在构建客户端和服务器,并且我们尝试将每个构建的所有文件的版本号保持同步,看起来我需要有一个进程来编辑客户端和服务器上的所有清单文件在完整构建发生之前,我所有孤立的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",但我怀疑可能有更好的方法。

1 个答案:

答案 0 :(得分:0)

最好的办法是利用自定义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>