Chimaera Posted June 28, 2013 Share Posted June 28, 2013 Just a small question for the learned masses if i may I have a script that uses command line to access Winrar and MultiPar and ive run into this scenario I currently use RunWait like this $ProcessPID = RunWait(@ComSpec & ' /c ' & @TempDir & '\Sup\par2j.exe' & ' r ' & '"' & $aParFile[$i] & '"', "", @SW_HIDE) and then i access $ProcessPID for all the exit codes of which there are many to provide error support for all the command programs i am using. So i made all the script, then i realised that i couldn't cancel the process and further investigation it looks like i will have to completely rewrite to be able to halt the process and use Run to be able to do it. The downside is i lose all that error support built in to the programs as i cant access it from Run and only give basic support like this ProcessWait($ProcessPID) $sOutput = "" While 1 $sOutput = StdoutRead($ProcessPID) If StringInStr($sOutput, "Password", 2) > 0 Then ; Monitoring Window for specific text during test process MsgBox(64, "Password Error", "Archive Is Passworded") Exit ElseIf StringInStr($sOutput, "No files extracted", 2) > 0 Then ; Monitoring Window for specific text during test process MsgBox(64, "Archive Error", "Archive Extraction Failed") Exit EndIf WEnd This is a shame because the support is already there and i cant access it. So the question i would like to ask is.. Can Run be made to return the $PID and if you set a flag then it returns the exit codes from the programs? There probably is a horrendously complicated answer but i would interested to hear why or why not. Thanks for your time If Ive just helped you ... miracles do happen. Chimaera CopyRobo() * Hidden Admin Account Enabler * Software Location From Registry * Find Display Resolution * _ChangeServices() Link to comment Share on other sites More sharing options...
water Posted June 28, 2013 Share Posted June 28, 2013 You call the DOS environment and let it run par2j.exe. The return value you get is form DOS not from par2j.exe Can't you directly call par2j? $ProcessPID = RunWait(@TempDir & '\Sup\par2j.exe' & ' r ' & '"' & $aParFile[$i] & '"', "", @SW_HIDE) My UDFs and Tutorials: Spoiler UDFs:Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - WikiExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example ScriptsOutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - WikiOutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - DownloadOutlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - WikiPowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - WikiTask Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs:Excel - Example Scripts - WikiWord - Wiki Tutorials:ADO - WikiWebDriver - Wiki Link to comment Share on other sites More sharing options...
JohnOne Posted June 28, 2013 Share Posted June 28, 2013 I'm quite sure I've seen a script which obtained the exit code from PID. Unfortunately I cannot remember the topic. AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
guinness Posted June 28, 2013 Share Posted June 28, 2013 Search OpenProcess in the Forum, that's where I would start. UDF List: _AdapterConnections() • _AlwaysRun() • _AppMon() • _AppMonEx() • _ArrayFilter/_ArrayReduce • _BinaryBin() • _CheckMsgBox() • _CmdLineRaw() • _ContextMenu() • _ConvertLHWebColor()/_ConvertSHWebColor() • _DesktopDimensions() • _DisplayPassword() • _DotNet_Load()/_DotNet_Unload() • _Fibonacci() • _FileCompare() • _FileCompareContents() • _FileNameByHandle() • _FilePrefix/SRE() • _FindInFile() • _GetBackgroundColor()/_SetBackgroundColor() • _GetConrolID() • _GetCtrlClass() • _GetDirectoryFormat() • _GetDriveMediaType() • _GetFilename()/_GetFilenameExt() • _GetHardwareID() • _GetIP() • _GetIP_Country() • _GetOSLanguage() • _GetSavedSource() • _GetStringSize() • _GetSystemPaths() • _GetURLImage() • _GIFImage() • _GoogleWeather() • _GUICtrlCreateGroup() • _GUICtrlListBox_CreateArray() • _GUICtrlListView_CreateArray() • _GUICtrlListView_SaveCSV() • _GUICtrlListView_SaveHTML() • _GUICtrlListView_SaveTxt() • _GUICtrlListView_SaveXML() • _GUICtrlMenu_Recent() • _GUICtrlMenu_SetItemImage() • _GUICtrlTreeView_CreateArray() • _GUIDisable() • _GUIImageList_SetIconFromHandle() • _GUIRegisterMsg() • _GUISetIcon() • _Icon_Clear()/_Icon_Set() • _IdleTime() • _InetGet() • _InetGetGUI() • _InetGetProgress() • _IPDetails() • _IsFileOlder() • _IsGUID() • _IsHex() • _IsPalindrome() • _IsRegKey() • _IsStringRegExp() • _IsSystemDrive() • _IsUPX() • _IsValidType() • _IsWebColor() • _Language() • _Log() • _MicrosoftInternetConnectivity() • _MSDNDataType() • _PathFull/GetRelative/Split() • _PathSplitEx() • _PrintFromArray() • _ProgressSetMarquee() • _ReDim() • _RockPaperScissors()/_RockPaperScissorsLizardSpock() • _ScrollingCredits • _SelfDelete() • _SelfRename() • _SelfUpdate() • _SendTo() • _ShellAll() • _ShellFile() • _ShellFolder() • _SingletonHWID() • _SingletonPID() • _Startup() • _StringCompact() • _StringIsValid() • _StringRegExpMetaCharacters() • _StringReplaceWholeWord() • _StringStripChars() • _Temperature() • _TrialPeriod() • _UKToUSDate()/_USToUKDate() • _WinAPI_Create_CTL_CODE() • _WinAPI_CreateGUID() • _WMIDateStringToDate()/_DateToWMIDateString() • Au3 script parsing • AutoIt Search • AutoIt3 Portable • AutoIt3WrapperToPragma • AutoItWinGetTitle()/AutoItWinSetTitle() • Coding • DirToHTML5 • FileInstallr • FileReadLastChars() • GeoIP database • GUI - Only Close Button • GUI Examples • GUICtrlDeleteImage() • GUICtrlGetBkColor() • GUICtrlGetStyle() • GUIEvents • GUIGetBkColor() • Int_Parse() & Int_TryParse() • IsISBN() • LockFile() • Mapping CtrlIDs • OOP in AutoIt • ParseHeadersToSciTE() • PasswordValid • PasteBin • Posts Per Day • PreExpand • Protect Globals • Queue() • Resource Update • ResourcesEx • SciTE Jump • Settings INI • SHELLHOOK • Shunting-Yard • Signature Creator • Stack() • Stopwatch() • StringAddLF()/StringStripLF() • StringEOLToCRLF() • VSCROLL • WM_COPYDATA • More Examples... Updated: 22/04/2018 Link to comment Share on other sites More sharing options...
Richard Robertson Posted June 28, 2013 Share Posted June 28, 2013 How could Run return the error code if the process hasn't finished yet? Link to comment Share on other sites More sharing options...
water Posted June 28, 2013 Share Posted June 28, 2013 I think you can't get the return code of the started program AND have the ability to cancel it whenever you need to. Doesn't each program give sufficient error information to the console? Use Run, grab all error messages sent to StdOut and kill the process of needed. My UDFs and Tutorials: Spoiler UDFs:Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - WikiExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example ScriptsOutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - WikiOutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - DownloadOutlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - WikiPowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - WikiTask Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs:Excel - Example Scripts - WikiWord - Wiki Tutorials:ADO - WikiWebDriver - Wiki Link to comment Share on other sites More sharing options...
BrewManNH Posted June 28, 2013 Share Posted June 28, 2013 I found >this thread while searching for information about this that might be what you're looking for. If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag GudeHow to ask questions the smart way! I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from. Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays. - ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script. - Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label. - _FileGetProperty - Retrieve the properties of a file - SciTE Toolbar - A toolbar demo for use with the SciTE editor - GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI. - Latin Square password generator Link to comment Share on other sites More sharing options...
wraithdu Posted June 28, 2013 Share Posted June 28, 2013 (edited) As part of a project I didn't want to deal with this issue, so I wrote a few functions to make it easier. One wraps the full CreateProcess API, the other checks the existence of the process by the handle returned from the first function. If the process has ended, it returns the exit code in @extended. expandcollapse popup#include <WinAPI.au3> #include <StructureConstants.au3> #include <WindowsConstants.au3> ; #FUNCTION# ==================================================================================================================== ; Name ..........: _Parallel_CreateProcess ; Description ...: Launch a new process. ; Syntax ........: _Parallel_CreateProcess($sCommand, $sWrkDir, $iShow, $iOpts) ; Parameters ....: $sCommand - Command line including parameters. ; $sWrkDir - Working directory. Default = "". ; $iShow - Initial state of any application window, any of the @SW_ macros. ; $iOpts - Options 0x10 or 0x10000 from internal Run() command, BitOR'd. ; Return values .: Success - A two element array: ; [0] - PID ; [1] - process handle (MUST be closed when finished with it) ; Failure - Sets @error = 1 and returns 0 as PID and handle ; Author ........: Erik Pilsits ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _Parallel_CreateProcess($sCommand, $sWrkDir, $iShow, $iOpts) ; use options provided by internal Run() command for consistent usage ; but only supports 0x10 and 0x10000 ; Local $aRet[2] = [0, 0] Local $sSTARTUP = DllStructCreate($tagSTARTUPINFO) Local $sPROCINFO = DllStructCreate($tagPROCESS_INFORMATION) DllStructSetData($sSTARTUP, "Size", DllStructGetSize($sSTARTUP)) DllStructSetData($sSTARTUP, "Flags", $STARTF_USESHOWWINDOW) DllStructSetData($sSTARTUP, "ShowWindow", $iShow) ; ; check options If BitAND($iOpts, 0x10) = 0x10 Then ; inherit parent stdio handles DllStructSetData($sSTARTUP, "Flags", BitOR($STARTF_USESHOWWINDOW, $STARTF_USESTDHANDLES)) DllStructSetData($sSTARTUP, "StdInput", _WinAPI_GetStdHandle(0)) DllStructSetData($sSTARTUP, "StdOutput", _WinAPI_GetStdHandle(1)) DllStructSetData($sSTARTUP, "StdError", _WinAPI_GetStdHandle(2)) EndIf Local $dwCreationFlags = 0 If BitAND($iOpts, 0x10000) = 0x10000 Then ; CREATE_NEW_CONSOLE = 0x10 $dwCreationFlags = 0x10 EndIf ; check working dir Local $sWrkDirType = "wstr" If $sWrkDir = "" Then $sWrkDirType = "ptr" $sWrkDir = 0 EndIf ; Local $ret = DllCall("kernel32.dll", "bool", "CreateProcessW", "ptr", 0, "wstr", $sCommand, "ptr", 0, "ptr", 0, "bool", 0, _ "dword", $dwCreationFlags, "ptr", 0, $sWrkDirType, $sWrkDir, "struct*", $sSTARTUP, "struct*", $sPROCINFO) If @error Or Not $ret[0] Then Return SetError(1, 0, $aRet) ; ; close unused thread handle _WinAPI_CloseHandle(DllStructGetData($sPROCINFO, "hThread")) ; ; return array of info, [0] = PID, [1] = process handle $aRet[0] = DllStructGetData($sPROCINFO, "ProcessID") $aRet[1] = DllStructGetData($sPROCINFO, "hProcess") Return SetError(0, 0, $aRet) EndFunc ;==>_Parallel_CreateProcess ; #FUNCTION# ==================================================================================================================== ; Name ..........: _ProcessExistsByHandle ; Description ...: Check if a process exists by handle. ; Syntax ........: _ProcessExistsByHandle($hProc) ; Parameters ....: $hProc - Open handle to a process, for example from a call to OpenProcess. ; Return values .: Success - 0 if process has ended, 1 if it still exists ; @extended contains the exit code ; Failure - 0 and sets @error ; Author ........: Erik Pilsits ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _ProcessExistsByHandle($hProc) ; there was an error creating the process If Not $hProc Then Return SetError(1, 0, 0) ; Local $iExit = DllCall("kernel32.dll", "bool", "GetExitCodeProcess", "handle", $hProc, "dword*", -1) If @error Or (Not $iExit[0]) Then ; error Return SetError(1, 0, 0) ElseIf $iExit[2] = 259 Then ; process STILL_ACTIVE ; extra check if process used STILL_ACTIVE as a valid exit code, $WAIT_OBJECT_0 If _WinAPI_WaitForSingleObject($hProc, 0) = 0 Then Return SetExtended($iExit[2], 0) Else Return 1 EndIf Else ; process does not exist, return exit code in @extended Return SetExtended($iExit[2], 0) EndIf EndFunc ;==>_ProcessExistsByHandle Edited June 30, 2013 by wraithdu Link to comment Share on other sites More sharing options...
guinness Posted June 28, 2013 Share Posted June 28, 2013 Nice couple of functions wraiithdu. UDF List: _AdapterConnections() • _AlwaysRun() • _AppMon() • _AppMonEx() • _ArrayFilter/_ArrayReduce • _BinaryBin() • _CheckMsgBox() • _CmdLineRaw() • _ContextMenu() • _ConvertLHWebColor()/_ConvertSHWebColor() • _DesktopDimensions() • _DisplayPassword() • _DotNet_Load()/_DotNet_Unload() • _Fibonacci() • _FileCompare() • _FileCompareContents() • _FileNameByHandle() • _FilePrefix/SRE() • _FindInFile() • _GetBackgroundColor()/_SetBackgroundColor() • _GetConrolID() • _GetCtrlClass() • _GetDirectoryFormat() • _GetDriveMediaType() • _GetFilename()/_GetFilenameExt() • _GetHardwareID() • _GetIP() • _GetIP_Country() • _GetOSLanguage() • _GetSavedSource() • _GetStringSize() • _GetSystemPaths() • _GetURLImage() • _GIFImage() • _GoogleWeather() • _GUICtrlCreateGroup() • _GUICtrlListBox_CreateArray() • _GUICtrlListView_CreateArray() • _GUICtrlListView_SaveCSV() • _GUICtrlListView_SaveHTML() • _GUICtrlListView_SaveTxt() • _GUICtrlListView_SaveXML() • _GUICtrlMenu_Recent() • _GUICtrlMenu_SetItemImage() • _GUICtrlTreeView_CreateArray() • _GUIDisable() • _GUIImageList_SetIconFromHandle() • _GUIRegisterMsg() • _GUISetIcon() • _Icon_Clear()/_Icon_Set() • _IdleTime() • _InetGet() • _InetGetGUI() • _InetGetProgress() • _IPDetails() • _IsFileOlder() • _IsGUID() • _IsHex() • _IsPalindrome() • _IsRegKey() • _IsStringRegExp() • _IsSystemDrive() • _IsUPX() • _IsValidType() • _IsWebColor() • _Language() • _Log() • _MicrosoftInternetConnectivity() • _MSDNDataType() • _PathFull/GetRelative/Split() • _PathSplitEx() • _PrintFromArray() • _ProgressSetMarquee() • _ReDim() • _RockPaperScissors()/_RockPaperScissorsLizardSpock() • _ScrollingCredits • _SelfDelete() • _SelfRename() • _SelfUpdate() • _SendTo() • _ShellAll() • _ShellFile() • _ShellFolder() • _SingletonHWID() • _SingletonPID() • _Startup() • _StringCompact() • _StringIsValid() • _StringRegExpMetaCharacters() • _StringReplaceWholeWord() • _StringStripChars() • _Temperature() • _TrialPeriod() • _UKToUSDate()/_USToUKDate() • _WinAPI_Create_CTL_CODE() • _WinAPI_CreateGUID() • _WMIDateStringToDate()/_DateToWMIDateString() • Au3 script parsing • AutoIt Search • AutoIt3 Portable • AutoIt3WrapperToPragma • AutoItWinGetTitle()/AutoItWinSetTitle() • Coding • DirToHTML5 • FileInstallr • FileReadLastChars() • GeoIP database • GUI - Only Close Button • GUI Examples • GUICtrlDeleteImage() • GUICtrlGetBkColor() • GUICtrlGetStyle() • GUIEvents • GUIGetBkColor() • Int_Parse() & Int_TryParse() • IsISBN() • LockFile() • Mapping CtrlIDs • OOP in AutoIt • ParseHeadersToSciTE() • PasswordValid • PasteBin • Posts Per Day • PreExpand • Protect Globals • Queue() • Resource Update • ResourcesEx • SciTE Jump • Settings INI • SHELLHOOK • Shunting-Yard • Signature Creator • Stack() • Stopwatch() • StringAddLF()/StringStripLF() • StringEOLToCRLF() • VSCROLL • WM_COPYDATA • More Examples... Updated: 22/04/2018 Link to comment Share on other sites More sharing options...
MHz Posted June 28, 2013 Share Posted June 28, 2013 Scite4AutoIt3 has been using Run to return the exitcode for several years. The quickest way for me to get the UDFs for my own use is to search Jos' sources rather then my own as I know where they exist. Link to comment Share on other sites More sharing options...
Developers Jos Posted June 28, 2013 Developers Share Posted June 28, 2013 (edited) Scite4AutoIt3 has been using Run to return the exitcode for several years. Have a look at AutoIt3Wrapper.au3 for any of these sections:Tidy, Obfuscator, AU3check or AutoIt3. Some of it was originally written by MHZ. Jos Edited June 28, 2013 by Jos SciTE4AutoIt3 Full installer Download page - Beta files Read before posting How to post scriptsource Forum etiquette Forum Rules Live for the present, Dream of the future, Learn from the past. Link to comment Share on other sites More sharing options...
Chimaera Posted June 28, 2013 Author Share Posted June 28, 2013 You call the DOS environment and let it run par2j.exe. The return value you get is form DOS not from par2j.exe Can't you directly call par2j? $ProcessPID = RunWait(@TempDir & '\Sup\par2j.exe' & ' r ' & '"' & $aParFile[$i] & '"', "", @SW_HIDE) Yet it still gives me the return codes everytime? Ill have a look later thx I'm quite sure I've seen a script which obtained the exit code from PID. Unfortunately I cannot remember the topic. I found the one below from BrewManNH just after i saw your post, thx to both I found >this thread while searching for information about this that might be what you're looking for. As part of a project I didn't want to deal with this issue, so I wrote a few functions to make it easier. One wraps the full CreateProcess API, the other checks the existence of the process by the handle returned from the first function. If the process has ended, it returns the exit code in @extended. ; #FUNCTION# ==================================================================================================================== ; Name ..........: _ProcessExistsByHandle ; Description ...: Check if a process exists by handle. ; Syntax ........: _ProcessExistsByHandle($hProc) ; Parameters ....: $hProc - Open handle to a process, for example from a call to OpenProcess. ; Return values .: Success - 0 if process has ended, 1 if it still exists ; @extended contains the exit code ; Failure - 0 and sets @error ; Author ........: Erik Pilsits ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _ProcessExistsByHandle($hProc) ; there was an error creating the process If Not $hProc Then Return SetError(1, 0, 0) ; Local $iExit = DllCall("kernel32.dll", "bool", "GetExitCodeProcess", "handle", $hProc, "dword*", -1) If @error Or (Not $iExit[0]) Then ; error Return SetError(1, 0, 0) ElseIf $iExit[2] = 259 Then ; process STILL_ACTIVE Return 1 Else ; process does not exist, return exit code in @extended Return SetExtended($iExit[2], 0) EndIf EndFunc ;==>_ProcessExistsByHandle Ill have a play with this as well and see what i can come up with thx for sharing. @Jos and Mhz i had a look at the suggested file and can see the parts you mentioned so ill read them in a bit thx The bit i am curious about is why it was never included with Run? Was there some major thing against it being added ? Just curious If Ive just helped you ... miracles do happen. Chimaera CopyRobo() * Hidden Admin Account Enabler * Software Location From Registry * Find Display Resolution * _ChangeServices() Link to comment Share on other sites More sharing options...
Developers Jos Posted June 28, 2013 Developers Share Posted June 28, 2013 The bit i am curious about is why it was never included with Run? Was there some major thing against it being added ? Just curious Think about this a little longer and come back when you still can't figure out why Run can't supply the ReturnCode at return time of the function. SciTE4AutoIt3 Full installer Download page - Beta files Read before posting How to post scriptsource Forum etiquette Forum Rules Live for the present, Dream of the future, Learn from the past. Link to comment Share on other sites More sharing options...
water Posted June 28, 2013 Share Posted June 28, 2013 Out of curiousity I did the following test: Compiled the following script to C.temptest.exe Exit 12345 If you then run $ReturnValue = RunWait(@ComSpec & ' /c ' & 'C:\temp\test.exe', "", @SW_HIDE) MsgBox(0, "ComSpec: Return Value", $ReturnValue) $ReturnValue = RunWait('C:\temp\test.exe', "", @SW_HIDE) MsgBox(0, "Run: Return Value", $ReturnValue) you will get 12345 both times. My UDFs and Tutorials: Spoiler UDFs:Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - WikiExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example ScriptsOutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - WikiOutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - DownloadOutlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - WikiPowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - WikiTask Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs:Excel - Example Scripts - WikiWord - Wiki Tutorials:ADO - WikiWebDriver - Wiki Link to comment Share on other sites More sharing options...
wraithdu Posted June 28, 2013 Share Posted June 28, 2013 (edited) I was hoping for more, but this is what SS64 has to say about it ErrorLevel CMD /C will return an errorlevel, for example CMD /c dir Z: where the drive Z: does not exist, will return %errorlevel% = 1 to the calling CMD shell. Edited June 28, 2013 by wraithdu Link to comment Share on other sites More sharing options...
funkey Posted June 28, 2013 Share Posted June 28, 2013 My two cents: #include <WinAPI.au3> Global Const $PROCESS_ALL_ACCESS = 0x1F0FFF Global $iPID = Run("test.exe") ConsoleWrite("PID: " & $iPID & @LF) Global $hProcess = _WinAPI_OpenProcess($PROCESS_ALL_ACCESS, 1, $iPID) ConsoleWrite("Process handle: " & $hProcess & @LF) ProcessWaitClose($iPID) Global $aRet = DllCall("kernel32.dll", "bool", "GetExitCodeProcess", "HANDLE", $hProcess, "dword*", -1) ConsoleWrite("Exit code: " & $aRet[2] & @LF) BTW: The only way how Run() could provide the exit code is through a callback function I think. But this is really not necessary. Programming today is a race between software engineers striving tobuild bigger and better idiot-proof programs, and the Universetrying to produce bigger and better idiots.So far, the Universe is winning. Link to comment Share on other sites More sharing options...
wraithdu Posted June 28, 2013 Share Posted June 28, 2013 The reason I disagree with the above and similar methods used in AutoIt3Wrapper.... it hinges on the fact that you can open that handle before the process has ended. What play a racing game? If the process ends before you can get that handle, your exit code is lost. If you do it my way (and I'm not saying my way is best), you take the chance out of it and you will always get your exit code. Those are my 2 cents. Link to comment Share on other sites More sharing options...
MHz Posted June 29, 2013 Share Posted June 29, 2013 @funkey Good except you are missing a UDF call to finish the task. Have a look at the examples in the link that BrewManNH posted at >#7 . @wraithdu I cannot disagree with your statement about your code. It is rather interesting code that you created and perhaps a good alternative for some. The mention of a race condition is that the UDFs used in Scite4AutoIt3 or used elsewhere have shown no signs of failure over the years. Perhaps with AutoIt already running at speed can run a process and open the handle to the process while the process is just getting setup to execute. There is some overhead in starting a process like reading the information in the header for how to execute, where to start reading the file to the end and add to the memory, etc. The CPU cycles of running a process and opening the process handle is possibly far few CPU cycles then what it takes to run a process and get to the point of execution. Yeah, it is just theory, though if no signs of failure exist then it can only be treated as a success. Does your process creation by UDF have enough advantage for users to not use the inbuilt function Run()? Users like convenience and like stuff built in and features added to enhance what already exists. For example, I would expect a UDF called _Run() would always come 2nd in a race to Run() based on choice. Another thing to consider is that WinAPI* functions already exist to open the process handle and to close the process handle. The function to get the exit code exists in WinAPIEx* and may be added as a STD UDF at some point. The functions that I have posted will become obsolete as the WinAPI* functions increase in number to include what is missing. This is what I see as the future. Link to comment Share on other sites More sharing options...
Ascend4nt Posted June 29, 2013 Share Posted June 29, 2013 (edited) One thing to keep in mind is that when AutoIt's Run() is used with STDOUT/ERR redirected is that internally AutoIt has to already have a process handle open, and can only close it once the entire redirected I/O has been read. AutoItWrapper has some calls with redirects like that, and its fine to get the Process handle before the first read from those pipes. Getting a process handle after any StdOut/ErrRead call is suspect, at best. And getting it after Run() without a redirect is definitely a toss-up. By the way, wraithdu - ProcessExistsByHandle() mistakenly assumes that any STILL_ACTIVE return code means the process is still running, whereas that can be a valid exit code. It needs to use WaitForSingleObject() - preferrably with a 0-ms wait instead. *edit: - strikethrough wrong comments - see >post #22 Edited June 29, 2013 by Ascend4nt My contributions: Performance Counters in Windows - Measure CPU, Disk, Network etc Performance | Network Interface Info, Statistics, and Traffic | CPU Multi-Processor Usage w/o Performance Counters | Disk and Device Read/Write Statistics | Atom Table Functions | Process, Thread, & DLL Functions UDFs | Process CPU Usage Trackers | PE File Overlay Extraction | A3X Script Extract | File + Process Imports/Exports Information | Windows Desktop Dimmer Shade | Spotlight + Focus GUI - Highlight and Dim for Eyestrain Relief | CrossHairs (FullScreen) | Rubber-Band Boxes using GUI's (_GUIBox) | GUI Fun! | IE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) | Magnifier (Vista+) Functions UDF | _DLLStructDisplay (Debug!) | _EnumChildWindows (controls etc) | _FileFindEx | _ClipGetHTML | _ClipPutHTML + ClipPutHyperlink | _FileGetShortcutEx | _FilePropertiesDialog | I/O Port Functions | File(s) Drag & Drop | _RunWithReducedPrivileges | _ShellExecuteWithReducedPrivileges | _WinAPI_GetSystemInfo | dotNETGetVersions | Drive(s) Power Status | _WinGetDesktopHandle | _StringParseParameters | Screensaver, Sleep, Desktop Lock Disable | Full-Screen Crash Recovery Wrappers/Modifications of others' contributions: _DOSWildcardsToPCRegEx (original code: RobSaunder's) | WinGetAltTabWinList (original: Authenticity) UDF's added support/programming to: _ExplorerWinGetSelectedItems | MIDIEx UDF (original code: eynstyne) (All personal code/wrappers centrally located at Ascend4nt's AutoIT Code) Link to comment Share on other sites More sharing options...
wraithdu Posted June 29, 2013 Share Posted June 29, 2013 (edited) The mention of a race condition is that the UDFs used in Scite4AutoIt3 or used elsewhere have shown no signs of failure over the years. Perhaps with AutoIt already running at speed can run a process and open the handle to the process while the process is just getting setup to execute. There is some overhead in starting a process like reading the information in the header for how to execute, where to start reading the file to the end and add to the memory, etc. The CPU cycles of running a process and opening the process handle is possibly far few CPU cycles then what it takes to run a process and get to the point of execution. Yeah, it is just theory, though if no signs of failure exist then it can only be treated as a success. Does your process creation by UDF have enough advantage for users to not use the inbuilt function Run()? Users like convenience and like stuff built in and features added to enhance what already exists. For example, I would expect a UDF called _Run() would always come 2nd in a race to Run() based on choice. You can rationalize the race condition all you want, but race conditions need to be avoided. Period. It's bad programming. My UDF is not, by any means, meant as a replacement for Run() / RunWait() except for the specific purpose of this topic, to guarantee the return of a valid process handle and exit code. One thing to keep in mind is that when AutoIt's Run() is used with STDOUT/ERR redirected is that internally AutoIt has to already have a process handle open, and can only close it once the entire redirected I/O has been read. AutoItWrapper has some calls with redirects like that, and its fine to get the Process handle before the first read from those pipes. Getting a process handle after any StdOut/ErrRead call is suspect, at best. And getting it after Run() without a redirect is definitely a toss-up. By the way, wraithdu - ProcessExistsByHandle() mistakenly assumes that any STILL_ACTIVE return code means the process is still running, whereas that can be a valid exit code. It needs to use WaitForSingleObject() - preferrably with a 0-ms wait instead. Your first point is interesting. We'd definitely need a dev's input on that. Would that mean that AutoIt indefinitely holds an open process handle when std output is redirected, until StdioClose() is manually called or all output has been read by the Std*Read() functions? Second point... my function does not mistakenly assume that at all. It makes the assumption with full knowledge and understanding. I'll refer you to the remarks for GetExitCodeProcess in MSDN: Important The GetExitCodeProcess function returns a valid error code defined by the application only after the thread terminates. Therefore, an application should not use STILL_ACTIVE (259) as an error code. If a thread returnsSTILL_ACTIVE (259) as an error code, applications that test for this value could interpret it to mean that the thread is still running and continue to test for the completion of the thread after the thread has terminated, which could put the application into an infinite loop. Edited June 29, 2013 by wraithdu 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