问题如下:我的VS2015解决方案有几个项目,其中包括A和B.
A是一个常规项目,其中包含一个程序/服务/代码,可以将某些源文件转换为已编译的资源(其想法是源是人类可维护的并且在源代码控制下但是生成的资源是机器优化的但是不受源头控制)。
项目B包含一个这样的源文件,而不是逐字逐句地放在项目B的结果程序集中,我希望A中的程序将其“编译”到资源文件中,并且只将它放在程序集B中(以及其他代码)正常编译的项目B。
+-------------------+ +-----------------+
|Project A | |Assembly A |
| | +----------------> | |
| | | |
+-------------------+ +-------+---------+
|
|
+--------------------------------+------+
| |
+-------------------+ +-----------------+
|Project B | | |Assembly B | |
| +----+---+ | +-----v--+
| |src.txt|| +----------------> | |res.txt||
| | || | | ||
| +--------| | +--------|
+-------------------+ +-----------------+
如何在Visual Studio 2015中执行此操作?
答案 0 :(得分:2)
您可以使用Visual Studio自定义工具实现此功能,而不是使用前/后构建步骤。这不是编译步骤和设计器转换一样,但仍应解决我认为您要问的问题。这将创建一个自定义代码生成器,类似于Visual Studio将.resx设计器中的资源字符串转换为可编译的C#代码。
您没有指定您要定位的.NET版本,但这假定您的目标是.NET 4.5。有good tutorial here用于创建自己的自定义工具,以下是基于此的工具。请注意,该文章是为Visual Studio 2012编写的,因此某些注册表项不同。
所有这一切的总结:
Microsoft.VisualStudio.TextTemplating.VSHost.BaseCodeGenerator
。这样做可以帮助您将src.txt
输入文件转换为res.txt
输出文件。src.txt
的属性以使用自定义工具。从现在开始,每次保存或修改src.txt
时,Visual Studio都会为您生成res.txt
,您可以将其嵌入到程序集B或任何您喜欢的内容中。请记住,如果您以后需要更改项目A,那么您需要重复步骤2并重新启动VS。实施代码生成器:
[assembly: ComVisible(false)]
更改为[assembly: ComVisible(true)]
创建一个新的代码生成器类,如下所示
[ComVisible(true)]
[Guid("C43E4E36-289C-40C8-9B87-7F79E2B57B0E")] // TODO: replace with your own random GUID
public class MyResConverter : Microsoft.VisualStudio.TextTemplating.VSHost.BaseCodeGenerator
{
public override string GetDefaultExtension()
{
// TODO: file extension of the resulting resource file
return ".res.txt";
}
protected override byte[] GenerateCode(string inputFileName, string inputFileContent)
{
// TODO: your "compile" step that converts `src.txt` to `res.txt`
return Encoding.UTF8.GetBytes(inputFileContent.ToUpper());
}
}
注册代码生成器:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm.exe /codebase C:\Path\To\ProjectA.dll
创建一个新的install.reg文本文件,以配置VS识别项目A中的新自定义工具,并在适当时替换TODO:
Windows Registry Editor Version 5.00
; TODO: Replace with your GUID
[HKEY_CURRENT_USER\SOFTWARE\Microsoft\VisualStudio\14.0_Config\CLSID\{C43E4E36-289C-40C8-9B87-7F79E2B57B0E}]
"InprocServer32"="C:\\Windows\\System32\\mscoree.dll"
"ThreadingModel"="Both"
"Class"="ProjectA.MyResConverter"
; TODO: Replace with your assembly
"Assembly"="ProjectA, Version=1.0.0.0, Culture=neutral"
; TODO: Replace with your dll file
"CodeBase"="file:///C:\\Path\\To\\ProjectA.dll"
; TODO: Replace with your tool name
[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\14.0_Config\Generators\{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}\MyResConverter]
; TODO: Replace with your GUID
"CLSID"="{C43E4E36-289C-40C8-9B87-7F79E2B57B0E}"
"GeneratesDesignTimeSource"=dword:00000001
; TODO: Replace with your description
@="My Custom Tool"
14.0_Config
密钥,因为这是VS2015。{FAE...
字符串是C#代码生成器的GUID,与您为自定义代码生成器创建的任何GUID无关。使用自定义工具:
src.txt
,然后单击属性MyResConverter
src.txt
文件以生成初始转换的资源文件(只需打开src.txt
并单击文件>保存以强制代码生成器运行)。您现在应该在src.res.txt
下方看到src.txt
了。您可以更改生成文件上的“属性”,将其作为资源嵌入到程序集中,或者随意嵌入。从现在开始,每当您修改src.txt
时,VS都会为您重新生成资源文件,您可以将其嵌入到项目B中。
答案 1 :(得分:1)
基本原理很简单,可以这样实现:确保A在B之前构建,然后使用A.exe作为B中的预建步骤。
要使构建顺序正确:在VS中打开包含两个项目的.sln,右键单击projectB,选择“构建Depedencies->项目依赖项...”并使projectB依赖于projectA。在构建顺序选项卡中验证A将在B之前构建。
现在在文本编辑器中打开projectB,一直滚动到最后,并在</Project>
结束标记之前添加这样的内容:
<Target Name="GenerateSomeFile" BeforeTargets="Build">
<PropertyGroup>
<SourceFile>$(MsBuildThisFileDirectory)\in.cs</SourceFile>
<TargetFile>$(MsBuildThisFileDirectory)\out.cs</TargetFile>
</PropertyGroup>
<Exec Command="/path/to/projectAOutputDir/A.exe $(SourceFile) $(TargetFile)"
</Target>