简体   繁体   English

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

[英]Can I detect if my code is executing in an Azure worker role?

I have some shared assemblies/projects that are used within Winforms apps, windows services and now Azure worker roles.我有一些在 Winforms 应用程序、Windows 服务和 Azure 辅助角色中使用的共享程序集/项目。

Is there any way that I can detect at runtime if I am running in an Azure role.如果我在 Azure 角色中运行,有什么方法可以在运行时检测到。

I have found how you can detect if running Azure emulator or not:我找到了如何检测是否正在运行 Azure 模拟器:

 Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.IsEmulated

But this does not do what I want.但这并不能满足我的要求。 I would also prefer not to have to add references to any of the Azure assemblies in my shared assemblies.我也不想在我的共享程序集中添加对任何 Azure 程序集的引用。

Ideally I would like something similar to what I use to detect if running as a console vs a service:理想情况下,我想要类似于我用来检测是作为控制台还是作为服务运行的东西:

System.Environment.UserInteractive

Is there anything that gives me this logic?有什么东西可以给我这个逻辑吗?

For anyone interested, thought I would sharehow I implemented, thanks to @Sandrino Di Mattia's answer:对于任何感兴趣的人,我想我会分享我是如何实施的,感谢@Sandrino Di Mattia 的回答:

You can check for the presence of the RoleRoot environment variable (for Cloud Services at least):您可以检查 RoleRoot 环境变量是否存在(至少对于云服务):

Note that this does NOT cater for a Winforms App as I only actually required it in the end for Services - ie detecting between service running as请注意,这并不适合 Winforms 应用程序,因为我实际上只在最后需要它用于服务 - 即检测运行为

  • Azure Worker Role Azure 工作者角色
  • Windows Service视窗服务
  • Console Application控制台应用程序

This is an outline:这是一个大纲:

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
        }
    }
}

You can check for the presence of the RoleRoot environment variable (for Cloud Services at least):您可以检查 RoleRoot 环境变量是否存在(至少对于云服务):

Or, why not simply add a setting to your config (AppSettings or Service Configuration):或者,为什么不简单地在您的配置中添加一个设置(AppSettings 或 Service Configuration):

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

Then you can simply check if the setting exists with a specific value to see where you're running.然后您可以简单地检查该设置是否存在具有特定值以查看您正在运行的位置。 This also means that during your (automated) build or deploy process you'll need to include this setting (this is possible with XDT for example).这也意味着在您的(自动)构建或部署过程中,您需要包含此设置(例如,这可以使用 XDT)。

We set an environment variable (in this example INAZURE) as a startup task via a batch file.我们通过批处理文件将环境变量(在本例中为 INAZURE)设置为启动任务。

Contents of SetEnvVar.cmd batch file: SetEnvVar.cmd 批处理文件的内容:

setx INAZURE True /M

Configure the batch file to start via your cscfg file:配置批处理文件以通过您的 cscfg 文件启动:

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

Then write something to read this environment variable.然后写一些东西来读取这个环境变量。 There is a static RoleEnvironment class in the Azure SDK you can use, but this references nasty unmanged assemblies that make build server configuration a PITA.您可以使用 Azure SDK 中的静态 RoleEnvironment 类,但这引用了令人讨厌的非托管程序集,这些程序集使构建服务器配置成为 PITA。 Things may have gotten better in more recent releases of the Azure SDK.在更新的 Azure SDK 版本中,情况可能变得更好。

I have a closely related blog article at: http://adrianwithy.com/2012/02/06/remove-msshrtmi-dll-as-a-dependency-in-your-azure-project/我有一篇密切相关的博客文章: http : //adrianwithy.com/2012/02/06/remove-msshrtmi-dll-as-a-dependency-in-your-azure-project/

When I tried the "RoleRoot" environment variable in a web role, it returned null, unfortunately breaking the elegant solution shown above.当我在 web 角色中尝试“RoleRoot”环境变量时,它返回 null,不幸的是破坏了上面显示的优雅解决方案。 Perhaps Microsoft changed something since 2013 or the solution is only valid for worker roles, not web roles.也许微软自 2013 年以来改变了一些东西,或者解决方案只对工人角色有效,而不是网络角色。

The alternative below I saw working properly for a from-the-box configured webrole (not running elevated).我看到下面的替代方案适用于即用型配置的 webrole(未运行提升)。 Although the role is by default running as "network service", it can detect the presence of "f:\\RoleModel.xml".尽管角色默认作为“网络服务”运行,但它可以检测到“f:\\RoleModel.xml”的存在。 Probably that is required because the configuration file contains information required in the role startup code.这可能是必需的,因为配置文件包含角色启动代码中所需的信息。 Note that the code does not depend on the actual drive letter, that may change in future Azure images:请注意,代码不依赖于实际的驱动器号,在未来的 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;
  }
}

Tested for a web role, but I'd expect it to work the same for worker roles (please comment if it doesn't).已针对 Web 角色进行测试,但我希望它对工作角色的工作方式相同(如果不是,请发表评论)。

Like you say, adding references to all your end-products is not the way to go.就像您说的那样,添加对所有最终产品的引用并不是要走的路。 I would say this is a problem solved very easily using Dependency Injection.我会说这是一个使用依赖注入很容易解决的问题。

Define an interface which yields this information (in a shared assembly):定义产生此信息的接口(在共享程序集中):

public enum DeploymentType { WinForms, WinServices, Azure }

public interface IWhatDeploymentAmIUsing {
    DeploymentType DeploymentType { get; }
}

And create a class that implements this interface.并创建一个实现此接口的类。

WinForms (in your winforms project): WinForms(在您的 winforms 项目中):

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

WinServices (in your windows service project): WinServices(在您的 Windows 服务项目中):

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

Azure (in your azure project): Azure(在您的 azure 项目中):

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

Now wire it up using your favorite DI tool.现在使用您最喜欢的 DI 工具将其连接起来。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM