Win32_Service System.InvalidCastException

G

Guest

i trying to collect windows services. i'm getting inconsistencies.

the collection works every time locally. but remote collection yields
different result depending on my lab environment.

1) in the same domain i start the collection on the remote machine
i can get some 19 services without a problem then it will fail with:

'wmiService.ClassPath' threw an exception of type
'System.InvalidCastException'
System.Management.ManagementPath {System.InvalidCastException}

here is more data:…
System.Management.ManagementException was unhandled
Message="Not found "
Source="System.Management"
StackTrace:
at
System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus
errorCode)
at System.Management.ManagementObject.Get()

yet it was successful some 19 times before.

2) when i try this over 2 domain and pass the options with all the logon
rights it will fail on the first collection.

i found an MSDN code sample that is what i want to do.
1) i get call "ServiceController"
2)i call a "Win32_Service"

i don't understand why the exception. i don't know how
to get away from it. when it dies it dies at
"wimService.Get()"

public string[] getXprServices(bool oRunning)
{
string strmachine = "MYREMOTEMACHINE";
ConnectionOptions options = new ConnectionOptions();

ServiceController[] xprServices;
xprServices = ServiceController.GetServices(strmachine);
string[,] aServices = new string[xprServices.Length + 1, 5];
int iElement = 1; //the service number incrementor
aServices[0, 0] = "Service Name";
aServices[0, 1] = "Display Name";
aServices[0, 2] = "Status";
aServices[0, 3] = "Log on As";
aServices[0, 4] = "# of Dependencies";
foreach (ServiceController sServices in xprServices)
{
aServices[iElement, 0] = sServices.ServiceName;
aServices[iElement, 1] = sServices.DisplayName;
aServices[iElement, 2] = sServices.Status.ToString();

ManagementScope scope = new ManagementScope("\\\\" + strmachine
+ "\\root\\cimv2");
ManagementObject wmiService;
wmiService = new ManagementObject("Win32_Service.Name='" +
sServices.ServiceName + "'");
wmiService.Get();
aServices[iElement, 3] = wmiService["StartName"].ToString();
aServices[iElement, 4] =
sServices.ServicesDependedOn.Length.ToString();

}
iElement++;
}//foreach(ServiceController sServices in xprServices)
return (saServices);
}
 
W

Willy Denoyette [MVP]

auldh said:
i trying to collect windows services. i'm getting inconsistencies.

the collection works every time locally. but remote collection yields
different result depending on my lab environment.

1) in the same domain i start the collection on the remote machine
i can get some 19 services without a problem then it will fail with:

'wmiService.ClassPath' threw an exception of type
'System.InvalidCastException'
System.Management.ManagementPath {System.InvalidCastException}

here is more data:…
System.Management.ManagementException was unhandled
Message="Not found "
Source="System.Management"
StackTrace:
at
System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus
errorCode)
at System.Management.ManagementObject.Get()

yet it was successful some 19 times before.

2) when i try this over 2 domain and pass the options with all the logon
rights it will fail on the first collection.

i found an MSDN code sample that is what i want to do.
1) i get call "ServiceController"
2)i call a "Win32_Service"

i don't understand why the exception. i don't know how
to get away from it. when it dies it dies at
"wimService.Get()"

public string[] getXprServices(bool oRunning)
{
string strmachine = "MYREMOTEMACHINE";
ConnectionOptions options = new ConnectionOptions();

ServiceController[] xprServices;
xprServices = ServiceController.GetServices(strmachine);
string[,] aServices = new string[xprServices.Length + 1, 5];
int iElement = 1; //the service number incrementor
aServices[0, 0] = "Service Name";
aServices[0, 1] = "Display Name";
aServices[0, 2] = "Status";
aServices[0, 3] = "Log on As";
aServices[0, 4] = "# of Dependencies";
foreach (ServiceController sServices in xprServices)
{
aServices[iElement, 0] = sServices.ServiceName;
aServices[iElement, 1] = sServices.DisplayName;
aServices[iElement, 2] = sServices.Status.ToString();

ManagementScope scope = new ManagementScope("\\\\" + strmachine
+ "\\root\\cimv2");
ManagementObject wmiService;
wmiService = new ManagementObject("Win32_Service.Name='" +
sServices.ServiceName + "'");
wmiService.Get();
aServices[iElement, 3] = wmiService["StartName"].ToString();
aServices[iElement, 4] =
sServices.ServicesDependedOn.Length.ToString();

}
iElement++;
}//foreach(ServiceController sServices in xprServices)
return (saServices);
}



Why mixing ServiceControler and System.Management classes, you should only user
System.Management for all.
Another remark is that you should definitely dispose your ManagementObject unmanaged
resources when done with it.
As for your exception Not Found means that no such class exists in the WMI namespace.

Willy.
 
G

Guest

Willy,
it seems that "Win32_Service" does not have anything equal to the
"ServiceDependedOn" which is an added bonus.

plus "ServiceController" does not have away to get to the
"StartName".

this is why the mix case.

i tried the "disposed" after the collection is done but it did not help.
it made little difference i still get a fail to collect any data in one
environment and failed to get all the objects in the other.



Willy Denoyette said:
auldh said:
i trying to collect windows services. i'm getting inconsistencies.

the collection works every time locally. but remote collection yields
different result depending on my lab environment.

1) in the same domain i start the collection on the remote machine
i can get some 19 services without a problem then it will fail with:

'wmiService.ClassPath' threw an exception of type
'System.InvalidCastException'
System.Management.ManagementPath {System.InvalidCastException}

here is more data:…
System.Management.ManagementException was unhandled
Message="Not found "
Source="System.Management"
StackTrace:
at
System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus
errorCode)
at System.Management.ManagementObject.Get()

yet it was successful some 19 times before.

2) when i try this over 2 domain and pass the options with all the logon
rights it will fail on the first collection.

i found an MSDN code sample that is what i want to do.
1) i get call "ServiceController"
2)i call a "Win32_Service"

i don't understand why the exception. i don't know how
to get away from it. when it dies it dies at
"wimService.Get()"

public string[] getXprServices(bool oRunning)
{
string strmachine = "MYREMOTEMACHINE";
ConnectionOptions options = new ConnectionOptions();

ServiceController[] xprServices;
xprServices = ServiceController.GetServices(strmachine);
string[,] aServices = new string[xprServices.Length + 1, 5];
int iElement = 1; //the service number incrementor
aServices[0, 0] = "Service Name";
aServices[0, 1] = "Display Name";
aServices[0, 2] = "Status";
aServices[0, 3] = "Log on As";
aServices[0, 4] = "# of Dependencies";
foreach (ServiceController sServices in xprServices)
{
aServices[iElement, 0] = sServices.ServiceName;
aServices[iElement, 1] = sServices.DisplayName;
aServices[iElement, 2] = sServices.Status.ToString();

ManagementScope scope = new ManagementScope("\\\\" + strmachine
+ "\\root\\cimv2");
ManagementObject wmiService;
wmiService = new ManagementObject("Win32_Service.Name='" +
sServices.ServiceName + "'");
wmiService.Get();
aServices[iElement, 3] = wmiService["StartName"].ToString();
aServices[iElement, 4] =
sServices.ServicesDependedOn.Length.ToString();

}
iElement++;
}//foreach(ServiceController sServices in xprServices)
return (saServices);
}



Why mixing ServiceControler and System.Management classes, you should only user
System.Management for all.
Another remark is that you should definitely dispose your ManagementObject unmanaged
resources when done with it.
As for your exception Not Found means that no such class exists in the WMI namespace.

Willy.
 
W

Willy Denoyette [MVP]

auldh said:
Willy,
it seems that "Win32_Service" does not have anything equal to the
"ServiceDependedOn" which is an added bonus.

No bonus at all, Win32_DependentService is the class to use when searching for Service
dependencies, you can also search the dependecies of a Service instance by an "association"
query.
plus "ServiceController" does not have away to get to the
"StartName".

That's why this class is of limitted use, for anything else use WMI, or use the management
tools that come with the system if you aren't fluent in WMI ;-).
One such tool is sc.exe, it allows you to do anything you like with services running locally
and remotely (security constrained of coarse).
I for one never advise to use "ServiceController", it only offers the basics, but lacks a
lot.
this is why the mix case.

i tried the "disposed" after the collection is done but it did not help.

So you removed it, while you shouldn't.

it made little difference i still get a fail to collect any data in one
environment and failed to get all the objects in the other.

Sure, but I don't see any error handling code in what you have posted.
You should also take care that what you are trying is complex, it's not guaranteed to work
all the time, some services are even accessible remotely, nor by WMI nor by anything else,
you have to deal with these exceptions. Also keep in mind that it's resource heavy (both CPU
and Network) and time consuming to query all running processes on a remote system, some
services may refuse to get queried by the SCM at that time... etc.
I don't even see why you want to query all running (or supposedly running) services on
remote boxes, what exactly are you trying to achieve?

Willy.
 
G

Guest

the program being build it a diagnostic tool for our support group.
we need to get a snap shot of what services are running at the time the user
reports a problem. there are much more that is occuring but as i work through
these hurdles i stumble...

i'm trying to automate the data collection so that when we trouble shoot our
application problem we can see everything at that time rather than keep going
back and forth waiting for the next time.

do you know if Win32 can get the dependencies? if so i will do that and not
the Framework call.
 
W

Willy Denoyette [MVP]

auldh said:
the program being build it a diagnostic tool for our support group.
we need to get a snap shot of what services are running at the time the user
reports a problem. there are much more that is occuring but as i work through
these hurdles i stumble...

i'm trying to automate the data collection so that when we trouble shoot our
application problem we can see everything at that time rather than keep going
back and forth waiting for the next time.

do you know if Win32 can get the dependencies? if so i will do that and not
the Framework call.

Sure you can use Win32 API's but then you better use C++ as language, there are way too many
API's to PInvoke, and you need to do deal with a lot of security issues.

Using System.Management is the way to go believe me (uless you are fuet in C++ and Win32),
herewith a complete sample, change it at will.

// C#, error handling to add....
using System;
using System.Management;
namespace Whatever
{
class Program
{
static void Main()
{
ConnectionOptions co = new ConnectionOptions();
co.Authentication = AuthenticationLevel.Default;
co.Username = "Administrator"; // remote administrator account here
co.Password = "ppppppppp"; // his password
co.Impersonation = ImpersonationLevel.Impersonate; // must impersonate
string remoteSystem = "remotePCame";
ManagementScope scope = new ManagementScope(@"\\"+ remoteSystem + @"\root\cimv2", co);
scope.Connect();
SelectQuery query = new SelectQuery("select name, state, status from Win32_Service");
using(ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))
{
foreach (ManagementObject service in searcher.Get()) {
Console.WriteLine("Name: {0} - State: {1} ", service["Name"], service["state"]);
string antecedentObject = String.Format(@"{0}:{1}",
service.Scope.Path.ToString().Replace("\\", "\\\\"),
service.Path.ToString().Replace('"', '\''));
SelectQuery depQry = new SelectQuery("select dependent from Win32_DependentService
where Antecedent =\"" + antecedentObject + "\"");

using(ManagementObjectSearcher depSearch = new ManagementObjectSearcher(scope, depQry))
{
foreach(ManagementObject depService in depSearch.Get())
{
using (ManagementObject dep = new ManagementObject(scope,
new ManagementPath(depService["dependent"].ToString()),
null))
{
Console.WriteLine("\tservice: {0}", dep["Name"]);
}
}
}
}
}
}
}
}

Willy.

PS Don't top post!
 
G

Guest

Willy,
are you saying the C# and Win32 are not possible? C++ maybe better but can
this not be done in C#. i'm not good with C++ or interest in finding ways to
support both
languages in one class.

Willy Denoyette said:
auldh said:
the program being build it a diagnostic tool for our support group.
we need to get a snap shot of what services are running at the time the user
reports a problem. there are much more that is occuring but as i work through
these hurdles i stumble...

i'm trying to automate the data collection so that when we trouble shoot our
application problem we can see everything at that time rather than keep going
back and forth waiting for the next time.

do you know if Win32 can get the dependencies? if so i will do that and not
the Framework call.

Sure you can use Win32 API's but then you better use C++ as language, there are way too many
API's to PInvoke, and you need to do deal with a lot of security issues.

Using System.Management is the way to go believe me (uless you are fuet in C++ and Win32),
herewith a complete sample, change it at will.

// C#, error handling to add....
using System;
using System.Management;
namespace Whatever
{
class Program
{
static void Main()
{
ConnectionOptions co = new ConnectionOptions();
co.Authentication = AuthenticationLevel.Default;
co.Username = "Administrator"; // remote administrator account here
co.Password = "ppppppppp"; // his password
co.Impersonation = ImpersonationLevel.Impersonate; // must impersonate
string remoteSystem = "remotePCame";
ManagementScope scope = new ManagementScope(@"\\"+ remoteSystem + @"\root\cimv2", co);
scope.Connect();
SelectQuery query = new SelectQuery("select name, state, status from Win32_Service");
using(ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))
{
foreach (ManagementObject service in searcher.Get()) {
Console.WriteLine("Name: {0} - State: {1} ", service["Name"], service["state"]);
string antecedentObject = String.Format(@"{0}:{1}",
service.Scope.Path.ToString().Replace("\\", "\\\\"),
service.Path.ToString().Replace('"', '\''));
SelectQuery depQry = new SelectQuery("select dependent from Win32_DependentService
where Antecedent =\"" + antecedentObject + "\"");

using(ManagementObjectSearcher depSearch = new ManagementObjectSearcher(scope, depQry))
{
foreach(ManagementObject depService in depSearch.Get())
{
using (ManagementObject dep = new ManagementObject(scope,
new ManagementPath(depService["dependent"].ToString()),
null))
{
Console.WriteLine("\tservice: {0}", dep["Name"]);
}
}
}
}
}
}
}
}

Willy.

PS Don't top post!
 
W

Willy Denoyette [MVP]

auldh said:
Willy,
are you saying the C# and Win32 are not possible? C++ maybe better but can
this not be done in C#. i'm not good with C++ or interest in finding ways to
support both
languages in one class.

No, I'm not saying it's impossible, I said it's better to use C++ in order to call a lot of
Win32 API's, the API's themselves are not such a problem, the real problem comes from the
number of stucts you need to declare in C#. Anyway the easiest is System.Management and WMI,
did you actually tried the sample?

Willy.
 
G

Guest

wow, that worked. i must have not looked in the right places.
very sweet!.

for my education how did you come to this conclusion?
i thought i looked everywhere. clearly i need to better in internet look up.

thanks Willy.
 
Top