I recently came across an issue and a solution for it regarding the use of the StdRegProv which enables us to access the registry via all other languages except Powershell.
Lets take a look at what I'm talking about:
The MOF looks like this:
uint32 EnumKey( [in, optional] uint32 hDefKey = HKEY_LOCAL_MACHINE, [in] string sSubKeyName, [out] string sNames[] );
We call it by creating the HKEY_ value in hex or dec:
Const HKEY_CLASSES_ROOT = &H80000000
or
Const HKEY_CLASSES_ROOT = 2147483648
Dim iret
Dim Names()
Dim sKey
sKey = "clsid"
Set oReg = GetObject("winmgmts:\\.\root\cimv2").Get("StdRegProv")
oReg.EnumKey HKEY_CLASSES_ROOT, sKey, Names
For each Name in Names
wscript.echo Name
Exit For
Next
Works flawlessly.
Now, let's turn this into a powershell script:
$HKEY_CLASSES_ROOT = 2147483648
[System.Int32]$iret
[System.String[]]$Names
[System.String]$sKey
$sKey = "clsid"
$oReg = Get-WmiObject -namespace root\cimv2 -class StdRegProv
$iret = $oReg.EnumKey($HKEY_CLASSES_ROOT, $sKey, $Names)
Foreach($Name in $Names)
{
write-host $Name
break
}
As it turns out, you can't call this as an instance of a class:
You cannot call a method on a null-valued expression.
At C:\Users\Administrator\Desktop\testregcode.ps1:9 char:1
+ $iret = $oReg.EnumKey($HKEY_CLASSES_ROOT, $sKey, $Names)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You need to call it as a class:
$HKEY_CLASSES_ROOT = 2147483648
[System.Int32]$iret
[System.String[]]$Names
[System.String]$sKey
$sKey = "clsid"
$oReg = [WMICLASS]"root\cimv2:StdRegProv"
$iret = $oReg.EnumKey($HKEY_CLASSES_ROOT, $sKey, $Names)
Foreach($Name in $Names)
{
write-host $Name
break
}
But you will still get an error:
Cannot find an overload for "EnumKey" and the argument count: "3".
At C:\Users\Administrator\Desktop\testregcode.ps1:9 char:1
+ $iret = $oReg.EnumKey($HKEY_CLASSES_ROOT, $sKey, $Names)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
Okay, so what is going on here? Well, it turns out that you pass in the correct IN parameters as you normally would and get passed back out a System.Management.ManagementBaseObject.
$HKEY_CLASSES_ROOT = 2147483648
[System.Int32]$iret
[System.String[]]$Names
[System.String]$sKey
[System.Object]$retValues
$sKey = "clsid"
$oReg = [WMICLASS]"root\cimv2:StdRegProv"
$retValues = $oReg.EnumKey($HKEY_CLASSES_ROOT, $sKey)
foreach($prop in $retValues.Properties)
{
$prop.Name
}
This will return:
ReturnValue
sNames
You will see this in examples on the web:
$HKEY_CLASSES_ROOT = 2147483648
[System.Int32]$iret
[System.String[]]$Names
[System.String]$sKey
[System.String[]]$strValues
$sKey = "clsid"
$oReg = [WMICLASS]"root\cimv2:StdRegProv"
$strValues = $oReg.EnumKey($HKEY_CLASSES_ROOT, $sKey).snames
foreach($val in $strValues)
{
write-host $val
}
This will return every subkey in HKEY_CLASSES_ROOT\clsid. With that said, you really need to parse for the return Value as it will tell you whether or not the call was successful or not.
$HKEY_CLASSES_ROOT = 2147483648
[System.Int32]$iret
[System.String[]]$Names
[System.String]$sKey
$OutVal
$sKey = "clsid"
$oReg = [WMICLASS]"root\cimv2:StdRegProv"
$OutVal = $oReg.EnumKey($HKEY_CLASSES_ROOT, $sKey)
if($OutVal.Properties.Item("ReturnValue").Value -eq 0)
{
$sNames = $OutVal.Properties.Item("sNames").Value
foreach($sName in $sNames)
{
write-host $sName
}
}
Here's an example of getting a DWORD value:
$HKEY_LOCAL_MACHINE = 2147483650
[System.Int32]$iret
[System.String[]]$Names
[System.String]$sKey
$OutVal
$sKey = "Software\Microsoft\Windows NT\CurrentVersion"
$oReg = [WMICLASS]"root\cimv2:StdRegProv"
$OutVal = $oReg.GetDWordValue($HKEY_LOCAL_MACHINE, $sKey, "InstallDate")
if($OutVal.Properties.Item("ReturnValue").Value -eq 0)
{
$Value = $OutVal.Properties.Item("uValue").Value
$vs = '{0:x}' -f $Value
$vs = "0x" + $vs + "(" + $Value + ")"
write-host $vs
}
Now, let's do the Reg_Binary:
$HKEY_LOCAL_MACHINE = 2147483650
[System.Int32]$iret
[System.String[]]$Names
[System.String]$sKey
[System.Management.ManagementBaseObject]$OutVal
$sKey = "Software\Microsoft\Windows NT\CurrentVersion"
[System.String]$vs = ""
$oReg = [WMICLASS]"root\cimv2:StdRegProv"
$Name = "DigitalProductId"
$OutVal = $oReg.GetBinaryValue($HKEY_LOCAL_MACHINE, $sKey, $Name)
if($OutVal.Properties.Item("ReturnValue").Value -eq 0)
{
$Value = $OutVal.Properties.Item("uValue").Value
foreach($v in $Value)
{
$vv = '{0:x}' -f $v
if($vv.ToString().Length -eq 1)
{
$vv = "0" + $vv
}
if($vs -ne "")
{
$vs = $vs + ","
}
$vs = $vs + $vv
$vv = ""
}
write-host $vs
}
Now, let's enumerate through Values:
$HKEY_LOCAL_MACHINE = 2147483650
[System.Int32[]]$DataTypes
[System.String[]]$ValueNames
[System.String]$sKey
[System.Management.ManagementBaseObject]$OutVal
$sKey = "SYSTEM\CurrentControlSet\Control\Session Manager"
[System.String]$vs = ""
$oReg = [WMICLASS]"root\cimv2:StdRegProv"
$Name = "DigitalProductId"
$OutVal = $oReg.EnumValues($HKEY_LOCAL_MACHINE, $sKey)
[System.String]$Value
[System.String]$v
[System.String]$vv
$ValueNames = $outVal.Properties.Item("sNames").Value
$DataTypes = $outVal.Properties.Item("Types").Value
for($x=0;$x -lt $DataTypes.GetLength(0); $x++)
{
switch ($DataTypes[$x])
{
1{
$OutVal = $oReg.GetStringValue($HKEY_LOCAL_MACHINE, $sKey, $ValueNames[$x])
if($OutVal.Properties.Item("ReturnValue").Value -eq 0)
{
$Value = $OutVal.Properties.Item("sValue").Value
}
Write-Host $ValueNames[$x] REG_SZ $Value
}
2{
$OutVal = $oReg.GetExpandedStringValue($HKEY_LOCAL_MACHINE, $sKey, $ValueNames[$x])
if($OutVal.Properties.Item("ReturnValue").Value -eq 0)
{
$Value = $OutVal.Properties.Item("sValue").Value
}
Write-Host $ValueNames[$x] REG_EXPAND_SZ $Value
}
3{
$OutVal = $oReg.GetBinaryValue($HKEY_LOCAL_MACHINE, $sKey, $ValueNames[$x])
if($OutVal.Properties.Item("ReturnValue").Value -eq 0)
{
$Value = $OutVal.Properties.Item("uValue").Value
foreach($v in $Value)
{
$vv = '{0:x}' -f $v
if($vv.ToString().Length -eq 1)
{
$vv = "0" + $vv
}
if($vs -ne "")
{
$vs = $vs + ","
}
$vs = $vs + $vv
$vv = ""
}
Write-Host $ValueNames[$x] REG_BINARY $vs
}
}
4{
$vs = ""
$OutVal = $oReg.GetDWordValue($HKEY_LOCAL_MACHINE, $sKey, $ValueNames[$x])
if($OutVal.Properties.Item("ReturnValue").Value -eq 0)
{
$Value = $OutVal.Properties.Item("uValue").Value
foreach($v in $Value)
{
$vv = '{0:x}' -f $v
if($vs -ne "")
{
$vs = $vs + ","
}
$vs = $vs + $vv
$vv = ""
}
Write-Host $ValueNames[$x] REG_DWORD $vs
}
}
7{
$OutVal = $oReg.GetMultiStringValue($HKEY_LOCAL_MACHINE, $sKey, $ValueNames[$x])
if($OutVal.Properties.Item("ReturnValue").Value -eq 0)
{
$Value = $OutVal.Properties.Item("sValue").Value
}
Write-Host $ValueNames[$x] REG_SZ $Value
}
}
}