• Welcome to Valhalla Legends Archive.
 

C# - Invoking Win32 API or...

Started by Mephisto, December 23, 2004, 09:08 PM

Previous topic - Next topic

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)

dxoigmn

#1
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.

MyndFyre

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.
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.