/// <summary> /// Determine whether the specified service is configured to trigger start /// </summary> /// <param name="hService"> /// A handle to the service. This handle is returned by the OpenService or /// CreateService function and must have the SERVICE_QUERY_CONFIG access right. /// </param> /// <returns></returns> public static bool IsTriggerStartService(SafeServiceHandle hService) { // Query the service trigger info size of the current serivce int cbBytesNeeded = -1; NativeMethods.QueryServiceConfig2(hService, ServiceConfig2InfoLevel.SERVICE_CONFIG_TRIGGER_INFO, IntPtr.Zero, 0, out cbBytesNeeded); if (cbBytesNeeded == -1) { // If failed, get the last Win32 error and throw a Win32Exception throw new Win32Exception(); } // Allocate memory for the service trigger info struct IntPtr pBuffer = Marshal.AllocHGlobal(cbBytesNeeded); try { // Retrieve the service trigger info if (!NativeMethods.QueryServiceConfig2(hService, ServiceConfig2InfoLevel.SERVICE_CONFIG_TRIGGER_INFO, pBuffer, cbBytesNeeded, out cbBytesNeeded)) { // If failed, get the last Win32 error and throw a Win32Exception throw new Win32Exception(); } SERVICE_TRIGGER_INFO sti = (SERVICE_TRIGGER_INFO) Marshal.PtrToStructure(pBuffer, typeof(SERVICE_TRIGGER_INFO)); // You can also retrieve more trigger information of the service //for (int i = 0; i < sti.cTriggers; i++) //{ // // Calculate the address of the SERVICE_TRIGGER struct // IntPtr pst = new IntPtr((long)sti.pTriggers + // i * Marshal.SizeOf(typeof(SERVICE_TRIGGER))); // // Marshal the native SERVICE_TRIGGER struct to .NET struct // SERVICE_TRIGGER st = (SERVICE_TRIGGER)Marshal.PtrToStructure(pst, // typeof(SERVICE_TRIGGER)); // // // Get more information from the SERVICE_TRIGGER struct // // ... //} return(sti.cTriggers > 0); } finally { // Free the memory of the service trigger info struct if (pBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(pBuffer); } } }
/// <summary> /// Determine if the current service is trigger-start /// </summary> /// <returns></returns> protected bool IsTriggerStartService() { using (ServiceController sc = new ServiceController(this.ServiceName)) { // Query the service trigger info size of the current serivce int cbBytesNeeded = -1, errorCode = 0; ServiceNative.QueryServiceConfig2(sc.ServiceHandle.DangerousGetHandle(), ServiceConfig2InfoLevel.SERVICE_CONFIG_TRIGGER_INFO, IntPtr.Zero, 0, out cbBytesNeeded); if (cbBytesNeeded == -1) { // If failed, throw the error information errorCode = Marshal.GetLastWin32Error(); throw Marshal.GetExceptionForHR(errorCode); } // Allocate memory for the service trigger info struct IntPtr pBuffer = Marshal.AllocHGlobal(cbBytesNeeded); // Retrieve the service trigger info bool bSuccess = ServiceNative.QueryServiceConfig2( sc.ServiceHandle.DangerousGetHandle(), ServiceConfig2InfoLevel.SERVICE_CONFIG_TRIGGER_INFO, pBuffer, cbBytesNeeded, out cbBytesNeeded) != 0; if (!bSuccess) { // If failed, clean up the memory and throw the error Marshal.FreeHGlobal(pBuffer); errorCode = Marshal.GetLastWin32Error(); throw Marshal.GetExceptionForHR(errorCode); } // Determine if the serivce is trigger-start SERVICE_TRIGGER_INFO serviceTriggerInfo = (SERVICE_TRIGGER_INFO) Marshal.PtrToStructure(pBuffer, typeof(SERVICE_TRIGGER_INFO)); bool bTriggerStart = serviceTriggerInfo.cTriggers > 0; Marshal.FreeHGlobal(pBuffer); return(bTriggerStart); } }
/// <summary> /// Set the service to trigger-start when the first IP address on the TCP/IP /// networking stack becomes available, and trigger-stop when the last IP /// address on the TCP/IP networking stack becomes unavailable. /// </summary> /// <param name="hService"> /// A handle to the service. This handle is returned by the OpenService or /// CreateService function and must have the SERVICE_CHANGE_CONFIG access right. /// </param> public static void SetServiceTriggerStartOnIPAddressArrival(SafeServiceHandle hService) { IntPtr pGuidIpAddressArrival = IntPtr.Zero; IntPtr pGuidIpAddressRemoval = IntPtr.Zero; IntPtr pServiceTriggers = IntPtr.Zero; IntPtr pServiceTriggerInfo = IntPtr.Zero; try { // Marshal Guid struct NETWORK_MANAGER_FIRST_IP_ADDRESS_ARRIVAL_GUID // and NETWORK_MANAGER_LAST_IP_ADDRESS_REMOVAL_GUID to native memory int cbGuid = Marshal.SizeOf(typeof(Guid)); pGuidIpAddressArrival = Marshal.AllocHGlobal(cbGuid); Marshal.StructureToPtr(NETWORK_MANAGER_FIRST_IP_ADDRESS_ARRIVAL_GUID, pGuidIpAddressArrival, false); pGuidIpAddressRemoval = Marshal.AllocHGlobal(cbGuid); Marshal.StructureToPtr(NETWORK_MANAGER_LAST_IP_ADDRESS_REMOVAL_GUID, pGuidIpAddressRemoval, false); // Allocate and set the SERVICE_TRIGGER structure for // NETWORK_MANAGER_FIRST_IP_ADDRESS_ARRIVAL_GUID to start the service SERVICE_TRIGGER serviceTrigger1 = new SERVICE_TRIGGER(); serviceTrigger1.dwTriggerType = ServiceTriggerType.SERVICE_TRIGGER_TYPE_IP_ADDRESS_AVAILABILITY; serviceTrigger1.dwAction = ServiceTriggerAction.SERVICE_TRIGGER_ACTION_SERVICE_START; serviceTrigger1.pTriggerSubtype = pGuidIpAddressArrival; // Allocate and set the SERVICE_TRIGGER structure for // NETWORK_MANAGER_LAST_IP_ADDRESS_REMOVAL_GUID to stop the service SERVICE_TRIGGER serviceTrigger2 = new SERVICE_TRIGGER(); serviceTrigger2.dwTriggerType = ServiceTriggerType.SERVICE_TRIGGER_TYPE_IP_ADDRESS_AVAILABILITY; serviceTrigger2.dwAction = ServiceTriggerAction.SERVICE_TRIGGER_ACTION_SERVICE_STOP; serviceTrigger2.pTriggerSubtype = pGuidIpAddressRemoval; // Marshal the 2 SERVICE_TRIGGER structs to native memory as an array int cbServiceTrigger = Marshal.SizeOf(typeof(SERVICE_TRIGGER)); pServiceTriggers = Marshal.AllocHGlobal(cbServiceTrigger * 2); Marshal.StructureToPtr(serviceTrigger1, pServiceTriggers, false); Marshal.StructureToPtr(serviceTrigger2, new IntPtr((long)pServiceTriggers + cbServiceTrigger), false); // Allocate and set the SERVICE_TRIGGER_INFO structure SERVICE_TRIGGER_INFO serviceTriggerInfo = new SERVICE_TRIGGER_INFO(); serviceTriggerInfo.cTriggers = 2; serviceTriggerInfo.pTriggers = pServiceTriggers; // Marshal the SERVICE_TRIGGER_INFO struct to native memory int cbServiceTriggerInfo = Marshal.SizeOf(typeof(SERVICE_TRIGGER_INFO)); pServiceTriggerInfo = Marshal.AllocHGlobal(cbServiceTriggerInfo); Marshal.StructureToPtr(serviceTriggerInfo, pServiceTriggerInfo, false); // Call ChangeServiceConfig2 with the SERVICE_CONFIG_TRIGGER_INFO level // and pass to it the address of the SERVICE_TRIGGER_INFO structure if (!NativeMethods.ChangeServiceConfig2(hService, ServiceConfig2InfoLevel.SERVICE_CONFIG_TRIGGER_INFO, pServiceTriggerInfo)) { // If the handle is invalid, get the last Win32 error and throw a // Win32Exception throw new Win32Exception(); } } finally { // Clean up the native memory if (pGuidIpAddressArrival != IntPtr.Zero) { Marshal.FreeHGlobal(pGuidIpAddressArrival); } if (pGuidIpAddressRemoval != IntPtr.Zero) { Marshal.FreeHGlobal(pGuidIpAddressRemoval); } if (pServiceTriggers != IntPtr.Zero) { Marshal.FreeHGlobal(pServiceTriggers); } if (pServiceTriggerInfo != IntPtr.Zero) { Marshal.FreeHGlobal(pServiceTriggerInfo); } } }
/// <summary> /// Set the service to trigger-start when a generic USB disk becomes available. /// </summary> /// <param name="hService"> /// A handle to the service. This handle is returned by the OpenService or /// CreateService function and must have the SERVICE_CHANGE_CONFIG access right. /// </param> public static void SetServiceTriggerStartOnUSBArrival(SafeServiceHandle hService) { IntPtr pGuidUSBDevice = IntPtr.Zero; IntPtr pUSBHardwareId = IntPtr.Zero; IntPtr pDeviceData = IntPtr.Zero; IntPtr pServiceTrigger = IntPtr.Zero; IntPtr pServiceTriggerInfo = IntPtr.Zero; try { // Marshal the Guid struct GUID_DEVINTERFACE_DISK to native memory pGuidUSBDevice = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Guid))); Marshal.StructureToPtr(GUID_DEVINTERFACE_DISK, pGuidUSBDevice, false); // Allocate and set the SERVICE_TRIGGER_SPECIFIC_DATA_ITEM structure SERVICE_TRIGGER_SPECIFIC_DATA_ITEM deviceData; deviceData.dwDataType = ServiceTriggerDataType.SERVICE_TRIGGER_DATA_TYPE_STRING; deviceData.cbData = (uint)(USBHardwareId.Length + 1) * 2; pUSBHardwareId = Marshal.StringToHGlobalUni(USBHardwareId); deviceData.pData = pUSBHardwareId; // Marshal SERVICE_TRIGGER_SPECIFIC_DATA_ITEM to native memory int cbDataItem = Marshal.SizeOf(typeof(SERVICE_TRIGGER_SPECIFIC_DATA_ITEM)); pDeviceData = Marshal.AllocHGlobal(cbDataItem); Marshal.StructureToPtr(deviceData, pDeviceData, false); // Allocate and set the SERVICE_TRIGGER structure SERVICE_TRIGGER serviceTrigger = new SERVICE_TRIGGER(); serviceTrigger.dwTriggerType = ServiceTriggerType.SERVICE_TRIGGER_TYPE_DEVICE_INTERFACE_ARRIVAL; serviceTrigger.dwAction = ServiceTriggerAction.SERVICE_TRIGGER_ACTION_SERVICE_START; serviceTrigger.pTriggerSubtype = pGuidUSBDevice; serviceTrigger.cDataItems = 1; serviceTrigger.pDataItems = pDeviceData; // Marshal the SERVICE_TRIGGER struct to native memory int cbServiceTrigger = Marshal.SizeOf(typeof(SERVICE_TRIGGER)); pServiceTrigger = Marshal.AllocHGlobal(cbServiceTrigger); Marshal.StructureToPtr(serviceTrigger, pServiceTrigger, false); // Allocate and set the SERVICE_TRIGGER_INFO structure SERVICE_TRIGGER_INFO serviceTriggerInfo = new SERVICE_TRIGGER_INFO(); serviceTriggerInfo.cTriggers = 1; serviceTriggerInfo.pTriggers = pServiceTrigger; // Marshal the SERVICE_TRIGGER_INFO struct to native memory int cbServiceTriggerInfo = Marshal.SizeOf(typeof(SERVICE_TRIGGER_INFO)); pServiceTriggerInfo = Marshal.AllocHGlobal(cbServiceTriggerInfo); Marshal.StructureToPtr(serviceTriggerInfo, pServiceTriggerInfo, false); // Call ChangeServiceConfig2 with the SERVICE_CONFIG_TRIGGER_INFO level // and pass to it the address of the SERVICE_TRIGGER_INFO structure if (!NativeMethods.ChangeServiceConfig2(hService, ServiceConfig2InfoLevel.SERVICE_CONFIG_TRIGGER_INFO, pServiceTriggerInfo)) { // If the handle is invalid, get the last Win32 error and throw a // Win32Exception throw new Win32Exception(); } } finally { // Clean up the native memory if (pGuidUSBDevice != IntPtr.Zero) { Marshal.FreeHGlobal(pGuidUSBDevice); } if (pUSBHardwareId != IntPtr.Zero) { Marshal.FreeHGlobal(pUSBHardwareId); } if (pDeviceData != IntPtr.Zero) { Marshal.FreeHGlobal(pDeviceData); } if (pServiceTrigger != IntPtr.Zero) { Marshal.FreeHGlobal(pServiceTrigger); } if (pServiceTriggerInfo != IntPtr.Zero) { Marshal.FreeHGlobal(pServiceTriggerInfo); } } }
private void SetServiceTriggerStartOnCustomEvent(string serviceName) { using (ServiceController sc = new ServiceController(serviceName)) { // Marshal Guid struct GUID_DEVINTERFACE_DISK to native memory IntPtr pGuidCustomEvent = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Guid))); Marshal.StructureToPtr(CUSTOM_EVENT_GUID, pGuidCustomEvent, false); //// Allocate and set the SERVICE_TRIGGER_SPECIFIC_DATA_ITEM structure //SERVICE_TRIGGER_SPECIFIC_DATA_ITEM deviceData; //deviceData.dwDataType = ServiceTriggerDataType.SERVICE_TRIGGER_DATA_TYPE_STRING; //deviceData.cbData = (uint)(USBHardwareId.Length + 1) * 2; //IntPtr pUSBHardwareId = Marshal.StringToHGlobalUni(USBHardwareId); //deviceData.pData = pUSBHardwareId; //// Marshal the SERVICE_TRIGGER_SPECIFIC_DATA_ITEM struct to native memory //IntPtr pDeviceData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof( // SERVICE_TRIGGER_SPECIFIC_DATA_ITEM))); //Marshal.StructureToPtr(deviceData, pDeviceData, false); // Allocate and set the SERVICE_TRIGGER structure SERVICE_TRIGGER serviceTrigger; serviceTrigger.dwTriggerType = ServiceTriggerType.SERVICE_TRIGGER_TYPE_CUSTOM; serviceTrigger.dwAction = ServiceTriggerAction.SERVICE_TRIGGER_ACTION_SERVICE_START; serviceTrigger.pTriggerSubtype = pGuidCustomEvent; serviceTrigger.cDataItems = 0; serviceTrigger.pDataItems = IntPtr.Zero; // Marshal the SERVICE_TRIGGER struct to native memory IntPtr pServiceTrigger = Marshal.AllocHGlobal(Marshal.SizeOf(typeof( SERVICE_TRIGGER))); Marshal.StructureToPtr(serviceTrigger, pServiceTrigger, false); // Allocate and set the SERVICE_TRIGGER_INFO structure. SERVICE_TRIGGER_INFO serviceTriggerInfo = new SERVICE_TRIGGER_INFO(); serviceTriggerInfo.cTriggers = 1; serviceTriggerInfo.pTriggers = pServiceTrigger; // Marshal the SERVICE_TRIGGER_INFO struct to native memory IntPtr pServiceTriggerInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof( SERVICE_TRIGGER_INFO))); Marshal.StructureToPtr(serviceTriggerInfo, pServiceTriggerInfo, false); // Call ChangeServiceConfig2 with the SERVICE_CONFIG_TRIGGER_INFO level // and pass to it the address of the SERVICE_TRIGGER_INFO structure. bool bSuccess = ServiceNative.ChangeServiceConfig2( sc.ServiceHandle.DangerousGetHandle(), ServiceConfig2InfoLevel.SERVICE_CONFIG_TRIGGER_INFO, pServiceTriggerInfo); int errorCode = Marshal.GetLastWin32Error(); // Clean up the native resources //Marshal.FreeHGlobal(pGuidUSBDevice); //Marshal.FreeHGlobal(pUSBHardwareId); //Marshal.FreeHGlobal(pDeviceData); Marshal.FreeHGlobal(pServiceTrigger); Marshal.FreeHGlobal(pServiceTriggerInfo); // If the service failed to be set as trigger start, throw the error // returned by the ChangeServiceConfig2 function. if (!bSuccess) { Marshal.ThrowExceptionForHR(errorCode); } } }
/// <summary> /// Set the service to trigger-start when the first IP address on the TCP/IP /// networking stack becomes available, and trigger-stop when the last IP address on /// the TCP/IP networking stack becomes unavailable. /// </summary> /// <param name="serviceName"></param> private void SetServiceTriggerStartOnIPAddressArrival(string serviceName) { using (ServiceController sc = new ServiceController(serviceName)) { // Marshal Guid struct NETWORK_MANAGER_FIRST_IP_ADDRESS_ARRIVAL_GUID and // NETWORK_MANAGER_LAST_IP_ADDRESS_REMOVAL_GUID to native memory IntPtr pGuidIpAddressArrival = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Guid))); Marshal.StructureToPtr(NETWORK_MANAGER_FIRST_IP_ADDRESS_ARRIVAL_GUID, pGuidIpAddressArrival, false); IntPtr pGuidIpAddressRemoval = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Guid))); Marshal.StructureToPtr(NETWORK_MANAGER_LAST_IP_ADDRESS_REMOVAL_GUID, pGuidIpAddressRemoval, false); // Allocate and set the SERVICE_TRIGGER structure for // NETWORK_MANAGER_FIRST_IP_ADDRESS_ARRIVAL_GUID to start the service SERVICE_TRIGGER serviceTrigger1 = new SERVICE_TRIGGER(); serviceTrigger1.dwTriggerType = ServiceTriggerType.SERVICE_TRIGGER_TYPE_IP_ADDRESS_AVAILABILITY; serviceTrigger1.dwAction = ServiceTriggerAction.SERVICE_TRIGGER_ACTION_SERVICE_START; serviceTrigger1.pTriggerSubtype = pGuidIpAddressArrival; // Allocate and set the SERVICE_TRIGGER structure for // NETWORK_MANAGER_LAST_IP_ADDRESS_REMOVAL_GUID to stop the service SERVICE_TRIGGER serviceTrigger2 = new SERVICE_TRIGGER(); serviceTrigger2.dwTriggerType = ServiceTriggerType.SERVICE_TRIGGER_TYPE_IP_ADDRESS_AVAILABILITY; serviceTrigger2.dwAction = ServiceTriggerAction.SERVICE_TRIGGER_ACTION_SERVICE_STOP; serviceTrigger2.pTriggerSubtype = pGuidIpAddressRemoval; // Marshal the two SERVICE_TRIGGER structs to native memory as an array IntPtr pServiceTriggers = Marshal.AllocHGlobal(Marshal.SizeOf(typeof( SERVICE_TRIGGER)) * 2 /*2 elements*/); Marshal.StructureToPtr(serviceTrigger1, pServiceTriggers, false); Marshal.StructureToPtr(serviceTrigger2, new IntPtr((long)pServiceTriggers + Marshal.SizeOf(typeof(SERVICE_TRIGGER))), false); // Allocate and set the SERVICE_TRIGGER_INFO structure SERVICE_TRIGGER_INFO serviceTriggerInfo = new SERVICE_TRIGGER_INFO(); serviceTriggerInfo.cTriggers = 2; serviceTriggerInfo.pTriggers = pServiceTriggers; // Marshal the SERVICE_TRIGGER_INFO struct to native memory IntPtr pServiceTriggerInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof( SERVICE_TRIGGER_INFO))); Marshal.StructureToPtr(serviceTriggerInfo, pServiceTriggerInfo, false); // Call ChangeServiceConfig2 with the SERVICE_CONFIG_TRIGGER_INFO level // and pass to it the address of the SERVICE_TRIGGER_INFO structure. bool bSuccess = ServiceNative.ChangeServiceConfig2( sc.ServiceHandle.DangerousGetHandle(), ServiceConfig2InfoLevel.SERVICE_CONFIG_TRIGGER_INFO, pServiceTriggerInfo); int errorCode = Marshal.GetLastWin32Error(); // Clean up the native resources Marshal.FreeHGlobal(pGuidIpAddressArrival); Marshal.FreeHGlobal(pGuidIpAddressRemoval); Marshal.FreeHGlobal(pServiceTriggers); Marshal.FreeHGlobal(pServiceTriggerInfo); // If the service failed to be set as trigger start, throw the error // returned by the ChangeServiceConfig2 function. if (!bSuccess) { Marshal.ThrowExceptionForHR(errorCode); } } }