【问题标题】:Setting CultureInfo before compilation and always resetting after在编译前设置 CultureInfo 并在编译后始终重置
【发布时间】:2012-03-13 13:58:49
【问题描述】:

我正在尝试执行一项任务,该任务更改 XNA 内容管道项目在编译时使用的语言环境/文化,并在编译结束后恢复原始文件。目的是允许在非英语机器中正确解析浮点数。

到目前为止,我正在像这样使用 BeforeBuild 和 AfterBuild:

<UsingTask TaskName="PressPlay.FFWD.BuildTasks.SetLocale" AssemblyFile="PressPlay.FFWD.BuildTasks.dll" />
<Target Name="BeforeBuild">
  <SetLocale> <!-- By default, set to 'en-US' -->
    <Output TaskParameter="PrevLocale" ItemName="OrigLocale" />
  </SetLocale>
</Target>
<Target Name="AfterBuild">
  <SetLocale Locale="@(OrigLocale)" />
</Target>

它可以正常工作,除非在编译期间发生错误(无效的 XML 或 ContentSerializer 错误),之后不会重置语言环境。 SO中的答案是矛盾的,因为有人说AfterBuild always executes(不是我的情况)而其他人说有no way to ensure a target is always ran在构建之后。我在 google 上没有找到关于这方面的准确信息。

我知道可以选择使用 PostBuildEvent 并将其设置为始终运行,但它会使用 Exec 运行命令,我怀疑它会在单独的线程中运行,从而违背了它的目的(我设置CurrentThread.CultureInfo 更改语言环境)。

那么,有没有办法确保目标始终运行?或者,有没有其他方法可以告诉 VS2010 以特定文化运行编译?

非常感谢您提供明确阐明该问题的文档链接。

-- 最终解决方案,遵循 Seva 的回答--

XNA 的内容管道没有声明 PreBuildEvent 也没有声明 PostBuildEvent。其他必需的属性(RunPostBuildEventPreBuildEventDependsOnPostBuildEventDependsOn)也未定义。但是,如果您定义它们,内容管道将像在任何其他项目中一样充分利用它们。

因此,我必须对 contentcsproj 文件进行的更改是:

<!-- Added to ensure the locale is always restored -->
<PropertyGroup>
  <RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>

<!-- Reference includes, project references and other stuff -->
<!-- ... -->
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\$(XnaFrameworkVersion)\Microsoft.Xna.GameStudio.ContentPipeline.targets" />

<!-- Customizations to change locale before compilation and restore it after -->
<!-- Needed to properly treat dots in the XMLs as decimal separators -->
<UsingTask TaskName="PressPlay.FFWD.BuildTasks.SetLocale" AssemblyFile="PressPlay.FFWD.BuildTasks.dll" />
<!-- Apparently ContentPipeline.targets does not define PreBuildEvent and PostBuildEvent -->
<!-- However, they are still used if defined -->
<Target Name="PreBuildEvent" DependsOnTargets="$(PreBuildEventDependsOn)"/>
<Target Name="PostBuildEvent" DependsOnTargets="$(PostBuildEventDependsOn)"/>
<PropertyGroup>
  <PreBuildEventDependsOn>
    $(PreBuildEventDependsOn);
    EstablishUSLocale
  </PreBuildEventDependsOn>
</PropertyGroup>
<PropertyGroup>
  <PostBuildEventDependsOn>
    $(PostBuildEventDependsOn);
    RestoreOriginalLocale
  </PostBuildEventDependsOn>
</PropertyGroup>

<Target Name="EstablishUSLocale">
  <SetLocale Locale="en-US">
    <Output TaskParameter="PrevLocale" ItemName="OrigLocale" />
  </SetLocale>
</Target>

<Target Name="RestoreOriginalLocale">
  <SetLocale Locale="@(OrigLocale)" />
</Target>

使用此解决方案可以间接解决另一个问题,即如果另一个项目重新定义 BeforeBuild 或 AfterBuild 时可能出现的潜在问题,从而导致其中一个定义覆盖另一个。

【问题讨论】:

    标签: visual-studio msbuild xna cultureinfo content-pipeline


    【解决方案1】:

    您可以使用 PostBuildEvent,因为您可以配置为始终在构建之后执行它。但是,正如您正确注意到的那样,在这里使用 Exec 任务将不起作用。但是 PostBuildEvent 实际上可以通过名为 $(PostBuildEventDependsOn) 的属性进行扩展。您将需要定义此属性:

    <PropertyGroup>
      <PostBuildEventDependsOn>RestoreOriginalLocale</PostBuildEventDependsOn>
    </PropertyGroup>
    

    目标 RestoreOriginalLocale 是您在 AfterBuild 目标中的内容:

    <Target Name="RestoreOriginalLocale">
      <SetLocale Locale="@(OrigLocale)" /> 
    </Target>
    

    您的 BeforeBuild 目标仍然需要,它仍然是您在问题中所写的内容。

    为确保 PostBuildEvent 在失败时执行(因此需要执行 RestoreOriginalLocale),您需要将属性 RunPostBuildEvent 设置为 Always。您可以通过 IDE 或手动编辑 .csproj 文件来完成。

    【讨论】:

    • 这个解决方案非常有效,但我必须调整它以与 XNA 的内容管道一起工作。我将在问题中详细说明最终解决方案,因为它包含一些代码。
    猜你喜欢
    • 1970-01-01
    • 2012-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-17
    • 1970-01-01
    • 2011-08-01
    • 2018-04-21
    相关资源
    最近更新 更多