Jump to content
rcmaehl

There's no _ArrayRemove is there....

Recommended Posts

rcmaehl

Hi All,

I see that _ArrayAdd can combine two arrays into one, however I can't see to find a way to undo that within a single function. For example:

$aRunning = ProcessList()
$aRunning[0][1] = $aRunning[0][0]
_ArrayColDelete($aRunning,0,True)
$aPreProcesses = $aRunning
$iNotepad = ShellExecute("notepad.exe")
$aRunning = ProcessList()
$aRunning[0][1] = $aRunning[0][0]
_ArrayColDelete($aRunning,0,True)
$aPostProcesss = $aRunning
_ArrayDisplay($aPreProcesses)
_ArrayDisplay($aPostProcesss)
_ArrayDelete($aPostProcesss, $aPreProcesses)
_ArrayDisplay($aPostProcesss)

Should leave only a single entry being the PID of Notepad but it isn't. Is there anyway to do this without taking a huge hit on script execution time?


My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated.

My Projects
Cisco FinesseGithubIRC UDFWindowEx UDF

 

Share this post


Link to post
Share on other sites
Subz

What about:

_ArrayDelete($aPostProcesss, "0-" & $aPreProcesses[0])

 

Share this post


Link to post
Share on other sites
rcmaehl
2 hours ago, Subz said:

What about:

_ArrayDelete($aPostProcesss, "0-" & $aPreProcesses[0])

 

That would always delete indexs 0 through $aPreProcesses[0] which could be incorrect :/ I guess it seems to technically work, I'm guessing ProcessList() lists in order of first created to last created but I don't wanna risk it. @guinness mind if I bug you to confirm this theory?


My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated.

My Projects
Cisco FinesseGithubIRC UDFWindowEx UDF

 

Share this post


Link to post
Share on other sites
Bilgus

That seems like a potentially flaky program to me

What if you altered the function _ArrayUnique() to remove any PID that exists twice??

#include <Array.au3>
$aRunning = ProcessList()
$aRunning_TRY2 = $aRunning
$aRunning[0][1] = $aRunning[0][0]
_ArrayColDelete($aRunning,0,True)
$aPreProcesses = $aRunning

$iNotepad = ShellExecute("notepad.exe")

$aRunning = ProcessList()
$aRunning_TRY3 = $aRunning
$aRunning[0][1] = $aRunning[0][0]
_ArrayColDelete($aRunning,0,True)
$aPostProcesses = $aRunning

_ArrayDisplay($aPreProcesses)
_ArrayDisplay($aPostProcesses)

;ConsoleWrite(_ArrayDelete($aPostProcesses, $aPreProcesses))
ConsoleWrite(_ArrayDelete($aPostProcesses, "1 - " & $aPreProcesses[0]) & ":" & @error & @CRLF)
_ArrayDisplay($aPostProcesses)

;-------------------------------------
Msgbox(0,"","Next")
;$aRunning = ProcessList()
;$aRunning[0][1] = $aRunning[0][0]
;_ArrayColDelete($aRunning,0,True)
$aPreProcesses = $aRunning_TRY2;$aRunning

;$iNotepad = ShellExecute("notepad.exe")

;$aRunning = ProcessList()
;$aRunning[0][1] = $aRunning[0][0]
;_ArrayColDelete($aRunning,0,True)
$aPostProcesses = $aRunning_TRY3;$aRunning


 _ArrayConcatenate ($aPostProcesses, $aPreProcesses, 1)
_ArrayDisplay(_ArrayDeDupe($aPostProcesses,1,0,1))


Func _ArrayDeDupe(Const ByRef $aArray, $iColumn = 0, $iBase = 0, $iCase = 0, $iCount = $ARRAYUNIQUE_COUNT, $iIntType = $ARRAYUNIQUE_AUTO)

    If $iColumn = Default Then $iColumn = 0
    If $iBase = Default Then $iBase = 0
    If $iCase = Default Then $iCase = 0
    If $iCount = Default Then $iCount = $ARRAYUNIQUE_COUNT
    ; Check array
    If UBound($aArray, $UBOUND_ROWS) = 0 Then Return SetError(1, 0, 0)
    Local $iDims = UBound($aArray, $UBOUND_DIMENSIONS), $iNumColumns = UBound($aArray, $UBOUND_COLUMNS)
    If $iDims > 2 Then Return SetError(2, 0, 0)
    ; Check parameters
    If $iBase < 0 Or $iBase > 1 Or (Not IsInt($iBase)) Then Return SetError(3, 0, 0)
    If $iCase < 0 Or $iCase > 1 Or (Not IsInt($iCase)) Then Return SetError(3, 0, 0)
    If $iCount < 0 Or $iCount > 1 Or (Not IsInt($iCount)) Then Return SetError(4, 0, 0)
    If $iIntType < 0 Or $iIntType > 4 Or (Not IsInt($iIntType)) Then Return SetError(5, 0, 0)
    If $iColumn < 0 Or ($iNumColumns = 0 And $iColumn > 0) Or ($iNumColumns > 0 And $iColumn >= $iNumColumns) Then Return SetError(6, 0, 0)
    ; Autocheck of first element
    If $iIntType = $ARRAYUNIQUE_AUTO Then
        Local $vFirstElem = ( ($iDims = 1) ? ($aArray[$iBase]) : ($aArray[$iColumn][$iBase]) )
        If IsInt($vFirstElem) Then
            Switch VarGetType($vFirstElem)
                Case "Int32"
                    $iIntType = $ARRAYUNIQUE_FORCE32
                Case "Int64"
                    $iIntType = $ARRAYUNIQUE_FORCE64
            EndSwitch
        Else
            $iIntType = $ARRAYUNIQUE_FORCE32
        EndIf
    EndIf
    ; Create error handler
    ObjEvent("AutoIt.Error", "__ArrayUnique_AutoErrFunc")
    ; Create dictionary
    Local $oDictionary = ObjCreate("Scripting.Dictionary")
    ; Set case sensitivity
    $oDictionary.CompareMode = Number(Not $iCase)
    ; Add elements to dictionary
    Local $vElem, $sType, $vKey, $bCOMError = False
    For $i = $iBase To UBound($aArray) - 1
        If $iDims = 1 Then
            ; 1D array
            $vElem = $aArray[$i]
        Else
            ; 2D array
            $vElem = $aArray[$i][$iColumn]
        EndIf
        ; Determine method to use
        Switch $iIntType
            Case $ARRAYUNIQUE_FORCE32

                If $oDictionary.Exists($vElem) Then ;<---------------------------------------------------DE-DUPE
                    ConsoleWrite("ARRAYUNIQUE_FORCE32 DUPE " & $vElem & @CRLF)
                    $oDictionary.Remove ($vElem)
                Else
                    ; Use element as key
                    $oDictionary.Item($vElem)
                EndIF


                If @error Then
                    $bCOMError = True ; Failed with an Int64, Ptr or Binary datatype
                    ExitLoop
                EndIf
            Case $ARRAYUNIQUE_FORCE64
                $sType = VarGetType($vElem)
                If $sType = "Int32" Then
                    $bCOMError = True ; Failed with an Int32 datatype
                    ExitLoop
                EndIf ; Create key
                $vKey = "#" & $sType & "#" & String($vElem)

                If $oDictionary.Exists($vKey) Then ;<---------------------------------------------------DE-DUPE
                    ConsoleWrite("ARRAYUNIQUE_FORCE64 DUPE " & $vKey & @CRLF)
                    $oDictionary.Remove ($vKey)
                Else
                    $oDictionary($vKey) = $vElem ; Store actual value in dictionary
                EndIF

            Case $ARRAYUNIQUE_MATCH
                $sType = VarGetType($vElem)
                If StringLeft($sType, 3) = "Int" Then
                    $vKey = "#Int#" & String($vElem)
                Else
                    $vKey = "#" & $sType & "#" & String($vElem)
                EndIf
                If $oDictionary.Exists($vKey) Then ;<---------------------------------------------------DE-DUPE
                    ConsoleWrite("ARRAYUNIQUE_MATCH DUPE " & $vKey & @CRLF)
                    $oDictionary.Remove ($vKey)
                Else
                    $oDictionary($vKey) = $vElem ; Store actual value in dictionary
                EndIF
            Case $ARRAYUNIQUE_DISTINCT
                $vKey = "#" & VarGetType($vElem) & "#" & String($vElem)
                If $oDictionary.Exists($vKey) Then ;<---------------------------------------------------DE-DUPE
                    ConsoleWrite("ARRAYUNIQUE_DISTINCT DUPE " & $vKey & @CRLF)
                    $oDictionary.Remove ($vKey)
                Else
                    $oDictionary($vKey) = $vElem ; Store actual value in dictionary
                EndIF
        EndSwitch
    Next
    ; Create return array
    Local $aValues, $j = 0
    If $bCOMError Then ; Mismatch Int32/64
        Return SetError(7, 0, 0)
    ElseIf $iIntType <> $ARRAYUNIQUE_FORCE32 Then
        ; Extract values associated with the unique keys
        Local $aValues[$oDictionary.Count]
        For $vKey In $oDictionary.Keys()
            $aValues[$j] = $oDictionary($vKey)
            ; Check for Ptr datatype
            If StringLeft($vKey, 5) = "#Ptr#" Then
                $aValues[$j] = Ptr($aValues[$j])
            EndIf
            $j += 1
        Next
    Else
        ; Only need to list the unique keys
        $aValues = $oDictionary.Keys()
    EndIf
    ; Add cout if required
    If $iCount Then
        _ArrayInsert($aValues, 0, $oDictionary.Count)
    EndIf
    ; Return array
    Return $aValues

EndFunc   ;==>_ArrayUnique

I added $oDictionary.Exists() to each of the key type because for some reason I couldn't get Force32 to work right when the key already existed so for consistency I did them all that way although you can probably remove quite a bit out of that function and only use FORCE32 and make it a DeDupe for Strictly PIDs

Share this post


Link to post
Share on other sites
Bilgus
Posted (edited)
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <Array.au3>
$aPreProcesses = ProcessList()

$iNotepad = ShellExecute("notepad.exe")
Msgbox(0,"Run or Exit Some Applications","")

$aPostProcesses = ProcessList()

_ArrayConcatenate($aPostProcesses, $aPreProcesses, 1)

_ArrayDisplay(_ArrayDeDupePID($aPostProcesses))
;With Process Name
_ArrayDisplay(_ArrayDeDupePID2($aPostProcesses))

Func _ArrayDeDupePID(Const ByRef $aProcList)

    ; Check array
    If UBound($aProcList, $UBOUND_ROWS) = 0 Then Return SetError(1, 0, 0)
    If UBound($aProcList, $UBOUND_DIMENSIONS) <> 2 Then Return SetError(2, 0, 0)

    ; Create error handler
    ObjEvent("AutoIt.Error", "__ArrayDeDupePID_AutoErrFunc")
    ; Create dictionary
    Local $oDictionary = ObjCreate("Scripting.Dictionary")
    ; Set case sensitivity
    $oDictionary.CompareMode = 0 ;Binary Compare
    ; Add elements to dictionary
    Local $vElem, $bCOMError = False
    For $i = 1 To UBound($aProcList) - 1
        ; 2D array
        $vElem = $aProcList[$i][1]

        If $oDictionary.Exists($vElem) Then
            ConsoleWrite("DUPE PID " & $vElem & @CRLF)
            $oDictionary.Remove($vElem)
        Else
            ; Use element as key
            $oDictionary.Item($vElem)
        EndIf

        If @error Then
            $bCOMError = True ; Failed with an Int64, Ptr or Binary datatype
            ExitLoop
        EndIf
    Next
    ; Create return array
    Local $aValues
    If $bCOMError Then ; Mismatch Int32/64
        Return SetError(7, 0, 0)
    Else
        ; Only need to list the unique keys
        $aValues = $oDictionary.Keys()
    EndIf
    $oDictionary.RemoveAll ;would be cleaned up anyway..
    ; Return array
    Return $aValues

EndFunc   ;==>_ArrayDeDupePID

Func _ArrayDeDupePID2(Const ByRef $aProcList)

    ; Check array
    If UBound($aProcList, $UBOUND_ROWS) = 0 Then Return SetError(1, 0, 0)
    If UBound($aProcList, $UBOUND_DIMENSIONS) <> 2 Then Return SetError(2, 0, 0)

    ; Create error handler
    ObjEvent("AutoIt.Error", "__ArrayDeDupePID_AutoErrFunc")
    ; Create dictionary
    Local $oDictionary = ObjCreate("Scripting.Dictionary")
    ; Set case sensitivity
    $oDictionary.CompareMode = 0 ;Binary Compare
    ; Add elements to dictionary
    Local $vElem, $bCOMError = False
    For $i = 1 To UBound($aProcList) - 1
        ; 2D array
        $vElem = $aProcList[$i][1]

        If $oDictionary.Exists($vElem) Then
            ConsoleWrite("DUPE PID " & $vElem & @CRLF)
            $oDictionary.Remove($vElem)
        Else
            ; Use element as key
            $oDictionary.Item($vElem) = $i
        EndIf

        If @error Then
            $bCOMError = True ; Failed with an Int64, Ptr or Binary datatype
            ExitLoop
        EndIf
    Next
    ; Create return array
    Local $aValues
    If $bCOMError Then ; Mismatch Int32/64
        Return SetError(7, 0, 0)
    Else
        ; Extract values associated with the unique keys
        Local $aValues[$oDictionary.Count][2], $j = 0
        For $vKey In $oDictionary.Keys()
            $aValues[$j][1] = $vKey
            $aValues[$j][0] = $aProcList[$oDictionary.Item($vKey)][0]
            $j += 1
        Next
    EndIf
    $oDictionary.RemoveAll ;would be cleaned up anyway..
    ; Return array
    Return $aValues

EndFunc   ;==>_ArrayDeDupePID2

Func __ArrayDeDupePID_AutoErrFunc()
    ; Do nothing special, just check @error after suspect functions.
EndFunc   ;==>__ArrayDeDupePID_AutoErrFunc

 

Edited by Bilgus
Got Fancy - added process name as well

Share this post


Link to post
Share on other sites
rcmaehl
9 hours ago, Bilgus said:

That seems like a potentially flaky program to me

What if you altered the function _ArrayUnique() to remove any PID that exists twice??

#include <Array.au3>
$aRunning = ProcessList()
$aRunning_TRY2 = $aRunning
$aRunning[0][1] = $aRunning[0][0]
_ArrayColDelete($aRunning,0,True)
$aPreProcesses = $aRunning

$iNotepad = ShellExecute("notepad.exe")

$aRunning = ProcessList()
$aRunning_TRY3 = $aRunning
$aRunning[0][1] = $aRunning[0][0]
_ArrayColDelete($aRunning,0,True)
$aPostProcesses = $aRunning

_ArrayDisplay($aPreProcesses)
_ArrayDisplay($aPostProcesses)

;ConsoleWrite(_ArrayDelete($aPostProcesses, $aPreProcesses))
ConsoleWrite(_ArrayDelete($aPostProcesses, "1 - " & $aPreProcesses[0]) & ":" & @error & @CRLF)
_ArrayDisplay($aPostProcesses)

;-------------------------------------
Msgbox(0,"","Next")
;$aRunning = ProcessList()
;$aRunning[0][1] = $aRunning[0][0]
;_ArrayColDelete($aRunning,0,True)
$aPreProcesses = $aRunning_TRY2;$aRunning

;$iNotepad = ShellExecute("notepad.exe")

;$aRunning = ProcessList()
;$aRunning[0][1] = $aRunning[0][0]
;_ArrayColDelete($aRunning,0,True)
$aPostProcesses = $aRunning_TRY3;$aRunning


 _ArrayConcatenate ($aPostProcesses, $aPreProcesses, 1)
_ArrayDisplay(_ArrayDeDupe($aPostProcesses,1,0,1))


Func _ArrayDeDupe(Const ByRef $aArray, $iColumn = 0, $iBase = 0, $iCase = 0, $iCount = $ARRAYUNIQUE_COUNT, $iIntType = $ARRAYUNIQUE_AUTO)

    If $iColumn = Default Then $iColumn = 0
    If $iBase = Default Then $iBase = 0
    If $iCase = Default Then $iCase = 0
    If $iCount = Default Then $iCount = $ARRAYUNIQUE_COUNT
    ; Check array
    If UBound($aArray, $UBOUND_ROWS) = 0 Then Return SetError(1, 0, 0)
    Local $iDims = UBound($aArray, $UBOUND_DIMENSIONS), $iNumColumns = UBound($aArray, $UBOUND_COLUMNS)
    If $iDims > 2 Then Return SetError(2, 0, 0)
    ; Check parameters
    If $iBase < 0 Or $iBase > 1 Or (Not IsInt($iBase)) Then Return SetError(3, 0, 0)
    If $iCase < 0 Or $iCase > 1 Or (Not IsInt($iCase)) Then Return SetError(3, 0, 0)
    If $iCount < 0 Or $iCount > 1 Or (Not IsInt($iCount)) Then Return SetError(4, 0, 0)
    If $iIntType < 0 Or $iIntType > 4 Or (Not IsInt($iIntType)) Then Return SetError(5, 0, 0)
    If $iColumn < 0 Or ($iNumColumns = 0 And $iColumn > 0) Or ($iNumColumns > 0 And $iColumn >= $iNumColumns) Then Return SetError(6, 0, 0)
    ; Autocheck of first element
    If $iIntType = $ARRAYUNIQUE_AUTO Then
        Local $vFirstElem = ( ($iDims = 1) ? ($aArray[$iBase]) : ($aArray[$iColumn][$iBase]) )
        If IsInt($vFirstElem) Then
            Switch VarGetType($vFirstElem)
                Case "Int32"
                    $iIntType = $ARRAYUNIQUE_FORCE32
                Case "Int64"
                    $iIntType = $ARRAYUNIQUE_FORCE64
            EndSwitch
        Else
            $iIntType = $ARRAYUNIQUE_FORCE32
        EndIf
    EndIf
    ; Create error handler
    ObjEvent("AutoIt.Error", "__ArrayUnique_AutoErrFunc")
    ; Create dictionary
    Local $oDictionary = ObjCreate("Scripting.Dictionary")
    ; Set case sensitivity
    $oDictionary.CompareMode = Number(Not $iCase)
    ; Add elements to dictionary
    Local $vElem, $sType, $vKey, $bCOMError = False
    For $i = $iBase To UBound($aArray) - 1
        If $iDims = 1 Then
            ; 1D array
            $vElem = $aArray[$i]
        Else
            ; 2D array
            $vElem = $aArray[$i][$iColumn]
        EndIf
        ; Determine method to use
        Switch $iIntType
            Case $ARRAYUNIQUE_FORCE32

                If $oDictionary.Exists($vElem) Then ;<---------------------------------------------------DE-DUPE
                    ConsoleWrite("ARRAYUNIQUE_FORCE32 DUPE " & $vElem & @CRLF)
                    $oDictionary.Remove ($vElem)
                Else
                    ; Use element as key
                    $oDictionary.Item($vElem)
                EndIF


                If @error Then
                    $bCOMError = True ; Failed with an Int64, Ptr or Binary datatype
                    ExitLoop
                EndIf
            Case $ARRAYUNIQUE_FORCE64
                $sType = VarGetType($vElem)
                If $sType = "Int32" Then
                    $bCOMError = True ; Failed with an Int32 datatype
                    ExitLoop
                EndIf ; Create key
                $vKey = "#" & $sType & "#" & String($vElem)

                If $oDictionary.Exists($vKey) Then ;<---------------------------------------------------DE-DUPE
                    ConsoleWrite("ARRAYUNIQUE_FORCE64 DUPE " & $vKey & @CRLF)
                    $oDictionary.Remove ($vKey)
                Else
                    $oDictionary($vKey) = $vElem ; Store actual value in dictionary
                EndIF

            Case $ARRAYUNIQUE_MATCH
                $sType = VarGetType($vElem)
                If StringLeft($sType, 3) = "Int" Then
                    $vKey = "#Int#" & String($vElem)
                Else
                    $vKey = "#" & $sType & "#" & String($vElem)
                EndIf
                If $oDictionary.Exists($vKey) Then ;<---------------------------------------------------DE-DUPE
                    ConsoleWrite("ARRAYUNIQUE_MATCH DUPE " & $vKey & @CRLF)
                    $oDictionary.Remove ($vKey)
                Else
                    $oDictionary($vKey) = $vElem ; Store actual value in dictionary
                EndIF
            Case $ARRAYUNIQUE_DISTINCT
                $vKey = "#" & VarGetType($vElem) & "#" & String($vElem)
                If $oDictionary.Exists($vKey) Then ;<---------------------------------------------------DE-DUPE
                    ConsoleWrite("ARRAYUNIQUE_DISTINCT DUPE " & $vKey & @CRLF)
                    $oDictionary.Remove ($vKey)
                Else
                    $oDictionary($vKey) = $vElem ; Store actual value in dictionary
                EndIF
        EndSwitch
    Next
    ; Create return array
    Local $aValues, $j = 0
    If $bCOMError Then ; Mismatch Int32/64
        Return SetError(7, 0, 0)
    ElseIf $iIntType <> $ARRAYUNIQUE_FORCE32 Then
        ; Extract values associated with the unique keys
        Local $aValues[$oDictionary.Count]
        For $vKey In $oDictionary.Keys()
            $aValues[$j] = $oDictionary($vKey)
            ; Check for Ptr datatype
            If StringLeft($vKey, 5) = "#Ptr#" Then
                $aValues[$j] = Ptr($aValues[$j])
            EndIf
            $j += 1
        Next
    Else
        ; Only need to list the unique keys
        $aValues = $oDictionary.Keys()
    EndIf
    ; Add cout if required
    If $iCount Then
        _ArrayInsert($aValues, 0, $oDictionary.Count)
    EndIf
    ; Return array
    Return $aValues

EndFunc   ;==>_ArrayUnique

I added $oDictionary.Exists() to each of the key type because for some reason I couldn't get Force32 to work right when the key already existed so for consistency I did them all that way although you can probably remove quite a bit out of that function and only use FORCE32 and make it a DeDupe for Strictly PIDs

I'll give it a try once I get back from lunch. Looks interesting.


My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated.

My Projects
Cisco FinesseGithubIRC UDFWindowEx UDF

 

Share this post


Link to post
Share on other sites
Bilgus
Posted (edited)

Here is the same just does the concatenate within the function

This gets rid of the overhead in extra checking of arrays and redim in _ArrayConcatenate

The change also allows you to easily take a single snapshot and check repeatedly against the new processlist

Edit - Now it returns PID, Processname, Status for the EX version of the function

 

 

You could then Check if the returned process exists in the PreProcesslist to see if  a process was stopped or started

Edit - Went ahead and added the functionality

Edited by Bilgus

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

×