コード例 #1
0
ファイル: WindowsService.cs プロジェクト: Underwood12/csharp
        /// <summary>开始执行服务</summary>
        /// <param name="service"></param>
        public override void Run(IHostedService service)
        {
            if (service == null)
            {
                throw new ArgumentNullException(nameof(service));
            }

            _service = service;

            var num    = Marshal.SizeOf(typeof(SERVICE_TABLE_ENTRY));
            var intPtr = Marshal.AllocHGlobal(checked ((1 + 1) * num));

            try
            {
                // Win32OwnProcess/StartPending
                _status.serviceType             = 16;
                _status.currentState            = ServiceControllerStatus.StartPending;
                _status.controlsAccepted        = 0;
                _status.win32ExitCode           = 0;
                _status.serviceSpecificExitCode = 0;
                _status.checkPoint = 0;
                _status.waitHint   = 0;

                // CanStop | CanShutdown | CanPauseAndContinue | CanHandlePowerEvent | CanHandleSessionChangeEvent
                //_acceptedCommands = 1 | 4 | 2 | 64 | 128;
                // CanStop | CanShutdown
                _acceptedCommands = 1 | 4;

                SERVICE_TABLE_ENTRY result = default;
                result.callback = ServiceMainCallback;
                result.name     = Marshal.StringToHGlobalUni(service.ServiceName);
                Marshal.StructureToPtr(result, intPtr, false);

                SERVICE_TABLE_ENTRY result2 = default;
                result2.callback = null;
                result2.name     = (IntPtr)0;
                Marshal.StructureToPtr(result2, intPtr + num, false);

                /*
                 * 如果StartServiceCtrlDispatcher函数执行成功,调用线程(也就是服务进程的主线程)不会返回,直到所有的服务进入到SERVICE_STOPPED状态。
                 * 调用线程扮演着控制分发的角色,干这样的事情:
                 * 1、在新的服务启动时启动新线程去调用服务主函数(主意:服务的任务是在新线程中做的);
                 * 2、当服务有请求时(注意:请求是由SCM发给它的),调用它对应的处理函数(主意:这相当于主线程“陷入”了,它在等待控制消息并对消息做处理)。
                 */

                XTrace.WriteLine("启动服务 {0}", service.ServiceName);

                var flag = StartServiceCtrlDispatcher(intPtr);
                if (!flag)
                {
                    XTrace.WriteLine("服务启动失败!");
                }
            }
            finally
            {
                Marshal.FreeHGlobal(intPtr);
            }
        }
コード例 #2
0
ファイル: ServiceBase.cs プロジェクト: axelheer/dotnet-corefx
        private SERVICE_TABLE_ENTRY GetEntry()
        {
            SERVICE_TABLE_ENTRY entry = new SERVICE_TABLE_ENTRY();

            _nameFrozen    = true;
            entry.callback = (Delegate)_mainCallback;
            entry.name     = _handleName;
            return(entry);
        }
コード例 #3
0
ファイル: ServiceBase.cs プロジェクト: axelheer/dotnet-corefx
        /// <devdoc>
        ///    <para>Provides the main entry point for an executable that
        ///       contains multiple associated services. Loads the specified services into memory so they can be
        ///       started.</para>
        /// </devdoc>
        public static void Run(ServiceBase[] services)
        {
            if (services == null || services.Length == 0)
            {
                throw new ArgumentException(SR.NoServices);
            }

            IntPtr entriesPointer = Marshal.AllocHGlobal((IntPtr)((services.Length + 1) * Marshal.SizeOf(typeof(SERVICE_TABLE_ENTRY))));

            SERVICE_TABLE_ENTRY[] entries = new SERVICE_TABLE_ENTRY[services.Length];
            bool   multipleServices       = services.Length > 1;
            IntPtr structPtr = (IntPtr)0;

            for (int index = 0; index < services.Length; ++index)
            {
                services[index].Initialize(multipleServices);
                entries[index] = services[index].GetEntry();
                structPtr      = (IntPtr)((long)entriesPointer + Marshal.SizeOf(typeof(SERVICE_TABLE_ENTRY)) * index);
                Marshal.StructureToPtr(entries[index], structPtr, true);
            }

            SERVICE_TABLE_ENTRY lastEntry = new SERVICE_TABLE_ENTRY();

            lastEntry.callback = null;
            lastEntry.name     = (IntPtr)0;
            structPtr          = (IntPtr)((long)entriesPointer + Marshal.SizeOf(typeof(SERVICE_TABLE_ENTRY)) * services.Length);
            Marshal.StructureToPtr(lastEntry, structPtr, true);

            // While the service is running, this function will never return. It will return when the service
            // is stopped.
            bool   res          = StartServiceCtrlDispatcher(entriesPointer);
            string errorMessage = "";

            if (!res)
            {
                errorMessage = new Win32Exception().Message;
                Console.WriteLine(SR.CantStartFromCommandLine);
            }

            foreach (ServiceBase service in services)
            {
                service.Dispose();
                if (!res)
                {
                    service.WriteLogEntry(SR.Format(SR.StartFailed, errorMessage), true);
                }
            }
        }
コード例 #4
0
        private static void Win32RunService(ServiceBase [] services)
        {
            SERVICE_TABLE_ENTRY[] table = new SERVICE_TABLE_ENTRY[services.Length + 1];

            NotifyStatus = new NotifyStatusCallback(Win32NotifyStatus);

            for (int i = 0; i < services.Length; i++)
            {
                table[i].lpServiceName = services[i].ServiceName ?? "";
                table[i].lpServiceProc = new LPSERVICE_MAIN_FUNCTION(services[i].ServiceMainCallback);
            }

            // table[services.Length] is a NULL terminator

            share_process = (services.Length > 1);

            if (!StartServiceCtrlDispatcher(table))
            {
                throw new Win32Exception();
            }
        }
コード例 #5
0
        /// <summary>开始执行服务</summary>
        /// <param name="service"></param>
        public override void Run(ServiceBase service)
        {
            _service = service ?? throw new ArgumentNullException(nameof(service));

            var num        = Marshal.SizeOf(typeof(SERVICE_TABLE_ENTRY));
            var table      = Marshal.AllocHGlobal((IntPtr)((1 + 1) * num));
            var handleName = Marshal.StringToHGlobalUni(service.ServiceName);

            try
            {
                // Win32OwnProcess/StartPending
                _status.serviceType             = ServiceType.Win32OwnProcess;
                _status.currentState            = ServiceControllerStatus.StartPending;
                _status.controlsAccepted        = 0;
                _status.win32ExitCode           = 0;
                _status.serviceSpecificExitCode = 0;
                _status.checkPoint = 0;
                _status.waitHint   = 0;

                // 正常运行后可接受的命令
#if NETSTANDARD2_0
                _acceptedCommands = ControlsAccepted.CanStop
                                    | ControlsAccepted.CanShutdown
                                    //| ControlsAccepted.CanPauseAndContinue
                                    | ControlsAccepted.ParamChange
                                    | ControlsAccepted.NetBindChange
                                    | ControlsAccepted.HardwareProfileChange
                                    | ControlsAccepted.CanHandlePowerEvent
                                    | ControlsAccepted.CanHandleSessionChangeEvent
                                    | ControlsAccepted.PreShutdown
                                    | ControlsAccepted.TimeChange
                                    | ControlsAccepted.TriggerEvent
                                    //| ControlsAccepted.UserModeReboot
                ;
#else
                _acceptedCommands = ControlsAccepted.CanStop
                                    | ControlsAccepted.CanShutdown
                ;
#endif

                //!!! 函数委托必须引着,避免GC回收导致PInvoke内部报错
                _table = new SERVICE_TABLE_ENTRY
                {
                    callback = ServiceMainCallback,
                    name     = handleName
                };
                Marshal.StructureToPtr(_table, table, true);

                var result2 = new SERVICE_TABLE_ENTRY
                {
                    callback = null,
                    name     = IntPtr.Zero
                };
                Marshal.StructureToPtr(result2, table + num, true);

                /*
                 * 如果StartServiceCtrlDispatcher函数执行成功,调用线程(也就是服务进程的主线程)不会返回,直到所有的服务进入到SERVICE_STOPPED状态。
                 * 调用线程扮演着控制分发的角色,干这样的事情:
                 * 1、在新的服务启动时启动新线程去调用服务主函数(主意:服务的任务是在新线程中做的);
                 * 2、当服务有请求时(注意:请求是由SCM发给它的),调用它对应的处理函数(主意:这相当于主线程“陷入”了,它在等待控制消息并对消息做处理)。
                 */

                //XTrace.WriteLine("运行服务 {0}", service.ServiceName);

                var flag = StartServiceCtrlDispatcher(table);
                if (!flag)
                {
                    XTrace.WriteLine(new Win32Exception().Message);
                }

                XTrace.WriteLine("退出服务 {0} CtrlDispatcher={1}", service.ServiceName, flag);
            }
            catch (Exception ex)
            {
                XTrace.WriteException(ex);
                XTrace.WriteLine("运行服务 {0} 出错,{1}", _service.ServiceName, new Win32Exception(Marshal.GetLastWin32Error()).Message);
            }
            finally
            {
                if (table != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(table);
                }
                if (handleName != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(handleName);
                }

                //_service.TryDispose();
            }
        }
コード例 #6
0
ファイル: ServiceBase.cs プロジェクト: zuimengaitianya/corefx
        /// <devdoc>
        ///    <para>Provides the main entry point for an executable that
        ///       contains multiple associated services. Loads the specified services into memory so they can be
        ///       started.</para>
        /// </devdoc>
        public static void Run(ServiceBase[] services)
        {
            if (services == null || services.Length == 0)
            {
                throw new ArgumentException(SR.NoServices);
            }

            int sizeOfSERVICE_TABLE_ENTRY = Marshal.SizeOf <SERVICE_TABLE_ENTRY>();

            IntPtr entriesPointer = Marshal.AllocHGlobal(checked ((services.Length + 1) * sizeOfSERVICE_TABLE_ENTRY));

            SERVICE_TABLE_ENTRY[] entries = new SERVICE_TABLE_ENTRY[services.Length];
            bool   multipleServices       = services.Length > 1;
            IntPtr structPtr;

            for (int index = 0; index < services.Length; ++index)
            {
                services[index].Initialize(multipleServices);
                entries[index] = services[index].GetEntry();
                structPtr      = entriesPointer + sizeOfSERVICE_TABLE_ENTRY * index;
                Marshal.StructureToPtr(entries[index], structPtr, fDeleteOld: false);
            }

            SERVICE_TABLE_ENTRY lastEntry = new SERVICE_TABLE_ENTRY();

            lastEntry.callback = null;
            lastEntry.name     = (IntPtr)0;
            structPtr          = entriesPointer + sizeOfSERVICE_TABLE_ENTRY * services.Length;
            Marshal.StructureToPtr(lastEntry, structPtr, fDeleteOld: false);

            // While the service is running, this function will never return. It will return when the service
            // is stopped.
            // After it returns, SCM might terminate the process at any time
            // (so subsequent code is not guaranteed to run).
            bool res = StartServiceCtrlDispatcher(entriesPointer);

            foreach (ServiceBase service in services)
            {
                if (service._startFailedException != null)
                {
                    // Propagate exceptions throw during OnStart.
                    // Note that this same exception is also thrown from ServiceMainCallback
                    // (so SCM can see it as well).
                    service._startFailedException.Throw();
                }
            }

            string errorMessage = "";

            if (!res)
            {
                errorMessage = new Win32Exception().Message;
                Console.WriteLine(SR.CantStartFromCommandLine);
            }

            foreach (ServiceBase service in services)
            {
                service.Dispose();
                if (!res)
                {
                    service.WriteLogEntry(SR.Format(SR.StartFailed, errorMessage), true);
                }
            }
        }
コード例 #7
0
 internal static extern int StartServiceCtrlDispatcher(SERVICE_TABLE_ENTRY[] lpServiceStartTable);
コード例 #8
0
ファイル: ServiceBase.cs プロジェクト: nlhepler/mono
		private static void Win32RunService (ServiceBase [] services)
		{
			SERVICE_TABLE_ENTRY[] table = new SERVICE_TABLE_ENTRY[services.Length + 1];

			NotifyStatus = new NotifyStatusCallback (Win32NotifyStatus);

			for (int i = 0; i<services.Length; i++)
			{
				table[i].lpServiceName = services[i].ServiceName ?? "";
				table[i].lpServiceProc = new LPSERVICE_MAIN_FUNCTION (services[i].ServiceMainCallback);
			}

			// table[services.Length] is a NULL terminator

			share_process = (services.Length > 1);

			if (!StartServiceCtrlDispatcher (table))
				throw new Win32Exception ();
		}