I'm trying to collect some registry values from remote server using StdRegProv class:
Invoke-Command -ComputerName $ComputerHost -Credential $cred -ScriptBlock { Get-WmiObject -List -Namespace "root\default" | Where-Object { $_.Name -eq "StdRegProv" } }
But it doesnt return methods for these class in output:
NameSpace: ROOT\default
Name Methods Properties PSComputerName
---- ------- ---------- --------------
StdRegProv
If i execute the command from ScriptBlock in machine locally, all works fine and output looks like these:
NameSpace: ROOT\default
Name Methods Properties
---- ------- ----------
StdRegProv {CreateKey, Delet... {}
Some of other commands, like Get-Service, works ok and i can see the output. What is the problem with these one? Remote machine is: Windows Server 2003 with installed .Net 3.5.1 and PowerShell 2.0
I thought, that StdRegProv class doesnt work in 2003 server, but it works ok locally
As an aside:
The CIM cmdlets (e.g., Get-CimInstance
) superseded the WMI cmdlets (e.g., Get-WmiObject
) in Windows PowerShell v3 (released in September 2012). Therefore, the WMI cmdlets should be avoided, not least because PowerShell (Core) 7+, the modern cross-platform success to Windows PowerShell where all future effort will go, doesn't even have them anymore. Note that WMI still underlies the CIM cmdlets, however. For more information, see this answer; the bottom section below shows a CIM solution.
Since you're running the - long obsolete - Windows PowerShell v2, the CIM cmdlets are not an option.
You're calling Get-WmiObject
via PowerShell remoting (Invoke-Command -ComputerName
), which for all but a handful of well-known types involves a loss of type fidelity:
[psobject]
instances that have a static copy of all the (public) properties of the original object - see this answer for details.This explains why the result object is lacking methods.
You have two options:
Either: Call any methods in the remotely executing script block, where the Get-WmiObject
output object still has all its original identity.
For instance, the following command calls the .GetStringValue
method to retrieve the data stored in the Path
value of registry key HKEY_LOCAL_MACHINE\SOFTWARE\DefaultUserEnvironment
on the remote machine:
Invoke-Command -ComputerName $ComputerHost -Credential $cred -ScriptBlock {
(Get-WmiObject -List StdRegProv).GetStringValue(2147483650, 'SOFTWARE\DefaultUserEnvironment', 'Path')
}
Or: Use the remoting provided by the WMI cmdlets, in which case there is no loss of type fidelity; however, note that they use a different remoting infrastructure than PowerShell, namely an obsolete DCOM-based one, and may therefore need separate configuration; however, as per your feedback, KB5004442 on caller machines actively prevents use of this infrastructure when targeting machines running older Windows versions.
# You can call methods such as `.GetStringValue()` directly
# on the output object.
(
Get-WmiObject -ComputerName $ComputerHost -Credential $cred -List StdRegProv
).GetStringValue(2147483650, 'SOFTWARE\DefaultUserEnvironment', 'Path')
CIM solution (PowerShell v3+)
For the sake of completeness, here is the equivalent solution based on the CIM cmdlets:
$regProv = Get-CimClass StdRegProv -CimSession (New-CimSession -ComputerName $ComputerHost -Credential $cred)
$regProv | Invoke-CimMethod -MethodName GetStringValue -Arguments @{ hDefKey = [Uint32] 2147483650; sSubKeyName = 'SOFTWARE\DefaultUserEnvironment'; sValueName = 'Path' }
However, you can use just an Invoke-CimMethod
call in this case and specify the target class via the -ClassName
parameter:
Invoke-CimMethod -ClassName StdRegProv -MethodName GetStringValue -Arguments @{ hDefKey = [Uint32] 2147483650; sSubKeyName = 'SOFTWARE\DefaultUserEnvironment'; sValueName = 'Path' }
The CIM cmdlets' remoting uses the same infrastructure as PowerShell's remoting.
While there is no loss in type fidelity, note that instances returned by CIM cmdlets do not have .NET methods that you can call directly; instead, CIM methods must be called via the Invoke-CimMethod
cmdlet, as shown above.
Arguments must be passed via the -Arguments
parameter, which requires a hashtable (dictionary) of parameter name-value pairs.
The parameter names can be gleaned from the .Parameters
property of the .CimClassMethods
property available on CIM class instances as returned by Get-CimClass
; for CIM instances, as returned by Get-CimInstance
, use .CimClass.CimClassMethods
; e.g.:
(Get-CimClass StdRegProv).CimClassMethods |
Where Name -eq GetStringValue |
ForEach Parameters
This yields the following display output (note that the out
-qualified parameter is the output value, returned as part of the result object - see below):
Name CimType Qualifiers ReferenceClassName
---- ------- ---------- ------------------
hDefKey UInt32 {ID, IN}
sSubKeyName String {ID, IN}
sValueName String {ID, in}
sValue String {ID, out}
Unfortunately, the parameter information does not indicate optional parameters or their default values; e.g., in the case of GetStringValue()
, the hDefKey
parameter is optional and defaults to HKEY_LOCAL_MACHINE (2147483650
)
Caveat:
[UInt32]
cast for the hDefKey
parameter above.Results are reported as [pscustomobject]
instances[1] with the following properties:
.ReturnValue
... the success status of the call; 0
indicates success..PSComputerName
... the name of the remote computer (if any) from which the result originates.<outParameterName>
... the variably named property corresponding to the method's out
parameter name, such as .sValue
in the call above.[1] These instances have an ETS (Extended Type System) type name that reflects the class and method that was invoked, e.g. Microsoft.Management.Infrastructure.CimMethodResult#StdRegProv#GetStringValue
, such as reported by Get-Member
.