Is there a way to invoke the Win32 with the .NET framework (specifically C#). I'm trying to create an online method of starting and stopping a service. Normally to start a service I'd use a Win32 API call to StartService(), but obviously you can't just do that in C# (or I don't know how), so could someone explain to me how I'd do this? Or if this isn't possible (and even if it is please tell me anyways) is there a way to start a service and stop a service native to .NET?
(btw, forgive me if there've been posts on this already, if so just direct me to them)
http://www.google.com/search?hl=en&q=StartService+C%23+.NET&btnG=Google+Search
Edit: You may also want to look at the System.ServiceProcess namespace on MSDN.
If you wanted to go entirely P/Invoke:
Here is the prototype for CreateService:
SC_HANDLE CreateService(
SC_HANDLE hSCManager,
LPCTSTR lpServiceName,
LPCTSTR lpDisplayName,
DWORD dwDesiredAccess,
DWORD dwServiceType,
DWORD dwStartType,
DWORD dwErrorControl,
LPCTSTR lpBinaryPathName,
LPCTSTR lpLoadOrderGroup,
LPDWORD lpdwTagId,
LPCTSTR lpDependencies,
LPCTSTR lpServiceStartName,
LPCTSTR lpPassword
);
C# import:
[DllImport("advapi32.dll")]
public static extern IntPtr CreateService(
IntPtr hSCManager,
string lpServiceName,
string lpDisplayName,
int dwDesiredAccess,
int dwServiceType,
int dwStartType,
int dwErrorControl,
string lpBinaryPathName,
string lpLoadOrderGroup,
[Out] out int lpdwTagId,
string lpDependencies,
string lpServiceStartName,
string lpPassword
);
This is the declaration for the dwAccessRights param:
#define SERVICE_QUERY_CONFIG 0x0001
#define SERVICE_CHANGE_CONFIG 0x0002
#define SERVICE_QUERY_STATUS 0x0004
#define SERVICE_ENUMERATE_DEPENDENTS 0x0008
#define SERVICE_START 0x0010
#define SERVICE_STOP 0x0020
#define SERVICE_PAUSE_CONTINUE 0x0040
#define SERVICE_INTERROGATE 0x0080
#define SERVICE_USER_DEFINED_CONTROL 0x0100
#define SERVICE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | \
SERVICE_QUERY_CONFIG | \
SERVICE_CHANGE_CONFIG | \
SERVICE_QUERY_STATUS | \
SERVICE_ENUMERATE_DEPENDENTS | \
SERVICE_START | \
SERVICE_STOP | \
SERVICE_PAUSE_CONTINUE | \
SERVICE_INTERROGATE | \
SERVICE_USER_DEFINED_CONTROL)
I'm not going to change that over to an enum. I do one for you below, you should be able to figure it out.
To get the IntPtr hSCManager, you need to call OpenSCManager. C Prototype:
SC_HANDLE OpenSCManager(
LPCTSTR lpMachineName,
LPCTSTR lpDatabaseName,
DWORD dwDesiredAccess
);
C# equiv:
[DllImport("advapi32.dll")]
public static extern IntPtr OpenSCManager(
string lpMachineName,
string lpDatabaseName,
SvcCtrlManagerPrivilegeFlags dwDesiredAccess
);
Also, you'll want to have the right access parameters. From WinSvc.h:
#define SC_MANAGER_CONNECT 0x0001
#define SC_MANAGER_CREATE_SERVICE 0x0002
#define SC_MANAGER_ENUMERATE_SERVICE 0x0004
#define SC_MANAGER_LOCK 0x0008
#define SC_MANAGER_QUERY_LOCK_STATUS 0x0010
#define SC_MANAGER_MODIFY_BOOT_CONFIG 0x0020
C#:
[Flags]
public enum SvcCtrlManagerPrivilegeFlags
{
SC_MANAGER_CONNECT = 0x0001
SC_MANAGER_CREATE_SERVICE = 0x0002
SC_MANAGER_ENUMERATE_SERVICE = 0x0004
SC_MANAGER_LOCK = 0x0008
SC_MANAGER_QUERY_LOCK_STATUS = 0x0010
SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020
}
Then you want to start the service. C prototype:
BOOL StartService(
SC_HANDLE hService,
DWORD dwNumServiceArgs,
LPCTSTR* lpServiceArgVectors
);
C# equivalent:
[DllImport("advapi32.dll")]
public static extern bool StartService(
IntPtr hService,
int dwNumServiceArgs,
[MarshalAs(UnmanagedType.LPArray)] string[] lpServiceArgVectors
);
So in total, with the above declarations, you'd want to do:
IntPtr hSCM = OpenSCManager(null, null, SvcCtrlManagerPrivilegeFlags.SC_MANAGER_CREATE_SERVICE);
IntPtr hSvc = CreateService(hSCM, "My Service", "My Service", AccessRightFlags.SERVICE_ALL_ACCESS, ServiceTypes.SERVICE_KERNEL_DRIVER, StartTypes.SERVICE_BOOT_START, ErrorControlTypes.SERVICE_ERROR_NORMAL, "mySvc.exe", out myTags, null, null, null);
bool done = StartService(hSvc, 0, null);
Code is untested and uncompiled, but should generally work as-is.
Constants are declared in WinSvc.h. If you need it, PM me.