Some Windows services can be triggered to start at certain events. These services have ‘Tigger Start’ in their startup name behind whatever you configured (like Manual).
Powershell does not have a native method to register the type of event that triggers such a service, C++ and C# do…..and Powershell can natively run C#.
To trigger a service, you’ll need its guid first:
run sc triggerinfo <SERVICENAME>
This will give you a GUID, for example for the WebClient service:
22b6d684-fa63-4578-87c9-effcbe6643c7
You can then use this GUID in the following script to trigger your service from Powershell đŸ™‚
$Source = @" using System; using System.Text; using System.Security; using System.Collections.Generic; using System.Runtime.Versioning; using Microsoft.Win32.SafeHandles; using System.Runtime.InteropServices; using System.Diagnostics.CodeAnalysis; namespace JosL.WebClient{ public static class Starter{ [StructLayout(LayoutKind.Explicit, Size=16)] public class EVENT_DESCRIPTOR{ [FieldOffset(0)]ushort Id = 1; [FieldOffset(2)]byte Version = 0; [FieldOffset(3)]byte Channel = 0; [FieldOffset(4)]byte Level = 4; [FieldOffset(5)]byte Opcode = 0; [FieldOffset(6)]ushort Task = 0; [FieldOffset(8)]long Keyword = 0; } [StructLayout(LayoutKind.Explicit, Size = 16)] public struct EventData{ [FieldOffset(0)] internal UInt64 DataPointer; [FieldOffset(8)] internal uint Size; [FieldOffset(12)] internal int Reserved; } public static void startService(){ Guid webClientTrigger = new Guid(0x22B6D684, 0xFA63, 0x4578, 0x87, 0xC9, 0xEF, 0xFC, 0xBE, 0x66, 0x43, 0xC7); long handle = 0; uint output = EventRegister(ref webClientTrigger, IntPtr.Zero, IntPtr.Zero, ref handle); bool success = false; if (output == 0){ EVENT_DESCRIPTOR desc = new EVENT_DESCRIPTOR(); unsafe { uint writeOutput = EventWrite(handle, ref desc, 0, null); success = writeOutput == 0; EventUnregister(handle); } } } [DllImport("Advapi32.dll", SetLastError = true)] public static extern uint EventRegister(ref Guid guid, [Optional] IntPtr EnableCallback, [Optional] IntPtr CallbackContext, [In][Out] ref long RegHandle); [DllImport("Advapi32.dll", SetLastError = true)] public static extern unsafe uint EventWrite(long RegHandle, ref EVENT_DESCRIPTOR EventDescriptor, uint UserDataCount, EventData* UserData); [DllImport("Advapi32.dll", SetLastError = true)] public static extern uint EventUnregister(long RegHandle); } } "@ $compilerParameters = New-Object System.CodeDom.Compiler.CompilerParameters $compilerParameters.CompilerOptions="/unsafe" Add-Type -TypeDefinition $Source -Language CSharp -CompilerParameters $compilerParameters [JosL.WebClient.Starter]::startService()
Thanks for the Article, got me headed in the right direction!
FYI – At least in windows 10, the command to get the GUID is “sc qtriggerinfo ” e.g. “sc qtriggerinfo WebClient”
I stumbled across this 3 years after you posted and used it for a C# project. I needed to send a custom trigger event so ended up using EventWriteString() which made the code much simpler (no need for event descriptor or data structures).
Anyway, thanks for sharing, you saved my bacon!