[英]Can I detect if my code is executing in an Azure worker role?
我有一些在 Winforms 应用程序、Windows 服务和 Azure 辅助角色中使用的共享程序集/项目。
如果我在 Azure 角色中运行,有什么方法可以在运行时检测到。
我找到了如何检测是否正在运行 Azure 模拟器:
Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.IsEmulated
但这并不能满足我的要求。 我也不想在我的共享程序集中添加对任何 Azure 程序集的引用。
理想情况下,我想要类似于我用来检测是作为控制台还是作为服务运行的东西:
System.Environment.UserInteractive
有什么东西可以给我这个逻辑吗?
对于任何感兴趣的人,我想我会分享我是如何实施的,感谢@Sandrino Di Mattia 的回答:
您可以检查 RoleRoot 环境变量是否存在(至少对于云服务):
请注意,这并不适合 Winforms 应用程序,因为我实际上只在最后需要它用于服务 - 即检测运行为
这是一个大纲:
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
}
}
}
您可以检查 RoleRoot 环境变量是否存在(至少对于云服务):
或者,为什么不简单地在您的配置中添加一个设置(AppSettings 或 Service Configuration):
<appSettings>
...
<add key="AppEnvironment" value="Azure.CloudService|Azure.Website" />
</appSettings>
然后您可以简单地检查该设置是否存在具有特定值以查看您正在运行的位置。 这也意味着在您的(自动)构建或部署过程中,您需要包含此设置(例如,这可以使用 XDT)。
我们通过批处理文件将环境变量(在本例中为 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/
当我在 web 角色中尝试“RoleRoot”环境变量时,它返回 null,不幸的是破坏了上面显示的优雅解决方案。 也许微软自 2013 年以来改变了一些东西,或者解决方案只对工人角色有效,而不是网络角色。
我看到下面的替代方案适用于即用型配置的 webrole(未运行提升)。 尽管角色默认作为“网络服务”运行,但它可以检测到“f:\\RoleModel.xml”的存在。 这可能是必需的,因为配置文件包含角色启动代码中所需的信息。 请注意,代码不依赖于实际的驱动器号,在未来的 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;
}
}
已针对 Web 角色进行测试,但我希望它对工作角色的工作方式相同(如果不是,请发表评论)。
就像您说的那样,添加对所有最终产品的引用并不是要走的路。 我会说这是一个使用依赖注入很容易解决的问题。
定义产生此信息的接口(在共享程序集中):
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 工具将其连接起来。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.