【问题标题】:Unable To Set Application Property Using MSbuild.exe无法使用 MSbuild.exe 设置应用程序属性
【发布时间】:2022-01-02 12:33:14
【问题描述】:

如果我转到 Project->MyApp->Properties->Settings 并输入 Name like WhichApp of type string 并输入 Scope 作为 PCB 的 Application 和 Value。当我在 我的主窗体使用MessageBox.Show(Properties.Settings.Default.WhichApp); 我看到一个显示“PCB”的消息框。

但如果我在查看属性值时尝试使用 MSBuild.exe -property:WhichApp=SUB 设置属性,我仍然会看到“PCB”。

如何在构建时调用 MSBuild.exe 编译工具设置属性?

我尝试在 Visual Studio 中使用外部工具..

标题:设置属性

命令:C:\Program Files(x86)\Microsoft Visual Studio\2017\WDExpress\MSBuild\15.0\Bin\MSBuild.exe

参数:-property:WhichApp=SUB

初始目录:$(ProjectDir)

----我试图在主窗体的 LOAD() 方法中完成的内容----

if (Properties.Settings.Default.PCAppConfig == "PCB")
{
// create new PCB form
// PCBForm.ShowDialog();
}
else if (Properties.Settings.Default.PCAppConfig == "SUB")
{
  // create new SUB form
  // SUBForm.ShowDialog();
}

--- 在 jtijn 的解决方案中,我尝试添加另一个名为 VersionNum 的属性,但失败了...... ---

<Target Name="BeforeBuild">
   <PropertyGroup>
     <!--Default value.-->
     <PcAppConfig Condition="'$(PcAppConfig)' == ''">PCB</PcAppConfig>
     <VersionNum Condition="'$(VersionNum)' == ''">1.0.0.66</VersionNum>
     <!--The source code.-->
     <TheSourceCode>internal static class PcAppConfig{ public static readonly string value = "$(PcAppConfig)"%3B%0A }internal static class VersionNum{ public static readonly string value = "$(VersionNum)"%3B</TheSourceCode>
   </PropertyGroup>
   <!--Get current source so we can only create it again when needed, to avoid being recompiled.-->
   <ReadLinesFromFile File="PcAppConfig.cs" ContinueOnError="True">
     <Output TaskParameter="Lines" ItemName="CurrentSourceCode" />
   </ReadLinesFromFile>
   <!--Write source, if needed.-->
   <WriteLinesToFile File="PcAppConfig.cs" Overwrite="True" Lines="$(TheSourceCode)" Condition="'@(CurrentSourceCode)' != '$(TheSourceCode)'" />
 </Target>

--- 值改变时不编译,创建设置文件失败... 我对 MSBuild.exe 的论点

SelectApp.csproj.user /p:PcAppConfig=SUB /p:VersionNum=1.0.0.67
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <ItemGroup>
        <Compile Update="Form1.cs">
            <SubType>Form</SubType>
        </Compile>
    </ItemGroup>
<Target Name="BeforeBuild">
    <PropertyGroup>
        <!--Default value.-->
        <PcAppConfig Condition="'$(PcAppConfig)' == ''">PCB</PcAppConfig>
        <VersionNum Condition="'$(VersionNum)' == ''">1.0.0.66</VersionNum>
        <!--The source code.-->
        <TheSourceCode>internal static class PCAppConfig{ public static readonly string value = "$(PcAppConfig)"%3B }%0Ainternal static class VersionNum{ public static readonly string value = "$(VersionNum)"%3B }</TheSourceCode>
    </PropertyGroup>
    <!--Get current source so we can only create it again when needed, to avoid being recompiled.-->
    <ReadLinesFromFile File="PcAppConfig.cs" ContinueOnError="True">
        <Output TaskParameter="Lines" ItemName="CurrentSourceCode" />
    </ReadLinesFromFile>
    <!--Write source, if needed.-->
    <WriteLinesToFile File="PcAppConfig.cs" Overwrite="True" Lines="$(TheSourceCode)" Condition="'@(CurrentSourceCode)' != '$(TheSourceCode)'" />
    <ItemGroup>
        <Compile Update="PcAppConfig.cs">
            <SubType>Component</SubType>
        </Compile>
    </ItemGroup>
</Target>
<Target Name="AfterCompile">
<Exec Command="&quot;$(ProgramFiles)\Microsoft Visual Studio\2019\Professional\Common7\IDE\devenv.com&quot; C:\DummyApps\SelectApp\PCBSetup\PCBSetup.vdproj /build &quot;Debug|AnyCPU&quot;"/>
</Target>
</Project>

【问题讨论】:

  • 应用程序设置是运行时属性,在运行时从文件中加载,在构建时尝试设置它几乎没有意义。并且 MSBuild 属性与应用程序设置完全不同,这就是您的尝试无效的原因。但你真正想做的是什么?更改设置的默认值?在构建时设置一个常量(不是设置)?
  • 是的,我明白了。我试图“优雅地”尝试使用属性或变量来检查 Winform Form 类,并根据运行时的值(PCB、SUB 等),创建另一个 Form 的实例并显示它。我不仅需要该属性,还需要一个可以用来保存版本号的字符串。运行时的应用程序设置将起作用,但我不想每次我想根据该属性的值编译应用程序时都更改属性值。
  • 如果我理解正确,您希望能够构建不同版本的应用程序(其中某些字符串常量不同)?
  • 是的,我相信这是正确的。因此,例如在我的主 Form 类中的 Load() 方法中......但是使用某种构建方法,我可以构建项目和相关的设置项目,可能使用 MSBuild.exe。请参阅上面的描述,了解我在此评论中的意思,

标签: visual-studio msbuild


【解决方案1】:

您可以让项目基于 msbuild 属性生成 C# 源代码。该目标位于项目文件的末尾:

<Target Name="BeforeBuild">
  <PropertyGroup>
     <!--Default value.-->
    <PcAppConfig Condition="'$(PcAppConfig)' == ''">PCB</PcAppConfig>
    <!--The source code.-->
    <TheSourceCode>internal static class PcAppConfig{ public static readonly string value = "$(PcAppConfig)"%3B }</TheSourceCode>
  </PropertyGroup>
  <!--Get current source so we can only create it again when needed, to avoid being recompiled.-->
  <ReadLinesFromFile File="PcAppConfig.cs" ContinueOnError="True">
    <Output TaskParameter="Lines" ItemName="CurrentSourceCode" />
  </ReadLinesFromFile>
  <!--Write source, if needed.-->
  <WriteLinesToFile File="PcAppConfig.cs" Overwrite="True" Lines="$(TheSourceCode)" Condition="'@(CurrentSourceCode)' != '$(TheSourceCode)'" />
</Target>

生成的源文件需要添加到您的项目中,可以在构建一次后在 VS 中执行此操作,或者将此行与其他 Compile 项目一起添加:

<Compile Include="PcAppConfig.cs" />

现在您可以在您的代码中使用PcAppConfig.value

改变价值构建就像

msbuild my.csproj /p:PcAppConfig=SUB

【讨论】:

  • 感谢 stijn,这与我的要求非常接近。如果 PcAppConfig.cs 已经存在(它确实存在)并且我只想使用 PcAppConfig.value 来查看属性值是什么,那么 项目代码会是什么?
  • WriteLinestoFile 的条件类似于Condition="!Exists(PcAppConfig.cs)",但我建议不要这样做,因为它使目标不再按预期运行。而且您现在已经可以查看该文件了,对吧?
  • 嘿 stijn,这行得通。我将 XML 放在 之前的 .csproj 文件中,并使用 MSBuild.exe 使用不同的值对其进行编译,效果很好。除了主项目之外,我唯一需要做的就是构建一个特定的安装项目。你能告诉我这是否是赖特命令吗? msbuild myProject.csproj mySetupProject.csproj /p:PcAppConfig=SUB
  • 是的,你可以像这样构建多个项目
  • 我了解到 msbuild.exe 不适用于 .vdproj(安装项目)。知道另一种方法吗?你能向我解释一下这些陈述在&lt;Target Name="BeforeBuild"&gt; 中的作用,所以我知道未来吗?然后我会将答案标记为正确答案。
猜你喜欢
  • 1970-01-01
  • 2012-01-28
  • 2015-11-21
  • 1970-01-01
  • 1970-01-01
  • 2013-06-03
  • 2015-10-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多