在构建时或运行时获取解决方案路径

问题描述:

我有一个C#解决方案,我希望在构建期间将解决方案的路径设置为app.config。例如。可以说我有解决方案c:\temp\visual studio\super fun project\super_fun_project.sln开放。我构建并在其中一个测试项目中将应用程序设置更改为解决方案的完整路径。即在构建时或运行时获取解决方案路径

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <appSettings> 
    <add key="fullSolutionPath" value="{setAtBuild}"/> 
    </appSettings> 
</configuration> 

,如果我去c:\temp\visual studio\super fun project\Foobar.Tests\bin\Debug\Foobar.Tests.dll.config它看起来是

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <appSettings> 
    <add key="fullSolutionPath" value="c:\temp\visual studio\super fun project\super_fun_project.sln"/> 
    </appSettings> 
</configuration> 

或但它需要得到格式化,这样,当在运行时我索要价值我确实得到了正确的路径。我已经看不起Transformation,但我无法弄清楚我将如何获得解决方案路径集。有没有其他的技巧来得到这个?

你可以做的就是修改项目文件和:

@echo off > newfile & setLocal ENABLEDELAYEDEXPANSION 
set old="{setAtBuild}" 
set new=%2 
set targetBinary=%3 


cd %1 
for /f "tokens=* delims= " %%a in (%targetBinary%.config) do (
set str=%%a 
set str=!str:%old%=%new%! 
>> newfile echo !str! 
) 

del /F /Q %targetBinary%.config 
rename "newfile" "%targetBinary%.config" 

然后在调用批处理脚本项目属性添加一个生成后事件添加一个MsBuild Target

目标可以使用Custom Inline Task,该源代码集成到项目文件中。

所以要加这个任务:

1)卸载项目(右键单击项目节点上,选择“卸载项目”)

2)编辑项目文件(右键单击项目节点,选择“编辑”)

3)将以下内容添加到项目文件(例如结束)并重新加载它,现在当您构建时,配置文件将相应地进行修改。

<Project ...> 
    ... 
    <Target Name="AfterBuild"> 
     <RegexReplace FilePath="$(TargetDir)$(TargetFileName).config" Input="setAtBuild" Output="$(SolutionPath)" /> 
    </Target> 
    <UsingTask TaskName="RegexReplace" TaskFactory="CodeTaskFactory" AssemblyName="Microsoft.Build.Tasks.Core" > 
     <ParameterGroup> 
     <FilePath Required="true" /> 
     <Input Required="true" /> 
     <Output Required="true" /> 
     </ParameterGroup> 
     <Task> 
     <Using Namespace="System.Text.RegularExpressions"/> 
     <Code Type="Fragment" Language="cs"><![CDATA[ 
       File.WriteAllText(FilePath, Regex.Replace(File.ReadAllText(FilePath), Input, Output)); 
      ]]></Code> 
     </Task> 
    </UsingTask> 
</Project> 

这里,我定义的输出使用Visual Studio的MSBuild Property命名为SolutionPath,但你可以重用此RegexReplace任务和更新InputOutput参数各种需求。

+0

我打算用这个答案代替另一个。我改变了输入来匹配'{setAtBuild}',但我喜欢它没有外部依赖。 –

我不知道你的用例是什么,但你可以调用一个本地生成的批处理文件来从你的项目的生成后事件中做到这一点。

例如:在您的项目名为“updateconf.bat”创建一个批处理脚本,确保它是ANSII编码(也许用记事本++编写剧本并确认ANSII),或者你会得到一个异常,表明在编译VS项目并检查输出时,该文件的前缀是非法字符。

批处理脚本的内容:

call $(ProjectDir)\updateconf.bat "$(TargetDir)" "$(SolutionPath)" $(TargetFileName) 
+0

我无法等待这一切。测试用例是我希望我的单元测试能够动态加载解决方案文件并读取解决方案中的项目并查找所有测试程序集。我不想硬编码的路径,如果我把它放在GitHub上 –

+0

@RobertSnyder - 好的,如果我了解你,那么这个场景是有意义的。你说的**解决方案文件名**代替了实际上是进入你的测试项目的配置文件。在运行时,您正在询问实际的解决方案文件以获取其* .proj文件名中含有say **'Test'**的项目。在这种情况下,我相信这个脚本将会以你所做的方式工作。 – Elmar

+0

我试过了,像魅力一样工作,我会接受一旦我确认我不想使用其他答案。作为一个附注,我忘了在我的批处理文件中设置为ANSII,但我没有收到VS2015的投诉,并且它在UTF-8上运行得很好。其他人可能感到非常小的烦恼是xml格式化丢失。 –