我可以检测我的代码是否在Azure辅助角色中执行?

时间:2013-12-13 08:14:33

标签: c# azure

我有一些在Winforms应用程序,Windows服务和现在Azure工作者角色中使用的共享程序集/项目。

如果我在Azure角色中运行,是否有任何方法可以在运行时检测到。

我已经找到了如何检测是否运行Azure模拟器:

 Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.IsEmulated

但这不符合我的要求。我也不希望在共享程序集中添加对任何Azure程序集的引用。

理想情况下,我想要一些类似于我用来检测作为控制台与服务运行的内容:

System.Environment.UserInteractive

有没有什么可以给我这个逻辑?

5 个答案:

答案 0 :(得分:4)

您可以检查是否存在RoleRoot环境变量(至少对于云服务):

或者,为什么不简单地在配置中添加设置(AppSettings或服务配置):

  <appSettings>
    ...
    <add key="AppEnvironment" value="Azure.CloudService|Azure.Website" />
  </appSettings>

然后,您只需检查设置是否存在特定值,即可查看您正在运行的位置。这也意味着在您的(自动)构建或部署过程中,您需要包含此设置(例如,这可以通过XDT实现)。

答案 1 :(得分:4)

对于任何有兴趣的人,以为我会分享我的实施方式,感谢@Sandrino Di Mattia的回答:

  

您可以检查是否存在RoleRoot环境变量(至少对于云服务):

请注意,这不适合Winforms应用程序,因为我实际上只需要它最终用于服务 - 即检测服务之间的运行

  • Azure工作者角色
  • Windows服务
  • 控制台应用程序

这是一个大纲:

public static class ServiceRunner
{
    private static bool IsAzureWorker
    { 
        get { return !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("RoleRoot")); } 
    }

    public static void Run(string[] args)
    {
        if (IsAzureWorker)
        {
            //Running as Azure Worker
        }
        else if (Environment.UserInteractive) //note, this is true for Azure emulator too
        {
            //Running as Console App
        }
        else
        {
            //Running as Windows Service
        }
    }
}

答案 2 :(得分:1)

我们通过批处理文件将环境变量(在此示例中为INAZURE)设置为启动任务。

SetEnvVar.cmd批处理文件的内容:

setx INAZURE True /M

将批处理文件配置为通过cscfg文件启动:

<Startup>
  <Task commandLine="SetEnvVar.cmd"
    executionContext="elevated"
    taskType="simple" />
</Startup>

然后写一些东西来阅读这个环境变量。您可以使用Azure SDK中的静态RoleEnvironment类,但这会引用使构建服务器配置成为PITA的令人讨厌的无人管集合。在最新版本的Azure SDK中,事情可能会变得更好。

我在http://adrianwithy.com/2012/02/06/remove-msshrtmi-dll-as-a-dependency-in-your-azure-project/

上有一篇密切相关的博客文章

答案 3 :(得分:1)

当我尝试&#34; RoleRoot&#34;在web角色中的环境变量,它返回null,遗憾的是打破了上面显示的优雅解决方案。也许微软自2013年以来改变了一些东西,或者该解决方案仅适用于工作者角色,而不适用于网络角色。

下面的替代方案我看到了一个从盒子配置的webrole(没有运行提升)正常工作。虽然默认情况下该角色作为&#34;网络服务&#34;运行,但它可以检测到&#34; f:\ RoleModel.xml&#34;的存在。可能这是必需的,因为配置文件包含角色启动代码中所需的信息。请注意,代码不依赖于实际的驱动器号,可能会在将来的Azure映像中更改:

/// <summary>
/// Returns true if the application is detected to be running in an Azure role (tested for web roles).
/// </summary>
public static bool RunningInAzure
{
  get
  {
    try
    {
      string sCurrentDrive = Path.GetPathRoot(AppDomain.CurrentDomain.BaseDirectory);
      if (!string.IsNullOrEmpty(sCurrentDrive))
        return File.Exists(Path.Combine(sCurrentDrive, "RoleModel.xml"));
    }
    catch { }
    return false;
  }
}

针对网络角色进行了测试,但我希望它对工作人员角色的工作方式相同(如果不是,请发表评论)。

答案 4 :(得分:0)

就像你说的那样,添加对所有最终产品的引用并不是一种方法。 我想说这是一个使用依赖注入很容易解决的问题。

定义一个产生此信息的接口(在共享程序集中):

public enum DeploymentType { WinForms, WinServices, Azure }

public interface IWhatDeploymentAmIUsing {
    DeploymentType DeploymentType { get; }
}

创建一个实现此接口的类。

WinForms(在你的winforms项目中):

public class WinFormDeploymentType : IWhatDeploymentAmIUsing {
    public DeploymentType DeploymentType { get { return DeploymentType.WinForms; } }
}

WinServices(在您的Windows服务项目中):

public class WinServicesDeploymentType : IWhatDeploymentAmIUsing {
    public DeploymentType DeploymentType { get { return DeploymentType.WinServices; } }
}

Azure(在你的azure项目中):

public class AzureDeploymentType : IWhatDeploymentAmIUsing {
    public DeploymentType DeploymentType { get { return DeploymentType.Azure; } }
}

现在使用您最喜欢的DI工具连接它。