22

我们使用Hudson来构建我们的项目,并且 Hudson 在编译时方便地定义了诸如“%BUILD_NUMBER%”之类的环境变量。

我想在代码中使用这个变量,所以我们可以做一些事情,比如在运行时记录这是什么构建。但是我不能做 System.Environment.GetEnvironmentVariable 因为那是访问运行时环境,我想要的是这样的:

#define BUILD_NUM = %BUILD_NUMBER%

或者

const string BUILD_NUM = %BUILD_NUMBER%

除了我不知道语法。有人可以指出我正确的方向吗?谢谢!

4

5 回答 5

21

好的,这就是我最终要做的。它不是很优雅,但它确实有效。我创建了一个如下所示的预构建步骤:

echo namespace Some.Namespace > "$(ProjectDir)\CiInfo.cs"
echo { >> "$(ProjectDir)\CiInfo.cs"
echo     ///^<summary^>Info about the continuous integration server build that produced this binary.^</summary^> >> "$(ProjectDir)\CiInfo.cs"
echo     public static class CiInfo >> "$(ProjectDir)\CiInfo.cs"
echo     { >> "$(ProjectDir)\CiInfo.cs"
echo         ///^<summary^>The current build number, such as "153"^</summary^> >> "$(ProjectDir)\CiInfo.cs"
echo         public const string BuildNumber = ("%BUILD_NUMBER%" == "" ? @"Unknown" : "%BUILD_NUMBER%"); >> "$(ProjectDir)\CiInfo.cs"
echo         ///^<summary^>String of the build number and build date/time, and other useful info.^</summary^> >> "$(ProjectDir)\CiInfo.cs"
echo         public const string BuildTag = ("%BUILD_TAG%" == "" ? @"nohudson" : "%BUILD_TAG%") + " built: %DATE%-%TIME%"; >> "$(ProjectDir)\CiInfo.cs"
echo     } >> "$(ProjectDir)\CiInfo.cs"
echo } >> "$(ProjectDir)\CiInfo.cs"

然后我将“CiInfo.cs”添加到项目中,但从版本控制中忽略了它。这样我就不必编辑或提交它,并且项目总是有一个可用的常量,即最新的构建号和时间。

于 2010-12-15T18:02:11.013 回答
7

一种方法是在编译之前添加一个构建步骤,该步骤在 %BUILD_NUMBER% 的适当源文件中进行正则表达式替换。

于 2010-12-15T13:15:18.773 回答
5

一种可能性是使用 T4 生成您的配置类,并实例化所有常量。T4 很好地集成到 MSVS 中,无需您自己的自定义构建步骤。

于 2010-12-15T13:22:38.330 回答
1

define 不允许您像在 C/C++ 中那样在 C# 中定义内容。

这个页面

#define 指令不能像 C 和 C++ 中通常那样用于声明常量值。C# 中的常量最好定义为类或结构的静态成员。如果您有多个这样的常量,请考虑创建一个单独的“常量”类来保存它们。

如果您希望在您的 AssemblyInfo 类中反映内部版本号,大多数构建工具都支持在构建时生成该类。MSBuild 有一个任务和 NAnt 一样。不知道哈德森是如何做到的。

于 2010-12-15T13:20:19.567 回答
1

我有一个类似的问题。

我正在开发一个带有 ASP.Net 后端的 Xamarin 移动应用程序。我有一个包含后端服务器 URL 的设置类:

namespace Company.Mobile
{
    public static class Settings
    {
#if DEBUG
        const string WebApplicationBaseUrl = "https://local-pc:44335/";
#else
        const string WebApplicationBaseUrl = "https://company.com/";
#endif
    }
}

它对调试和发布配置有不同的值。但是当几个开发人员开始从事该项目时,这并没有奏效。每台开发机器都有自己的 IP 地址,手机需要使用唯一的 IP 地址进行连接。

我需要在每台开发机器上从文件或环境变量中设置常量值。这就是Fody适合的地方。我用它来创建一个in solution weaver。以下是详细信息

我将我的Settings课程放在 Xamarin 应用程序项目中。该项目必须包含 Fody Nuget 包:

<ItemGroup>
    <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Fody" Version="6.2.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
    <WeaverFiles Include="$(SolutionDir)Company.Mobile.Models\bin\Debug\netstandard2.0\Company.Mobile.Models.dll" WeaverClassNames="SetDevServerUrlWeaver" />
  </ItemGroup>

我只在调试配置上进行设置,因为我不希望在发布版本上发生替换。

weaver 类放置在移动项目所依赖的类库项目 (Company.Mobile.Models) 中(您不需要也不应该有这种依赖关系,但 Fody 文档明确表示包含 weaver 的项目必须是在发出编织程序集的项目之前构建)。这个库项目包括 FodyHelpers Nuget 包:

<ItemGroup Condition="'$(Configuration)' == 'Debug'">
        <PackageReference Include="FodyHelpers" Version="6.2.0" />
    </ItemGroup>

weaver 类定义如下:

#if DEBUG

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

using Fody;

namespace Company.Mobile.Models
{
    public class SetDevServerUrlWeaver : BaseModuleWeaver
    {
        private const string SettingsClassName = "Settings",
            DevServerUrlFieldName = "WebApplicationBaseUrl",
            DevServerUrlSettingFileName = "devServerUrl.txt";

        public override void Execute()
        {
            var target = this.ModuleDefinition.Types.SingleOrDefault(t => t.IsClass && t.Name == SettingsClassName);

            var targetField = target.Fields.Single(f => f.Name == DevServerUrlFieldName);

            try
            {
                targetField.Constant = File.ReadAllText(Path.Combine(this.ProjectDirectoryPath, DevServerUrlSettingFileName));
            }
            catch
            {
                this.WriteError($"Place a file named {DevServerUrlSettingFileName} and place in it the dev server URL");

                throw;
            }
        }

        public override IEnumerable<string> GetAssembliesForScanning()
        {
            yield return "Company.Mobile";
        }
    }
}

#endif

这是放置在移动应用程序项目中的 FodyWeavers.xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
  <SetDevServerUrlWeaver />
</Weavers>

devServerUrl.txt 只包含我的本地 IP https://192.168.1.111:44335/:。不得将此文件添加到源代码管理中。将它添加到您的源代码管理忽略文件中,以便每个开发人员都有自己的版本。

您可以轻松地从环境变量 ( System.Environment.GetEnvironmentVariable) 或任何地方而不是文件中读取替换值。

我希望有更好的方法来做到这一点,比如 Roslyn,或者这个属性似乎可以完成这项工作,但事实并非如此。

于 2020-07-04T12:39:59.163 回答