rcmaehl Posted March 15, 2018 Share Posted March 15, 2018 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 WhyNotWin11Cisco Finesse, Github, IRC UDF, WindowEx UDF Link to comment Share on other sites More sharing options...
Subz Posted March 16, 2018 Share Posted March 16, 2018 What about: _ArrayDelete($aPostProcesss, "0-" & $aPreProcesses[0]) Link to comment Share on other sites More sharing options...
rcmaehl Posted March 16, 2018 Author Share Posted March 16, 2018 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 WhyNotWin11Cisco Finesse, Github, IRC UDF, WindowEx UDF Link to comment Share on other sites More sharing options...
Bilgus Posted March 16, 2018 Share Posted March 16, 2018 That seems like a potentially flaky program to me What if you altered the function _ArrayUnique() to remove any PID that exists twice?? expandcollapse popup#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 Link to comment Share on other sites More sharing options...
Bilgus Posted March 16, 2018 Share Posted March 16, 2018 (edited) expandcollapse popup#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 March 16, 2018 by Bilgus Got Fancy - added process name as well Link to comment Share on other sites More sharing options...
rcmaehl Posted March 16, 2018 Author Share Posted March 16, 2018 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?? expandcollapse popup#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 WhyNotWin11Cisco Finesse, Github, IRC UDF, WindowEx UDF Link to comment Share on other sites More sharing options...
Bilgus Posted March 16, 2018 Share Posted March 16, 2018 (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 March 16, 2018 by Bilgus 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