我需要重新注册我的组件构建完成后(我已经做了一些其他的事情吧),所以我就开始通过增加一个<Exec>
任务调用C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\sn.exe
。 这有可能对其他开发人员/环境下工作,所以我希望我可以只复制sn.exe
和sn.exe.config
从该文件夹,并将其存储在我们的代码库,所以我总是可以从已知的调用它的公共版本地点。
sn.exe
崩溃隔离SDK目录之外的,所以我不知道我怎么可以参考它不知道它会是什么路径下。 不同的人有不同的环境(86 VS 64,不同的安装目录,不同的版本),所以我想应该可以轻松地引用最新版本的工具(或者任何版本)的。 似乎是一个很简单的工具,也许还有另一种方式签署与其他工具/命令/ MSBuild任务的组件? 任何帮助,将不胜感激。
要正确地引用类似的工具sn
或sqlmetal
中,将针对大多数人的工作方式一个MSBuild脚本(我是谁)后,你必须考虑到工作环境和框架实施的考虑不同方面。 Microsoft Windows和Microsoft的实施框架,然后一切(我指的是单声道/ UNIX):有两种主要情况是。 支持我能想到的,结束时所列情形的正确方法的一个例子。
微软
找到正确的方法,其中sn
或其他类似的工具住在Windows与启动GetFrameworkSdkPath任务 ,如已经提到 。
然而,由于这个问题表明,该FrameworkSdkPath中的准确位置sn
或其他工具生命无法直接确定。 该参考答案表明,FrameworkSdkPath下唯一可能的文件夹工具驻留在是bin
和bin/NETFX 4.0 Tools
。 然而,其他值是可能的(Visual Studio的2013预览使用bin/NETFX 4.5.1 Tools
)。 因此,要搜索的唯一有道sn
是使用全局正则表达式或递归搜索。 我有麻烦搞清楚怎么办水珠扩张与MSBuild的和内置的MSBuild任务似乎并不支持FrameworkSdkPath下寻找特定的工具。 然而,CMD的WHERE
具有此功能,可以用来做搜索。 其结果是一样的东西下面的MSBuild代码:
<Target Name="GetSNPath" BeforeTargets="AfterBuild">
<GetFrameworkSdkPath>
<Output TaskParameter="Path" PropertyName="WindowsSdkPath" />
</GetFrameworkSdkPath>
<Exec Command="WHERE /r "$(WindowsSdkPath.TrimEnd('\\'))" sn > sn-path.txt" />
<ReadLinesFromFile File="sn-path.txt">
<Output TaskParameter="Lines" PropertyName="SNPath"/>
</ReadLinesFromFile>
<Delete Files="sn-path.txt" />
<PropertyGroup>
<SNPath>$([System.Text.RegularExpressions.Regex]::Replace('$(SNPath)', ';.*', ''))</SNPath>
</PropertyGroup>
</Target>
(参见属性函数 ,看看为什么我可以使用String.TrimEnd
这里。 WHERE
不喜欢尾随斜线编辑:我添加使用属性函数的访问Regex.Replace()
删除所有,但第一个找到的路径在SNPath
财产我的一位朋友的机器的的WHERE
某些命令调用将输出多个结果,并打破任何企图<Exec/>
的喜欢的工具。这种变化确保只有一个结果被发现,那<Exec/>
5事实上成功。)
现在,你可以调用sn
与<Exec Command=""$(SNPath)"" />
<Exec Command=""$(SNPath)"" />
手提
不出所料,解决的路径sn
比Windows之外的任何操作系统上要简单得多。 在Mac OSX和Linux的任何分配,我发现sn
在PATH中。 使用GetFrameworkSdkPath
在这样的情况没有帮助; 事实上,这似乎返回其下一个路径sn
不能发现,至少对于旧版本的单2.10的我同时使用xbuild测试:
- 在Mac OSX
FrameworkSdkPath
是/Library/Frameworks/Mono.framework/Versions/2.10.5/lib/mono/2.0
和/usr/bin/sn
是一个符号链接/Library/Frameworks/Mono.framework/Commands/sn
。 - 在一定Linux下安装,
FrameworkSdkPath
是/usr/lib64/mono/2.0
和sn
是/usr/bin/sn
(这是一个shell脚本调用/usr/lib64/mono/4.0/sn.exe
带mono
)。
因此,我们需要做的就是尝试执行sn
。 任何UNIX用户把他们的sn
实现非规范的地方已经知道适当地更新路径,所以构建脚本已经没有必要不断寻找它。 此外, WHERE
不存在UNIX。 因此,在UNIX的情况下,我们要替换的第一<Exec/>
调用的东西,将输出只sn
在UNIX和还是做全搜索时,在Windows上运行。 为了区分类Unix和Windows环境中,我们使用了一招,其利用Unix外壳的快捷方式,为true
条命令和CMD的标签语法。 作为一个小例子,下面的脚本将输出I'm unix!
在UNIX shellout和I'm Windows :-/
在Windows shellout。
:; echo 'I’m unix!'; exit $?
echo I’m Windows :-/
趁着这一点,我们得到的GetSNPath
任务是这样的:
<Target Name="GetSNPath" BeforeTargets="AfterBuild">
<GetFrameworkSdkPath>
<Output TaskParameter="Path" PropertyName="WindowsSdkPath" />
</GetFrameworkSdkPath>
<Exec Command=":; echo sn > sn-path.txt; exit $?
WHERE /r "$(WindowsSdkPath.TrimEnd('\\'))" sn > sn-path.txt" />
<ReadLinesFromFile File="sn-path.txt">
<Output TaskParameter="Lines" PropertyName="SNPath"/>
</ReadLinesFromFile>
<Delete Files="sn-path.txt" />
<PropertyGroup>
<SNPath>$([System.Text.RegularExpressions.Regex]::Replace('$(SNPath)', ';.*', ''))</SNPath>
</PropertyGroup>
</Target>
其结果是用于查找调用所需的字符串一便携式方法sn
。 这最后的解决方案让您同时支持微软和它的MSBuild使用xbuild所有其他平台。 它还克服了硬编码bin\NETFX 4.0 Tools
到.csproj的文件,同时支持微软的工具未来和当前版本。
原来,有一个名为“GetFrameworkSdkPath”的任务,将获得Windows SDK的位置。 从那里,我不得不测试,看看是否SN.EXE直接在已有的bin
文件夹,或者如果它在bin\NETFX 4.0 Tools\
。 似乎可靠至今。
<PropertyGroup>
<SNExePath>NotSet</SNExePath>
</PropertyGroup>
<!-- Sometimes theres nothing in the WindowsSdkPath dir and there's stuff in a deeper folder called 'NETFX 4.0 Tools'. -->
<Target Name="GetSNPath" BeforeTargets="AfterBuild">
<GetFrameworkSdkPath>
<Output TaskParameter="Path" PropertyName="WindowsSdkPath" />
</GetFrameworkSdkPath>
<PropertyGroup>
<SNExePath>$(WindowsSdkPath)bin\sn.exe</SNExePath>
</PropertyGroup>
<PropertyGroup>
<SNExePath Condition="!Exists($(SNExePath))">$(WindowsSdkPath)bin\NETFX 4.0 Tools\sn.exe</SNExePath>
</PropertyGroup>
</Target>
<Target Name="AfterBuild">
<Exec Command="$(SNExePath) -R $(TargetPath) $(SignatureFile)" />
</Target>
我使用的是目前该方法包括使用属性函数来执行的SN.EXE框架SDK路径下搜索 - ALA:
<GetFrameworkSDKPath>
<Output TaskParameter="Path" PropertyName="DotNetFrameworkDir"/>
</GetFrameworkSDKPath>
<PropertyGroup>
<SNPath>$([System.IO.Directory]::GetFiles("$(DotNetFrameworkDir)", "sn.exe", SearchOption.AllDirectories)[0])</SNPath>
</PropertyGroup>
到目前为止,我只在Visual Studio的测试2013这一个人,但文档意味着它应该回到工作到Visual Studio 2010。
您可以创建每个开发机器引用的可执行文件,它的MSBuild可以让你引用一个属性上的环境变量。
因此,通过系统属性的高级选项卡中创建环境变量。 我通常只是建立一个系统环境变量,而不是一个仅限当前用户。 你将不得不重新启动Visual Studio它把它捡起来。
然后,引用它的MSBuild:
<Exec Command="$(SnExe)">
其中SnExe
是你定义的环境变量。
对于什么它值得$(SDK40ToolsPath)可变类似的情况为我工作。 这否定了需要知道其中的工具的特定版本安装例如:
<PropertyGroup>
<XsdExePath>$(SDK40ToolsPath)xsd.exe</XsdExePath>
</PropertyGroup>
<Target Name="BeforeBuild">
<ItemGroup>
<xsd Include="Objects.xsd" />
</ItemGroup>
<Exec Command=""$(XsdExePath)" @(xsd) /c /namespace:Blah.Objects" />
</Target>