Valhalla Legends Forums Archive | .NET Platform | C# - Invoking Win32 API or...

AuthorMessageTime
Mephisto
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)
December 24, 2004, 3:08 AM
kamakazie
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.
December 24, 2004, 3:23 AM
Myndfyr
If you wanted to go entirely P/Invoke:

Here is the prototype for CreateService:
[code]
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
);
[/code]

C# import:
[code]
[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
);
[/code]
This is the declaration for the dwAccessRights param:
[code]
#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)
[/code]
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:
[code]
SC_HANDLE OpenSCManager(
  LPCTSTR lpMachineName,
  LPCTSTR lpDatabaseName,
  DWORD dwDesiredAccess
);
[/code]
C# equiv:
[code]
[DllImport("advapi32.dll")]
public static extern IntPtr OpenSCManager(
  string lpMachineName,
  string lpDatabaseName,
  SvcCtrlManagerPrivilegeFlags dwDesiredAccess
);
[/code]
Also, you'll want to have the right access parameters.  From WinSvc.h:
[code]
#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
[/code]
C#:
[code]
[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
}
[/code]
Then you want to start the service.  C prototype:
[code]
BOOL StartService(
  SC_HANDLE hService,
  DWORD dwNumServiceArgs,
  LPCTSTR* lpServiceArgVectors
);
[/code]
C# equivalent:
[code]
[DllImport("advapi32.dll")]
public static extern bool StartService(
  IntPtr hService,
  int dwNumServiceArgs,
  [MarshalAs(UnmanagedType.LPArray)] string[] lpServiceArgVectors
);
[/code]

So in total, with the above declarations, you'd want to do:
[code]
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]

Code is untested and uncompiled, but should generally work as-is.

Constants are declared in WinSvc.h.  If you need it, PM me.
December 24, 2004, 4:00 AM

Search