Sign in to follow this  
Followers 0
StillLearningThisStuff

Merge 2 x 1d temp arrays into one 2d array

4 posts in this topic

#1 ·  Posted (edited)

Hello all,

Summary: I have a basic piece of code that is to be a part of a much larger project; I just can't seem to get the right output. I'm retrieving two lots of powershell data into 2 x 1d arrays and trying to add them into a single 2d array. Retrieving the data together into the 2d array seemed harder, due to the application names varying too much to string split. Data being pulled is application name and GUID. From here I will use this info in a drop down box and an uninstall button to run the required command to remove the selected software (have this sorted already).

Problem: When I merge the data it doesn't put the application name and GUID on the same row in differing columns eg. my test box has 24 applications plus some superfluous data from Powershell to be cleaned up by the _arraydeletes. Instead I end up with an array with 58 rows and 2 columns; whereas my temp 1d arrays have 28 rows. As you can see I've tried both _ArrayInsert and _ArrayAdd but I still get the same result.

Question: Is there something that I'm doing wrong in putting the data into the 2d array or do I just need to do some more post processing to tidy it up and align the names and GUIDs?

Code:

#include <Array.au3>

$Cmd1 = (" /c Powershell.exe " & Chr(34) & "Get-WmiObject -Class win32reg_addremoveprograms | where {$_.ProdID -like " & Chr(34) & Chr(123) & Chr(42) & Chr(125) & Chr(34) & "} | select DisplayName" & Chr(34))
$Cmd2 = (" /c Powershell.exe " & Chr(34) & "Get-WmiObject -Class win32reg_addremoveprograms | where {$_.ProdID -like " & Chr(34) & Chr(123) & Chr(42) & Chr(125) & Chr(34) & "} | select ProdID" & Chr(34))

Global $aNameGUID[1][2]
;_ArrayDisplay($aNameGUID)
ReadApps($Cmd1,0)
;_ArrayDisplay($aNameGUID)
ReadApps($Cmd2,1)
_ArrayDisplay($aNameGUID)
Terminate()

Func ReadApps($Command,$col)
    $DOS = Run(@ComSpec & $Command, "", @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
    ProcessWaitClose($DOS)
    $DOSOut = StdoutRead($DOS)
    ;MsgBox(0,"Data",$DOSOut) ;Show the line items that we want in the array
    Local $tmpArray = StringSplit(StringTrimRight(StringStripCR($DOSOut), StringLen(@CRLF)), @CRLF)
    If @error Then
        MsgBox(0,"FAIL","I failed to find objects")
        Exit
    Else
        _ArrayDisplay($tmpArray)
    EndIf
        ;_ArrayDelete($tmpArray, 3)
        ;_ArrayDelete($tmpArray, 2)
        ;_ArrayDelete($tmpArray, 1)
        ;$tmpArray[0] = $tmpArray[0] - 3
        For $i = 0 To UBound($tmpArray) - 1
            ;_ArrayAdd($aNameGUID, $tmpArray[$i], $col)
            _ArrayInsert($aNameGUID, 0, $tmpArray[$i], $col)
        Next
    $tmpArray = 0
EndFunc ;==>ReadApps

While 1
    Sleep(1500)
WEnd

Func Terminate()
    Exit 0
EndFunc   ;==>Terminate

Thanks in advance,

Luxyboy

Edited by StillLearningThisStuff
update

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Could you not retrieve both the DisplayName and ProdID in a single query?

Get-WmiObject -Class win32reg_addremoveprograms | where {$_.ProdID -like "{*}"} | select DisplayName, ProdID | Format-Table

You could also bypass using PowerShell and just query WMI directly from AutoIt (via COM object) and then format the data any way you want/need.

edit: WMI example

#include <Array.au3>  ;only needed for demo

$objWMIService = WMIService(@ComputerName)  ;WMIService Object - Establish Connection
If $objWMIService = 0 Then Exit

Local $strData[2]= ["DisplayName","ProdID"]  ;Data to Return from WMI Query

$arrResults = WMIQuery($objWMIService,"SELECT * FROM Win32Reg_AddRemovePrograms",$strData)  ;Run WMI Query against WMIService Object
$objWMIService = 0  ;Termninate WMIService Object

_ArrayDisplay($arrResults)

Func WMIService($host) ;Connects to WMI Service
    $objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $host & "\root\cimv2")
    If not IsObj($objWMIService) Then return 0
    return $objWMIService
EndFunc

Func WMIQuery($objWMIService,$strWMIQuery,$arrData) ;Perform WMI Query with Query String and Data Return Parameters
    If not IsArray($arrData) then return 0
    $colItems = $objWMIService.ExecQuery ($strWMIQuery)  ;Execute query against WMI Service Object
    $iCount = $colItems.count
    If $iCOunt <= 0 Then return 0
    $iBound = UBound($arrData)
    Local $arrResults[$colItems.count+1][$iBound] ;Two-Dimension Array to store query Results

    For $i = 0 to $iBound-1
        $arrResults[0][$i] = $arrData[$i]
    Next

    Local $iIdx = 1
    For $objItem in $colItems
        For $i = 0 to $iBound - 1  ;Loop through WMI Query Results
            ;$arrResults[$iIdx][$i] = $arrData[$i]  ;Property/Data Name
            $arrResults[$iIdx][$i] = Execute("$objitem." & $arrData[$i])  ;Result
        Next
        $iIdx += 1
    Next

    return $arrResults  ;Return Result Array
EndFunc

 

Edited by spudw2k

Share this post


Link to post
Share on other sites

This should do it:

Func ReadApps($Command,$col)
    $DOS = Run(@ComSpec & $Command, "", @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
    ProcessWaitClose($DOS)
    $DOSOut = StdoutRead($DOS)
    ;MsgBox(0,"Data",$DOSOut) ;Show the line items that we want in the array
    Local $tmpArray = StringSplit(StringTrimRight(StringStripCR($DOSOut), StringLen(@CRLF)), @CRLF)
    If @error Then
        MsgBox(0,"FAIL","I failed to find objects")
        Exit
    Else
        _ArrayDisplay($tmpArray)
    EndIf
        ;_ArrayDelete($tmpArray, 3)
        ;_ArrayDelete($tmpArray, 2)
        ;_ArrayDelete($tmpArray, 1)
        ;$tmpArray[0] = $tmpArray[0] - 3
        If UBound($aNameGUID) < UBound($tmpArray) Then ReDim $aNameGUID[UBound($tmpArray)][2]
        For $i = 0 To UBound($tmpArray) - 1
            ;_ArrayAdd($aNameGUID, $tmpArray[$i], $col)
            ;_ArrayInsert($aNameGUID, 0, $tmpArray[$i], $col)
            $aNameGUID[$i][$col] = $tmpArray[$i]
        Next
    $tmpArray = 0
EndFunc ;==>ReadApps

 


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!
¯\_(ツ)_/¯

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

You can merge two 1D arrays to produce two columns like this, if that's what you want (see my signature).

#include 'ArrayWorkshop.au3'
Local $aTarget = ['a','b','c'], $aSource = [1,2,3]
_ArrayAttach($aTarget, $aSource, 2)

 

Edited by czardas

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  
Followers 0

  • Similar Content

    • SkysLastChance
      By SkysLastChance
      I keep losing the count of my $r varable when I go into the dropdown () function and call the same function.
      #include <Excel.au3> #include <AutoItConstants.au3> #include<GUIConstantsEx.au3> #include<EditConstants.au3> #include<GUIConstants.au3> Global $iBox, $oExcel, $oWorkbook, $r = 1, $x = 3 HowMany() Excel () Dropdown () Sleep (500) Func Dropdown () $list = GUICreate("Chart", 225, 80) $combobox = GUICtrlCreateCombo("Clinic 1", 10, 10, 120, 20) GUICtrlSetData(-1, "Clinic 2|Clinic 3|Clinic 4") $button = GUICtrlCreateButton("Select", 10, 40, 60, 20) GUISetState(@SW_SHOW) While 1 $guibox = GUIGetMsg() Select Case $guibox = $button Select Case GUICtrlRead($combobox) = "Clinic 1" GUIDelete($list) Auto () EndSelect Case $guibox = $GUI_EVENT_CLOSE EndSelect WEnd EndFunc Func HowMany() Local $iMsg While 1 ;~ Turn input into a number $iBox = Number(InputBox ("Regestration", "How Many Patients are there total?")) ;~ If user enters a string or cancels then get them to try again If $iBox = 0 Then $iMsg = MsgBox(1,'Regestration', 'Please enter a valid number') If $iMsg = 2 Then Exit Else ExitLoop EndIf WEnd EndFunc Func Excel() While ProcessExists("EXCEL.EXE") $ms = MsgBox(5,"","Process error. You have an Excel sheet open. You must close it in order to let this program work. Please close it now.") If $ms=2 Then Exit ;~ Doesn't require sleep since the script is paused by the MsgBox above ;~ Sleep(250) WEnd ;~ Shouldn't use Global Scope inside functions moved to top of script Local $sExcelFile = FileOpenDialog("Choose/Create Excel File", @ScriptDir, "(*.xlsx)") If FileExists($sExcelFile) Then ;~ Shouldn't use Global Scope inside functions moved to top of script $oExcel = _Excel_Open () $oWorkbook = _Excel_BookOpen($oExcel,$sExcelFile) ;this will open the chosen xls file. Else $oExcel = _Excel_Open() $oWorkbook = _Excel_BookNew($oExcel, 2);this is here to create the xls file if it does not exist. EndIf EndFunc Func Auto() Local $aArray1 = _Excel_RangeRead($oWorkbook) ;~ If $iBox is greater than no. of rows in $aArray then $iBox equals the number of rows in $aArray If $iBox > (UBound($aArray1) - 1) Then $iBox = UBound($aArray1) - 1 For $i = 2 To UBound($aArray1) - 1 ;$i =0 Start from row A If $aArray1[$i][1] = "" Then Continueloop $sR0 = $aArray1[$i][0] ;status $sR1 = $aArray1[$i][1] ;Last Name $sR2 = $aArray1[$i][2] ;First Name $sR3 = $aArray1[$i][3] ;DOB $sR4 = $aArray1[$i][4] ;Sex $sR5 = $aArray1[$i][5] ;Mailling Address $sR6 = $aArray1[$i][6] ;Zip $sR7 = $aArray1[$i][7] ;Phone # $sR8 = $aArray1[$i][8] ;Visit Reason $sR9 = $aArray1[$i][9] ;Insurance $sR10 = $aArray1[$i][10] ;Clinic $sR11 = $aArray1[$i][11] ;Provider $sR12 = $aArray1[$i][12] ;Appt Time $sR13 = $aArray1[$i][13] ;Appt Date WinWaitActive ("Untitled - Notepad") ControlSend("Untitled - Notepad", "", "", $sR1 & ',' & $sR2 & @CR) $r += 1 If $r > $iBox Then Exit Dropdown () Next EndFunc so the second time I choose clinic 1 I want it to go to the next row which would be Champ brett in my example excel.
       
      Test.xlsx
      Example Format.xlsx
    • 31290
      By 31290
      Hi guys, 
      I'd like to write a piece of tool that would allow me to update a certain field in our Active Directory from a comma separated csv file composed like this:

      This file, automatically generated, can hold more than 10k lines.
      Thus, I need column A to be in one variable, column B in a second one and column C in a third one.
      I'm really missing this part as updating the AD is fairly easy once the 3 variable are populated. 
      I see things like this:
      Here's my attempts at the moment:
      #include <File.au3> #include <Array.au3> Global $csv_file = @DesktopDir & "\Book1.csv" Global $aRecords If Not _FileReadToArray($csv_file,$aRecords) Then MsgBox(4096,"Error", " Error reading log to Array error:" & @error) Exit EndIf For $x = 1 to $aRecords[0] Msgbox(0,'Record:' & $x, $aRecords[$x]) ; Shows the line that was read from file $csv_line_values = StringSplit($aRecords[$x], ",",1) ; Splits the line into 2 or more variables and puts them in an array ; _ArrayDisplay($csv_line_values) ; Shows what's in the array you just created. ; $csv_line_values[0] holds the number of elements in array ; $csv_line_values[1] holds the value ; $csv_line_values[2] holds the value ; etc Msgbox(0, 0, $csv_line_values[1]) Next Any help on this please? 
      Thanks in advance
      -31290-
    • StMaSi
      By StMaSi
      So, I have a text file like this...
      "Label", {left}, {top}, {width}, {height} "Label", {left}, {top}, {width}, {height} "Label", {left}, {top}, {width}, {height} "Label", {left}, {top}, {width}, {height} "Label", {left}, {top}, {width}, {height} What I'm attempting to do is read the data from this file, into an array, and use it to create checkboxes on a form like this...
      For $cb = 0 to 4 ; line numbers $Checkbox[$cb] = GUICtrlCreateCheckbox({label}, {left}, {top}, {width}, {height}) Next However, I can't figure out how to read the file into the array so as to be able to assign the data elements appropriately. I'm obviously missing something (or more than likely more than one something), but can't figure it out.
      Can anyone assist with this?
      Thanx.
       
    • dexto
      By dexto
      Why idea why would I get an error (Autoit Beta 3.3.15.0):
      Local $json[] Local $map[] $map['test'] = 'hello' Local $array[5] = [1, 2, 3, 4, 5] $json["data"] = $map $json["data"]["arr"] = $array ConsoleWrite($json["data"]["arr"][0] & @CRLF)  
    • cookiemonster
      By cookiemonster
      Im trying to read a JSON file into an array.
       
      The JSON looks like this:
       
      { "project_info": { "project_number": "123456789", "url": "https://www.website.com", "project_id": "PRJ08", "Bucket": "Buk09" }, "client": [ { "client_info": { "id": "1:1001306455", "info": { "name": "banana" } }, "oauth_client": [ { "client_id": "1001306455694-m3h6v", "client_type": 3 } ], "a_key": [ { "key": "dkldkdkd" } ], "Avail": { "ana": { "status": 1 }, "vit": { "status": 1, "other": [] }, "ad": { "status": 2 } } }, { "client_info": { "id": "1:1838346", "info": { "name": "orange" } }, "oauth_client": [ { "client_id": "2145696315633-dmdhe", "client_type": 3 } ], "a_key": [ { "key": "osikdme" } ], "Avail": { "ana": { "status": 1 }, "vit": { "status": 1, "other": [] }, "ad": { "status": 2 } } }, ], "configuration_version": "1" } What I want to do is read it all into one single large array, can anyone help? 
      All I have so far is:
      #include "JSON.au3" #include "array.au3" $file = fileread("C:\file.json") JsonToArray($file) Func JsonToArray($JSON) $JSON = StringRegExpReplace($JSON, "[\[\]{}]", "") $sBreak = StringSplit($JSON, ",") For $a = 1 To $sBreak[0] $t = _JSONDecode("{" & $sBreak[$a] & "}") _ArrayDisplay($t, "multi " & $a & " of " & $sBreak[0]) Next EndFunc ;==>JsonToArray