/\/\o\/\/ PowerShelled

This blog has moved to http://ThePowerShellGuy.com Greetings /\/\o\/\/
$AtomFeed = ("Atom.xml")
$PreviousItems = (" Saving a WMI instance to a XML-file from MSH "," MSH Orphan share remover Tool "," MSH Welcome screen "," Read the raw Monad XML helpfiles "," MSH prompt-User function with Help "," Monad IRC Bot "," Getting performanceMonitor info from Monad "," Monad -and More bytes with -band = shorter script "," Tip from Monad "," MSH AD querying with .NET 2.0 framework "," ")

Wednesday, December 21, 2005

 


Passing (not so) mandatory Parameters to WMI methods in MSH



I do this blogitem about a question in the NG, about setting the name and password of a service, I will show a MSH WMI script for that.

I wanted to start this entry with showing a simpler way from Monad but failed to do it.

first I tryed :
set-service [-ServiceName] System.String [-DisplayName] System.String [[-Description] System.String] [[-StartupType] {...}]

Hmm, no parameter for that.

no, problem I did think just take a method of the service :
MSH>(get-service "Alerter") | gm


TypeName: System.ServiceProcess.ServiceController

Name MemberType Definition
---- ---------- ----------
...
set_DisplayName Method System.Void set_DisplayName(String value)
set_MachineName Method System.Void set_MachineName(String value)
set_ServiceName Method System.Void set_ServiceName(String value)
set_Site Method System.Void set_Site(ISite value)
...

Oops, not there either so this might be a good example for setting the Service account too ;-)
b.t.w. I think I can come up with a .NET way, but it was just an example setting WMI properties anyway, so lets go on.

The question in the NG was about this line in Vbscript, acting on a win32_service instance, it would give back error 21 ( Invalid parameters have been passed to the service) see also GWM output below:
 errServiceChange = objService.Change( , , , , , ,"Domain\User")
errPasswdChange = objService.Change( , , , , , , ,"Passwd")
wscript.echo(errServiceChange &":"& errPasswdChange)

I first recommended hem to set them on one line

errServiceChange = objService.Change( , , , , , ,"Domain\User","Passwd")

but that did not seem to help (strange as it did work when I tested it in a Vbscipt after the MSH check I will describe) but this got me started in MSH

First I took my Monad WMI Method Help script WMI help Part 3 (Methods) that also creates Sample Scripts to make a script :
(use the link to get the updated version in a later post, that is the one used here)
The command Get-WmiMethodHelp (GWM) will produce the following output :
(b.t.w. it's a lot of output, but I will explain it below also it's not good pastable but I will post a paste-able script below also)
MSH>get-wmimethodHelp
No WMIClass given
MSH>gwm win32_service change
win32_service : change :


The Change method modifies a service. The Win32_LoadOrderGroup parameter represents a grouping of system services defining execution depend
encies. The services must be initiated in the order specified by the Load Order Group as the services are dependent on each other. These de
pendent services require the presence of the antecedent services in order to function correctly.It returns one of the following integer val
ues:
0 - The request was accepted.
1 - The request is not supported.
2 - The user did not have the necessary access.
3 - The service cannot be stopped because other services that are running are dependent on it.
4 - The requested control code is not valid, or it is unacceptable to the service.
5 - The requested control code cannot be sent to the service because the state of the service (Win32_BaseService:State) is equal to 0, 1, o
r 2.
6 - The service has not been started.
7 - The service did not respond to the start request in a timely fashion.
8 - Unknown failure when starting the service.
9 - The directory path to the service executable was not found.
10 - The service is already running.
11 - The database to add a new service is locked.
12 - A dependency for which this service relies on has been removed from the system.
13 - The service failed to find the service needed from a dependent service.
14 - The service has been disabled from the system.
15 - The service does not have the correct authentication to run on the system.
16 - This service is being removed from the system.
17 - There is no execution thread for the service.
18 - There are circular dependencies when starting the service.
19 - There is a service running under the same name.
20 - There are invalid characters in the name of the service.
21 - Invalid parameters have been passed to the service.
22 - The account, which this service is to run under is either invalid or lacks the permissions to run the service.
23 - The service exists in the database of services available from the system.
24 - The service is currently paused in the system.
Other - For integer values other than those listed above, refer to Win32 error code documentation.


change Parameters :


Name = DesktopInteract
Type = boolean
Optional = False


Name = DisplayName
Type = string
Optional = False


Name = ErrorControl
Type = uint8
Optional = False


Name = LoadOrderGroup
Type = string
Optional = False


Name = LoadOrderGroupDependencies
Type = string
Optional = False


Name = PathName
Type = string
Optional = False


Name = ServiceDependencies
Type = string
Optional = False


Name = ServiceType
Type = uint8
Optional = False


Name = StartMode
Type = string
Optional = False


Name = StartName
Type = string
Optional = False


Name = StartPassword
Type = string
Optional = False


Sample Script :


# win32_service change-Method Sample Script
# Created by Get-WmiMethodHelp
# /\/\o\/\/ 2005
# Fill InParams values before Executing
# InParams that are Remarked (#) are Optional


$Class = "win32_service"
$Method = "change"
$Computer = "."


#win32_service Key Properties :
$Name = [string]


$filter = "Name = '$Name'"
$MC = get-WMIObject $class -computer $Computer -filter $filter


$InParams = $mc.GetMethodParameters($Method)


$InParams["DesktopInteract"] = [boolean]
$InParams["DisplayName"] = [string]
$InParams["ErrorControl"] = [uint8]
$InParams["LoadOrderGroup"] = [string]
$InParams["LoadOrderGroupDependencies"] = [string]
$InParams["PathName"] = [string]
$InParams["ServiceDependencies"] = [string]
$InParams["ServiceType"] = [uint8]
$InParams["StartMode"] = [string]
$InParams["StartName"] = [string]
$InParams["StartPassword"] = [string]


"Calling win32_service : change with Parameters :"
$inparams.get_properties() | select name,Value


$R = $mc.InvokeMethod($Method, $inParams, $Null)
"Result : "
$R


MSH>

First You see that after a short description, all the return values are listed, very handy later on ;-)

after that all the Parameters of the Change Method, note that they are all mandatory.
(I will explain why later on)

and the generated script, I pasted that in notepad, and started to fill in.

First as this Method works agains an instance I needed to provide the Key properties of the service I want to change, in this case the name (GWM did lookup that) I provided Alerter for this test:
#win32_service Key Properties :
$Name = [string]"Alerter"


than I need to fill the Properties, as get-WmiMethodHelp also did look them up for me, also you can see that it did look up the type of variable WMI expects for that property, you can fill in the value after them.

Now you see something interesting, the script does say that all Properties are Mandatory so We have to provide them, but as we see the Vbscript version (also the working) leaves them empty

the working VB example, I wrote later :
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Set SWBemlocator = CreateObject("WbemScripting.SWbemLocator")
Set objWMIService = SWBemlocator.ConnectServer(strComputer,"\root\CIMV2")
Set colItems = objWMIService.ExecQuery("Select * from Win32_Service where Name = 'Alerter'",,48)

For each objService in colItems
errServiceChange = objService.Change( , , , , , ,".\mow","test")
next

wscript.echo(errServiceChange )

as explained a bit already in the GWM post, there is something weird about the WMI Optional Qualifier, as explained in that post a Qualifier is mandatory if the Optional Qualifier is NOT found, and now we see that the are not Mandatory ?

At First it may look that way, but you might have noticed that the Vbscript version did contain a lot of comma's before the startname and Password value.
these are not realy empty Vbscript fills them with Null values !

so what is the case here is that the Values ARE mandatory, but that they CAN be $null, that mean's do not change them.
that what is happening in the Vbscript version.

So if We change Only This lines,
$InParams["StartName"] = [string]".\mow"
$InParams["StartPassword"] = [string]"test"

We get an 21 Error also, but if you look in the output you might already See what is going wrong, as the script contains [string] as an helper already it fill's the parameter with an empty string.

but if we cange all other parameters to $null, like this :
$InParams["DesktopInteract"] = $null
etc.

the sample script will work.
but the good news is the $InParams standard fills the properties with $null,
so we can just leave out those lines.

so the final script will look like this :

$Class = "win32_service"
$Method = "change"
$Computer = "."


#win32_service Key Properties :
$Name = [string]"Alerter"


$filter = "Name = '$Name'"
$MC = get-WMIObject $class -computer $Computer -filter $filter


$InParams = $mc.GetMethodParameters($Method)

$InParams["StartName"] = [string]".\mow"
$InParams["StartPassword"] = [string]"test"


"Calling win32_service : change with Parameters :"
$inparams.get_properties() | select name,Value


$R = $mc.InvokeMethod($Method, $inParams, $Null)
"Result : "
$R


So you see the mandatory Properties in WMI are not alway's so mandatory as they seem
sometimes (as in this case) this could be a bit confusing (have to set to $null or delete the lines in the generated script), but there is no way for the get-WmiMethodHelp script to see this, even with extendedQualifiers (for more info, see WMI help serie), sometimes this $null behavour is mentioned in the Embedded help in the WMI class, shown by Get-WmiMethodHelp but as you see in this example not always.

but as you can see now, we are still a lot better of as in the Vbscript example as we also have to look up the order and the number of properties in the SDK there :

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/change_method_in_class_win32_service.asp

so as you can see this behavour of WMI is a bit confusing but I think that the $null is handled in the Provider so WMI also does not know, only I should think this should be in the MOF help, (you can b.t.w. always add it to the MOF is you want) but as also explained before the help in the MOF's is not alway's as good as we would want.

hope I could explain this behavour a bit in this (very Long) post,
and hope you don't see this as a bug in get-WmiMethodHelp as it say's optional properties should be Commented out ;-)

gr /\/\o\/\/


Comments: Post a Comment



<< Home

Archives

October 2005   November 2005   December 2005   January 2006   February 2006   March 2006   April 2006   May 2006   June 2006   July 2006   August 2006   September 2006   October 2006   November 2006   December 2006  

$Links = ("PowerShell RC1 Docs"," PowerShell RC1 X86"," PowerShell RC1 X64"," Monad GettingStarted guide"," Monad Progamming Guide"," Monad SDK"," Monad videos on Channel 9"," MSH Community Workspace"," scripts.readify.net "," MonadSource"," www.reskit.net"," PowerShell Blog"," Under The Stairs"," computerperformance powershell Home"," proudlyserving"," MSH on wikipedia"," MSHWiki Channel 9"," Keith Hill's Blog"," Precision Computing"," PowerShell for fun"," MSH Memo (Japanese)"," monadblog")

find-blog -about "PowerShell","Monad" | out-Technorati.
find-blog -contains "","" | out-Technorati.
Google
 
Web mow001.blogspot.com

This page is powered by Blogger. Isn't yours?