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

get solution path at build time or runtime

我有一个 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,但我不知道如何设置解决方案路径。还有其他技巧吗?

我不知道你的用例是什么,但你可以调用一个自制的批处理文件来从你的项目的 post-build 事件中做到这一点。

示例: 在名为 'updateconf.bat' 的项目中创建一个批处理脚本,确保它是 ANSII 编码的(可能使用notepad++ 编写脚本并确认 ansii) 否则当你编译你的 VS 项目并检查输出时,你会得到一个异常,表明该文件以非法字符为前缀。

批处理脚本内容:

@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"

然后在调用批处理脚本的项目属性中添加一个 post-build 事件:

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

你可以做的是修改项目文件并添加一个MsBuild Target.

目标可以使用 Custom Inline Task,一个源代码集成到项目文件中的任务。

所以要添加这个任务:

1)卸载项目(右击项目节点,select"Unload Project")

2) 编辑项目文件(右击项目节点,select "Edit ")

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>

在这里,我将输出定义为使用名为 SolutionPath 的 Visual Studio 的 MSBuild Property,但您可以重复使用此 RegexReplace 任务并更新 InputOutput 参数满足各种需求。