在编译之前设置CultureInfo并在之后重置

时间:2012-03-13 13:58:50

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

我正在尝试执行一项任务,该任务更改在编译时为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。我还没有找到关于谷歌的确切信息。

我知道可以选择使用PostBuildEvent并将其设置为始终运行,但是它使用Exec来运行命令,我怀疑它会在一个单独的线程中运行,从而击败它目的(我设置CurrentThread.CultureInfo来更改区域设置)。

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

非常感谢明确澄清问题的文档链接。

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

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

因此,我必须对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,则会出现潜在的问题,导致其中一个定义覆盖另一个。

1 个答案:

答案 0 :(得分:0)

您可以使用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文件来完成。