Exemple #1
0
        private static SERVICE_STATUS_PROCESS GetServiceStatus(string serviceName, string machineName)
        {
            IntPtr scHandle  = IntPtr.Zero;
            IntPtr svcHandle = IntPtr.Zero;
            IntPtr buffer    = IntPtr.Zero;

            try
            {
                scHandle = OpenServiceControlManager(machineName,
                                                     SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);

                svcHandle = OpenService(scHandle, serviceName, SERVICE_RIGHTS.SERVICE_QUERY_STATUS);
                if (svcHandle == IntPtr.Zero)
                {
                    throw CreateCannotOpenServiceException(serviceName, machineName);
                }

                int bufferSize  = 0;
                int bytesNeeded = 0;

                while (true)
                {
                    if (!QueryServiceStatusEx(svcHandle, SC_STATUS_PROCESS_INFO, buffer, bufferSize, out bytesNeeded))
                    {
                        int err = Marshal.GetLastWin32Error();
                        if (err == ERROR_INSUFFICIENT_BUFFER)
                        {
                            buffer     = Marshal.AllocHGlobal(bytesNeeded);
                            bufferSize = bytesNeeded;
                        }
                        else
                        {
                            throw new Win32Exception(err);
                        }
                    }
                    else
                    {
                        SERVICE_STATUS_PROCESS serviceStatus = (SERVICE_STATUS_PROCESS)Marshal.PtrToStructure(
                            buffer, typeof(SERVICE_STATUS_PROCESS));
                        return(serviceStatus);
                    }
                }
            }
            finally
            {
                if (scHandle != IntPtr.Zero)
                {
                    CloseServiceHandle(scHandle);
                }
                if (svcHandle != IntPtr.Zero)
                {
                    CloseServiceHandle(svcHandle);
                }
                if (buffer != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(buffer);
                }
            }
        }
Exemple #2
0
        public static ServiceState GetServiceState(string serviceName)
        {
            SERVICE_STATUS_PROCESS ssp = GetServiceStatus(serviceName);

            if (ssp == null)
            {
                return(ServiceState.NotFound);
            }
            return((ServiceState)ssp.dwCurrentState);
        }
            /// <summary>
            /// Gets the status of the service.
            /// </summary>
            /// <returns>A SERVICE_STATUS_PROCESS structure.</returns>
            public SERVICE_STATUS_PROCESS GetStatus()
            {
                SERVICE_STATUS_PROCESS status = new SERVICE_STATUS_PROCESS();
                int retLen;

                if (!QueryServiceStatusEx(this, 0, ref status, Marshal.SizeOf(status), out retLen))
                {
                    ThrowLastWin32Error();
                }

                return(status);
            }
Exemple #4
0
        public static int GetServiceProcessId(ServiceController sc)
        {
            if (sc == null)
            {
                throw new ArgumentNullException("sc");
            }

            IntPtr zero = IntPtr.Zero;

            try
            {
                UInt32 dwBytesNeeded;
                // Call once to figure the size of the output buffer.
                QueryServiceStatusEx(sc.ServiceHandle, SC_STATUS_PROCESS_INFO, zero, 0, out dwBytesNeeded);
                if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
                {
                    // Allocate required buffer and call again.
                    zero = Marshal.AllocHGlobal((int)dwBytesNeeded);

                    if (QueryServiceStatusEx(sc.ServiceHandle, SC_STATUS_PROCESS_INFO, zero, dwBytesNeeded, out dwBytesNeeded))
                    {
                        var ssp = new SERVICE_STATUS_PROCESS();
                        Marshal.PtrToStructure(zero, ssp);
                        return((int)ssp.dwProcessId);
                    }
                }
            }
            catch (Exception e)
            {
                if (Settings.bDebug)
                {
                    Console.WriteLine("Exception: " + e);
                }
            }
            finally
            {
                if (zero != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(zero);
                }
            }
            return(-1);
        }
Exemple #5
0
    public static int GetServiceProcessId(string serviceName)
    {
        IntPtr scm     = OpenSCManager(ScmAccessRights.Connect);
        IntPtr zero    = IntPtr.Zero;
        IntPtr service = IntPtr.Zero;

        try
        {
            service = OpenService(scm, serviceName, ServiceAccessRights.QueryStatus);

            UInt32 dwBytesAlloc  = 0;
            UInt32 dwBytesNeeded = 36;
            do
            {
                dwBytesAlloc = dwBytesNeeded;
                // Allocate required buffer and call again.
                zero = Marshal.AllocHGlobal((int)dwBytesAlloc);
                if (QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, zero, dwBytesAlloc, out dwBytesNeeded))
                {
                    var ssp = new SERVICE_STATUS_PROCESS();
                    Marshal.PtrToStructure(zero, ssp);
                    return((int)ssp.dwProcessId);
                }
                // retry with new size info
            } while (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER && dwBytesAlloc < dwBytesNeeded);
        }
        finally
        {
            if (zero != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(zero);
            }
            if (service != IntPtr.Zero)
            {
                CloseServiceHandle(service);
            }
            CloseServiceHandle(scm);
        }
        return(-1);
    }
        public void SetStartTime()
        {
            IntPtr handle  = IntPtr.Zero;
            IntPtr service = IntPtr.Zero;

            try
            {
                handle = OpenSCManager(null, null, (uint)SCM_ACCESS.SC_MANAGER_ALL_ACCESS);
                if (handle != IntPtr.Zero)
                {
                    service = OpenService(handle, ServiceName, (uint)SERVICE_ALL_ACCESS);
                    if (service != IntPtr.Zero)
                    {
                        SERVICE_STATUS_PROCESS status = QueryServiceStatusEx(service);

                        if (status != null)
                        {
                            Process process = Process.GetProcessById(status.processID);

                            StartTime = process.StartTime;
                            SetUptime();
                        }
                    }
                }
            }
            catch { }
            finally
            {
                if (service != IntPtr.Zero)
                {
                    CloseServiceHandle(service);
                }
                if (handle != IntPtr.Zero)
                {
                    CloseServiceHandle(handle);
                }
            }
        }
Exemple #7
0
        public static void KillServiceProcess(this ServiceController sc)
        {
            var ssp = new SERVICE_STATUS_PROCESS();

            if (!QueryServiceStatusEx(sc.ServiceHandle.DangerousGetHandle(), SC_STATUS_PROCESS_INFO, ref ssp, Marshal.SizeOf(ssp), out _))
            {
                throw new Exception("Couldn't obtain service process information.");
            }

            sc.Stop();

            try
            {
                // Attempt to stop service using servicecontroller
                sc.StopServiceAndWaitForExit(TimeSpan.FromSeconds(15d));
                return;
            }
            catch (TimeoutException)
            {
                // Service did not stop within specified timespan.
                // Kill the service's process instead.
            }

            if (ssp.dwProcessId != 0)
            {
                try
                {
                    Process.GetProcessById(ssp.dwProcessId).Kill();
                }
                catch (ArgumentException)
                {
                    // The process was killed by sc.Stop()
                }
            }

            sc.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(15d));
        }
Exemple #8
0
 public static extern bool QueryServiceStatusEx(int Service, int InfoLevel,
     ref SERVICE_STATUS_PROCESS ServiceStatus, int BufSize, out int BytesNeeded);
Exemple #9
0
 public static extern IntPtr QueryServiceStatusEx(IntPtr serviceHandle, SC_STATUS_TYPE infoLevel, ref SERVICE_STATUS_PROCESS serviceStatusProcess, int serviceStatusProcessSize, ref uint bytesNeeded);
Exemple #10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="controller"></param>
        /// <returns></returns>
        private bool StopServiceAndWaitForExit(ServiceController controller)
        {
            SERVICE_STATUS_PROCESS ssp = new SERVICE_STATUS_PROCESS();
            int ignored;

            try
            {   // Obtain information about the service, and specifically its hosting process,
                // from the Service Control Manager.
                if (!QueryServiceStatusEx(controller.ServiceHandle.DangerousGetHandle(), SC_STATUS_PROCESS_INFO, ref ssp, Marshal.SizeOf(ssp), out ignored))
                {
                    WriteConsole(String.Format("Couldn't obtain service:{0} process information....", controller.ServiceName), ConsoleTextColor.Exception);
                    return(false);
                }

                // A few quick sanity checks that what the caller wants is *possible*.
                if (ssp.dwServiceType != SERVICE_WIN32_OWN_PROCESS)
                {
                    WriteConsole(String.Format("Can't wait for service:{0} process termination! Shared hosting process!!!", controller.ServiceName), ConsoleTextColor.Notify);
                    return(false);
                }

                if ((ssp.dwServiceFlags & SERVICE_RUNS_IN_SYSTEM_PROCESS) != 0)
                {
                    WriteConsole(String.Format("Can't wait for service:{0} process temination! System hosting process!!!", controller.ServiceName), ConsoleTextColor.Notify);
                    return(false);
                }
                //throw new Exception(

                if (ssp.dwProcessId == 0)
                {
                    WriteConsole(String.Format("Can't wait for service:{0} process temination! Process Id not found...", controller.ServiceName), ConsoleTextColor.Exception);
                    return(false);
                }

                // Note: It is possible for the next line to throw an ArgumentException if the
                // Service Control Manager's information is out-of-date (e.g. due to the process
                // having *just* been terminated in Task Manager) and the process does not really
                // exist. This is a race condition. The exception is the desirable result in this
                // case.
                using (Process process = Process.GetProcessById(ssp.dwProcessId))
                {
                    // EDIT: There is no need for waiting in a separate thread, because MSDN says
                    //"The handles are valid until closed, even after the process or thread they
                    //represent has been terminated."
                    //( http://msdn.microsoft.com/en-us/library/windows/desktop/ms684868%28v=vs.85%29.aspx ),
                    //so to keep things in the same thread, the process HANDLE should be opened from the
                    //process id before the service is stopped, and the Wait should be done after that.


                    // Response to EDIT: What you report is true, but the problem is that the handle
                    // isn't actually opened by Process.GetProcessById. It's only opened within the
                    //.WaitForExit method, which won't return until the wait is complete. Thus, if we
                    // try the wait on the current therad, we can't actually do anything until it's done,
                    //and if we defer the check until after the process has completed, it won't be
                    //possible to obtain a handle to it any more.

                    // The actual wait, using process.WaitForExit, opens a handle with the SYNCHRONIZE
                    // permission only and closes the handle before returning. As long as that handle
                    // is open, the process can be monitored for termination, but if the process exits
                    // before the handle is opened, it is no longer possible to open a handle to the
                    // original process and, worse, though it exists only as a technicality, there is
                    // a race condition in that another process could pop up with the same process ID.
                    // As such, we definitely want the handle to be opened before we ask the service
                    // to close, but since the handle's lifetime is only that of the call to WaitForExit
                    // and while WaitForExit is blocking the thread we can't make calls into the SCM,
                    // it would appear to be necessary to perform the wait on a separate thread.
                    ProcessWaitForExitData threadData = new ProcessWaitForExitData();
                    Thread processWaitForExitThread   = new Thread(ProcessWaitForExitThreadProc);

                    threadData.Process = process;
                    processWaitForExitThread.IsBackground = Thread.CurrentThread.IsBackground;

                    WriteConsole(String.Format("Stopping service:{0} process(s)...", controller.ServiceName), ConsoleTextColor.Normal);
                    processWaitForExitThread.Start(threadData);
                    WriteConsole(String.Format("Service:{0} process(s) ended, stopping service...", controller.ServiceName), ConsoleTextColor.Normal);

                    // Now we ask the service to exit.
                    WriteConsole(String.Format("Executing service:{0} stop request, stopping service...", controller.ServiceName), ConsoleTextColor.Normal);
                    controller.Stop();

                    // Instead of waiting until the *service* is in the "stopped" state, here we
                    // wait for its hosting process to go away. Of course, it's really that other
                    // thread waiting for the process to go away, and then we wait for the thread
                    // to go away.
                    lock (threadData.Sync)
                        while (!threadData.HasExited)
                        {
                            Monitor.Wait(threadData.Sync);
                        }

                    //if we get here, thread has exited..
                    WriteConsole(String.Format("Service:{0} process(s) terminated, service stopped...", controller.ServiceName), ConsoleTextColor.Normal);
                    return(true);
                }
            }
            catch (Exception ex)
            {
                WriteConsole(String.Format("Exception processing service:{0} process(s)/n {1}", controller.ServiceName, ex.Message), ConsoleTextColor.Exception);
                return(false);
            }
        }
Exemple #11
0
        public static void StopServiceAndWaitForExit(this ServiceController service, TimeSpan timeout)
        {
            SERVICE_STATUS_PROCESS ssp = new SERVICE_STATUS_PROCESS();
            int ignored;

            // Obtain information about the service, and specifically its hosting process,
            // from the Service Control Manager.
            if (!QueryServiceStatusEx(service.ServiceHandle.DangerousGetHandle(), SC_STATUS_PROCESS_INFO, ref ssp, Marshal.SizeOf(ssp), out ignored))
            {
                throw new Exception("Couldn't obtain service process information.");
            }

            // A few quick sanity checks that what the caller wants is *possible*.
            if (ssp.dwServiceType != SERVICE_WIN32_OWN_PROCESS)
            {
                throw new Exception("Can't wait for the service's hosting process to exit because there may be multiple services in the process (dwServiceType is not SERVICE_WIN32_OWN_PROCESS");
            }

            if ((ssp.dwServiceFlags & SERVICE_RUNS_IN_SYSTEM_PROCESS) != 0)
            {
                throw new Exception("Can't wait for the service's hosting process to exit because the hosting process is a critical system process that will not exit (SERVICE_RUNS_IN_SYSTEM_PROCESS flag set)");
            }

            if (ssp.dwProcessId == 0)
            {
                throw new Exception("Can't wait for the service's hosting process to exit because the process ID is not known.");
            }

            // Note: It is possible for the next line to throw an ArgumentException if the
            // Service Control Manager's information is out-of-date (e.g. due to the process
            // having *just* been terminated in Task Manager) and the process does not really
            // exist. This is a race condition. The exception is the desirable result in this
            // case.
            using (Process process = Process.GetProcessById(ssp.dwProcessId))
            {
                // EDIT: There is no need for waiting in a separate thread, because MSDN says "The handles are valid until closed, even after the process or thread they represent has been terminated." ( http://msdn.microsoft.com/en-us/library/windows/desktop/ms684868%28v=vs.85%29.aspx ), so to keep things in the same thread, the process HANDLE should be opened from the process id before the service is stopped, and the Wait should be done after that.

                // Response to EDIT: What you report is true, but the problem is that the handle isn't actually opened by Process.GetProcessById. It's only opened within the .WaitForExit method, which won't return until the wait is complete. Thus, if we try the wait on the current therad, we can't actually do anything until it's done, and if we defer the check until after the process has completed, it won't be possible to obtain a handle to it any more.

                // The actual wait, using process.WaitForExit, opens a handle with the SYNCHRONIZE
                // permission only and closes the handle before returning. As long as that handle
                // is open, the process can be monitored for termination, but if the process exits
                // before the handle is opened, it is no longer possible to open a handle to the
                // original process and, worse, though it exists only as a technicality, there is
                // a race condition in that another process could pop up with the same process ID.
                // As such, we definitely want the handle to be opened before we ask the service
                // to close, but since the handle's lifetime is only that of the call to WaitForExit
                // and while WaitForExit is blocking the thread we can't make calls into the SCM,
                // it would appear to be necessary to perform the wait on a separate thread.
                ProcessWaitForExitData threadData = new ProcessWaitForExitData();

                threadData.Process = process;

                Thread processWaitForExitThread = new Thread(ProcessWaitForExitThreadProc);

                processWaitForExitThread.IsBackground = Thread.CurrentThread.IsBackground;
                processWaitForExitThread.Start(threadData);

                // Now we ask the service to exit.
                var duration = Stopwatch.StartNew();
                service.Stop();

                // Instead of waiting until the *service* is in the "stopped" state, here we
                // wait for its hosting process to go away. Of course, it's really that other
                // thread waiting for the process to go away, and then we wait for the thread
                // to go away.
                lock (threadData.Sync)
                {
                    while (!threadData.HasExited)
                    {
                        var remainingWait = (timeout - duration.Elapsed);
                        if (remainingWait != null && remainingWait.TotalMilliseconds <= 0)
                        {
                            throw new TimeoutException($"Service {service.ServiceName} did not stop within the allowed time limit {timeout}");
                        }

                        Monitor.Wait(threadData.Sync, remainingWait != null ? (int)remainingWait.TotalMilliseconds : -1);
                    }
                }
            }
        }
 public ENUM_SERVICE_STATUS_PROCESS(ref ptr <ushort> ServiceName = default, ref ptr <ushort> DisplayName = default, SERVICE_STATUS_PROCESS ServiceStatusProcess = default)
 {
     this.ServiceName          = ServiceName;
     this.DisplayName          = DisplayName;
     this.ServiceStatusProcess = ServiceStatusProcess;
 }
        public static int GetServiceProcessId(ServiceController sc)
        {
            if (sc == null)
                throw new ArgumentNullException("sc");

            IntPtr zero = IntPtr.Zero;

            try
            {
                UInt32 dwBytesNeeded;
                // Call once to figure the size of the output buffer.
                QueryServiceStatusEx(sc.ServiceHandle, SC_STATUS_PROCESS_INFO, zero, 0, out dwBytesNeeded);
                if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
                {
                    // Allocate required buffer and call again.
                    zero = Marshal.AllocHGlobal((int)dwBytesNeeded);

                    if (QueryServiceStatusEx(sc.ServiceHandle, SC_STATUS_PROCESS_INFO, zero, dwBytesNeeded, out dwBytesNeeded))
                    {
                        var ssp = new SERVICE_STATUS_PROCESS();
                        Marshal.PtrToStructure(zero, ssp);
                        return (int)ssp.dwProcessId;
                    }
                }
            }
            catch (Exception e)
            {
                if (Settings.bDebug)
                    Console.WriteLine("Exception: " + e);
            }
            finally
            {
                if (zero != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(zero);
                }
            }
            return -1;
        }
Exemple #14
0
 public SERVICE_NOTIFY(uint Version = default, System.UIntPtr NotifyCallback = default, System.UIntPtr Context = default, uint NotificationStatus = default, SERVICE_STATUS_PROCESS ServiceStatus = default, uint NotificationTriggered = default, ref ptr <ushort> ServiceNames = default)
 {
     this.Version               = Version;
     this.NotifyCallback        = NotifyCallback;
     this.Context               = Context;
     this.NotificationStatus    = NotificationStatus;
     this.ServiceStatus         = ServiceStatus;
     this.NotificationTriggered = NotificationTriggered;
     this.ServiceNames          = ServiceNames;
 }
Exemple #15
0
 public static extern bool QueryServiceStatusEx(int Service, int InfoLevel,
                                                ref SERVICE_STATUS_PROCESS ServiceStatus, int BufSize, out int BytesNeeded);
 internal static extern bool QueryServiceStatus(SafeServiceHandle hService, out SERVICE_STATUS_PROCESS status);
Exemple #17
0
 internal static extern bool QueryServiceStatus(SafeServiceHandle hService, out SERVICE_STATUS_PROCESS status);
Exemple #18
0
 static extern bool QueryServiceStatusEx(IntPtr hService, int InfoLevel, ref SERVICE_STATUS_PROCESS lpBuffer, int cbBufSize, out int pcbBytesNeeded);