Jump to content
Sign in to follow this  
nerdie

Change array to print

Recommended Posts

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.

#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 by nerdie

Share this post


Link to post
Share on other sites

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 2020-10-10 - Version 1.5.2.1) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2020-06-30 - Version 1.6.2.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (NEW 2020-06-27 - Version 1.3.2.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
Task Scheduler (2019-12-03 - Version 1.5.1.0) - Download - General Help & Support - Wiki

Tutorials:
ADO - Wiki, WebDriver - Wiki

 

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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)

 

Share this post


Link to post
Share on other sites

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.

 

Share this post


Link to post
Share on other sites

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

 

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

 

 

Share this post


Link to post
Share on other sites

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 by Subz

Share this post


Link to post
Share on other sites

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

 

 

Share this post


Link to post
Share on other sites

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

 

Share this post


Link to post
Share on other sites

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")

 

Share this post


Link to post
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
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...