nerdie Posted August 9, 2019 Share Posted August 9, 2019 (edited) Hi I am using the uninstall script by iguinch. I just can't figure out how to make it print out to a text file instead of an array. I've read and reread FileWriteFromArray and I just can't get it. I can't figure out how to change the positions of the columns. expandcollapse popup#include <Date.au3> ; needed for _UninstallList function #include <File.au3> #Include <Array.au3> ; Just for _ArrayDisplay Local $aList = _UninstallList("", "","Publisher|InstallLocation|DisplayVersion") _ArrayDisplay($aList, "All uninstall keys", Default, Default, Default, "RergistryPath|Key|DisplayName|InstallationDate|Publisher|InstallLocation|DisplayVersion") ; #FUNCTION# ==================================================================================================================== ; Name ..........: _UninstallList ; Description ...: Returns an array of matching uninstall keys from registry, with an optional filter ; Syntax ........: _UninstallList([$sValueName = ""[, $sFilter = ""[, $sCols = ""[, $iSearchMode = 0[,$ iArch = 3]]]]]]) ; Parameters ....: $sValueName - [optional] Registry value used for the filter. ; Default is all keys ($sFilter do not operates). ; $sFilter - [optional] String to search in $sValueName. Filter is not case sensitive. ; $sCols - [optional] Additional values to retrieve. Use "|" to separate each value. ; Each value adds a column in the returned array ; $iSearchMode - [optional] Search mode. Default is 0. ; 0 : Match string from the start. ; 1 : Match any substring. ; 2 : Exact string match. ; 3 : $sFilter is a regular expression ; $iArch - [optional] Registry keys to search in. Default is 3. ; 1 : x86 registry keys only ; 2 : x64 registry keys only ; 3 : both x86 and x64 registry keys ; Return values .: Returns a 2D array of registry keys and values : ; $array[0][0] : Number of keys ; $array[n][0] : Registry key path ; $array[n][1] : Registry subkey ; $array[n][2] : Display name ; $array[n][3] : Installation date (YYYYMMDD format) ; $array[n][4] : 1st additional value specified in $sCols (only if $sCols is set) ; $array[n][5] : 2nd additional value specified in $sCols (only if $sCols contains at least 2 entries) ; $array[n][x] : Nth additional value ... ; Author ........: jguinch ; =============================================================================================================================== Func _UninstallList($sValueName = "", $sFilter = "", $sCols = "", $iSearchMode = 0, $iArch = 3) Local $sHKLMx86, $sHKLM64, $sHKCU = "HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall" Local $aKeys[1] = [ $sHKCU ] Local $sDisplayName, $sSubKey, $sKeyDate, $sDate, $sValue, $iFound, $n, $aResult[1][4], $iCol Local $aCols[1] = [0] If NOT IsInt($iArch) OR $iArch < 0 OR $iArch > 3 Then Return SetError(1, 0, 0) If NOT IsInt($iSearchMode) OR $iSearchMode < 0 OR $iSearchMode > 3 Then Return SetError(1, 0, 0) $sCols = StringRegExpReplace( StringRegExpReplace($sCols, "(?i)(DisplayName|InstallDate)\|?", ""), "\|$", "") If $sCols <> "" Then $aCols = StringSplit($sCols, "|") If @OSArch = "X86" Then $iArch = 1 $sHKLMx86 = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" Else If @AutoitX64 Then $sHKLMx86 = "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" $sHKLM64 = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" Else $sHKLMx86 = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" $sHKLM64 = "HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" EndIf EndIf If BitAND($iArch, 1) Then Redim $aKeys[ UBound($aKeys) + 1] $aKeys [ UBound($aKeys) - 1] = $sHKLMx86 EndIf If BitAND($iArch, 2) Then Redim $aKeys[ UBound($aKeys) + 1] $aKeys [ UBound($aKeys) - 1] = $sHKLM64 EndIf For $i = 0 To UBound($aKeys) - 1 $n = 1 While 1 $iFound = 1 $aSubKey = _RegEnumKeyEx($aKeys[$i], $n) If @error Then ExitLoop $sSubKey = $aSubKey[0] $sKeyDate = StringRegExpReplace($aSubKey[1], "^(\d{4})/(\d{2})/(\d{2}).+", "$1$2$3") $sDisplayName = RegRead($aKeys[$i] & "\" & $sSubKey, "DisplayName") $sDate = RegRead($aKeys[$i] & "\" & $sSubKey, "InstallDate") If $sDate = "" Then $sDate = $sKeyDate If $sDisplayName <> "" Then If $sValueName <> "" Then $iFound = 0 $sValue = RegRead( $aKeys[$i] & "\" & $sSubKey, $sValueName) If ( $iSearchMode = 0 AND StringInStr($sValue, $sFilter) = 1 ) OR _ ( $iSearchMode = 1 AND StringInStr($sValue, $sFilter) ) OR _ ( $iSearchMode = 2 AND $sValue = $sFilter ) OR _ ( $iSearchMode = 3 AND StringRegExp($sValue, $sFilter) ) Then $iFound = 1 EndIf EndIf If $iFound Then Redim $aResult[ UBound($aResult) + 1][ 4 + $aCols[0] ] $aResult[ UBound($aResult) - 1][0] = $aKeys[$i] $aResult[ UBound($aResult) - 1][1] = $sSubKey $aResult[ UBound($aResult) - 1][2] = $sDisplayName $aResult[ UBound($aResult) - 1][3] = $sDate For $iCol = 1 To $aCols[0] $aResult[ UBound($aResult) - 1][3 + $iCol] = RegRead( $aKeys[$i] & "\" & $sSubKey, $aCols[$iCol]) Next EndIf EndIf $n += 1 WEnd Next $aResult[0][0] = UBound($aResult) - 1 Return $aResult EndFunc ; #FUNCTION# ==================================================================================================================== ; Name ..........: _RegEnumKeyEx ; Description ...: Enumerates the subkeys of the specified open registry key. The function retrieves information about one subkey ; each time it is called. ; Syntax ........: _RegEnumKeyEx($sKey, $iInstance) ; Parameters ....: $sKey - The registry key to read. ; $iInstance - The 1-based key instance to retrieve. ; Return values .: Success - A 1D array : ; $aArray[0] = subkey name ; $aArray[1] = time at which the enumerated subkey was last written ; Failure - Returns 0 and set @eror to non-zero value ; Author ........: jguinch ; =============================================================================================================================== Func _RegEnumKeyEx($sKey, $iInstance) If NOT IsDeclared("KEY_WOW64_32KEY") Then Local Const $KEY_WOW64_32KEY = 0x0200 If NOT IsDeclared("KEY_WOW64_64KEY") Then Local Const $KEY_WOW64_64KEY = 0x0100 If NOT IsDeclared("KEY_ENUMERATE_SUB_KEYS") Then Local Const $KEY_ENUMERATE_SUB_KEYS = 0x0008 If NOT IsDeclared("tagFILETIME") Then Local Const $tagFILETIME = "struct;dword Lo;dword Hi;endstruct" Local $iSamDesired = $KEY_ENUMERATE_SUB_KEYS Local $iX64Key = 0, $sRootKey, $aResult[2] Local $sRoot = StringRegExpReplace($sKey, "\\.+", "") Local $sSubkey = StringRegExpReplace($sKey, "^[^\\]+\\", "") $sRoot = StringReplace($sRoot, "64", "") If @extended Then $iX64Key = 1 If NOT IsInt($iInstance) OR $iInstance < 1 Then Return SetError(2, 0, 0) Switch $sRoot Case "HKCR", "HKEY_CLASSES_ROOT" $sRootKey = 0x80000000 Case "HKLM", "HKEY_LOCAL_MACHINE" $sRootKey = 0x80000002 Case "HKCU", "HKEY_CURRENT_USER" $sRootKey = 0x80000001 Case "HKU", "HKEY_USERS" $sRootKey = 0x80000003 Case "HKCC", "HKEY_CURRENT_CONFIG" $sRootKey = 0x80000005 Case Else Return SetError(1, 0, 0) EndSwitch If StringRegExp(@OSArch, "64$") Then If @AutoItX64 OR $iX64Key Then $iSamDesired = BitOR($iSamDesired, $KEY_WOW64_64KEY) Else $iSamDesired = BitOR($iSamDesired, $KEY_WOW64_32KEY) EndIf EndIf Local $aRetOPen = DllCall('advapi32.dll', 'long', 'RegOpenKeyExW', 'handle', $sRootKey, 'wstr', $sSubKey, 'dword', 0, 'dword', $iSamDesired, 'ulong_ptr*', 0) If @error Then Return SetError(@error, @extended, 0) If $aRetOPen[0] Then Return SetError(10, $aRetOPen[0], 0) Local $hKey = $aRetOPen[5] Local $tFILETIME = DllStructCreate($tagFILETIME) Local $lpftLastWriteTime = DllStructGetPtr($tFILETIME) Local $aRetEnum = DllCall('Advapi32.dll', 'long', 'RegEnumKeyExW', 'long', $hKey, 'dword', $iInstance - 1, 'wstr', "", 'dword*', 255, 'dword', "", 'ptr', "", 'dword', "", 'ptr', $lpftLastWriteTime) If Not IsArray($aRetEnum) OR $aRetEnum[0] <> 0 Then Return SetError( 3, 0, 1) Local $tFILETIME2 = _Date_Time_FileTimeToLocalFileTime($lpftLastWriteTime) Local $localtime = _Date_Time_FileTimeToStr($tFILETIME2, 1) $aResult[0] = $aRetEnum[3] $aResult[1] = $localtime Return $aResult EndFunc Edited August 12, 2019 by nerdie Link to comment Share on other sites More sharing options...
water Posted August 9, 2019 Share Posted August 9, 2019 Welcome to AutoIt and the forum! To change the order of the columns in the array you need to create a new array and copy the data in the needed order. My UDFs and Tutorials: Spoiler UDFs:Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - WikiExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example ScriptsOutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - WikiOutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - DownloadOutlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - WikiPowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - WikiTask Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs:Excel - Example Scripts - WikiWord - Wiki Tutorials:ADO - WikiWebDriver - Wiki Link to comment Share on other sites More sharing options...
Nine Posted August 9, 2019 Share Posted August 9, 2019 You can also use _ArraySwap to interchange columns in 2D arrays. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
nerdie Posted August 10, 2019 Author Share Posted August 10, 2019 Hi and thanks for the help. By using ArraySwap I now have the columns in the order I want them in. _ArraySwap($aList, 0, 5, True) _ArraySwap($aList, 0, 4, True) _ArraySwap($aList, 0, 2, True) _ArraySwap($aList, 1, 6, True) The array display has a heading above each column how do I move these headings to align with the new column data please. They are above row 0 so I assume they are in the program itself. Link to comment Share on other sites More sharing options...
nerdie Posted August 10, 2019 Author Share Posted August 10, 2019 Hi there again I fixed the headings. So now all I have to work out is how to get it to print out to a text file instead of an array. I need more help with FileWriteFromArray please. Link to comment Share on other sites More sharing options...
Nine Posted August 10, 2019 Share Posted August 10, 2019 If you post code, please use this tool. What kind of help do you want with _FileWriteFromArray, seems pretty straightforward ? Maybe try : _FileWriteFromArray ("Output.txt", $aList, Default, Default, @TAB) If @error then Exit MsgBox (0,"Error",@error) “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
nerdie Posted August 10, 2019 Author Share Posted August 10, 2019 Sorry about that. Thanks for the help. Are the swap lines okay? I can get it to print out into a text file - now I'm trying to work out how to sort it out into columns again. I used your script and got this output. I've only posted a few entries. Microsoft OneDrive 19.103.0527.0003 Microsoft Corporation 20190730 HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall OneDriveSetup.exe Adobe Flash Player 32 NPAPI 32.0.0.101 Adobe Systems Incorporated 20190730 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall Adobe Flash Player NPAPI AutoIt v3.3.14.2 3.3.14.2 AutoIt Team 20170715 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall AutoItv3 The seven headings are: DisplayName - DisplayVersion - Publisher - InstallDate - InstallLocation - RergistryPath - Key They print out in the correct order in the array but not at all in the file. Link to comment Share on other sites More sharing options...
Subz Posted August 10, 2019 Share Posted August 10, 2019 Couple of examples: #include <Array.au3> Local $aList = _UninstallList("", "","Publisher|InstallLocation|DisplayVersion") Local $sHeader = "Registry Path|Registry Key|Display Name|Install Date|Publisher|Install Location|Display Version" _ArrayDelete($aList, 0) ;~ Delete the first row _ArrayInsert($aList, 0, $sHeader) ;~ Insert the header to the top of the array _ArraySwap($aList, 0, 5, True) _ArraySwap($aList, 0, 4, True) _ArraySwap($aList, 0, 2, True) _ArraySwap($aList, 1, 6, True) ;~ Example 1 Local $hUninstall = FileOpen(@ScriptDir & "\Uninstall.csv", 2) FileWrite($hUninstall, '"' & _ArrayToString($aList, '","', 0, -1, '"' & @CRLF & '"') & '"' & @CRLF) FileClose($hUninstall) ;~ Example 2 ;~ This method removes any double quotes from the values, as this can cause issues when writing to csv. Local $sUninstall, $hUninstall = FileOpen(@ScriptDir & "\Uninstall2.csv", 2) For $i = 0 To UBound($aList) - 1 $sUninstall = _ArrayToString($aList, "|", $i, $i) If @error Then ContinueLoop FileWrite($hUninstall, '"' & StringReplace(StringReplace($sUninstall, '"', ""), "|", '","') & '"' & @CRLF) Next Link to comment Share on other sites More sharing options...
Nine Posted August 10, 2019 Share Posted August 10, 2019 I showed you how to write text file using _FileWriteFromArray with @TAB separators. Subz showed you other ways with "," separator (example 1) and "|" separator (example 2). I have a feeling that it might not be what you are aiming for. Maybe you want a nice print out where all columns a well align like you have in an _ArrayDisplay. Am i right ? If so I suggest you give us an example of the final formatted text file you want... “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
nerdie Posted August 11, 2019 Author Share Posted August 11, 2019 Thank you both. The printout from both of Subz examples is fine except: It is printed in an excel file I want a text file and I want a separator line between the headings and the list. So really it just needs tweaking to tidy it up. but that is what I'm chasing. Thanks again. Example 1. Display Name Display Version Publisher Install Date Install Location Registry Path Registry Key Microsoft OneDrive 19.123.0624.0005 Microsoft Corporation 20190811 HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall OneDriveSetup.exe Adobe Flash Player 32 NPAPI 32.0.0.101 Adobe Systems Incorporated 20190730 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall Adobe Flash Player NPAPI AutoIt v3.3.14.2 3.3.14.2 AutoIt Team 20170715 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall AutoItv3 Example 2. Display Name Display Version Publisher Install Date Install Location Registry Path Registry Key Microsoft OneDrive 19.123.0624.0005 Microsoft Corporation 20190811 HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall OneDriveSetup.exe Adobe Flash Player 32 NPAPI 32.0.0.101 Adobe Systems Incorporated 20190730 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall Adobe Flash Player NPAPI AutoIt v3.3.14.2 3.3.14.2 AutoIt Team 20170715 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall AutoItv3 Link to comment Share on other sites More sharing options...
Subz Posted August 12, 2019 Share Posted August 12, 2019 (edited) One way: #include <Array.au3> #include <Date.au3> #include <String.au3> Local $aList = _UninstallList("", "","Publisher|InstallLocation|DisplayVersion") Local $sHeader = "Registry Path|Registry Key|Display Name|Install Date|Publisher|Install Location|Display Version" _ArrayDelete($aList, 0) ;~ Delete the first row _ArrayInsert($aList, 0, $sHeader) ;~ Insert the header to the top of the array _ArraySwap($aList, 0, 5, True) _ArraySwap($aList, 0, 4, True) _ArraySwap($aList, 0, 2, True) _ArraySwap($aList, 1, 6, True) Local $sUninstall, $hUninstall = FileOpen(@ScriptDir & "\Uninstall.txt", 2) Local $aTextSize[1][UBound($aList, 2)] For $i = 0 To UBound($aList) - 1 For $j = 0 To UBound($aList, 2) - 1 If StringLen($aList[$i][$j]) > Number($aTextSize[0][$j]) Then $aTextSize[0][$j] = StringLen($aList[$i][$j]) Next Next For $i = 0 To UBound($aList) - 1 $sRegistryPath = $aList[$i][0] & _StringRepeat(" ", $aTextSize[0][0] - StringLen($aList[$i][0])) & @TAB $sRegistryKey = $aList[$i][1] & _StringRepeat(" ", $aTextSize[0][1] - StringLen($aList[$i][1])) & @TAB $sDisplayName = $aList[$i][2] & _StringRepeat(" ", $aTextSize[0][2] - StringLen($aList[$i][2])) & @TAB $sInstallDate = $aList[$i][3] & _StringRepeat(" ", $aTextSize[0][3] - StringLen($aList[$i][3])) & @TAB $sPublisher = $aList[$i][4] & _StringRepeat(" ", $aTextSize[0][4] - StringLen($aList[$i][4])) & @TAB $sInstallLocation = $aList[$i][5] & _StringRepeat(" ", $aTextSize[0][5] - StringLen($aList[$i][5])) & @TAB $sDisplayVersion = $aList[$i][6] & _StringRepeat(" ", $aTextSize[0][6] - StringLen($aList[$i][6])) FileWrite($hUninstall, $sRegistryPath & $sRegistryKey & $sDisplayName & $sInstallDate & $sPublisher & $sInstallLocation & $sDisplayVersion & @CRLF) Next Edited August 12, 2019 by Subz Link to comment Share on other sites More sharing options...
nerdie Posted August 12, 2019 Author Share Posted August 12, 2019 Thanks for your invaluable help Subz That's the general idea thanks it just needs some tweaking and tidying up. some way to compress it. Display Name Display Version Publisher Install Date Install Location Registry Path Registry Key Microsoft OneDrive 19.123.0624.0005 Microsoft Corporation 20190811 HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall OneDriveSetup.exe Adobe Flash Player 32 NPAPI 32.0.0.101 Adobe Systems Incorporated 20190730 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall Adobe Flash Player NPAPI AutoIt v3.3.14.2 3.3.14.2 AutoIt Team 20170715 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall AutoItv3 Link to comment Share on other sites More sharing options...
Subz Posted August 12, 2019 Share Posted August 12, 2019 The code basically gets the longest string length of each column and then when it writes the data fills the remaining data with spaces so that the columns are even, so you have to decide if you want them all even or if you only want to use a separator like tab or something else., you could probably get rid of the Registry Path, you could also use elipse if you only want to have so many letters in a column for example "Adobe Flash Player ...", you can do this within the look and using String functions like StriingLeft or StringTrimRight etc... Link to comment Share on other sites More sharing options...
nerdie Posted August 14, 2019 Author Share Posted August 14, 2019 I've got the first 4 columns to print out perfectly in an array so I think I'll call it quits while I'm ahead. I removed the registry path and key. Now I'm going to try to put "/" in the install date. Local $aList = _UninstallList("", "","Publisher|InstallLocation|DisplayVersion") _ArraySwap($aList, 0, 5, True) _ArraySwap($aList, 0, 4, True) _ArraySwap($aList, 0, 2, True) _ArraySwap($aList, 1, 6, True) _ArrayColDelete($aList, 5) _ArrayColDelete($aList, 5) _ArrayDisplay($aList, "All uninstall keys", Default, Default, Default, "DisplayName|DisplayVersion|Publisher|InstallDate|InstallLocation|RergistryPath|Key") Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now