lod3n Posted March 1, 2007 Share Posted March 1, 2007 (edited) I've had a personal UDF similar to this one for some time that I was fond of, which only returned the stdout and stderr text from a command, because it's a hassle to set it up every time you want capture stdout data. And then MHz's _ProcessOpenHandle() and _ProcessGetExitCode() hit the forum, and I just had to incorporate that functionality. I think it's pretty useful at this point, so I thought I'd share it.Just be aware that it returns the stdout and stderr values with blank lines removed and tab delimited, so if that's not something you feel like dealing with, well, then change it. No includes are required. Also, it (necessarily) waits until the command is finished, similar to RunWait. Below I've written another function checkNet, which utilizes the UDF.Let me know what you think, and please point out any bugs that I missed.Edit: Added mrRevoked's changes, so you can pick a delimiter other than @tab, and optionally have it return one of the items in the array, instead of the array itself. Much more flexible, thanks mrRevoked.Edit: ptrex pointed out that it wouldn't run tasklist. It seemed to be hanging on the While ProcessExists loop, though I don't know why. So I took that out, and placed the exit code determination after the stdout and stderr reads. It runs now, and quite a bit faster too!Edit: Updated for 3.2.10.0. (Hey thanks for the kudos, flyingboz!)expandcollapse popup;example single item return mode usage - by mrRevoked MsgBox(0,'Ipconfig...',_RunReadStd("ipconfig",0,@WorkingDir,0,1,@LF)) ; example array mode usage if checknet("localhost") then ; do stuff! EndIf func checknet($server) ConsoleWrite("Active network adapter?... ") local $aOutput = _RunReadStd("ipconfig") ;$aOutput[1] now contains the StdOut from ipconfig, so the idea here is that ;if your network cable is unplugged, ipconfig will not list a subnet mask: if not stringinstr($aOutput[1],"255.") then ConsoleWrite("FAIL" & @crlf) return false Else ConsoleWrite("PASS" & @crlf) EndIf ConsoleWrite("Checking server connection... ") if not ping($server) then ConsoleWrite("FAIL" & @crlf) return False Else ConsoleWrite("PASS" & @crlf) EndIf return true EndFunc ;=============================================================================== ; ; Function Name: _RunReadStd() ; ; Description:: Run a specified command, and return the Exitcode, StdOut text and ; StdErr text from from it. StdOut and StdErr are @tab delimited, ; with blank lines removed. ; ; Parameter(s): $doscmd: the actual command to run, same as used with Run command ; $timeoutSeconds: maximum execution time in seconds, optional, default: 0 (wait forever), ; $workingdir: directory in which to execute $doscmd, optional, default: @ScriptDir ; $flag: show/hide flag, optional, default: @SW_HIDE ; $sDelim: stdOut and stdErr output deliminter, optional, default: @TAB ; $nRetVal: return single item from function instead of array, optional, default: -1 (return array) ; ; Requirement(s): AutoIt 3.2.10.0 ; ; Return Value(s): An array with three values, Exit Code, StdOut and StdErr ; ; Author(s): lod3n ; (Thanks to mrRevoked for delimiter choice and non array return selection) ; (Thanks to mHZ for _ProcessOpenHandle() and _ProcessGetExitCode()) ; (MetaThanks to DaveF for posting these DllCalls in Support Forum) ; (MetaThanks to JPM for including CloseHandle as needed) ; ;=============================================================================== func _RunReadStd($doscmd,$timeoutSeconds=0,$workingdir=@ScriptDir,$flag=@SW_HIDE,$nRetVal = -1, $sDelim = @TAB) local $aReturn,$i_Pid,$h_Process,$i_ExitCode,$sStdOut,$sStdErr,$runTimer dim $aReturn[3] ; run process with StdErr and StdOut flags $runTimer = TimerInit() $i_Pid = Run($doscmd, $workingdir, $flag, 6) ; 6 = $STDERR_CHILD+$STDOUT_CHILD ; Get process handle sleep(100) ; or DllCall may fail - experimental $h_Process = DllCall('kernel32.dll','ptr', 'OpenProcess','int', 0x400,'int', 0,'int', $i_Pid) ; create tab delimited string containing StdOut text from process $aReturn[1] = "" $sStdOut = "" While 1 $sStdOut &= StdoutRead($i_Pid) If @error Then ExitLoop Wend $sStdOut = StringReplace($sStdOut,@cr,@tab) $sStdOut = StringReplace($sStdOut,@lf,@tab) $aStdOut = StringSplit($sStdOut,@tab,1) for $i = 1 to $aStdOut[0] $aStdOut[$i] = StringStripWS($aStdOut[$i],3) if StringLen($aStdOut[$i]) > 0 then $aReturn[1] &= $aStdOut[$i] & $sDelim EndIf Next $aReturn[1] = StringTrimRight($aReturn[1],1) ; create tab delimited string containing StdErr text from process $aReturn[2] = "" $sStderr = "" While 1 $sStderr &= StderrRead($i_Pid) If @error Then ExitLoop Wend $sStderr = StringReplace($sStderr,@cr,@tab) $sStderr = StringReplace($sStderr,@lf,@tab) $aStderr = StringSplit($sStderr,@tab,1) for $i = 1 to $aStderr[0] $aStderr[$i] = StringStripWS($aStderr[$i],3) if StringLen($aStderr[$i]) > 0 then $aReturn[2] &= $aStderr[$i] & $sDelim EndIf Next $aReturn[2] = StringTrimRight($aReturn[2],1) ; kill the process if it exceeds $timeoutSeconds if $timeoutSeconds > 0 Then if TimerDiff($runTimer)/1000 > $timeoutSeconds Then ProcessClose($i_Pid) EndIf EndIf ; fetch exit code and close process handle If IsArray($h_Process) Then Sleep(100) ; or DllCall may fail - experimental $i_ExitCode = DllCall('kernel32.dll','ptr', 'GetExitCodeProcess','ptr', $h_Process[0],'int*', 0) if IsArray($i_ExitCode) Then $aReturn[0] = $i_ExitCode[2] Else $aReturn[0] = -1 EndIf Sleep(100) ; or DllCall may fail - experimental DllCall('kernel32.dll','ptr', 'CloseHandle','ptr', $h_Process[0]) Else $aReturn[0] = -2 EndIf ; return single item if correctly specified with with $nRetVal If $nRetVal <> -1 And $nRetVal >= 0 And $nRetVal <= 2 Then Return $aReturn[$nRetVal] ; return array with exit code, stdout, and stderr return $aReturn EndFuncChanged post title at herewasplato's request to assist in finding it via forum search. Edited June 16, 2009 by lod3n fjorger 1 [font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font] Link to comment Share on other sites More sharing options...
WeMartiansAreFriendly Posted March 1, 2007 Share Posted March 1, 2007 (edited) nice script.. i modified just a bit, nothing interesting just so you can have it return a specific value, in place of the array. edit added optional delim value. expandcollapse popupMsgBox(0,'Ipconfig...',_RunReadStd("ipconfig",0,@WorkingDir,0,1,@LF)) ;=============================================================================== ; ; Function Name: _RunReadStd() ; ; Description:: Run a specified command, and return the Exitcode, StdOut text and ; StdErr text from from it. StdOut and StdErr are @tab delimited, ; with blank lines removed. ; ; Parameter(s): $doscmd: the actual command to run, same as used with Run command ; $timeoutSeconds: maximum execution time in seconds, optional, default: 0 (wait forever), ; $workingdir: directory in which to execute $doscmd, optional, default: @ScriptDir ; $flag: show/hide flag, optional, default: @SW_HIDE ; ; Requirement(s): AutoIt 3.1.1 ; ; Return Value(s): An array with three values, Exit Code, StdOut and StdErr ; ; Author(s): lod3n ; (Thanks to mHZ for _ProcessOpenHandle() and _ProcessGetExitCode()) ; (MetaThanks to DaveF for posting these DllCalls in Support Forum) ; (MetaThanks to JPM for including CloseHandle as needed) ; ;=============================================================================== func _RunReadStd($sDoscmd, $nTimeoutSeconds = 0, $sWorkingdir = @ScriptDir, $nFlag = @SW_HIDE, $nRetVal = -1, $sDelim = @TAB) local $aReturn,$i_Pid,$h_Process,$i_ExitCode,$sStdOut,$sStdErr,$runTimer dim $aReturn[3] ; run process with StdErr and StdOut flags $runTimer = TimerInit() $i_Pid = Run($sDoscmd, $sWorkingdir, $nFlag, 6); 6 = $STDERR_CHILD+$STDOUT_CHILD ; Get process handle sleep(100); or DllCall may fail - experimental $h_Process = DllCall('kernel32.dll','ptr', 'OpenProcess','int', 0x400,'int', 0,'int', $i_Pid) ; wait for process to exit, or kill it if it exceeds $timeoutSeconds While ProcessExists($i_Pid) Sleep(100) if $ntimeoutSeconds > 0 Then if TimerDiff($runTimer)/1000 > $ntimeoutSeconds Then ProcessClose($i_Pid) EndIf EndIf WEnd ; fetch exit code and close process handle If IsArray($h_Process) Then Sleep(100); or DllCall may fail - experimental $i_ExitCode = DllCall('kernel32.dll','ptr', 'GetExitCodeProcess','ptr', $h_Process[0],'int_ptr', 0) If IsArray($i_ExitCode) Then $aReturn[0] = $i_ExitCode[2] Else $aReturn[0] = -1 EndIf Sleep(100); or DllCall may fail - experimental DllCall('kernel32.dll','ptr', 'CloseHandle','ptr', $h_Process[0]) Else $aReturn[0] = -2 EndIf ; create tab delimited string containing StdOut text from process $aReturn[1] = "" $sStdOut = "" While 1 $sStdOut &= StdoutRead($i_Pid) If @error Then ExitLoop Wend $sStdOut = StringReplace($sStdOut,@cr,$sDelim) $sStdOut = StringReplace($sStdOut,@lf,$sDelim) $aStdOut = StringSplit($sStdOut,$sDelim,1) for $i = 1 to $aStdOut[0] $aStdOut[$i] = StringStripWS($aStdOut[$i],3) if StringLen($aStdOut[$i]) > 0 then $aReturn[1] &= $aStdOut[$i] & $sDelim EndIf Next $aReturn[1] = StringTrimRight($aReturn[1],1) ; create tab delimited string containing StdErr text from process $aReturn[2] = "" $sStderr = "" While 1 $sStderr &= StderrRead($i_Pid) If @error Then ExitLoop Wend $sStderr = StringReplace($sStderr,@cr,$sDelim) $sStderr = StringReplace($sStderr,@lf,$sDelim) $aStderr = StringSplit($sStderr,$sDelim,1) for $i = 1 to $aStderr[0] $aStderr[$i] = StringStripWS($aStderr[$i],3) if StringLen($aStderr[$i]) > 0 then $aReturn[2] &= $aStderr[$i] & $sDelim EndIf Next $aReturn[2] = StringTrimRight($aReturn[2],1) ; if the process is somehow still running, close it - experimental ProcessClose($i_Pid) ;if nreturn <> -1 then return a that specific value. If $nRetVal <> -1 And $nRetVal >= 0 And $nRetVal <= 2 Then Return $aReturn[$nRetVal] ; return array with exit code, stdout, and stderr return $aReturn EndFunc Edited March 1, 2007 by mrRevoked Don't bother, It's inside your monitor!------GUISetOnEvent should behave more like HotKeySet() Link to comment Share on other sites More sharing options...
ptrex Posted March 1, 2007 Share Posted March 1, 2007 @lod3n Doesn't seem to work for all commands ? Try this _RunReadStd("tasklist",0,@WorkingDir,0,1,@LF)) reagrds, ptrex Contributions :Firewall Log Analyzer for XP - Creating COM objects without a need of DLL's - UPnP support in AU3Crystal Reports Viewer - PDFCreator in AutoIT - Duplicate File FinderSQLite3 Database functionality - USB Monitoring - Reading Excel using SQLRun Au3 as a Windows Service - File Monitor - Embedded Flash PlayerDynamic Functions - Control Panel Applets - Digital Signing Code - Excel Grid In AutoIT - Constants for Special Folders in WindowsRead data from Any Windows Edit Control - SOAP and Web Services in AutoIT - Barcode Printing Using PS - AU3 on LightTD WebserverMS LogParser SQL Engine in AutoIT - ImageMagick Image Processing - Converter @ Dec - Hex - Bin -Email Address Encoder - MSI Editor - SNMP - MIB ProtocolFinancial Functions UDF - Set ACL Permissions - Syntax HighLighter for AU3ADOR.RecordSet approach - Real OCR - HTTP Disk - PDF Reader Personal Worldclock - MS Indexing Engine - Printing ControlsGuiListView - Navigation (break the 4000 Limit barrier) - Registration Free COM DLL Distribution - Update - WinRM SMART Analysis - COM Object Browser - Excel PivotTable Object - VLC Media Player - Windows LogOnOff Gui -Extract Data from Outlook to Word & Excel - Analyze Event ID 4226 - DotNet Compiler Wrapper - Powershell_COM - New Link to comment Share on other sites More sharing options...
lod3n Posted March 1, 2007 Author Share Posted March 1, 2007 Thanks mrRevoked and ptrex, code updated, see original post. [font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font] Link to comment Share on other sites More sharing options...
ptrex Posted March 3, 2007 Share Posted March 3, 2007 @lod3n Good job seems to run fine now. regards ptrex Contributions :Firewall Log Analyzer for XP - Creating COM objects without a need of DLL's - UPnP support in AU3Crystal Reports Viewer - PDFCreator in AutoIT - Duplicate File FinderSQLite3 Database functionality - USB Monitoring - Reading Excel using SQLRun Au3 as a Windows Service - File Monitor - Embedded Flash PlayerDynamic Functions - Control Panel Applets - Digital Signing Code - Excel Grid In AutoIT - Constants for Special Folders in WindowsRead data from Any Windows Edit Control - SOAP and Web Services in AutoIT - Barcode Printing Using PS - AU3 on LightTD WebserverMS LogParser SQL Engine in AutoIT - ImageMagick Image Processing - Converter @ Dec - Hex - Bin -Email Address Encoder - MSI Editor - SNMP - MIB ProtocolFinancial Functions UDF - Set ACL Permissions - Syntax HighLighter for AU3ADOR.RecordSet approach - Real OCR - HTTP Disk - PDF Reader Personal Worldclock - MS Indexing Engine - Printing ControlsGuiListView - Navigation (break the 4000 Limit barrier) - Registration Free COM DLL Distribution - Update - WinRM SMART Analysis - COM Object Browser - Excel PivotTable Object - VLC Media Player - Windows LogOnOff Gui -Extract Data from Outlook to Word & Excel - Analyze Event ID 4226 - DotNet Compiler Wrapper - Powershell_COM - New Link to comment Share on other sites More sharing options...
Reaper HGN Posted March 5, 2007 Share Posted March 5, 2007 Great job on this one. It seems like every time I need this, I am reinventing the wheel and figuring out how I did it the last time. This works much better than my own implementation as well. Thanks Link to comment Share on other sites More sharing options...
GtaSpider Posted March 5, 2007 Share Posted March 5, 2007 hi...nice, ive written smth like this, too but nobody intressed... ( http://www.autoitscript.com/forum/index.php?showtopic=39564 )spder www.AutoIt.de - Moderator of the German AutoIt Forum Link to comment Share on other sites More sharing options...
Xenobiologist Posted March 5, 2007 Share Posted March 5, 2007 Hi, nice one. I like it. Maybe you'dlike to change this: Global $sStdOut = "Hello " & @CR & @CRLF & " World" & @LF Global $s1 = $sStdOut ConsoleWrite("1: " & $sStdOut & @CRLF) $sStdOut = StringReplace($sStdOut, @CR, @TAB) $sStdOut = StringReplace($sStdOut, @LF, @TAB) ConsoleWrite("2: " & $sStdOut & @CRLF) $s1 = StringRegExpReplace($s1, "[\r\n]", @TAB) ConsoleWrite("3: " & $s1 & @CRLF) So long, Mega Scripts & functions Organize Includes Let Scite organize the include files Yahtzee The game "Yahtzee" (Kniffel, DiceLion) LoginWrapper Secure scripts by adding a query (authentication) _RunOnlyOnThis UDF Make sure that a script can only be executed on ... (Windows / HD / ...) Internet-Café Server/Client Application Open CD, Start Browser, Lock remote client, etc. MultipleFuncsWithOneHotkey Start different funcs by hitting one hotkey different times Link to comment Share on other sites More sharing options...
baghenamoth Posted March 7, 2007 Share Posted March 7, 2007 I've been waiting this for a long time ! Thank you very much for this great stuff Link to comment Share on other sites More sharing options...
lod3n Posted March 7, 2007 Author Share Posted March 7, 2007 (edited) @th.meger, I originally tried something like that, but in my testing, I found that in the output there were sometimes @CRs without @LFs, so I couldn't reliably handle that unless I dealt with the two characters separately. I may be wrong though... I will work on a nice fast regex replacement for that part that makes both of us happy. @GtaSpider, your script is neat too, and it's very much like my own original personal UDF. Grabbing the exit code was complex enough though that I thought it might be useful to more people than just me. @Reaper HGN and @baghenamoth: thanks and you're welcome. Edited March 7, 2007 by lod3n [font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font] Link to comment Share on other sites More sharing options...
lordofthestrings Posted May 15, 2007 Share Posted May 15, 2007 I read here that tasklist doesn 't work with this code.. why on earth would you like to try tasklist with such a complex setup. all you need to run tasklist on a remote comp is the /S switch.. Link to comment Share on other sites More sharing options...
lod3n Posted May 15, 2007 Author Share Posted May 15, 2007 This is just a general purpose stdout/stderr/exit code capturer. It does work with tasklist (now), but that doesn't mean it's a good idea to do so, it just means that it can. Use at your own discretion. [font="Fixedsys"][list][*]All of my AutoIt Example Scripts[*]http://saneasylum.com[/list][/font] Link to comment Share on other sites More sharing options...
Oldschool Posted March 16, 2008 Share Posted March 16, 2008 This is just a general purpose stdout/stderr/exit code capturer. It does work with tasklist (now), but that doesn't mean it's a good idea to do so, it just means that it can. Use at your own discretion. 3.2.10.0 crashes when I try to run it, even after fixing the 'long_ptr' thing... Link to comment Share on other sites More sharing options...
flyingboz Posted March 16, 2008 Share Posted March 16, 2008 (edited) 3.2.10.0 crashes when I try to run it, even after fixing the 'long_ptr' thing...insufficient data to debug. Rest assured that I am using a variant of this effectively with the latest releases w/o issues.Quick Note: _RunReadStd() is an indispensable part of my everyday toolkit. I just noticed I hadn't weighed in this thread to express my appreciation for this code publicly. Edited March 16, 2008 by flyingboz Reading the help file before you post... Not only will it make you look smarter, it will make you smarter. Link to comment Share on other sites More sharing options...
Oldschool Posted March 16, 2008 Share Posted March 16, 2008 insufficient data to debug. Rest assured that I am using a variant of this effectively with the latest releases w/o issues.I copy/paste the OP, and get the following after executing:!>18:03:37 AutoIT3.exe ended.rc:-1073741819 Link to comment Share on other sites More sharing options...
flyingboz Posted March 16, 2008 Share Posted March 16, 2008 I copy/paste the OP, and get the following after executing:!>18:03:37 AutoIT3.exe ended.rc:-1073741819insufficient data to debug.version? beta?o/s s/p?how are you calling the function.Quit whining, and take ownership for your problem. give us enough info to help.Don't assume that everyone has your environment, or is interested in duplicating your environment for you.Give us the above, show us how you're calling it, and you _might_ get a useful response. Reading the help file before you post... Not only will it make you look smarter, it will make you smarter. Link to comment Share on other sites More sharing options...
Oldschool Posted March 17, 2008 Share Posted March 17, 2008 3.2.10.0, XP SP2, copy/paste/F5 Anyway, it don't matter...found a 5 liner that works just fine... #include <Array.au3> $result = Run(@ComSpec & " /c ipconfig", "", @SW_HIDE ,$STDERR_CHILD + $STDOUT_CHILD) $line = StdoutRead($result) ; capture output string Capture the resulting output string to a variable $result $result_array = StringSplit($line, @LF) ; Split string at line boundaries Split the string into lines and save a an array _ArrayDisplay($result_array, "IPconfig") Link to comment Share on other sites More sharing options...
flyingboz Posted March 17, 2008 Share Posted March 17, 2008 (edited) I made the one change indicated by the runtime warning, and get expected output. @OldSchool I expect that you misread the help file and went mucking around with other values that you should have left alone. While the code you show will provide access to stdout, it is nowhere near as flexible or useful as _RunReadStd() If nothing else, perhaps you have learned what information is necessary to get useful help on this or any other forum. Best regards. Edited March 17, 2008 by flyingboz Reading the help file before you post... Not only will it make you look smarter, it will make you smarter. Link to comment Share on other sites More sharing options...
ken82m Posted November 5, 2008 Share Posted November 5, 2008 Thanks, works perfectly. I'll get alot of use out of this one. I do have one suggestion. Set @error to 1 if the program couldn't be executed? I mean I can of course check by seeing if row 1 and 2 are null, but still would be a nice feature Thanks, Kenny "I believe that when we leave a place, part of it goes with us and part of us remains... Go anywhere, when it is quiet, and just listen.. After a while, you will hear the echoes of all our conversations, every thought and word we've exchanged.... Long after we are gone our voices will linger in these walls for as long as this place remains." 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