以普通用户角色启动和停止Windows服务

时间:2019-03-10 09:41:06

标签: c# process windows-services privileges servicecontroller

就我而言,我有一个WPF应用程序,负责与用户进行交互,并且背后运行着一个支持Windows的服务。

我必须仅以普通用户权限(非管理员)执行WPF应用。由于该应用程序必须在那里启动和停止Windows服务,因此出现了“访问级别”异常。

我尝试使用ServiceController类来停止服务,

 public bool StopLibraryService()
    {
        try
        {
            var service = new ServiceController(ServiceName);
            if (service.Status == ServiceControllerStatus.Running)
            {
                service.Stop();
                var timeout = new TimeSpan(0, 0, 5);                     service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);

                if (service.Status != ServiceControllerStatus.Stopped)
                    throw new Exception($"Failed in stopping service {ServiceName}");
            }
        }
        catch (InvalidOperationException exAccess)
        {
            throw;
        }
        catch (Exception exception)
        {

        }
        return true;
    }

如果以管理员身份打开WPF应用程序,则这部分代码将正确执行。

在同一解决方案中有一个单独的类库项目,负责访问Windows服务,我尝试添加app.Manifest文件并将角色更改为<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

自从它是一个图书馆项目以来,我还没有看到拥有它的任何影响。

我还尝试使用Process

        var info = new ProcessStartInfo(path)
        {
            CreateNoWindow = true,
            UseShellExecute = false,
            Arguments = command,
            WindowStyle = ProcessWindowStyle.Hidden,
            Verb = "runas"

        };

        Process.Start(info);

但这只是开始过程,对我可能没有用。

或者,我选择编写一个控制台应用程序来操纵Windows服务状态,在清单中,我将requestedExecutionLevel级别设置为requireAdministrator并将其包含在解决方案中并进行调用。 (每次执行代码时都会获得UAC)我不认为这是最佳做法。

有没有更好的方法以正常的用户权限以编程方式停止和启动Windows服务。

1 个答案:

答案 0 :(得分:0)

不确定这是否适用于非管理员。

            ConnectionOptions options = new ConnectionOptions();

            ManagementScope scope = new ManagementScope(@"\\servername\root\cimv2", options);
            scope.Connect();

            ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Service");
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);

            ManagementObjectCollection queryCollection = searcher.Get();

            foreach (ManagementObject m in queryCollection)
            {

                    if (m["Started"].Equals(true))
                    {
                        m.InvokeMethod("StopService", null);
                    }

            }