【问题标题】:How do I retrieve the username that a Windows service is running under?如何检索运行 Windows 服务的用户名?
【发布时间】:2010-06-29 13:50:53
【问题描述】:

给定一个服务名称,我想检索它运行时使用的用户名(即服务属性窗口的“登录”选项卡中显示的用户名)。

ServiceController 类中似乎没有任何东西可以检索此基本信息。 System.ServiceProcess 中的其他内容似乎也没有公开此信息。

是否有一个托管的解决方案,或者我将不得不下降到较低级别的东西?

【问题讨论】:

    标签: c# authentication windows-services


    【解决方案1】:

    使用 WMI,通过 System.Management 您可以尝试以下代码:

    using System;
    namespace WindowsServiceTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                System.Management.SelectQuery sQuery = new System.Management.SelectQuery(string.Format("select name, startname from Win32_Service")); // where name = '{0}'", "MCShield.exe"));
                using (System.Management.ManagementObjectSearcher mgmtSearcher  = new System.Management.ManagementObjectSearcher(sQuery))
                {
                    foreach (System.Management.ManagementObject service in mgmtSearcher.Get())
                    {
                        string servicelogondetails =
                            string.Format("Name: {0} ,  Logon : {1} ", service["Name"].ToString(), service["startname"]).ToString();
                        Console.WriteLine(servicelogondetails);
                    }
                }
                Console.ReadLine();
            }
        }
    }
    

    然后您可以稍后将注释代码替换为您的服务名称,它应该只返回正在运行的服务进程的实例。

    【讨论】:

      【解决方案2】:

      WMI 是您的朋友。查看Win32_Service,特别是StartName 属性。您可以通过 System.Management.ManagementClass 从 C# 访问 WMI。

      如果你以前没有使用过 WMI,this 的文章似乎是一个不错的教程。

      【讨论】:

        【解决方案3】:

        试试这个:

        System.Security.Principal.WindowsIdentity.GetCurrent();
        

        但最明显的是您将获得 LOCAL SYSTEM 或 NETWORK。您无法显示此用户的原因 - 该服务可以管理多个用户(由桌面共享,附加到当前 Windows 会话,使用共享资源......) 系统启动服务,但任何用户都可以使用。

        【讨论】:

        • 那么就可以得到上面命令返回的WindowsIdentity对象的Name属性了。
        • -1 这将返回当前用户的WindowsIdentity,而不是指定服务的。
        • @Pwninstein 像往常一样从系统或网络凭据启动服务 - 而不是从“登录”用户启动。请参阅我对此的编辑。所以澄清你想要获得启动服务的系统帐户(我的回答是正确的)或当前登录的用户列表,可以使用这个服务?
        • 通常服务作为本地系统或网络服务运行,但您可以安装服务以在标准用户帐户下运行(我们在我正在处理的项目中这样做)。
        • 我不确定您是否理解我想要做什么:我想获取运行特定服务的用户名。我想从一个完全独立的客户端应用程序中执行此操作(即检索用户名的所有代码都在客户端中)。您对用户 GetCurrent() 的建议将不起作用,因为根据 MSDN,它“返回代表当前 Windows 用户的 WindowsIdentity 对象”。在这种情况下,它将是运行 CLIENT 应用程序的当前 Windows 用户的 WindowsIdentity,而不是 SERVICE 的 WindowsIdentity。
        【解决方案4】:

        这个解决方案对我来说很好:

            ManagementObject wmiService = new ManagementObject("Win32_Service.Name='" + this.ServiceName + "'");
            wmiService.Get();
            string user = wmiService["startname"].ToString();
        

        【讨论】:

        • 添加一些解释,说明此答案如何帮助 OP 解决当前问题
        【解决方案5】:

        您可以使用 Windows 注册表找到它,读取以下字符串值,将 [SERVICE_NAME] 替换为 Windows 服务的名称:

        HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\[SERVICE_NAME]\ObjectName
        

        【讨论】:

          【解决方案6】:
              public String getUsername() {
              string username = null;
              try {
                ManagementScope ms = new ManagementScope("\\\\.\\root\\cimv2");
                ms.Connect();
                ObjectQuery query = new ObjectQuery
                        ("SELECT * FROM Win32_ComputerSystem");
                ManagementObjectSearcher searcher =
                        new ManagementObjectSearcher(ms, query);
                foreach (ManagementObject mo in searcher.Get()) {
                  username = mo["UserName"].ToString();
                }
                string[] usernameParts = username.Split('\\');
                username = usernameParts[usernameParts.Length - 1];
              } catch (Exception) {
                username = "SYSTEM";
              }
              return username;
            }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-06-19
            • 1970-01-01
            • 1970-01-01
            • 2022-11-10
            • 2016-12-03
            • 1970-01-01
            相关资源
            最近更新 更多