我有一些在Winforms应用程序,Windows服务和现在Azure工作者角色中使用的共享程序集/项目。
如果我在Azure角色中运行,是否有任何方法可以在运行时检测到。
我已经找到了如何检测是否运行Azure模拟器:
Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.IsEmulated
但这不符合我的要求。我也不希望在共享程序集中添加对任何Azure程序集的引用。
理想情况下,我想要一些类似于我用来检测作为控制台与服务运行的内容:
System.Environment.UserInteractive
有没有什么可以给我这个逻辑?
答案 0 :(得分:4)
您可以检查是否存在RoleRoot环境变量(至少对于云服务):
或者,为什么不简单地在配置中添加设置(AppSettings或服务配置):
<appSettings>
...
<add key="AppEnvironment" value="Azure.CloudService|Azure.Website" />
</appSettings>
然后,您只需检查设置是否存在特定值,即可查看您正在运行的位置。这也意味着在您的(自动)构建或部署过程中,您需要包含此设置(例如,这可以通过XDT实现)。
答案 1 :(得分:4)
对于任何有兴趣的人,以为我会分享我的实施方式,感谢@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
}
}
}
答案 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工具连接它。