SetServiceStatus返回false,GetlastWin32Error与SetServiceStatus无关

时间:2013-06-06 15:21:36

标签: c# windows-services pinvoke

我正在使用QueryServiceStatus来接收当前服务状态,稍后将其设置为waitHint为0,因为Process Hacker显示默认值为180000。我想更改controlsAccepted等其他内容。 QueryServiceStatus工作正常,但SetServiceStatus返回false,Marshal.GetLastWin32Error没有帮助。它返回183,这是ERROR_ALREADY_EXISTS(当该文件已存在时无法创建文件。)因为我认为这是来自在我的计算机上运行的另一个应用程序。

IntPtr scm = WinAPI.Service.OpenSCManager(null, null, WinAPI.Service.SCM_ACCESS.SC_MANAGER_ALL_ACCESS);
IntPtr service = WinAPI.Service.OpenService(scm, "mySvc", WinAPI.Service.SERVICE_ACCESS.SERVICE_ALL_ACCESS);
var lpServiceStatus = new WinAPI.Service.SERVICE_STATUS();
bool queryStatus = WinAPI.Service.QueryServiceStatus(service, ref lpServiceStatus);
Svc.debugWr("queryStatus: " + queryStatus + (!queryStatus ? "LastWin32Error: " + Marshal.GetLastWin32Error() : ""));
Svc.debugWr("checkPoint: " + lpServiceStatus.checkPoint);
Svc.debugWr("controlsAccepted: " + lpServiceStatus.controlsAccepted);
Svc.debugWr("currentState" + lpServiceStatus.currentState);
Svc.debugWr("exit code: " + lpServiceStatus.serviceSpecificExitCode);
Svc.debugWr("serviceType: " + lpServiceStatus.serviceType);
Svc.debugWr("Wait hint: " + lpServiceStatus.waitHint);
Svc.debugWr("Win32 exit code: " + lpServiceStatus.win32ExitCode);
lpServiceStatus.waitHint = 0;
Svc.debugWr("Wait hint: " + lpServiceStatus.waitHint);
bool setStatus = WinAPI.Service.SetServiceStatus(service, ref lpServiceStatus);
Svc.debugWr("setStatus: " + setStatus + (!setStatus ? "LastWin32Error: " + Marshal.GetLastWin32Error() : ""));

以下是SetServiceStatusSERVICE_STATUSQueryServiceStatus

的声明
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool SetServiceStatus(IntPtr hServiceStatus, ref SERVICE_STATUS lpServiceStatus);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool QueryServiceStatus(IntPtr hService, ref SERVICE_STATUS dwServiceStatus);
[StructLayout(LayoutKind.Sequential)]
public struct SERVICE_STATUS {
    public int serviceType;
    public int currentState;
    public int controlsAccepted;
    public int win32ExitCode;
    public int serviceSpecificExitCode;
    public int checkPoint;
    public int waitHint;
}

1 个答案:

答案 0 :(得分:1)

GetLastWin32Error()没有返回有意义值的原因是你的p / invoke声明没有告诉框架记住最后一个错误代码。你需要这样的声明:

[DllImport("advapi32.dll", SetLastError=true)]
....

SetServiceStatus的调用失败,因为您在第一个参数中传递的句柄确实无效。再看看documentation。您打算通过SERVICE_STATUS_HANDLE但是您传递SC_HANDLE

SetServiceStatusQueryServiceStatus会收到不同类型的句柄。而你错过了一个。 SetServiceStatus的文档说明您需要传递:

  

当前服务的状态信息结构的句柄。这个句柄由RegisterServiceCtrlHandlerEx函数返回。