Shaggi Posted March 15, 2011 Posted March 15, 2011 (edited) Sup,This isn't really an advanced UDF, but implements a couple of functions and features, with the idea of substituting the original functions like ConsoleWrite() and ConsoleWriteError() and the seriously sketchy ConsoleRead() lol.Public functions:Cout()Cin()Getch()Cerr()system()RegisterConsoleEvent()The motive for writing this was the missing ability to read user input from consoles in AutoIt, known as std::cin >> in C++. The UDF's design allows quick and simple access to the functions, without startup / shutdown and handle passing - all this is automatically taken care of. Some users may have know, that you cannot open a console if the script is running from SciTE - this UDF handles that problem, so you can open an console while running scripts through SciTE.Features:Dynamically opens and closes consolesUse the STDOUT, STDERR and STDIN streams like in other languages.Print coloured/styled textAccess the command interpreter through the console.Uses unicode.Register console events.The UDF is designed to work standalone and to have minimal overhead (> 0.1 ms for writing a coloured string)The UDF supports my style of scripting. I hate long names so standard UDF naming like _Console_WriteConsoleW() is abbreviated to Cout() for now. I also hate having to start up certain UDF's by calling funcs etc., so this is handled first time you call a function. Handles are controlled globally and closed when needed, so you don't need to pass them around lol.Why would anyone need this?Good question. I guess this mainly goes out to people with a bit of nostalgia in them. I personally like the feel of a console.Picture:Changelog:25-06-2012 Fixed system() to allow case sensitive text.25-06-2012 Fixed typo's.Changed frequent dllcalls to use dllcalladdress for speed.Added RegisterConsoleEvent - functions can be registrered to be called on certain events, like closure of console. This can be used to mimic OnAutoItExit behaviour, that wont be called in case of bad closure.Various optimizations.09-07-2011 Added Getch() function.Better error handling all around.Put back color attribute constants as they are more symbolic imo.Decreased the standard size of Cin allocation (bit harsh to allocate 2 kb memory each time) - it's now changed to 128 chars.05-06-2011 Added color constants thanks to Warmonger.16-03-2011 Fixed Cin() bug.Cin() isn't returning a trailing CRLF anymore.Fixed startup function, so it should run from SciTE now.15-03-2011 - Initial release.NotesI know Matt Diesel was/is working on large, similar UDF, however i wanted something simpler and easier to use. This is the result. Thoughts? Console.au3 Edited August 6, 2012 by Shaggi arqstaad, mvk25 and Gianni 3 Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG
UEZ Posted March 15, 2011 Posted March 15, 2011 Looks very interesting. Any example available? Br, UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
ProgAndy Posted March 15, 2011 Posted March 15, 2011 Not bad. I think I'll have to improve my Console UDFs, too *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes
Shaggi Posted March 15, 2011 Author Posted March 15, 2011 (edited) Looks very interesting. Any example available? Br, UEZ Thanks and yes, well this is a pretty common example: expandcollapse popup#include <Console.au3> Main() Func Main() Local $Name Local $Age Local $Answer Local $Continue = True While $Continue Cout("Enter your name: ") Cin($Name) Cout("Enter your age: ") Cin($Age) Cout("Do you want your answers printed in red? y/n: ") Cin($Answer) If StringInStr($Answer,"y") Then Cout(@LF & "Your name is ") Cout($Name & @LF,$FOREGROUND_RED) Cout("You were born in ") Cout(@Year - $Age & @LF,$FOREGROUND_RED) Else Cout(@LF & "Your name is ") Cout($Name & @LF) Cout("You were born in ") Cout(@Year - $Age & @LF) EndIf $Answer = "" Cout(@LF & "Do you want to try again? y/n: ") Cin($Answer) If StringInStr($Answer,"n") Then $Continue = False EndIf WEnd system("pause") EndFunc Not bad. I think I'll have to improve my Console UDFs, too Thanks. Edited March 15, 2011 by Shaggi mLipok 1 Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG
taietel Posted March 16, 2011 Posted March 16, 2011 Thanks for sharing Shaggi. One suggestion: I had an error regarding writting memory, but when I modified it (see below), it worked. In your Cin function, add this (see the <<<<<<<<<<< sign): Local $aResult = DllCall($__Dll_Kernel32, "BOOL", "ReadConsoleW", _ "handle", $__ConsoleHandle__Input, _ "ptr", DllStructGetPtr($lpBuffer), _ "dword", DllStructGetSize($lpBuffer), _ "dword*", $lpNumberOfCharsRead, _ "ptr", 0) ;<<<<<<<<<<< ADD THIS taietel Things you should know first...In the beginning there was only ONE! And zero... Progs: Create PDF(TXT2PDF,IMG2PDF) 3D Bar Graph DeskGadget Menu INI Photo Mosaic 3D Text
Mat Posted March 16, 2011 Posted March 16, 2011 You are right that it is a lot easier to use than mine, as mine is a direct wrapper around the WinAPI. Maybe I'll implement similar functions when I finish my UDF. It still doesn't work running from SciTE (mine has the same problem). Any idea how to fix that? AutoIt Project Listing
UEZ Posted March 16, 2011 Posted March 16, 2011 Thanks for the example. As taietel said it is crashing but working when I add the line mentioned by him. Br, UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
Shaggi Posted March 16, 2011 Author Posted March 16, 2011 You are right that it is a lot easier to use than mine, as mine is a direct wrapper around the WinAPI. Maybe I'll implement similar functions when I finish my UDF. It still doesn't work running from SciTE (mine has the same problem). Any idea how to fix that? Well currently mine does (by me, anyway - anyone having trouble with new version?). It opens a new instance of the script around SciTE but still does the checking etc. As for that last parameter, it should be optional (according to MSDN): BOOL WINAPI ReadConsole( __in HANDLE hConsoleInput, __out LPVOID lpBuffer, __in DWORD nNumberOfCharsToRead, __out LPDWORD lpNumberOfCharsRead, __in_opt LPVOID pInputControl );But i added it anyway in the new release... Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG
Mat Posted March 16, 2011 Posted March 16, 2011 (edited) You should do the command line properly. ShellExecuteWait is not a good solution because (as is the case with me) it doesn't always work. Edit: It works when I use:Local $iReturnCode = RunWait(@AutoItExe & ' ' & StringStripWS(StringTrimLeft($CmdLineRaw, StringLen("/ErrorStdOut")), 0x1 + 0x2)) Edited March 16, 2011 by Mat AutoIt Project Listing
ProgAndy Posted March 16, 2011 Posted March 16, 2011 As for that last parameter, it should be optional (according to MSDN):Optional means, that it is allowed to be NULL. AFAIK, this parameter has a default value of NULL in the C-headers, so it is not required to add it to the actual function call, but in AutoIt you have to use the complete call. *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes
Shaggi Posted March 16, 2011 Author Posted March 16, 2011 Optional means, that it is allowed to be NULL. AFAIK, this parameter has a default value of NULL in the C-headers, so it is not required to add it to the actual function call, but in AutoIt you have to use the complete call. I see I haven't experienced a crash yet though... Maybe it depends on os, or length of the input string? You should do the command line properly. ShellExecuteWait is not a good solution because (as is the case with me) it doesn't always work. Edit: It works when I use:Local $iReturnCode = RunWait(@AutoItExe & ' ' & StringStripWS(StringTrimLeft($CmdLineRaw, StringLen("/ErrorStdOut")), 0x1 + 0x2)) Isn't this fixed in the new version? Try redownloading. Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG
Mat Posted March 16, 2011 Posted March 16, 2011 Yes sorry, it is fixed. There must be a better way to do it than to spawn a new process though... AutoIt Project Listing
hezi Posted March 16, 2011 Posted March 16, 2011 Looks very nice, can it be used for "expect like" scripting? running commands in console and wait for output. it can save me using TKL and use only autoit. Thanks.
Shaggi Posted March 16, 2011 Author Posted March 16, 2011 Yes sorry, it is fixed. There must be a better way to do it than to spawn a new process though... Apparently not.. hm. Looks very nice, can it be used for "expect like" scripting? running commands in console and wait for output. it can save me using TKL and use only autoit. Thanks. Well, something like this? #include <Console.au3> _Main() Func _Main() Local $CommandString, $Answer, $Continue = True While $Continue Cin($CommandString) Cout(Execute($CommandString) & @CRLF,$BACKGROUND_GREEN) Cout(@LF & "Do you want to try again? y/n: ") Cin($answer) If $Answer == "n" Then $Continue = False EndIf WEnd system("pause") EndFunc Please elaborate, i'm not quite sure i understand you. Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG
ProgAndy Posted March 17, 2011 Posted March 17, 2011 Here is some code I use in the development-version of my console.au3 With this, the console should be displayed when running from scite. If Not @Compiled And StringRegExp($CMDLINERAW, "(?i)(\A|\s)/ErrorStdOut(\s|\Z)") Then Local $aTmp[3][2] = [["CONIN$", 2],["CONOUT$", 4],["CONERR$", 4]] For $i = 0 To 2 $GLOBAL_hConsole[$i] = _WinAPI_CreateFile($aTmp[$i][0], 2, $aTmp[$i][1], $aTmp[$i][1]) If $GLOBAL_hConsole[$i] = 0 Then If $ExitOnFatal Then _WinAPI_FatalAppExit("GetStdHandle for " & $msg[$i] & " failed") Return SetError(2 + $i, 0, 0) EndIf Next Else For $i = 0 To 2 $GLOBAL_hConsole[$i] = _WinAPI_GetStdHandle($i) If $GLOBAL_hConsole[$i] <= 0 Then If $ExitOnFatal Then _WinAPI_FatalAppExit("GetStdHandle for " & $msg[$i] & " failed") Return SetError(2 + $i, 0, 0) EndIf Next EndIf *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes
hezi Posted March 17, 2011 Posted March 17, 2011 Apparently not.. hm. Well, something like this? #include <Console.au3> _Main() Func _Main() Local $CommandString, $Answer, $Continue = True While $Continue Cin($CommandString) Cout(Execute($CommandString) & @CRLF,$BACKGROUND_GREEN) Cout(@LF & "Do you want to try again? y/n: ") Cin($answer) If $Answer == "n" Then $Continue = False EndIf WEnd system("pause") EndFunc Please elaborate, i'm not quite sure i understand you. Thanks, but i think its not what im looking for, i will try to explain: my goal is to open cmd window and run command into it, wait for the output and then run the next command, and so on. the flow should look something like: run cmd -> send to console - format x: wait for output - "Proceed with Format (Y/N)?" send to console - "N" wait for output - "c:\" (the prompt) I want to use it to automate ssh connections, the format is just example...
Shaggi Posted March 17, 2011 Author Posted March 17, 2011 Thanks, but i think its not what im looking for, i will try to explain: my goal is to open cmd window and run command into it, wait for the output and then run the next command, and so on. the flow should look something like: run cmd -> send to console - format x: wait for output - "Proceed with Format (Y/N)?" send to console - "N" wait for output - "c:\" (the prompt) I want to use it to automate ssh connections, the format is just example... Yes, that is possible. However since the system() command blocks, you can't use it like you probably would... #include <Console.au3> __main() Func __Main() Local $CommandString, $Answer, $Continue = True, $iReturn While $Continue Cout(@CRLF & "Enter your command: " & @CRLF,$FOREGROUND_RED) Cin($CommandString) $iReturn = system($commandstring) Cout(@LF & "Return from system: ") Cout(" " & $iReturn & @CRLF,$BACKGROUND_GREEN) Cout(@LF & "Do you want to try again? y/n: ") Cin($answer) If $Answer == "n" Then $Continue = False EndIf WEnd system("pause") EndFunc Try something like this instead: expandcollapse popup$iHandle = Run("cmd.exe",@ScriptDIr,@SW_HIDE,0x1 + 0x8) Global $lastErr While 1 $Command = GetCommand() If $LastErr THen ExitLoop Dispatch($Command) PrintOutput() Wend StdIoClose($iHandle) Func GetCommand() Local $ans = InputBox("Command Interpreter","Please enter a command...") $LastErr = @Error Return $Ans EndFunc Func Dispatch($szCommand) StdinWrite($iHandle,$szCommand & @CRLF) EndFunc Func PrintOutput() $nMsg = StdoutRead($iHandle) Local $hasBeenRead = False, $Count = 0 While NOT @error IF $hasBeenRead AND $nMsg == "" Then $Count += 1 Sleep(100) If $Count > 10 Then ExitLoop EndIf ConsoleWrite($nMsg) $nMsg = StdoutRead($iHandle) If $nMsg <> "" Then $hasBeenRead = True If @Error Then ExitLoop WEnd EndFunc Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG
hezi Posted March 21, 2011 Posted March 21, 2011 I think it can work with some modifications, it will take me some time to try, but you gave me good start. Thanks!
MvGulik Posted March 23, 2011 Posted March 23, 2011 Plugging in your console UDF seemed like a easy way to get colored output in the console I'm using ... but that was a short exercise. (My exe being a CUI thats using the real windows-dos console. Oops, small communication mismatch on the word 'Console'.) Still a nice UDF though. "Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions.""The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014) "Believing what you know ain't so" ... Knock Knock ...
Warmonger Posted May 18, 2011 Posted May 18, 2011 (edited) Here's a update to this UDF (Shaggi I hope you don't mind just minor things). You can now use all 255 color combinations in a console, however you cannot Obfuscate your source no longer (bug).Removed:$FOREGROUND_X $BACKGROUND_XAdded:$COLOR_X (1-255)#include <Console.au3> Dim $COLOR_ For $i = 1 to 255 Cout($i & ' ', $COLOR_ & $i) Sleep(10) Next While 1 = 1 Sleep(1000) WEndConsole.au3 Edited May 18, 2011 by Warmonger [AutoIt File Patcher]
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