GPinzone Posted November 22, 2010 Share Posted November 22, 2010 I came up with this idea based on other users' posts. If you search this forum, you will find out it's possible to display a MsgBox for informational purposes without stopping your script if you run it as another program. For example, the function Func _NoHaltMsgBox($code=0, $title = "",$text = "" ,$timeout = 0) Run (@AutoItExe & ' /AutoIt3ExecuteLine "MsgBox(' & $code & ', '''& $title & ''', '''& $text &''',' & $timeout & ')"') EndFunc will display a MsgBox in a separate thread. The problem is that it's impossible to know what the value of the button click since it will terminate when the selection is made and make no effort to send the return value back to the main script. I discovered today that AutoIt has functions that allow a script to read from the standard output (and standard error) of a running process. Therefore, by outputting the return value to the threaded process' console, it is possible to send the return value back to the main script! #include <Constants.au3> Local $mypid, $myStr $mypid = _NoHaltMsgBox(50, "Hello", "This will return a value of 3, 4, or 5.") ; Do some other stuff... $myStr = _GetNoHaltMsgBoxValue($mypid) MsgBox(0, "Returned value...", $myStr) Exit ; End MAIN Func _NoHaltMsgBox($code=0, $title = "",$text = "" ,$timeout = 0) Local $PID $PID = Run (@AutoItExe & ' /AutoIt3ExecuteLine "ConsoleWrite( MsgBox(' & $code & ', '''& $title & ''', '''& $text &''',' & $timeout & ')")', @SystemDir, "", $STDOUT_CHILD) Return $PID EndFunc Func _GetNoHaltMsgBoxValue($PID) Local $Output While (ProcessExists($PID)) If @error Then ExitLoop Sleep(500) $Output = $Output & StdoutRead($PID) ; Appending ensures value won't get overwritten WEnd Return $Output EndFunc This seems to work well with one caveat: The processes in between the non-blocking message box and the function to read its return value CANNOT take longer than it takes the user to click the message box's button. If it does, the value is lost. To see an example of this, create another MsgBox under the "Do some other stuff..." section. If you close that message box first, it works. If you close the threaded message box first, the return value is blank because the thread has already been terminated. I don't know if any of this is useful, since I'm not an expert. Perhaps someone with more experience with AutoIt can determine if there's any use before I pursue this further. Gerard J. Pinzonegpinzone AT yahoo.com Link to comment Share on other sites More sharing options...
PsaltyDS Posted November 22, 2010 Share Posted November 22, 2010 Actually, you can get the exit code after a process closes. A at one time by a certain rakishly good looking bird... 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 More sharing options...
GPinzone Posted November 23, 2010 Author Share Posted November 23, 2010 Dumb question: Will _ProcessGetExitCode() be able to get the exit code if the process had already finished? You know in advance the good ping will finish before the bad one. So, if: ; Wait for both to finish... ProcessWaitClose($iRunPID1) ProcessWaitClose($iRunPID2) was ; Wait for both to finish... ProcessWaitClose($iRunPID2) ProcessWaitClose($iRunPID1) would it still work? I can't test it right now. Gerard J. Pinzonegpinzone AT yahoo.com Link to comment Share on other sites More sharing options...
PsaltyDS Posted November 23, 2010 Share Posted November 23, 2010 (edited) Note the exit codes in that script are not retrieved until ProcessWaitClose() is done on both. So both are retrieved after the process exits. Bigger problem is that increased process security in Vista/Win7/2008 may keep you from getting that to work on those OS's. The demo was originally tested on XP, where it still works fine. I added #RequireAdmin, changed the ConsoleWrite() to ToolTip(), compiled it, and ran it with "Run As Administrator" on Vista Business and I still got 0 returned for both pings. Probably have to specify a higher permission than $PROCESS_QUERY_INFORMATION to get that value in the later versions. Edited November 23, 2010 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 More sharing options...
James Posted November 23, 2010 Share Posted November 23, 2010 Actually, you can get the exit code after a process closes. A at one time by a certain rakishly good looking bird...I'm in awe at your modesty. Blog - Seriously epic web hosting - Twitter - GitHub - Cachet HQ Link to comment Share on other sites More sharing options...
GPinzone Posted November 24, 2010 Author Share Posted November 24, 2010 Very nice stuff! I made the following changes to my original post based on PsaltyDS' code if anyone is interested: expandcollapse popupLocal $myPID, $myStr, $hRun $myPID = _NoHaltMsgBox(50, "Hello", "This will return a value of 3, 4, or 5.") $hRun = _ProcessGetHandle($myPID) ; Do some other stuff... MsgBox(0, "", "Wasting time...") $myStr = _GetNoHaltMsgBoxValue($myPID, $hRun) MsgBox(0, "Returned value...", $myStr) Exit ; End MAIN Func _NoHaltMsgBox($code=0, $title = "",$text = "" ,$timeout = 0) Local $iPID $iPID = Run (@AutoItExe & ' /AutoIt3ExecuteLine "Exit(MsgBox(' & $code & ', '''& $title & ''', '''& $text &''',' & $timeout & ')")') Return $iPID EndFunc Func _GetNoHaltMsgBoxValue($iPID, $hRun) Local $iExit ; Wait for both to finish... ProcessWaitClose($iPID) $iExit = _ProcessGetExitCode($hRun) _ProcessCloseHandle($hRun) Return $iExit EndFunc Func _ProcessGetHandle($iPID) Local Const $PROCESS_QUERY_INFORMATION = 0x0400 Local $avRET = DllCall("kernel32.dll", "ptr", "OpenProcess", "int", $PROCESS_QUERY_INFORMATION, "int", 0, "int", $iPID) If @error Then Return SetError(1, 0, 0) Else Return $avRET[0] EndIf EndFunc ;==>_ProcessGetHandle ; Close process handle Func _ProcessCloseHandle($hProc) Local $avRET = DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hProc) If @error Then Return SetError(1, 0, 0) Else Return 1 EndIf EndFunc ;==>_ProcessCloseHandle ; Get process exit code from handle Func _ProcessGetExitCode($hProc) Local $t_ExitCode = DllStructCreate("int") Local $avRET = DllCall("kernel32.dll", "int", "GetExitCodeProcess", "ptr", $hProc, "ptr", DllStructGetPtr($t_ExitCode)) If @error Then Return SetError(1, 0, 0) Else Return DllStructGetData($t_ExitCode, 1) EndIf EndFunc ;==>_ProcessGetExitCode Now the spawned MsgBox can be closed before the main thread completes or after. Of course, it may not work on Vista or Windows 7 due to the security issues, but it works perfectly on XP. Some notes: If you don't get the handle before you throw up another MsgBox ($hRun = _ProcessGetHandle($myPID)), the exit code of the "threaded" MsgBox will be lost. I'd add it to the _NoHaltMsgBox function, but I don't know how to send both the handle and pid back. Do I need the PID once the handle is created? What I mean is maybe the PID could be determined from the handle. If so, I could just return the handle and just pass that around. Gerard J. Pinzonegpinzone AT yahoo.com Link to comment Share on other sites More sharing options...
Yashied Posted November 24, 2010 Share Posted November 24, 2010 Why are you so complicated, just use a WM_COPYDATA... My UDFs: iKey | FTP Uploader | Battery Checker | Boot Manager | Font Viewer | UDF Keyword Manager | Run Dialog Replacement | USBProtect | 3D Axis | Calculator | Sleep | iSwitcher | TM | NetHelper | File Types Manager | Control Viewer | SynFolders | DLL Helper Animated Tray Icons UDF Library | Hotkeys UDF Library | Hotkeys Input Control UDF Library | Caret Shape UDF Library | Context Help UDF Library | Most Recently Used List UDF Library | Icons UDF Library | FTP UDF Library | Script Communications UDF Library | Color Chooser UDF Library | Color Picker Control UDF Library | IPHelper (Vista/7) UDF Library | WinAPI Extended UDF Library | WinAPIVhd UDF Library | Icon Chooser UDF Library | Copy UDF Library | Restart UDF Library | Event Log UDF Library | NotifyBox UDF Library | Pop-up Windows UDF Library | TVExplorer UDF Library | GuiHotKey UDF Library | GuiSysLink UDF Library | Package UDF Library | Skin UDF Library | AITray UDF Library | RDC UDF Library Appropriate path | Button text color | Gaussian random numbers | Header's styles (Vista/7) | ICON resource enumeration | Menu & INI | Tabbed string size | Tab's skin | Pop-up circular menu | Progress Bar without animation (Vista/7) | Registry export | Registry path jumping | Unique hardware ID | Windows alignment More... Link to comment Share on other sites More sharing options...
GPinzone Posted November 24, 2010 Author Share Posted November 24, 2010 Why are you so complicated, just use a WM_COPYDATA...There's an excellent reason why... I don't know what it is. But now that you've mentioned it, I'll Google to find out more. Gerard J. Pinzonegpinzone AT yahoo.com Link to comment Share on other sites More sharing options...
Yashied Posted November 24, 2010 Share Posted November 24, 2010 expandcollapse popup#NoTrayIcon #Include <WindowsConstants.au3> Opt('TrayAutoPause', 0) If ($CmdLine[0] = 6) And ($CmdLine[1] = '-msgbox') Then $ID = MsgBox($CmdLine[3], $CmdLine[4], $CmdLine[5], $CmdLine[6]) $tData = DllStructCreate('ulong_ptr;dword;ptr') DllStructSetData($tData, 1, BitOR(BitShift(@AutoItPID, -16), $ID)) DllStructSetData($tData, 2, 0) DllStructSetData($tData, 3, 0) DllCall('user32.dll', 'lresult', 'SendMessage', 'hwnd', $CmdLine[2], 'uint', $WM_COPYDATA, 'ptr', 0, 'ptr', DllStructGetPtr($tData)) Exit EndIf Opt('TrayIconHide', 0) $hReceiver = GUICreate('') GUIRegisterMsg($WM_COPYDATA, 'WM_COPYDATA') ConsoleWrite('#1 = ' & _NoHaltMsgBox(3 + 32, '#1', 'Simple text.') & @CR) ConsoleWrite('#2 = ' & _NoHaltMsgBox(3 + 32, '#2', 'Simple text.') & @CR) ConsoleWrite('#3 = ' & _NoHaltMsgBox(3 + 32, '#3', 'Simple text.') & @CR) ConsoleWrite('------------------------------' & @CR) While 1 Sleep(1000) WEnd Func _NoHaltMsgBox($iFlags, $sTitle, $sText, $iTimeOut = 0) If @compiled Then Return Run(@ScriptFullPath & ' -msgbox') Else Return Run(@AutoItExe & ' "' & @ScriptFullPath & '" -msgbox ' & $hReceiver & ' ' & $iFlags & ' "' & $sTitle & '" "' & $sText & '" ' & $iTimeOut) EndIf EndFunc ;==>_NoHaltMsgBox Func WM_COPYDATA($hWnd, $iMsg, $wParam, $lParam) Switch $hWnd Case $hReceiver Local $tData = DllStructCreate('ulong_ptr;dword;ptr', $lParam) ConsoleWrite('PID = ' & BitShift(DllStructGetData($tData, 1), 16) & ' ID = ' & BitAND(DllStructGetData($tData, 1), 0xFFFF) & @CR) Return 1 EndSwitch Return 0 EndFunc ;==>WM_COPYDATA My UDFs: iKey | FTP Uploader | Battery Checker | Boot Manager | Font Viewer | UDF Keyword Manager | Run Dialog Replacement | USBProtect | 3D Axis | Calculator | Sleep | iSwitcher | TM | NetHelper | File Types Manager | Control Viewer | SynFolders | DLL Helper Animated Tray Icons UDF Library | Hotkeys UDF Library | Hotkeys Input Control UDF Library | Caret Shape UDF Library | Context Help UDF Library | Most Recently Used List UDF Library | Icons UDF Library | FTP UDF Library | Script Communications UDF Library | Color Chooser UDF Library | Color Picker Control UDF Library | IPHelper (Vista/7) UDF Library | WinAPI Extended UDF Library | WinAPIVhd UDF Library | Icon Chooser UDF Library | Copy UDF Library | Restart UDF Library | Event Log UDF Library | NotifyBox UDF Library | Pop-up Windows UDF Library | TVExplorer UDF Library | GuiHotKey UDF Library | GuiSysLink UDF Library | Package UDF Library | Skin UDF Library | AITray UDF Library | RDC UDF Library Appropriate path | Button text color | Gaussian random numbers | Header's styles (Vista/7) | ICON resource enumeration | Menu & INI | Tabbed string size | Tab's skin | Pop-up circular menu | Progress Bar without animation (Vista/7) | Registry export | Registry path jumping | Unique hardware ID | Windows alignment More... 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