Jump to content

[Solved] Read installed software on x64 systems via registry


UEZ
 Share

Recommended Posts

I've tried to read the installed software this way because I want to read also remote systems:

#AutoIt3Wrapper_Change2CUI=y
#AutoIt3Wrapper_UseUpx=n
#include <array.au3>
Global $server  =  "localhost"


$objWMIService = ObjGet("winmgmts:{impersonationLevel = impersonate}!\\" & $server & "\root\cimv2")

Software($server)

Func Software($srv) 
    Local $function_name = "Software"
    Local $objReg, $HKLM, $BaseKey, $BaseKey64, $server, $arrSubKeys, $SubKey, $Value, $objRegService
    Local $software, $Key, $SW_DisplayName, $SW_DisplayVersion, $SW_Publisher, $SW_InstallDate, $line, $TimeStamp
    Local $filename_sw = $function_name & "_" & $srv
    Local $filename_error_current = $function_name & "_" & $srv & "_error.log"
    $HKLM = 0x80000002
    $BaseKey = "Software\Microsoft\Windows\CurrentVersion\Uninstall\"
;~  $BaseKey64 = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
    If StringLower(@OSVersion) <> StringLower("WIN_2000") Then
        $objWMILocator = ObjCreate("WbemScripting.SWbemLocator")
        $objRegService = $objWMILocator.ConnectServer($srv, "\root\default", "", "", "", "", 0x80)
        $objReg = $objRegService.Get("StdRegProv")
    Else
        $objReg = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $srv & "\root\default:StdRegProv")
    EndIf

    If IsObj($objReg) Then
        $objReg.EnumKey($HKLM, $BaseKey, $arrSubKeys)
;~      _ArrayDisplay($arrSubKeys)
        For $SubKey In $arrSubKeys
            $SW_DisplayName = ""
            $SW_DisplayVersion = ""
            $SW_Publisher = ""
            $SW_InstallDate = ""
            $Key = $objReg.GetStringValue($HKLM, $BaseKey & $SubKey, "DisplayName", $Value)
            If $Value <> "" Then ConsoleWrite($Value & @CRLF)
        Next
    EndIf
EndFunc   ;==>Software

When I start the script in SciTE via F5 it will display me the installed software under "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" where DisplayName is not empty.

But when I compile and run it in CMD it displays me the keys under "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"!

Test system Windows 7 x64!

Can somebody help?

Thanks,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

You RUN it with x64 and COMPILE with x86. You don't see the problem here yourself?

When you choose compile then check the checkbox that says "Use X64 version of AutoIt3/Aut2Exe".

Edit: Or did you want you want your x86 code to not be redirected? Then read "Running under Windows 64-bit Edition" in the helpfile.

Edit2: By the way, why are you using WMI instead of RegRead?

Edited by AdmiralAlkex
Link to comment
Share on other sites

And what about the path: $BaseKey = "Software\Microsoft\Windows\CurrentVersion\Uninstall\"?

When I compile it in x86 then path is changing in the registry?

Sorry, I've not much experience with x64!

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

You RUN it with x64 and COMPILE with x86. You don't see the problem here yourself?

When you choose compile then check the checkbox that says "Use X64 version of AutoIt3/Aut2Exe".

Edit: Or did you want you want your x86 code to not be redirected? Then read "Running under Windows 64-bit Edition" in the helpfile.

Edit2: By the way, why are you using WMI instead of RegRead?

with the line #AutoIt3Wrapper_UseX64=y it runs as expected!

The reason is that I want to read remotely the installed software of several systems!

I need to figure out what I need to check when running on x32 and try to read the software on x64 via registry keys!

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

There is alot of articles on this subject for anyone interested inm working with the registry under x64 windows. For example: Registry Redirector

Search google for things like registry redirection/reflection and you will find alot of examples and discussions about it.

Remember that you have filesystem redirection too, which work in a similar way (SysWOW64 etc). Microsoft did some really annoying stuff under x64 :D (but they did improve it with Win7!)

Link to comment
Share on other sites

Here is a tip for you

When using Reg*() functions Just Add the 64 to the key anyway. AutoIt handles it internally.

Example

RegRead("HKLM64\Software", "Some value") will work just fine on both 32 and 64 bit systems. That could be a code bug so don't tell Valik or he might decide to fix it.

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

Here my commandline version to read the installed software (for all users only) and without updates from remote systems from the registry via WMI:

;Coded by UEZ 2009
#AutoIt3Wrapper_Change2CUI=y
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_UseX64=n
#include <array.au3>
Global $server  =  "localhost"
If $CmdLine[0] > 0 Then $server = $CmdLine[1]

$objWMIService = ObjGet("winmgmts:{impersonationLevel = impersonate}!\\" & $server & "\root\cimv2")

ConsoleWrite(@CRLF & "Installed software on " & $server & @CRLF & @CRLF)
Software($server)

Func Software($srv) ; registry read version 2
    Local $function_name = "Software"
    Local $objReg, $HKLM, $BaseKey, $BaseKey64, $server, $arrSubKeys, $SubKey, $Value, $objRegService, $chk_nr, $chk_url, $chk_sc
    Local $software, $Key, $key_value, $SW_DisplayName, $SW_DisplayVersion, $SW_Publisher, $SW_InstallDate, $line, $TimeStamp
    Local $filename_sw = $function_name & "_" & $srv
    Local $filename_error_current = $function_name & "_" & $srv & "_error.log"
    $HKLM = 0x80000002
    $BaseKey = "Software\Microsoft\Windows\CurrentVersion\Uninstall\"
    $BaseKey64 = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"
    If @OSArch = "X64" And ($srv = @ComputerName Or _
                             $srv = "localhost" Or _
                             $srv = @IPAddress1 Or _
                             $srv = @IPAddress2 Or _
                             $srv = @IPAddress3 Or _
                             $srv = @IPAddress4) Then
        $i = 1
        While 1
            $key = RegEnumKey("HKEY_LOCAL_MACHINE\" & $BaseKey, $i)
            If @error <> 0 Then ExitLoop
            $key_value = RegRead("HKEY_LOCAL_MACHINE\" & $BaseKey & "\" & $key, "DisplayName")
            $chk_sc = RegRead("HKEY_LOCAL_MACHINE\" & $BaseKey & "\" & $key, "SystemComponent")
            $chk_url = RegRead("HKEY_LOCAL_MACHINE\" & $BaseKey & "\" & $key, "MoreInfoURL")
            $chk_nr = RegRead("HKEY_LOCAL_MACHINE\" & $BaseKey & "\" & $key, "NoRemove")
            If $key_value <> "" And _
                    StringIsASCII($key_value) <> 0 And _
                    $key_value <> "Security Update for" And _
                    $key_value <> "Hotfix for" And _
                    $key_value <> "Update for Office" And _
                    $key_value <> "Windows 2000 Hotfix" And _
                    StringInStr(StringLower($key), StringLower("InstallShield_")) = 0  And _
                    StringInStr(StringLower($chk_url), StringLower("http://support.microsoft.com/kb/")) = 0 And _
                    $chk_nr <> 1 And $chk_sc <> 1 Then
                $SW_DisplayName = StringStripWS($key_value, 7)
                $SW_Publisher = RegRead("HKEY_LOCAL_MACHINE\" & $BaseKey & "\" & $key, "Publisher")
                $SW_InstallDate = RegRead("HKEY_LOCAL_MACHINE\" & $BaseKey & "\" & $key, "InstallDate")
                $SW_DisplayVersion = RegRead("HKEY_LOCAL_MACHINE\" & $BaseKey & "\" & $key, "DisplayVersion")
                $software &= $srv & ";" & $SW_DisplayName & ";" & $SW_DisplayVersion & ";" & $SW_Publisher & ";" & $SW_InstallDate & ";" & @CRLF
            EndIf
            $i += 1
        WEnd

        $i = 1
        While 1
            $key = RegEnumKey("HKEY_LOCAL_MACHINE64\" & $BaseKey, $i)
            If @error <> 0 Then ExitLoop
            $key_value = RegRead("HKEY_LOCAL_MACHINE64\" & $BaseKey & "\" & $key, "DisplayName")
            $chk_sc = RegRead("HKEY_LOCAL_MACHINE64\" & $BaseKey & "\" & $key, "SystemComponent")
            $chk_url = RegRead("HKEY_LOCAL_MACHINE64\" & $BaseKey & "\" & $key, "MoreInfoURL")
            $chk_nr = RegRead("HKEY_LOCAL_MACHINE64\" & $BaseKey & "\" & $key, "NoRemove")
            If $key_value <> "" And _
                    StringIsASCII($key_value) <> 0 And _
                    $key_value <> "Security Update for" And _
                    $key_value <> "Hotfix for" And _
                    $key_value <> "Update for Office" And _
                    $key_value <> "Windows 2000 Hotfix" And _
                    StringInStr(StringLower($key), StringLower("InstallShield_")) = 0  And _
                    StringInStr(StringLower($chk_url), StringLower("http://support.microsoft.com/kb/")) = 0 And _
                    $chk_nr <> 1 And $chk_sc <> 1 Then
                $SW_DisplayName = StringStripWS($key_value, 7)
                $SW_Publisher = RegRead("HKEY_LOCAL_MACHINE64\" & $BaseKey & "\" & $key, "Publisher")
                $SW_InstallDate = RegRead("HKEY_LOCAL_MACHINE64\" & $BaseKey & "\" & $key, "InstallDate")
                $SW_DisplayVersion = RegRead("HKEY_LOCAL_MACHINE64\" & $BaseKey & "\" & $key, "DisplayVersion")
                $software &= $srv & ";" & $SW_DisplayName & ";" & $SW_DisplayVersion & ";" & $SW_Publisher & ";" & $SW_InstallDate & ";" & @CRLF
            EndIf
            $i += 1
        WEnd
    Else
        If StringLower(@OSVersion) <> StringLower("WIN_2000") Then
            $objWMILocator = ObjCreate("WbemScripting.SWbemLocator")
            $objRegService = $objWMILocator.ConnectServer($srv, "\root\default", "", "", "", "", 0x80)
            $objReg = $objRegService.Get("StdRegProv")
        Else
            $objReg = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $srv & "\root\default:StdRegProv")
        EndIf

        If IsObj($objReg) Then
            $objReg.EnumKey($HKLM, $BaseKey, $arrSubKeys)
            For $SubKey In $arrSubKeys
                $SW_DisplayName = ""
                $SW_DisplayVersion = ""
                $SW_Publisher = ""
                $SW_InstallDate = ""
                $Key = $objReg.GetStringValue($HKLM, $BaseKey & $SubKey, "DisplayName", $Value)
                $objReg.GetDWORDValue($HKLM, $BaseKey & $SubKey, "NoRemove", $chk_nr)
                $objReg.GetDWORDValue($HKLM, $BaseKey & $SubKey, "SystemComponent", $chk_sc)
                $objReg.GetStringValue($HKLM, $BaseKey & $SubKey, "MoreInfoURL", $chk_url)
                If $Key <> 0 Or StringLeft($SubKey, 2) = "KB" Or StringLeft($SubKey, 1) = "Q" Then
                    $Key = $objReg.GetStringValue($HKLM, $BaseKey & $SubKey, "QuietDisplayName", $Value)
                EndIf
                If $Value <> "" And StringIsASCII($Value) <> 0 _
                        And $Key = 0 And StringInStr(StringLower($Value), StringLower("Security Update for")) = 0 _
                        And StringInStr(StringLower($Value), StringLower("Update for Windows")) = 0 _
                        And StringInStr(StringLower($Value), StringLower("Hotfix for")) = 0 _
                        And StringInStr(StringLower($Value), StringLower("Update for Office")) = 0 _
                        And StringInStr(StringLower($SubKey), StringLower("InstallShield_")) = 0 _
                        And StringInStr(StringLower($Value), StringLower("Windows 2000 Hotfix")) = 0 _
                        And StringInStr(StringLower($chk_url), StringLower("http://support.microsoft.com/kb/")) = 0 _
                        And $chk_nr <> 1 _
                        And $chk_sc <> 1 Then
                    $SW_DisplayName = $Value

                    $Key = $objReg.GetStringValue($HKLM, $BaseKey & $SubKey, "DisplayVersion", $Value)
                    If $Value <> "" And StringIsASCII($Value) <> 0 Then
                        $SW_DisplayVersion = StringStripWS($Value, 7)
                    EndIf

                    $Key = $objReg.GetStringValue($HKLM, $BaseKey & $SubKey, "Publisher", $Value)
                    If $Value <> "" And StringIsASCII($Value) <> 0 Then
                        $SW_Publisher = StringStripWS($Value, 7)
                    EndIf

                    $Key = $objReg.GetStringValue($HKLM, $BaseKey & $SubKey, "InstallDate", $Value)
                    If $Value <> "" And StringIsASCII($Value) <> 0 Then $SW_InstallDate = $Value
                    $line = $srv & ";" & $SW_DisplayName & ";" & $SW_DisplayVersion & ";" & $SW_Publisher & ";" & $SW_InstallDate & ";" & @CRLF
                    $software &= $line
                EndIf
            Next

            Dim $arrSubKeys
            $objReg.EnumKey($HKLM, $BaseKey64, $arrSubKeys)
            If UBound($arrSubKeys) > 0 Then
                For $SubKey In $arrSubKeys
                    $SW_DisplayName = ""
                    $SW_DisplayVersion = ""
                    $SW_Publisher = ""
                    $SW_InstallDate = ""
                    $Key = $objReg.GetStringValue($HKLM, $BaseKey64 & $SubKey, "DisplayName", $Value)
                    $objReg.GetDWORDValue($HKLM, $BaseKey64 & $SubKey, "NoRemove", $chk_nr)
                    $objReg.GetDWORDValue($HKLM, $BaseKey64 & $SubKey, "SystemComponent", $chk_sc)
                    $objReg.GetStringValue($HKLM, $BaseKey64 & $SubKey, "MoreInfoURL", $chk_url)
                    If $Key <> 0 Or StringLeft($SubKey, 2) = "KB" Or StringLeft($SubKey, 1) = "Q" Then
                        $Key = $objReg.GetStringValue($HKLM, $BaseKey64 & $SubKey, "QuietDisplayName", $Value)
                    EndIf
                    If $Value <> "" And StringIsASCII($Value) <> 0 _
                            And $Key = 0 And StringInStr(StringLower($Value), StringLower("Security Update for")) = 0 _
                            And StringInStr(StringLower($Value), StringLower("Update for Windows")) = 0 _
                            And StringInStr(StringLower($Value), StringLower("Hotfix for")) = 0 _
                            And StringInStr(StringLower($Value), StringLower("Update for Office")) = 0 _
                            And StringInStr(StringLower($SubKey), StringLower("InstallShield_")) = 0 _
                            And StringInStr(StringLower($Value), StringLower("Windows 2000 Hotfix")) = 0 _
                            And StringInStr(StringLower($chk_url), StringLower("http://support.microsoft.com/kb/")) = 0 _
                            And $chk_nr <> 1 _
                            And $chk_nr <> 1 Then
                        $SW_DisplayName = $Value

                        $Key = $objReg.GetStringValue($HKLM, $BaseKey64 & $SubKey, "DisplayVersion", $Value)
                        If $Value <> "" And StringIsASCII($Value) <> 0 Then
                            $SW_DisplayVersion = StringStripWS($Value, 7)
                        EndIf

                        $Key = $objReg.GetStringValue($HKLM, $BaseKey64 & $SubKey, "Publisher", $Value)
                        If $Value <> "" And StringIsASCII($Value) <> 0 Then
                            $SW_Publisher = StringStripWS($Value, 7)
                        EndIf

                        $Key = $objReg.GetStringValue($HKLM, $BaseKey64 & $SubKey, "InstallDate", $Value)
                        If $Value <> "" And StringIsASCII($Value) <> 0 Then $SW_InstallDate = $Value
                        $line = $srv & ";" & $SW_DisplayName & ";" & $SW_DisplayVersion & ";" & $SW_Publisher & ";" & $SW_InstallDate & ";" & @CRLF
                        $software &= $line
                    EndIf
                Next
            EndIf
        EndIf
    EndIf
    ConsoleWrite($software & @CRLF)
EndFunc   ;==>Software

No error handling! You need access rights on remote system.

Probably there is a much better way but...

@GEOSoft: thanks for the HKLM64 trick :)

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...