English 中文(简体)
检测代码是否作为服务运行
原标题:
  • 时间:2009-01-05 18:55:52
  •  标签:

.NET库有没有一种方法可以检测它是否正在作为服务运行?

我的库可以以两种方式运行。但是当它作为服务运行时,开发人员需要调用额外的方法来指示事实,否则某些功能将无法正确工作。我希望我的处理日志的库在没有调用该方法的情况下在服务中使用时写出一个警告。

最佳回答

您可以添加Microsoft.Extensions.Hosting.WindowsServices NuGet软件包,并使用WindowsServiceHelpers.IsWindowsService()辅助方法。

对于 Linux,您可以使用 Microsoft.Extensions.Hosting.SystemdSystemdHelpers.IsSystemdService() 方法。

问题回答

经过在智能感应、调试器和文档中的搜索,我们未能找到任何严格可靠的东西。可能可以获取当前进程ID并尝试确定该进程是否已在SCM中注册,但是,虽然.NET提供了一种获取所有服务集合的方式,但它们的进程ID并不在可用信息中。将进程名称与服务名称进行比较是可能的,但并不一定可靠。

然而,有两件相对容易检查的事情,如果不能准确判断“此代码是否作为服务运行”,可能足以满足您的区分需要。

System.Environment.UserInteractive:(正如Stephen Martin所指出的)如果为真,则它不能是服务。大多数不是服务(也不是设备驱动程序)的进程将会返回 true。一些控制台应用程序在非交互情况下运行时(例如作为编译过程的一部分)可能会返回 false。

System.Diagnostics.Process.GetCurrentProcess().SessionId:(我认为这和皮埃尔所说的是一样的)如果这个值不是0,就不是作为服务启动的。大多数正常应用程序不会在会话0中(有些不那么正常的例外情况由Pierre和Stephen指出)。最大的问题是它在老的操作系统如XP或之前的版本下的行为方式。XP和Windows 2000显然在会话0中运行服务,但正常应用程序也将在会话0中。XP的某些配置(例如不在域中)允许同时进行多个用户会话,并且每个会话都有不同的会话ID,但第一个会话得到会话0。因此,在Vista之前,它并不是一个有效的检查。

因此,根据您需要区分的内容,这两个检查中的一个或两个都可能适用于您。

目前并没有任何方法可以确定你的库是否在服务的上下文中运行,但你可以使用Environment.UserInteractive来猜测。

但通常图书馆不应依赖其应用程序上下文。图书馆应提供服务于应用程序,如果需要根据调用方式提供不同的参数,则应要求应用程序提供这些参数。

你的图书馆可能不会严格根据其是否托管在服务中而采取不同的行动,而是需要一些关于服务环境或用户的信息,您的图书馆需要知道。 应用程序应将必要的条件或信息通知图书馆,图书馆不应该独自猜测。

Edit

如有必要,请使用重载方法,如果未提供所有必要信息,则仅简单失败。

你可能需要检查一下你是否在会话零中运行 (至少如果你的目标是 Vista 操作系统)。你可以使用 WTSRegisterSessionNotification,就像这个示例中一样:

  [DllImport("kernel32.dll")]
  private static extern int WTSGetActiveConsoleSessionId();

一种快速而简单的方法是在注册表中的HKLMSystemCurrentControlSetservicesMyServiceImagePath 条目中应用命令行开关,然后在主函数中检查该开关。

然后,您会知道是否由services.exe启动。是的,这是一个黑客。

有一点晚了,但是考虑使用ServiceController.GetServices获取服务列表,然后检查您的进程ID是否与其匹配?

如何获取正在运行的 Windows 服务进程 ID? (http://social.msdn.microsoft.com/Forums/zh-CN/netfxbcl/thread/a979351c-800f-41e7-b153-2d53ff6aac29)

一种方法是查看应用程序的用户上下文。如果你看到它正在作为“系统”用户运行,那么你就是在运行服务(或至少是以服务级别的权限运行)。

0xA3针对这个问题的答案实际上包含了查询SCM的C#代码,就像Rob Parker在他的回答中所描述的那样。

Seems I am bit late to the party, but topic seems popular. Interesting difference when run as a service is that at app start current folder points to system directory (C:windowssystem32 by default). Its hardly unlikely user app will start from the system folder in any real life situation.

因此,我使用以下技巧(C#):

protected static bool IsRunAsService()
{
    string CurDir = Directory.GetCurrentDirectory();
    if (CurDir.Equals(Environment.SystemDirectory, StringComparison.CurrentCultureIgnoreCase))
    { 
         return true; 
    }

    return (false);
}

更多详细信息请参见:https://stackoverflow.com/a/60174944/8494004





相关问题
热门标签