当尝试使用P / Invoke ControlServiceEx函数停止Windows服务时,出现代码122的错误:ERROR_INSUFFICIENT_BUFFER

时间:2016-09-16 19:22:02

标签: .net windows-services pinvoke

当尝试使用ControlServiceEx函数停止Windows服务时,我收到错误122 ERROR_INSUFFICIENT_BUFFER。

我有以下实现:

    <DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
   Private Shared Function OpenSCManager(ByVal machineName As String, ByVal databaseName As String, ByVal desiredAccess As ScmAccessRights) As IntPtr
   End Function

   <DllImport("advapi32.dll", CharSet:=CharSet.Unicode, SetLastError:=True)>
    Public Shared Function QueryServiceStatusEx(hService As IntPtr, infoLevel As Integer, lpBuffer As IntPtr, cbBufSize As Integer, ByRef pcbBytesNeeded As Integer) As Boolean
    End Function

   <DllImport("advapi32.dll", SetLastError:=True)>
   Private Shared Function ControlServiceEx(hService As IntPtr, dwControl As ServiceControl, dwInfoLevel As Integer, ByRef pControlParams As SERVICE_CONTROL_STATUS_REASON_PARAMS) As Integer
   End Function

  Private Shared Sub StopService(service As IntPtr)
      Dim Status As SERVICE_STATUS_PROCESS
      Status = QueryServiceStatusEx(service)
      If Status.dwCurrentState <> ServiceState.ServiceStopped AndAlso Status.dwCurrentState <> ServiceState.NotFound Then
           Dim ScStatusReasonInfoParam As New SERVICE_CONTROL_STATUS_REASON_PARAMS
           ScStatusReasonInfoParam.dwReason = ServiceStopReason.ServicePlannedStop
           ScStatusReasonInfoParam.ServiceStatus = Status ' New SERVICE_STATUS_PROCESS
           Dim Res = ControlServiceEx(service, ServiceControl.[Stop], SERVICE_CONTROL_STATUS_REASON_INFO, ScStatusReasonInfoParam)
           Dim ChangedStatus = WaitForServiceStatus(service, ServiceState.ServiceStopPending, ServiceState.ServiceStopped)
           If Not ChangedStatus Then
                Dim winError = New Win32Exception(Marshal.GetLastWin32Error())
                Throw New ApplicationException("Unable to stop service", winError)
           End If
      End If
  End Sub

Public Shared Function QueryServiceStatusEx(serviceHandle As IntPtr) As SERVICE_STATUS_PROCESS
    Dim buf As IntPtr = IntPtr.Zero
    Try
        Dim size As Integer = 0
        QueryServiceStatusEx(serviceHandle, SC_STATUS_PROCESS_INFO, buf, size, size)
        buf = Marshal.AllocHGlobal(size)
        If Not QueryServiceStatusEx(serviceHandle, SC_STATUS_PROCESS_INFO, buf, size, size) Then
            Throw New Win32Exception(Marshal.GetLastWin32Error())
        End If
        Return DirectCast(Marshal.PtrToStructure(buf, GetType(SERVICE_STATUS_PROCESS)), SERVICE_STATUS_PROCESS)
    Finally
        If Not buf.Equals(IntPtr.Zero) Then
            Marshal.FreeHGlobal(buf)
        End If
    End Try
End Function

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
Public Structure SERVICE_STATUS_PROCESS
    Public dwServiceType As ServiceTypeFlag
    Public dwCurrentState As ServiceState
    Public dwControlsAccepted As Integer
    Public dwWin32ExitCode As Integer
    Public dwServiceSpecificExitCode As Integer
    Public dwCheckPoint As Integer
    Public dwWaitHint As Integer
    Public dwProcessID As Integer
    Public dwServiceFlags As Integer
End Structure

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
Public Structure SERVICE_CONTROL_STATUS_REASON_PARAMS
    Public dwReason As Integer
    <MarshalAs(UnmanagedType.LPTStr)> Public pszComment As String 'string
    Public ServiceStatus As SERVICE_STATUS_PROCESS
End Structure

Public Enum ServiceStopReason
    SERVICE_STOP_REASON_FLAG_PLANNED = &H40000000
    SERVICE_STOP_REASON_MAJOR_NONE = &H60000
    SERVICE_STOP_REASON_MINOR_NONE = &H60000
    ServicePlannedStop = (SERVICE_STOP_REASON_FLAG_PLANNED Or SERVICE_STOP_REASON_MAJOR_NONE Or SERVICE_STOP_REASON_MINOR_NONE)
End Enum

我哪里错了?

0 个答案:

没有答案