Jump to content

Need some help with an "installed programs" script...


Recommended Posts

This question is a bit of a follow-up from this post:

I used the code provided by boththose (and credits to ripdad) to try and mold the script into doing what I am trying to achieve, but I've run into a snag of sorts, and I haven't been able to puzzle it out.

Before I start, let me say I haven't coded much of anything since 2004/2005...so to say I'm rusty...that would be very polite...

I'm trying to inventory the list of installed programs, print out a subset of programs applicable to the software I'm trying to find, and then provide a single-button-click to install any software that needs to be updated. The program works, all of the relevant messages are displayed and it seems like it displays the proper software in the list and runs the proper .exe at the right time. Everything looks good...

On my test PC, I ran the script .exe, did a right-click Uninstall on the Java software. Seems to have run fine. Executing the script again shows no listing of Java. I run the Java installer from the button at the bottom (64-bit) and the installer runs fine. I see Java installed in the Control Panel. I actually see the Java key in the Uninstall registry keys. However, the script no longer lists Java as an installed program.

Any insight would be appreciated...I've been staring at boththose and ripdad's code for a while, but I can't find the issue...

#include
Opt("TrayAutoPause", 0)
Opt('GUIOnEventMode', 1)
Opt('GUICloseOnEsc' , 1)

Global $i

;Filling an array with software names I want to check against the installed software listing array.
Global $m[2] = ["java", "openvpn"]
Global $n

Local $sSft
Global $sGui = GUICreate('Currently Installed Software for ' & @OSVersion & ' ' & @OSArch, 810, 650, -1, -1)
Global $sLvw = GUICtrlCreateListView('#|Installed Software|Display Version|Publisher|Uninstall String', 5, 5, 800, 600)

;Function call to create a C:\temp folder and copy the .exe's to it for the software to be updated.
_FileList()

_ComputerGetSoftware($sSft)

For $i = 1 To ubound($sSft) - 1
GUICtrlCreateListViewItem($i & '|' & $sSft[$i][0] & '|' & $sSft[$i][1] & '|' & $sSft[$i][2] & '|' & $sSft[$i][3], $sLvw)
Next

GUICtrlSendMsg($sLvw, 0x101E, 1, 175)
GUICtrlSendMsg($sLvw, 0x101E, 2, 65)
GUICtrlSendMsg($sLvw, 0x101E, 3, 150)
GUICtrlSendMsg($sLvw, 0x101E, 4, 350)

Local $mMen = GUICtrlCreateContextMenu($sLvw)

Local $CopI = GUICtrlCreateMenuItem('Uninstall Current Selection', $mMen)
GUICtrlSetOnEvent($CopI, '_Uninstall')

;Creating buttons on the GUI to call the .exe's to install software from C:\temp.
Local $java32 = GUICtrlCreateButton(' Java Update (32bit) ', 5, 615 )
GUICtrlSetOnEvent($java32, '_JavaUpdate32')
Local $java64 = GUICtrlCreateButton(' Java Update (64bit) ',175, 615)
GUICtrlSetOnEvent($java64, '_JavaUpdate64')
Local $VPN = GUICtrlCreateButton(' OpenVPN 2.2 ',550, 615)
GUICtrlSetOnEvent($VPN, '_OpenVPN')

;Function call to check Windows Registry for Windows Updates enabled or not.
_WUpdateRegRead()

GUISetOnEvent(-3, '_AllExit')
GUISetState(@SW_SHOW, $sGui)

While 1
Sleep(10)
WEnd
;

Func _AllExit()
GUIDelete($sGui)
Exit
EndFunc
;

Func _Uninstall()
Local $proc = StringSplit(GUICtrlRead(GUICtrlRead($sLvw)), '|', 1)
If $proc[1] == 0 Then Return -1
If $proc[5] Then RunWait ($proc[5])
exit
EndFunc
;

Func _ComputerGetSoftware(ByRef $aSoftwareInfo)
Local Const $UnInstKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
Local $i = 1
Local $n = 0
Dim $aSoftwareInfo[1][4]
$input = inputbox ("Which Software" , "You are running " & @OSVersion & " " & @OSARCH & @CRLF & @CRLF & "Which Software would you like to view, ALL or Some?", 'Some')
If @Error = 1 Then Exit
If $input = 'ALL' Then
For $j = 1 To 500
$AppKey = RegEnumKey($UnInstKey, $j)
If @error <> 0 Then Exitloop
If RegRead($UnInstKey & "\" & $AppKey, "DisplayName") = '' Then ContinueLoop
ReDim $aSoftwareInfo[UBound($aSoftwareInfo) + 1][4]
$aSoftwareInfo[$i][0] = StringStripWS(StringReplace(RegRead($UnInstKey & "\" & $AppKey, "DisplayName"), " (remove only)", ""), 3)
$aSoftwareInfo[$i][1] = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "DisplayVersion"), 3)
$aSoftwareInfo[$i][2] = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "Publisher"), 3)
$aSoftwareInfo[$i][3] = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "UninstallString"), 3)
$i = $i + 1

Next
$aSoftwareInfo[0][0] = UBound($aSoftwareInfo, 1) - 1
If $aSoftwareInfo[0][0] < 1 Then SetError(1, 1, 0)
Return _ArraySort($aSoftwareInfo,0,1)

Else
IF $input = 'Some' Then
;Looping the array from above, checking for "java" or "openvpn" in the list of installed programs.
For $n = 0 to 2 - 1
For $j = 1 To 500
$AppKey = RegEnumKey($UnInstKey, $j)
If @error <> 0 Then Exitloop
$Reg = RegRead($UnInstKey & "\" & $AppKey, "DisplayName")
$string = stringinstr($Reg, $m[$n])
If $string = 0 Then Continueloop
ReDim $aSoftwareInfo[UBound($aSoftwareInfo) + 1][4]
$aSoftwareInfo[$i][0] = StringStripWS(StringReplace(RegRead($UnInstKey & "\" & $AppKey, "DisplayName"), " (remove only)", ""), 3)
$aSoftwareInfo[$i][1] = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "DisplayVersion"), 3)
$aSoftwareInfo[$i][2] = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "Publisher"), 3)
$aSoftwareInfo[$i][3] = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "UninstallString"), 3)
$i = $i + 1
Next
Next
$aSoftwareInfo[0][0] = UBound($aSoftwareInfo, 1) - 1
If $aSoftwareInfo[0][0] < 1 Then SetError(1, 1, 0)
Return _ArraySort($aSoftwareInfo,0,1)

Endif

Endif

EndFunc
;

;Function to copy .exe installers to the local C:\temp of the PC the script is executing on.
Func _FileList()
DirCreate("C:\temp\")
FileInstall('C:\Users\me\Desktop\Installers\jre-6u39-windows-x64.exe', 'C:\temp\', 1)
FileInstall('C:\Users\me\Desktop\Installers\jre-6u39-windows-i586.exe', 'C:\temp\', 1)
FileInstall('C:\Users\me\Desktop\Installers\openvpn-setup-final.exe', 'C:\temp\', 1)
EndFunc
;

;Start 32-bit Java install
Func _JavaUpdate32()
Run("C:\temp\jre-6u39-windows-i586.exe")
EndFunc
;

;Start 64-bit Java install
Func _JavaUpdate64()
Run("C:\temp\jre-6u39-windows-x64.exe")
EndFunc
;

;Start OpenVPN install
Func _OpenVPN()
Run("C:\temp\openvpn-setup-final.exe")
EndFunc
;

;Read registry to see if WUpdate is enabled, if not, display a button click to run the relevant function to add registry entries to enable WUpdate.
Func _WUpdateRegRead()
Local $wupdate = RegRead("HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate\AU", "NoAutoUpdate")
If $wupdate <> 0 Then
If @OSArch = 'x64' Then
Local $w7updategui64 = GUICtrlCreateButton(' Enable Windows Updates ', 50, 615 )
GUICtrlSetOnEvent($w7updategui64, '_W7UpdateRegWrite64')
ElseIf @OSArch <> 'x64' Then
Local $w7updategui32 = GUICtrlCreateButton(' Enable Windows Updates ', 300, 615 )
GUICtrlSetOnEvent($w7updategui32, '_W7UpdateregWrite32')
EndIf
EndIf
EndFunc
;

;Placeholder for registry entries to enable WUpdate for 64-bit Win 7
Func _W7UpdateRegWrite64()
MsgBox(4096, "Enabling Windows Updates", "Applying Windows Update Policies for Windows 7 (64-bit)", 5)
EndFunc
;

;Placeholder for registry entries to enable WUpdate for 32-bit Win 7
Func _W7UpdateRegWrite32()
MsgBox(4096, "Enabling Windows Updates", "Applying Windows Update Policies for Windows 7 (32-bit)", 5)
EndFunc
;
Link to comment
Share on other sites

So the new java installation does not show even under the 'ALL' selection?

If you change the $uninstkey to HKLM64 (or just add that key as an additional location to poll and add to the array), do you get different results?

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Link to comment
Share on other sites

I made a quick edit to the script. It runs fine on my machine to report the installed softare, yet when I run it on my test machine, still no report of software installed.

Func _ComputerGetSoftware(ByRef $aSoftwareInfo)
If @OSArch = "X64" Then
$registry = "HKLM"
Else
$registry = "HKLM64"
EndIf

Local Const $UnInstKey = $registry & "\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"

I can see the registry key where Java is installed. It is directly under "ComputerHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionUninstall{26A24AE4-039D-4CA4-87B4-2F86416039FF} and the DisplayName entry is "Java 6 Update 39 (64-bit)". It just isn't showing up in the GUI screen.

I'm really not sure what is going on. It was working great until I did an uninstall/reinstall of Java, and now the script doesn't even see it in the Registry, but it's right there.

Thanks for showing up boththose, I was hoping I'd hear from you :)

Link to comment
Share on other sites

sorry i am not of more assistance, I have uninstalled and reinstalled 6u43 a couple of times and cannot replicate the issue. If you put

msgbox (0, '' , "looking for " & $m[$n] & " inside the string: " & $Reg)

after the regread can you determine whether it has even cycled through the java entry. That and maybe comment out the continueloop line to ensure that it is not being skipped.

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Link to comment
Share on other sites

Added the msgbox line and went through the gamut of registry entries and noticed something weird...

I have 2 machines, both Windows 7 Enterprise (64-bit) SP1...

My primary machine lists Java as installed, but has the registry entry saved in: ComputerHKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftWindowsCurrentVersionUninstall{26A24AE4-039D-4CA4-87B4-2F83216039FF}

My test machine lists Java as *not* installed, but has the registry entry saved in: ComputerHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionUninstall{26A24AE4-039D-4CA4-87B4-2F86416039FF}

The only difference is the uninstall key changes slightly in the last segment, and the keys are stored in the Wow6432Node subkey on the PC that is actually displaying the software as installed, but nowhere in the script does it reference the Wow6432Node subtree...

I'm confused... *shakes fist at Bill Gates*

Link to comment
Share on other sites

Yeah, the registry has me lost. The script is solid, the registry is the killer.

So pointing the script towards "HKLM64SoftwareMicrosoftWindowsCurrentVersionUninstall" reads the key stored in "ComputerHKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftWindowsCurrentVersionUninstall{26A24AE4-039D-4CA4-87B4-2F83216039FF}" and reports it as installed.

It does not read the key stored in "ComputerHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionUninstall{26A24AE4-039D-4CA4-87B4-2F86416039FF}"

Pointing the script towards "HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionUninstall" does the exact same thing.

Link to comment
Share on other sites

edit: i am lost as well, so all stabs that follow are into darkness

have you tried disabling redirection? This call seems to fix most of my x86/x64 issues.

DllCall("kernel32.dll", "int", "Wow64DisableWow64FsRedirection", "int", 1)

http://www.autoitscript.com/autoit3/docs/intro/64-bit_support.htm

Edited by boththose

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Link to comment
Share on other sites

Yeah, still no dice. So here's another question, more of a logic question than anything...

If I were to populate an array called $regpath with both "HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoft" and "HKEY_LOCAL_MACHINESOFTWAREMicrosoft", how would you recommend I go about looping through that array so I could use "$UnInstKey = $regpath[$r] & "WindowsCurrentVersionUninstall" to get an inventory of both options?

I trimmed out everything else, and just trying to lock down this cycle through the array. If I run it, I get my msgbox pop up that says $r = 0, and $UnInstKey = HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftWindowsCurrentVersionUninstall....so I know I'm on the right path, I just can't get it to run through the other item in the array...

Sorry if this is starting to seem like a coding lesson, but I'm missing something that is probably right in front of my eyes, and I just can't see it...

#include 
Opt("TrayAutoPause", 0)
Opt('GUIOnEventMode', 1)
Opt('GUICloseOnEsc' , 1)


Global $i
Global $r = 0
Global $m[2] = ["Java", "openvpn"]
Global $regpath[2] = ["HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft", "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft"]
Local $sSft
Global $sGui = GUICreate('Currently Installed Software for ' & @OSVersion & ' ' & @OSArch, 810, 650, -1, -1)
Global $sLvw = GUICtrlCreateListView('#|Installed Software|Display Version|Publisher|Uninstall String', 5, 5, 800, 600)

_ComputerGetSoftware($sSft)

For $i = 1 To ubound($sSft) - 1
GUICtrlCreateListViewItem($i & '|' & $sSft[$i][0] & '|' & $sSft[$i][1] & '|' & $sSft[$i][2] & '|' & $sSft[$i][3], $sLvw)
Next

GUICtrlSendMsg($sLvw, 0x101E, 1, 175)
GUICtrlSendMsg($sLvw, 0x101E, 2, 65)
GUICtrlSendMsg($sLvw, 0x101E, 3, 150)
GUICtrlSendMsg($sLvw, 0x101E, 4, 350)

Local $mMen = GUICtrlCreateContextMenu($sLvw)


GUISetOnEvent(-3, '_AllExit')
GUISetState(@SW_SHOW, $sGui)

While 1
Sleep(10)
WEnd
;

Func _AllExit()
GUIDelete($sGui)
Exit
EndFunc
;

Func _ComputerGetSoftware(ByRef $aSoftwareInfo)
Local $i = 1
Local $n = 0
Local $r = 0
Dim $aSoftwareInfo[1][4]
$input = inputbox ("Which Software" , "You are running " & @OSVersion & " " & @OSARCH & @CRLF & @CRLF & "Which Software would you like to view, ALL or Some?", 'Some')
If @Error = 1 Then Exit
If $input = 'ALL' Then
For $r = 0 to 1
Local $UnInstKey = $regpath[$r] & "\Windows\CurrentVersion\Uninstall"
For $j = 1 To 500
$AppKey = RegEnumKey($UnInstKey, $j)
If @error <> 0 Then Exitloop
If RegRead($UnInstKey & "\" & $AppKey, "DisplayName") = '' Then ContinueLoop
ReDim $aSoftwareInfo[UBound($aSoftwareInfo) + 1][4]
$aSoftwareInfo[$i][0] = StringStripWS(StringReplace(RegRead($UnInstKey & "\" & $AppKey, "DisplayName"), " (remove only)", ""), 3)
$aSoftwareInfo[$i][1] = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "DisplayVersion"), 3)
$aSoftwareInfo[$i][2] = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "Publisher"), 3)
$aSoftwareInfo[$i][3] = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "UninstallString"), 3)
$i = $i + 1
Next

Next
$aSoftwareInfo[0][0] = UBound($aSoftwareInfo, 1) - 1
If $aSoftwareInfo[0][0] < 1 Then SetError(1, 1, 0)
Return _ArraySort($aSoftwareInfo,0,1)

Else

IF $input = 'Some' Then
For $r = 0 to 1
Local $UnInstKey = $regpath[$r] & "\Windows\CurrentVersion\Uninstall"
msgbox (0, '', $r & " " & $UnInstKey)
For $n = 0 to 1
For $j = 1 To 500
Local $UnInstKey = $regpath[$r] & "\Windows\CurrentVersion\Uninstall"
$AppKey = RegEnumKey($UnInstKey, $j)
If @error <> 0 Then Exitloop
$Reg = RegRead($UnInstKey & "\" & $AppKey, "DisplayName")
;msgbox (0, '', "looking for " & $m[$n] & " inside the string: " & $Reg)
;msgbox (0, '', "Looking in " & $UnInstKey & " ")
$string = stringinstr($Reg, $m[$n])
If $string = 0 Then Continueloop
ReDim $aSoftwareInfo[UBound($aSoftwareInfo) + 1][4]
$aSoftwareInfo[$i][0] = StringStripWS(StringReplace(RegRead($UnInstKey & "\" & $AppKey, "DisplayName"), " (remove only)", ""), 3)
$aSoftwareInfo[$i][1] = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "DisplayVersion"), 3)
$aSoftwareInfo[$i][2] = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "Publisher"), 3)
$aSoftwareInfo[$i][3] = StringStripWS(RegRead($UnInstKey & "\" & $AppKey, "UninstallString"), 3)
$i = $i + 1
Next

Next

$aSoftwareInfo[0][0] = UBound($aSoftwareInfo, 1) - 1
If $aSoftwareInfo[0][0] < 1 Then SetError(1, 1, 0)
Return _ArraySort($aSoftwareInfo,0,1)
Next
Endif


Endif
EndFunc
;
Link to comment
Share on other sites

  • Developers

The only difference is the uninstall key changes slightly in the last segment, and the keys are stored in the Wow6432Node subkey on the PC that is actually displaying the software as installed, but nowhere in the script does it reference the Wow6432Node subtree...

I'm confused... *shakes fist at Bill Gates*

Are you using the x86 version of AutoIt3 (AutoIT3.exe) or the x64 version (AutoIt3_x64.exe) when testing?

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

Chimaera offered this solution for gathering all potential locations:

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Link to comment
Share on other sites

I figured out one of my issues, it was that I added 2 nested For loops to the Some structure, and neglected to relocate the Return call. I moved it outside of my top level For loop, and it's parsing both registry keys. Now I just need to muddle my way through editing the Array to contain a third field for keeping track of the $regpath[$r] value so that it doesn't spit out the same data in the Array twice.

I will also definitely take a look at Chimaera's code. Thanks!!

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...