ServiceController class startup type

  • Thread starter Thread starter Vinay
  • Start date Start date
V

Vinay

HI,
I am writing a utility which will list all the services
running on system like services.msc program. Now I want
to display the Startup type of service like
manual/automation.

How can I get that property? I just want to read that
property, and do not want to create new one.

TIA,
Vinay
 
Vinay,

You can get service information through the QueryServiceConfig API
function. You can call this through the P/Invoke layer and it should give
you all the information that you need about the service.

Hope this helps.
 
hi Vinay,
I'm not sure if there's a .net function for what you need, but i know
for some information about services, you need to resort to win32 calls,
so you might find this helpful. be aware that it was my first time
getting down and dirty with marshalling in c#, but it seems to work fine
for me (except for TagID. i wasn't really sure what it does, so don't
rely on it's value).
HI,
I am writing a utility which will list all the services
running on system like services.msc program. Now I want
to display the Startup type of service like
manual/automation.

How can I get that property? I just want to read that
property, and do not want to create new one.

TIA,
Vinay


public namespace Services
{
/// <summary>
/// Some wrappers around Win32 calls dealing with services.
/// </summary>
public class ServiceConfigurator
{
[StructLayout(LayoutKind.Sequential)]
private struct QueryServiceConfigStruct
{
public int serviceType;
public int startType;
public int errorControl;
public IntPtr binaryPathName;
public IntPtr loadOrderGroup;
public int tagID;
public IntPtr dependencies;
public IntPtr startName;
public IntPtr displayName;
}

public struct ServiceInfo
{
public int serviceType;
public int startType;
public int errorControl;
public string binaryPathName;
public string loadOrderGroup;
public int tagID;
public string dependencies;
public string startName;
public string displayName;
}

#region constants
private enum SCManagerAccess :int
{
GENERIC_ALL = 0x10000000
}
private enum ServiceAccess :int
{
QUERY_CONFIG = 0x1,
CHANGE_CONFIG = 0x2,
}
private const int SERVICE_NO_CHANGE = 0xFFFF;
#endregion

#region DllImports
[DllImport("advapi32.dll",
SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr OpenSCManager(
[MarshalAs(UnmanagedType.LPTStr)]
string machineName,
[MarshalAs(UnmanagedType.LPTStr)]
string databaseName,
int desiredAccess);

[DllImport("advapi32.dll",
SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr OpenService(
IntPtr scManager,
[MarshalAs(UnmanagedType.LPTStr)]
string serviceName,
int desiredAccess);

[DllImport("advapi32.dll",
SetLastError = true, CharSet = CharSet.Auto)]
private static extern int ChangeServiceConfig(
IntPtr service,
int serviceType,
int startType,
int errorControl,
[MarshalAs(UnmanagedType.LPTStr)]
string binaryPathName,
[MarshalAs(UnmanagedType.LPTStr)]
string loadOrderGroup,
IntPtr tagID,
[MarshalAs(UnmanagedType.LPTStr)]
string dependencies,
[MarshalAs(UnmanagedType.LPTStr)]
string startName,
[MarshalAs(UnmanagedType.LPTStr)]
string password,
[MarshalAs(UnmanagedType.LPTStr)]
string displayName);

[DllImport("advapi32.dll",
SetLastError = true, CharSet = CharSet.Auto)]
private static extern int QueryServiceConfig(
IntPtr service,
IntPtr queryServiceConfig,
int bufferSize,
ref int bytesNeeded);


#endregion

public static ServiceInfo GetServiceInfo(string ServiceName)
{
if (ServiceName.Equals(""))
throw new NullReferenceException(
"ServiceName must contain a valid service name.");
IntPtr scManager = OpenSCManager(".", null,
(int)SCManagerAccess.GENERIC_ALL);
if (scManager.ToInt32() <= 0)
throw new Win32Exception();

IntPtr service = OpenService(scManager,
ServiceName, (int) ServiceAccess.QUERY_CONFIG);
if (service.ToInt32() <= 0)
throw new NullReferenceException();

int bytesNeeded = 5;
QueryServiceConfigStruct qscs = new QueryServiceConfigStruct();
IntPtr qscPtr = Marshal.AllocCoTaskMem(0);

int retCode = QueryServiceConfig(service, qscPtr,
0, ref bytesNeeded);
if (retCode == 0 && bytesNeeded == 0)
{
throw new Win32Exception();
}
else
{
qscPtr = Marshal.AllocCoTaskMem(bytesNeeded);
retCode = QueryServiceConfig(service, qscPtr,
bytesNeeded, ref bytesNeeded);
if (retCode == 0)
{
throw new Win32Exception();
}
qscs.binaryPathName = IntPtr.Zero;
qscs.dependencies = IntPtr.Zero;
qscs.displayName = IntPtr.Zero;
qscs.loadOrderGroup = IntPtr.Zero;
qscs.startName = IntPtr.Zero;

qscs = (QueryServiceConfigStruct)
Marshal.PtrToStructure(qscPtr,
new QueryServiceConfigStruct().GetType());
}

ServiceInfo serviceInfo = new ServiceInfo();
serviceInfo.binaryPathName =
Marshal.PtrToStringAuto(qscs.binaryPathName);
serviceInfo.dependencies =
Marshal.PtrToStringAuto(qscs.dependencies);
serviceInfo.displayName =
Marshal.PtrToStringAuto(qscs.displayName);
serviceInfo.loadOrderGroup =
Marshal.PtrToStringAuto(qscs.loadOrderGroup);
serviceInfo.startName =
Marshal.PtrToStringAuto(qscs.startName);

serviceInfo.errorControl = qscs.errorControl;
serviceInfo.serviceType = qscs.serviceType;
serviceInfo.startType = qscs.startType;
serviceInfo.tagID = qscs.tagID;

Marshal.FreeCoTaskMem(qscPtr);
return serviceInfo;
}

public static void ChangeAccount(string ServiceName,
string Username, string Password)
{
ServiceInfo serviceInfo = GetServiceInfo(ServiceName);

IntPtr scManager = OpenSCManager(".", null,
(int)SCManagerAccess.GENERIC_ALL);
if (scManager.ToInt32() <= 0)
throw new Win32Exception();

IntPtr service = OpenService(scManager,
ServiceName, (int)ServiceAccess.CHANGE_CONFIG);
if (service.ToInt32() <= 0)
throw new Win32Exception();

if (ChangeServiceConfig(service, serviceInfo.serviceType,
serviceInfo.startType, serviceInfo.errorControl,
serviceInfo.binaryPathName, serviceInfo.loadOrderGroup,
IntPtr.Zero, serviceInfo.dependencies,
Username, Password, serviceInfo.displayName) == 0)
{
throw new Win32Exception();
}
}

}
}
 
-----Original Message-----
Vinay,

You can get service information through the QueryServiceConfig API
function. You can call this through the P/Invoke layer and it should give
you all the information that you need about the service.

Hope this helps.

Nicholas,
Thanks for the help. Do you tell me the protocol of the
imported function in C#?
like bool QueryServiceConfig(int, ??, int, int**)
or you want me to write QUERY_SERVICE_CONFIG structure on
my own?

TIA,
Vinay
 
hi Vinay,

I attached a file to my first post that shows how to use this structure
in c#. if you didn't get it, i can copy and paste.

`ben
 
Back
Top