I need to remotely collect the data about installed software on a device from these 2 locations:
HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\
HKLM:\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\
For that I am using WMI class StdRegProv
.
Application which collects the data needs to be 32-bit.
The problem is that I recive only the data from Wow6432Node
and it is doubled. E.g. If there are 3 records in 64-bit part and 5 records in 32-bit part I will receive 10 records (5 unique) in total.
How can I stop WMI from doing the redirection?
VB not C# but this worked for me and is coded to work whether your app is running as a 32 bit process or as a 64 bit process. The magic bit is the IF statement around line 8 - IntPtr.Size will only be 4 if your process is a 32 bit process.
Public Function GetSettingEx(PredefinedKey As PredefinedKeyEnum, Section As String, Key As String, Default_Renamed As String, sComputerName As String, Optional b64Bit As Boolean = False) As String
Try
Dim options As New ConnectionOptions()
options.Impersonation = ImpersonationLevel.Impersonate
Dim scope As New ManagementScope("\\" & sComputerName & "\root\default", options)
If IntPtr.Size = 4 Then
scope.Options.Context.Add("__ProviderArchitecture", 64)
scope.Options.Context.Add("__RequiredArchitecture", True)
End If
scope.Connect()
Dim regclass As New ManagementClass(scope, New ManagementPath("StdRegProv"), Nothing)
Dim hDefKey As UInteger = MapPredefinedKeyToWMI(PredefinedKey)
Dim methodParams As ManagementBaseObject = regclass.GetMethodParameters("EnumValues")
methodParams("hDefKey") = hDefKey
methodParams("sSubKeyName") = Section
Dim outParams As ManagementBaseObject = regclass.InvokeMethod("EnumValues", methodParams, Nothing)
If CUInt(outParams("ReturnValue")) = 0 Then
Dim valueNames As String() = DirectCast(outParams.Properties("sNames").Value, String())
Dim valueTypes As Integer() = DirectCast(outParams.Properties("Types").Value, Integer())
If valueNames Is Nothing Then
Return ""
End If
For i As Integer = 0 To valueNames.Length - 1
Dim name As String = valueNames(i)
If name = Key Then
Dim regtype As RegistryTypes = CType(valueTypes(i), RegistryTypes)
Select Case regtype
Case RegistryTypes.REG_SZ, RegistryTypes.REG_EXPAND_SZ
Dim methodParamssz As ManagementBaseObject = regclass.GetMethodParameters("GetStringValue")
methodParamssz("hDefKey") = hDefKey
methodParamssz("sSubKeyName") = Section
methodParamssz("sValueName") = Key
Dim outParamssz As ManagementBaseObject = regclass.InvokeMethod("GetStringValue", methodParamssz, Nothing)
Dim value As Object = outParamssz.Properties("sValue").Value
Return CStr(value)
Case RegistryTypes.REG_MULTI_SZ
Dim methodParamssz As ManagementBaseObject = regclass.GetMethodParameters("GetMultiStringValue")
methodParamssz("hDefKey") = hDefKey
methodParamssz("sSubKeyName") = Section
methodParamssz("sValueName") = Key
Dim outParamssz As ManagementBaseObject = regclass.InvokeMethod("GetMultiStringValue", methodParamssz, Nothing)
Dim value As Object = outParamssz.Properties("sValue").Value
Return String.Join(",", DirectCast(value, String()))
Case RegistryTypes.REG_DWORD
Dim methodParamsdword As ManagementBaseObject = regclass.GetMethodParameters("GetDWORDValue")
methodParamsdword("hDefKey") = hDefKey
methodParamsdword("sSubKeyName") = Section
methodParamsdword("sValueName") = Key
Dim outParamsdword As ManagementBaseObject = regclass.InvokeMethod("GetDWORDValue", methodParamsdword, Nothing)
Dim value As Object = outParamsdword.Properties("uValue").Value
Return CStr(value)
Case RegistryTypes.REG_QWORD
Dim methodParamsqword As ManagementBaseObject = regclass.GetMethodParameters("GetQWORDValue")
methodParamsqword("hDefKey") = hDefKey
methodParamsqword("sSubKeyName") = Section
methodParamsqword("sValueName") = Key
Dim outParamsqword As ManagementBaseObject = regclass.InvokeMethod("GetQWORDValue", methodParamsqword, Nothing)
Dim value As Object = outParamsqword.Properties("uValue").Value
Return CStr(value)
Case RegistryTypes.REG_BINARY
Dim methodParamsbinary As ManagementBaseObject = regclass.GetMethodParameters("GetBinaryValue")
methodParamsbinary("hDefKey") = hDefKey
methodParamsbinary("sSubKeyName") = Section
methodParamsbinary("sValueName") = Key
Dim outParamsbinary As ManagementBaseObject = regclass.InvokeMethod("GetBinaryValue", methodParamsbinary, Nothing)
Dim value As Object = outParamsbinary.Properties("uValue").Value
Return BitConverter.ToString(DirectCast(value, Byte()))
Case Else
Throw New Exception("Unknown registry type : " & regtype.ToString)
End Select
End If
Next
End If
Return Default_Renamed
Catch ex As Exception
Return Default_Renamed
End Try
End Function
Public Enum PredefinedKeyEnum
HKEY_CLASSES_ROOT = &H80000000
HKEY_CURRENT_USER = &H80000001
HKEY_LOCAL_MACHINE = &H80000002
HKEY_USERS = &H80000003
HKEY_PERFORMANCE_DATA = &H80000004
HKEY_CURRENT_CONFIG = &H80000005
HKEY_DYN_DATA = &H80000006
End Enum
Private Function MapPredefinedKeyToWMI(PredefinedKey As PredefinedKeyEnum) As UInteger
Dim ret As UInteger
Select Case PredefinedKey
Case PredefinedKeyEnum.HKEY_CLASSES_ROOT
ret = 2147483648 ' &H80000000
Case PredefinedKeyEnum.HKEY_CURRENT_USER
ret = 2147483649 ' &H80000001
Case PredefinedKeyEnum.HKEY_LOCAL_MACHINE
ret = 2147483650 ' &H80000002
Case PredefinedKeyEnum.HKEY_USERS
ret = 2147483651 ' &H80000003
Case PredefinedKeyEnum.HKEY_PERFORMANCE_DATA
ret = 2147483652 ' &H80000004
Case PredefinedKeyEnum.HKEY_CURRENT_CONFIG
ret = 2147483653 ' &H80000005
Case PredefinedKeyEnum.HKEY_DYN_DATA
ret = 2147483654 ' &H80000006
Case Else
Throw New ArgumentException("Invalid predefinedKey")
End Select
Return ret
End Function