首页 > 解决方案 > 如何在单元测试中以管理员身份运行 sc.exe

问题描述

我创建了一个 Windows 服务程序。该程序采用命令行参数/install /uninstall /start /stop以便可以使用通过进程启动的sc.exe在内部从命令行轻松安装、卸载、启动和停止服务。如果我从以 runas admin 启动的命令窗口中的参数执行程序,我的服务程序的行为就像预期的那样。

现在我想从单元测试中测试这种行为。但是无论我做什么,内部调用的sc.exe都会返回:StdOutput:[SC] OpenSCManager ERROR 5: Access Denied。

我正在使用我的用户凭据创建流程。我是系统的本地管理员。我做错了什么?

我正在使用的相关代码如下所示:

    [TestMethod]
    public void CanBe_Installed_Started_Stopped_And_Uninstalled()
    {
        // Arrange
        Assert.IsFalse(this.IdfServiceIsInstalled(), "Service is already installed");

        // Act/Assert
        this.InstallService();
        Assert.IsTrue(this.IdfServiceIsInstalled(), "Service is not Installed");
        //Assert.IsFalse(this.ServiceIsStarted(), "Service is already Started");

        //this.StartService();
        //Assert.IsTrue(this.ServiceIsStarted(), "Service is not started");

        //this.StopService();
        //Assert.IsFalse(this.ServiceIsStarted(), "Service is still started");

        //this.UninstallService();
        //Assert.IsFalse(this.IdfServiceIsInstalled(), "Service is still installed");
    }
    
    private void InstallService()
    {
        try
        {
            // ToDo: find generic way to get the path to IdfService!
            var serviceBinPath = Path.Combine(@"C:\Entwicklung\ImageDataForwarder\Output\netcoreapp3.1", "IdfService.exe");
            var fi = new FileInfo(serviceBinPath);
            Assert.IsTrue(fi.Exists);

            var serviceProcess = this.PrepareServiceProcess(serviceBinPath);
            serviceProcess.StartInfo.ArgumentList.Add("/install");
            serviceProcess.Start();
            serviceProcess.WaitForExit();

            var reader = serviceProcess.StandardOutput;
            var output = reader.ReadToEnd();
            var exitCode = serviceProcess.ExitCode;
            Assert.AreEqual(0, exitCode, output);
        }
        catch (Exception exception)
        {
            Assert.Fail($"IdfServiceIsInstalled failed: {exception}");
        }
    }

    private Process PrepareServiceProcess(string serviceBinPath)
    {
        var psi = new ProcessStartInfo
            {
                FileName = serviceBinPath,
                UserName = USER_NAME,
                Password = this.GetSecurePassword(),
                Domain = DOMAIN,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                Verb = "runas",
            };

        var serviceProcess = new Process { StartInfo = psi };
        return serviceProcess;
    }

标签: c#unit-testing

解决方案


推荐阅读