Jump to content

Some stupid problem with probably easy solution


Sars!
 Share

Recommended Posts

Hey guys,

I took my favourite memory searcher (T-search) and went to look for the ammount of memory a certain program uses. I opened taskmanager, and looked for the value. For some reason I didn't find any adress for the value. The program I want to create:

I want the program to detect the memory usage of a certain process, and as soon as the value changes do an action. As soon as the value stays constant, I want it to do another action.

Looking forward for help :)

Grtz,

Sars!

Link to comment
Share on other sites

Try looking at the Process... functions in the help file. I have not worked with them that much, but they should do the job for you.

David Nuttall
Nuttall Computer Consulting

An Aquarius born during the Age of Aquarius

AutoIt allows me to re-invent the wheel so much faster.

I'm off to write a wizard, a wonderful wizard of odd...

Link to comment
Share on other sites

BUMP?

I don't know enough of c++ :P

Thx in advance,

Sars!

Is this an AutoIt question? Because this is an AutoIt forum...

:)

Edit: If it is an AutoIt solution you were looking for, I haven't found it yet. I did a UDF called _ProcessListProperties(), but never figured out how to get per-process memory usage for it. I understand it can be done with third-party .exe or .dll files (weaponx mentioned one, I believe), but I'm hoping to find a way with just AutoIt and the existing Windows environment.

:)

Edited by PsaltyDS
Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

Well I'm aiming for it to be done through autoit...

Alternatives that are possible are welcome too :)

Grtz,

Sars!

I also found this:

_API_GlobalMemStatus

$aMem[0] - Percent of Mem in use

$aMem[1] - Physical Mem: Total

$aMem[2] - Physical Mem: Free

$aMem[3] - Paging file: Total

$aMem[4] - Paging file: Free

$aMem[5] - User Mem: Total

$aMem[6] - User Mem: Free

But won't give a specific process information...

Grtz,

Sars!

Edited by Sars!
Link to comment
Share on other sites

Well I'm aiming for it to be done through autoit...

Alternatives that are possible are welcome too :)

Grtz,

Sars!

I also found this:

_API_GlobalMemStatus

But won't give a specific process information...

That's part of PaulIA's excellent Auto3Lib AutoIt Library, and very similar to the native MemGetStats(). But, as you say, neither gives info on a single process.

This looks like it might do it: GetProcessMemoryInfo Function

Uses PSAPI.dll which comes with Windows (NT and above at least), but I don't know enough about DLLs yet to figure out the call from AutoIt.

:)

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

:) Woo Hoo! I think I found it! :)

#include <array.au3> ; for _ArrayDisplay()

$avRET = _ProcessListProperties()
_ArrayDisplay($avRET, "Debug: $avProcs, @error = " & @error)


;===============================================================================
; Function Name:    _ProcessListProperties()
; Description:      Get various properties of a process, or all processes
; Call With:        _ProcessListProperties( [$Process [, $sComputer]] )
; Parameter(s):     (optional) $Process - PID or name of a process, default is all
;                   (optional) $sComputer - remote computer to get list from, default is local
; Requirement(s):   AutoIt v3.2.4.9+
; Return Value(s):  On Success - Returns a 2D array of processes, as in ProcessList()
;             with additional columns added:
;             [0][0] - Number of processes listed (can be 0 if no matches found)
;             [1][0] - 1st process name
;             [1][1] - 1st process PID
;             [1][2] - 1st process Parent PID
;             [1][3] - 1st process owner
;             [1][4] - 1st process priority (0 = low, 31 = high)
;             [1][5] - 1st process executable path
;             [1][6] - 1st process CPU usage
;             [1][7] - 1st process memory usage
;             ...
;             [n][0] thru [n][7] - last process properties
; On Failure:       Returns array with [0][0] = 0 and sets @Error to non-zero (see code below)
; Author(s):        PsaltyDS at http://www.autoitscript.com/forum
; Notes:            If a numeric PID or string process name is provided and no match is found,
;             then [0][0] = 0 and @error = 0 (not treated as an error, same as ProcessList)
;           This function requires admin permissions to the target computer.
;           All properties come from the Win32_Process class in WMI.
;===============================================================================
Func _ProcessListProperties($Process = "", $sComputer = ".")
    Local $sUserName, $sMsg, $sUserDomain, $avProcs
    If $Process = "" Then
        $avProcs = ProcessList()
    Else
        $avProcs = ProcessList($Process)
    EndIf

    ; Return for no matches
    If $avProcs[0][0] = 0 Then Return $avProcs

    ; ReDim array for additional property columns
    ReDim $avProcs[$avProcs[0][0] + 1][8]

    ; Connect to WMI and get process objects
    $oWMI = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $sComputer & "\root\cimv2")
    If IsObj($oWMI) Then
        ; Get collection of all processes from Win32_Process
        $colProcs = $oWMI.ExecQuery ("select * from win32_process")
        If IsObj($colProcs) Then
            ; For each process...
            For $oProc In $colProcs
                ; Find it in the array
                For $n = 1 To $avProcs[0][0]
                    If $avProcs[$n][1] = $oProc.ProcessId Then

                        ; [n][2] = Parent PID
                        $avProcs[$n][2] = $oProc.ParentProcessId
                        ; [n][3] = Owner
                        If $oProc.GetOwner ($sUserName, $sUserDomain) = 0 Then $avProcs[$n][3] = $sUserDomain & "\" & $sUserName
                        ; [n][4] = Priority
                        $avProcs[$n][4] = $oProc.Priority
                        ; [n][5] = Executable path
                        $avProcs[$n][5] = $oProc.ExecutablePath

                        ExitLoop
                    EndIf
                Next
            Next
        Else
            SetError(2) ; Error getting process collection from WMI
        EndIf

        ; Get collection of all processes from Win32_PerfFormattedData_PerfProc_Process
        ; Have to use an SWbemRefresher to pull the collection, or all Perf data will be zeros
        Local $oRefresher = ObjCreate("WbemScripting.SWbemRefresher")
        $colProcs = $oRefresher.AddEnum ($oWMI, "Win32_PerfFormattedData_PerfProc_Process" ).objectSet
        $oRefresher.Refresh
        
        ; Time delay before calling refresher
        Local $iTime = TimerInit()
        Do
            Sleep(10)
        Until TimerDiff($iTime) > 100
        $oRefresher.Refresh
        
        ; Get PerfProc data
        For $oProc In $colProcs
            ; Find it in the array
            For $n = 1 To $avProcs[0][0]
                If $avProcs[$n][1] = $oProc.IDProcess Then
                    $avProcs[$n][6] = $oProc.PercentProcessorTime
                    $avProcs[$n][7] = $oProc.WorkingSet
                    ExitLoop
                EndIf
            Next
        Next
    Else
        SetError(1) ; Error connecting to WMI
    EndIf

    ; Return array
    Return $avProcs
EndFunc   ;==>_ProcessListProperties

Call it with $avRET = _ProcessListProperties($PID) where $PID is the process ID you want the info for, and $avRET[1][7] should be the memory usage.

I had been in that WMI function before, but didn't see that the .WorkingSet property was what the TaskManager seems to report for process memory usage.

:P

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

Although the WMI method posted above and the Computer Info UDF mentioned by Saunders (probably uses WMI too) solve the topic, so this will be kind of redundant, but for learning purposes...

This looks like it might do it: GetProcessMemoryInfo Function

Uses PSAPI.dll which comes with Windows (NT and above at least), but I don't know enough about DLLs yet to figure out the call from AutoIt.

Call it like this:

Run("notepad")
WinWait("Untitled - Notepad")
MsgBox(0,"",_ProcessGetMem("notepad.exe"))

Func _ProcessGetMem($sProcess)
    ;get process ID
    $nPID = ProcessExists($sProcess)
    If $nPID = 0 Then Return -1
    ;get process handle, required for GetProcessMemoryInfo
    $aRet = DllCall("Kernel32.dll", "int", "OpenProcess", _
                                        "dword", $PROCESS_QUERY_INFORMATION+$PROCESS_VM_READ, "dword", False, "dword", $nPID)
    If @error Or ($aRet[0] = 0) Then Return -1
    $hProc = $aRet[0]
    ;create PPROCESS_MEMORY_COUNTERS to receive data, required for GetProcessMemoryInfo
    $structPROCESS_MEMORY_COUNTERS = DllStructCreate("dword; dword; uint peakmemsize; uint memsize; uint; uint; uint; uint; uint; uint")
    $nSize = DllStructGetSize($structPROCESS_MEMORY_COUNTERS)
    ;call GetProcessMemoryInfo
    $aRet = DllCall("Psapi.dll", "int", "GetProcessMemoryInfo", _
                                        "hwnd", $hProc, "ptr", DllStructGetPtr($structPROCESS_MEMORY_COUNTERS), "dword", $nSize)
    ;close process handle
    DllCall("Kernel32.dll", "int", "CloseHandle", "hwnd", $hProc)
    ;return memory size in kb
    Return DllStructGetData($structPROCESS_MEMORY_COUNTERS, "memsize") / 1024
EndFunc
Edited by Siao

"be smart, drink your wine"

Link to comment
Share on other sites

Although the WMI method posted above and the Computer Info UDF mentioned by Saunders (probably uses WMI too) solve the topic, so this will be kind of redundant, but for learning purposes...

Oh, you 'da man! Thanks! I had to add this to get it to run though:

Global Const $PROCESS_QUERY_INFORMATION = 0x400
Global Const $PROCESS_VM_READ = 0x10

JSThePatriot's UDF does in fact use the same WMI Win32_Process interface I used for the first six properties in mine. He's using the .WorkingSetSize property from there, and I used the .WorkingSet property from Win32_PerfFormattedData_PerfProc_Process because I already had it open for the percent processor time, which the Win32_Process interface doesn't provide (I don't think so, anyway).

My input parameter options are different, too.

:)

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

  • 1 month later...

:P Woo Hoo! I think I found it! ;)

#include <array.au3> ; for _ArrayDisplay()

$avRET = _ProcessListProperties()
_ArrayDisplay($avRET, "Debug: $avProcs, @error = " & @error)


;===============================================================================
; Function Name:    _ProcessListProperties()
; Description:      Get various properties of a process, or all processes
; Call With:        _ProcessListProperties( [$Process [, $sComputer]] )
; Parameter(s):     (optional) $Process - PID or name of a process, default is all
;                   (optional) $sComputer - remote computer to get list from, default is local
; Requirement(s):   AutoIt v3.2.4.9+
; Return Value(s):  On Success - Returns a 2D array of processes, as in ProcessList()
;             with additional columns added:
;             [0][0] - Number of processes listed (can be 0 if no matches found)
;             [1][0] - 1st process name
;             [1][1] - 1st process PID
;             [1][2] - 1st process Parent PID
;             [1][3] - 1st process owner
;             [1][4] - 1st process priority (0 = low, 31 = high)
;             [1][5] - 1st process executable path
;             [1][6] - 1st process CPU usage
;             [1][7] - 1st process memory usage
;             ...
;             [n][0] thru [n][7] - last process properties
; On Failure:       Returns array with [0][0] = 0 and sets @Error to non-zero (see code below)
; Author(s):        PsaltyDS at http://www.autoitscript.com/forum
; Notes:            If a numeric PID or string process name is provided and no match is found,
;             then [0][0] = 0 and @error = 0 (not treated as an error, same as ProcessList)
;           This function requires admin permissions to the target computer.
;           All properties come from the Win32_Process class in WMI.
;===============================================================================
Func _ProcessListProperties($Process = "", $sComputer = ".")
    Local $sUserName, $sMsg, $sUserDomain, $avProcs
    If $Process = "" Then
        $avProcs = ProcessList()
    Else
        $avProcs = ProcessList($Process)
    EndIf

    ; Return for no matches
    If $avProcs[0][0] = 0 Then Return $avProcs

    ; ReDim array for additional property columns
    ReDim $avProcs[$avProcs[0][0] + 1][8]

    ; Connect to WMI and get process objects
    $oWMI = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $sComputer & "\root\cimv2")
    If IsObj($oWMI) Then
        ; Get collection of all processes from Win32_Process
        $colProcs = $oWMI.ExecQuery ("select * from win32_process")
        If IsObj($colProcs) Then
            ; For each process...
            For $oProc In $colProcs
                ; Find it in the array
                For $n = 1 To $avProcs[0][0]
                    If $avProcs[$n][1] = $oProc.ProcessId Then

                        ; [n][2] = Parent PID
                        $avProcs[$n][2] = $oProc.ParentProcessId
                        ; [n][3] = Owner
                        If $oProc.GetOwner ($sUserName, $sUserDomain) = 0 Then $avProcs[$n][3] = $sUserDomain & "\" & $sUserName
                        ; [n][4] = Priority
                        $avProcs[$n][4] = $oProc.Priority
                        ; [n][5] = Executable path
                        $avProcs[$n][5] = $oProc.ExecutablePath

                        ExitLoop
                    EndIf
                Next
            Next
        Else
            SetError(2) ; Error getting process collection from WMI
        EndIf

        ; Get collection of all processes from Win32_PerfFormattedData_PerfProc_Process
        ; Have to use an SWbemRefresher to pull the collection, or all Perf data will be zeros
        Local $oRefresher = ObjCreate("WbemScripting.SWbemRefresher")
        $colProcs = $oRefresher.AddEnum ($oWMI, "Win32_PerfFormattedData_PerfProc_Process" ).objectSet
        $oRefresher.Refresh
        
        ; Time delay before calling refresher
        Local $iTime = TimerInit()
        Do
            Sleep(10)
        Until TimerDiff($iTime) > 100
        $oRefresher.Refresh
        
        ; Get PerfProc data
        For $oProc In $colProcs
            ; Find it in the array
            For $n = 1 To $avProcs[0][0]
                If $avProcs[$n][1] = $oProc.IDProcess Then
                    $avProcs[$n][6] = $oProc.PercentProcessorTime
                    $avProcs[$n][7] = $oProc.WorkingSet
                    ExitLoop
                EndIf
            Next
        Next
    Else
        SetError(1) ; Error connecting to WMI
    EndIf

    ; Return array
    Return $avProcs
EndFunc   ;==>_ProcessListProperties

Call it with $avRET = _ProcessListProperties($PID) where $PID is the process ID you want the info for, and $avRET[1][7] should be the memory usage.

I had been in that WMI function before, but didn't see that the .WorkingSet property was what the TaskManager seems to report for process memory usage.

:)

This function works great with one small issue :P

If I call this function at the same time as process is closing, I will get an error:

The requested action with this object has failed.:

If $oProc.GetOwner ($sUserName, $sUserDomain) = 0 Then $avProcs[$n][3] = $sUserDomain & "\" & $sUserName

If $oProc.GetOwner ($sUserName, $sUserDomain) ^ ERROR

AutoIt 3.2.9.4

My Projects - WindowDarken (Darken except the active window) Yahsmosis Chat Client (Discontinued) StarShooter Game (Red alert! All hands to battlestations!) YMSG Protocol Support (Discontinued) Circular Keyboard and OSK example. (aka Iris KB) Target Screensaver Drive Toolbar Thingy Rollup Pro (Minimize-to-Titlebar & More!) 2D Launcher physics example Ascii Screenshot AutoIt3 Quine Example ("Is a Quine" is a Quine.) USB Lock (Another system keydrive - with a toast.)

Link to comment
Share on other sites

This function works great with one small issue ;)

If I call this function at the same time as process is closing, I will get an error:

The requested action with this object has failed.:

If $oProc.GetOwner ($sUserName, $sUserDomain) = 0 Then $avProcs[$n][3] = $sUserDomain & "\" & $sUserName

If $oProc.GetOwner ($sUserName, $sUserDomain) ^ ERROR

AutoIt 3.2.9.4

Hmm... interesting problem. Thanks for finding and reporting that.

To keep the error from interrupting your script just add a COM error handler:

$oMyError = ObjEvent("AutoIt.Error","MyErrFunc") ; Install a custom error handler

; ... Rest of the script

; This is my custom error handler 
Func MyErrFunc() 
   $HexNumber=hex($oMyError.number,8) 
   ConsoleWrite("Debug:  Intercepted COM Error:  Number = " & $HexNumber & _
        "  Windescription = " & $oMyError.windescription & @LF) 
   SetError(1) ; something to check for when this function returns 
Endfunc

As for the error itself, I looked at having the the function test for existence of the process as it loops, but that leads to a question: Does the coder want to know about that disappearing process or not? If not, we just delete it from the array and ignore it. But if they are interested in it, then null data might be more appropriate. This is relatively likely to come up, since a fairly long 100ms delay is required to make the WbemScripting.SWbemRefresher work correctly, there is plenty of time for a processes to close (or open) while the function is running. On my system, when run without parameters to list all processes, it takes about 2.7sec on the first run and about 1.3sec for each run after that (some Windows caching speeds up repeated use of the WMI, I believe). That's a long time in CPU cycles and the life a process.

Here's what I'm thinking would be most useful to most people:

1. Add a COM error handler to your script any time you use COM methods in this function or any other (some UDFs like IE.au3 have their own).

2. Mod the function to return a value (like in @extended) to indicate if the process list changed while the function ran.

I would like to hear what other think would be the best generic behavior for this function and I will post a modified version.

:P

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

Actually, I haven't been able to reproduce the COM error. I tested it this way, with a debug hack in the middle of the function that kills notepad.exe after the process collection is retrieved, but before its properties are gathered. When I do this, notepad.exe is listed in the returned array with all null properties, as expected and no COM error, even though I don't have a COM error handler installed set up:

#include <array.au3> ; for _ArrayDisplay()

$PID = Run("notepad.exe")
$iTotalTime = TimerInit()
$avRET = _ProcessListProperties()
$iTotalTime = Round(TimerDiff($iTotalTime) / 1000, 3)
_ArrayDisplay($avRET, "Debug: $avProcs, $iTotalTime = " & $iTotalTime & "secs")

;===============================================================================
; Function Name:    _ProcessListProperties()
; Description:   Get various properties of a process, or all processes
; Call With:       _ProcessListProperties( [$Process [, $sComputer]] )
; Parameter(s):     (optional) $Process - PID or name of a process, default is all
;           (optional) $sComputer - remote computer to get list from, default is local
; Requirement(s):   AutoIt v3.2.4.9+
; Return Value(s):  On Success - Returns a 2D array of processes, as in ProcessList()
;             with additional columns added:
;             [0][0] - Number of processes listed (can be 0 if no matches found)
;             [1][0] - 1st process name
;             [1][1] - 1st process PID
;             [1][2] - 1st process Parent PID
;             [1][3] - 1st process owner
;             [1][4] - 1st process priority (0 = low, 31 = high)
;             [1][5] - 1st process executable path
;             [1][6] - 1st process CPU usage
;             [1][7] - 1st process memory usage
;             ...
;             [n][0] thru [n][7] - last process properties
; On Failure:       Returns array with [0][0] = 0 and sets @Error to non-zero (see code below)
; Author(s):        PsaltyDS at http://www.autoitscript.com/forum
; Notes:            If a numeric PID or string process name is provided and no match is found,
;             then [0][0] = 0 and @error = 0 (not treated as an error, same as ProcessList)
;           This function requires admin permissions to the target computer.
;           All properties come from the Win32_Process class in WMI.
;===============================================================================
Func _ProcessListProperties($Process = "", $sComputer = ".")
    Local $sUserName, $sMsg, $sUserDomain, $avProcs
    If $Process = "" Then
        $avProcs = ProcessList()
    Else
        $avProcs = ProcessList($Process)
    EndIf

    ; Return for no matches
    If $avProcs[0][0] = 0 Then Return $avProcs

    ; ReDim array for additional property columns
    ReDim $avProcs[$avProcs[0][0] + 1][8]

    ; Connect to WMI and get process objects
    $oWMI = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $sComputer & "\root\cimv2")
    If IsObj($oWMI) Then
        ; Get collection of all processes from Win32_Process
        $colProcs = $oWMI.ExecQuery("select * from win32_process")
        If IsObj($colProcs) Then
            
            ; !!! --------------------------------------------------------------!!!
            ; Debug:  kill notepad so the proces is gone before checking the object
            ProcessClose($PID, 1)
            ProcessWaitClose($PID, 2)
            ; !!! --------------------------------------------------------------!!!
            
            ; For each process...
            For $oProc In $colProcs
                ; Find it in the array
                For $n = 1 To $avProcs[0][0]
                    If $avProcs[$n][1] = $oProc.ProcessId Then

                        ; [n][2] = Parent PID
                        $avProcs[$n][2] = $oProc.ParentProcessId
                        ; [n][3] = Owner
                        If $oProc.GetOwner($sUserName, $sUserDomain) = 0 Then $avProcs[$n][3] = $sUserDomain & "\" & $sUserName
                        ; [n][4] = Priority
                        $avProcs[$n][4] = $oProc.Priority
                        ; [n][5] = Executable path
                        $avProcs[$n][5] = $oProc.ExecutablePath

                        ExitLoop
                    EndIf
                Next
            Next
        Else
            SetError(2) ; Error getting process collection from WMI
        EndIf

        ; Get collection of all processes from Win32_PerfFormattedData_PerfProc_Process
        ; Have to use an SWbemRefresher to pull the collection, or all Perf data will be zeros
        Local $oRefresher = ObjCreate("WbemScripting.SWbemRefresher")
        $colProcs = $oRefresher.AddEnum($oWMI, "Win32_PerfFormattedData_PerfProc_Process"  ).objectSet
        $oRefresher.Refresh

        ; Time delay before calling refresher
        Local $iTime = TimerInit()
        Do
            Sleep(10)
        Until TimerDiff($iTime) > 100
        $oRefresher.Refresh

        ; Get PerfProc data
        For $oProc In $colProcs
            ; Find it in the array
            For $n = 1 To $avProcs[0][0]
                If $avProcs[$n][1] = $oProc.IDProcess Then
                    $avProcs[$n][6] = $oProc.PercentProcessorTime
                    $avProcs[$n][7] = $oProc.WorkingSet
                    ExitLoop
                EndIf
            Next
        Next
    Else
        SetError(1) ; Error connecting to WMI
    EndIf

    ; Return array
    Return $avProcs
EndFunc   ;==>_ProcessListProperties

I've tried it on two machines, one has much better hardware specs than the other, but they are both XP Pro SP2 running AutoIt 3.2.8.1 Production and 3.2.9.9 Beta.

Anybody get a COM error out of this on a different config?

:P

Edited by PsaltyDS
Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

Now, just wait a cotton pick'n minute!

I just ran it several times as above without errors. Then I ran it with this change:

; !!! --------------------------------------------------------------!!!
            ; Debug:  kill notepad so the proces is gone before checking the object
            ;ProcessClose($PID, 1)
            ;ProcessWaitClose($PID, 2)
            MsgBox(64, "Breakpoint", "Breakpoint") ; Per WeaponX
            ; !!! --------------------------------------------------------------!!!

Closing notepad while the MsgBox was up caused the problem, cool!

But then put the original ProcessClose method back, and I'm still getting the COM error indication... Wha...? :P

Waited a few minutes and tried it again, no COM error. Ran it again within a few seconds -- got COM error... Wha...? ;)

My computer is mocking me... :P

Did it again with the COM error handler in place and it's the same, no error the first time, but I get this if I do it again quickly:

>Running:(3.2.8.1):C:\Program Files\AutoIt3\autoit3.exe "C:\Scripts\Test\Test1.au3" 
Debug:  Intercepted COM Error:  Number = 80020009  Windescription = ????
+>14:10:14 AutoIT3.exe ended.rc:0

I still think the best solution is to just use the function as is and be sure to have a COM error handler in place any time you use COM objects in your scripts.

:)

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

Didn't take long to change my mind on that.

This change prevents any COM errors, as per Weaponx' suggestion earlier:

; For each process...
            For $oProc In $colProcs
                $sObjName = ObjName($oProc, 3) ; 3 = ProgID
                If @error Then ContinueLoopoÝ÷ Ù*-êZµÈ^v÷«²*'¡ûayû§rبz0$²X¤zØb±«­¢+Øìôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôô(ìչѥ½¸9µè}AɽÍÍ1¥ÍÑAɽÁÉÑ¥Ì ¤(ìÍÉ¥ÁÑ¥½¸èÐÙÉ¥½ÕÌÁɽÁÉѥ̽ÁɽÍÌ°½È±°ÁɽÍÍÌ(ì
±°]¥Ñ è}AɽÍÍ1¥ÍÑAɽÁÉÑ¥Ì lÀÌØíAɽÍÌl°ÀÌØíÍ
½µÁÕÑÉut¤(ìAɵÑȡ̤衽ÁÑ¥½¹°¤ÀÌØíAɽÍÌ´A%½È¹µ½ÁɽḬ́ձХ̱°(졽ÁÑ¥½¹°¤ÀÌØíÍ
½µÁÕÑȴɵ½Ñ½µÁÕÑÈѼб¥ÍÐɽ´°Õ±Ð¥Ì±½°(ìIÅեɵ¹Ð¡Ì¤èÕѽ%ÐØ̸ȸиä¬(ìIÑÕɸY±Õ¡Ì¤è=¸MÕÍÌ´IÑÕɹÌÉÉÉä½ÁɽÍÍÌ°Ì¥¸AɽÍÍ1¥ÍÐ ¤(ìÝ¥Ñ ¥Ñ¥½¹°½±Õµ¹Ìè(ìlÁulÁt´9յȽÁɽÍÍ̱¥ÍÑ¡¸À¥¹¼µÑ¡Ì½Õ¹¤(ìlÅulÁt´ÅÍÐÁɽÍ̹µ(ìlÅulÅt´ÅÍÐÁɽÍÌA%(ìlÅulÉt´ÅÍÐÁɽÍÌAɹÐA%(ìlÅulÍt´ÅÍÐÁɽÍ̽ݹÈ(ìlÅulÑt´ÅÍÐÁɽÍÌÁÉ¥½É¥Ñä Àô±½Ü°ÌÄô¡¥ ¤(ìlÅulÕt´ÅÍÐÁɽÍÌáÕѱÁÑ (ìlÅulÙt´ÅÍÐÁɽÍÌ
ATÕÍ(ìlÅulÝt´ÅÍÐÁɽÍ̵µ½ÉäÕÍ(츸¸(ìm¹ulÁtÑ¡ÉÔm¹ulÝt´±ÍÐÁɽÍÌÁɽÁÉÑ¥Ì(ì=¸¥±ÕÉèIÑÕɹÌÉÉäÝ¥Ñ lÁulÁtôÀ¹ÍÑÌÉɽÈѼ¹½¸µéɼ¡Í½±½Ü¤(ìÕÑ¡½È¡Ì¤èAͱÑåLСÑÑÀè¼½ÝÝܹÕѽ¥ÑÍÉ¥Áй½´½½ÉÕ´(ì9½ÑÌè%¹ÕµÉ¥A%½ÈÍÑÉ¥¹ÁɽÍ̹µ¥ÌÁɽ٥¹¹¼µÑ ¥Ì½Õ¹°(ìÑ¡¸lÁulÁtôÀ¹ÉɽÈôÀ¡¹½ÐÑÉÑ̸ÉɽȰ͵ÌAɽÍÍ1¥ÍФ(ìQ¡¥Ìչѥ½¸ÉÅÕ¥É̵¥¸Áɵ¥ÍÍ¥½¹ÌѼѡÑÉнµÁÕÑȸ(ì±°ÁɽÁÉѥ̽µÉ½´Ñ¡]¥¸ÌÉ}AɽÍ̱ÍÌ¥¸]5$¸(ìôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôô)Õ¹}AɽÍÍ1¥ÍÑAɽÁÉÑ¥Ì ÀÌØíAɽÍÌôÅÕ½ÐìÅÕ½Ðì°ÀÌØíÍ
½µÁÕÑÈôÅÕ½Ðì¸ÅÕ½Ðì¤(1½°ÀÌØíÍUÍÉ9µ°ÀÌØíÍ5Í°ÀÌØíÍUÍɽµ¥¸°ÀÌØíÙAɽÌ(%ÀÌØíAɽÍÌôÅÕ½ÐìÅÕ½ÐìQ¡¸(ÀÌØíÙAɽÌôAɽÍÍ1¥ÍÐ ¤(±Í(ÀÌØíÙAɽÌôAɽÍÍ1¥ÍÐ ÀÌØíAɽÍ̤(¹%((ìIÑÕɸ½È¹¼µÑ¡Ì(%ÀÌØíÙAɽÍlÁulÁtôÀQ¡¸IÑÕɸÀÌØíÙAɽÌ((ìI¥´ÉÉä½È¥Ñ¥½¹°ÁɽÁÉÑä½±Õµ¹Ì(I¥´ÀÌØíÙAɽÍlÀÌØíÙAɽÍlÁulÁt¬Åulát((ì
½¹¹ÐѼ]5$¹ÐÁɽÍ̽©ÑÌ(ÀÌØí½]5$ô=©Ð ÅÕ½ÐíÝ¥¹µµÑÌéí¥µÁÉͽ¹Ñ¥½¹1Ù°õ¥µÁÉͽ¹ÑôÌÌìÀäÈìÀäÈìÅÕ½ÐìµÀìÀÌØíÍ
½µÁÕÑȵÀìÅÕ½ÐìÀäÈíɽ½ÐÀäÈí¥µØÈÅÕ½Ðì¤(%%Í=¨ ÀÌØí½]5$¤Q¡¸(ìн±±Ñ¥½¸½±°ÁɽÍÍÌɽ´]¥¸ÌÉ}AɽÍÌ(ÀÌØí½±AɽÌôÀÌØí½]5$¹áEÕÉä ÅÕ½ÐíͱШɽ´Ý¥¸ÌÉ}ÁɽÍÌÅÕ½Ðì¤(%%Í=¨ ÀÌØí½±Aɽ̤Q¡¸($$$ì½È ÁɽÍ̸¸¸($$%½ÈÀÌØí½Aɽ%¸ÀÌØí½±AɽÌ($$$$ÀÌØíÍ=©9µô=©9µ ÀÌØí½Aɽ°Ì¤ìÌôAɽ%($$$%%ÉɽÈQ¡¸
½¹Ñ¥¹Õ1½½ÀìM­¥À¥ÁɽÍ̹¼±½¹Èá¥ÍÑÌ(쥹¥Ð¥¸Ñ¡ÉÉä(½ÈÀÌØí¸ôÄQ¼ÀÌØíÙAɽÍlÁulÁt(%ÀÌØíÙAɽÍlÀÌØí¹ulÅtôÀÌØí½Aɽ¹AɽÍÍ%Q¡¸((ìm¹ulÉtôAɹÐA%(ÀÌØíÙAɽÍlÀÌØí¹ulÉtôÀÌØí½Aɽ¹AɹÑAɽÍÍ%(ìm¹ulÍtô=ݹÈ(%ÀÌØí½Aɽ¹Ñ=Ý¹È ÀÌØíÍUÍÉ9µ°ÀÌØíÍUÍɽµ¥¸¤ôÀQ¡¸ÀÌØíÙAɽÍlÀÌØí¹ulÍtôÀÌØíÍUÍɽµ¥¸µÀìÅÕ½ÐìÀäÈìÅÕ½ÐìµÀìÀÌØíÍUÍÉ9µ(ìm¹ulÑtôAÉ¥½É¥Ñä(ÀÌØíÙAɽÍlÀÌØí¹ulÑtôÀÌØí½Aɽ¹AÉ¥½É¥Ñä(ìm¹ulÕtôáÕѱÁÑ (ÀÌØíÙAɽÍlÀÌØí¹ulÕtôÀÌØí½Aɽ¹áÕѱAÑ ((á¥Ñ1½½À(¹%(9áÐ(9áÐ(±Í(MÑÉÉ½È È¤ìÉɽÈÑÑ¥¹ÁɽÍ̽±±Ñ¥½¸É½´]5$(¹%((ìн±±Ñ¥½¸½±°ÁɽÍÍÌɽ´]¥¸ÌÉ}AɽɵÑÑÑ}AÉAɽ}AɽÍÌ(ì!ÙѼÕ͸M]µIÉÍ¡ÈѼÁÕ±°Ñ¡½±±Ñ¥½¸°½È±°AÉÑÝ¥±°éɽÌ(1½°ÀÌØí½IÉÍ¡Èô=©
ÉÑ ÅÕ½Ðí]µMÉ¥ÁÑ¥¹¹M]µIÉÍ¡ÈÅÕ½Ðì¤(ÀÌØí½±AɽÌôÀÌØí½IÉ͡ȹ¹Õ´ ÀÌØí½]5$°ÅÕ½Ðí]¥¸ÌÉ}AɽɵÑÑÑ}AÉAɽ}AɽÍÌÅÕ½Ð줹½©ÑMÐ(ÀÌØí½IÉ͡ȹIÉÍ ((ìQ¥µ±ä½É±±¥¹ÉÉÍ¡È(1½°ÀÌØí¥Q¥µôQ¥µÉ%¹¥Ð ¤(¼(M±À ÄÀ¤(U¹Ñ¥°Q¥µÉ¥ ÀÌØí¥Q¥µ¤ÐìÄÀÀ(ÀÌØí½IÉ͡ȹIÉÍ ((ìÐAÉAɽÑ(½ÈÀÌØí½Aɽ%¸ÀÌØí½±AɽÌ(쥹¥Ð¥¸Ñ¡ÉÉä(½ÈÀÌØí¸ôÄQ¼ÀÌØíÙAɽÍlÁulÁt(%ÀÌØíÙAɽÍlÀÌØí¹ulÅtôÀÌØí½Aɽ¹%AɽÍÌQ¡¸(ÀÌØíÙAɽÍlÀÌØí¹ulÙtôÀÌØí½Aɽ¹AɹÑAɽÍͽÉQ¥µ(ÀÌØíÙAɽÍlÀÌØí¹ulÝtôÀÌØí½Aɽ¹]½É­¥¹MÐ(á¥Ñ1½½À(¹%(9áÐ(9áÐ(±Í(MÑÉÉ½È Ä¤ìÉɽȽ¹¹Ñ¥¹Ñ¼]5$(¹%((ìIÑÕɸÉÉä(IÑÕɸÀÌØíÙAɽÌ)¹Õ¹ìôôÐí}AɽÍÍ1¥ÍÑAɽÁÉÑ¥Ì

Cheers, and thanks to Weaponx.

:P

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...