Print(), PrintDebug(), Stdout() & Stdin()

Post your working scripts, libraries and tools for AHK v1.1 and older
CyL0N
Posts: 211
Joined: 27 Sep 2018, 09:58

Print(), PrintDebug(), Stdout() & Stdin()

03 Oct 2018, 04:36

UPDATE:
  • Added Stdout() to output to a created console output,appending every subsequent output to console...
    Added Stdin() to accept input from console to var...


This is method seldom used to display script output for reasons beyond me,with most people deferring to MsgBox,ToolTip & TrayTip commands or Gui's to display output, TBH i've really only ever seen it used from a script by Lexikos which is where i picked up the idea from... Thought i'd share it, if anything so that people use that builtin GUI for something... Cheers...

Code: Select all


Print("Hello World")
Loop, 100
	PrintDebug(A_Index)
MsgBox
PrintDebug()		;clear debug output...
MsgBox
PrintDebug("A new debug session...")
MsgBox

Print(string){
	ListVars
	WinWait ahk_id %A_ScriptHwnd%
	ControlSetText Edit1, %string%
	WinWaitClose
}


PrintDebug(string:=""){
	Static
	string := string ? string . "`r`n" . lastStr : "", lastStr := string
	If !WinActive("ahk_class AutoHotkey"){
		ListVars
		WinWait ahk_id %A_ScriptHwnd%
		WinGetTitle, title, ahk_id %A_ScriptHwnd%
	}Else If !string{
		PostMessage, 0x112, 0xF060,,, %title% ; 0x112 = WM_SYSCOMMAND, 0xF060 = SC_CLOSE
		Return
	}
	ControlSetText Edit1, %string%, ahk_id %A_ScriptHwnd%
}



Stdout() below basically lets output directly to console,without running the script with a | more pipe or even running it from a console, allowing use of console just as any MsgBox,ToolTip & TrayTip commands or Gui's to display output...
StdIn() accepts console input to var...
As per wolf_II's suggestion Stdout is compatible with SciTE, though Stdin is not as i don't know how to read from SciTE console...
Updated: Fixed to work with scripts being run from console,i.e output to console being run on, StdIn may have some issues though with intermittent gafs when accepting input from existing console, cause unkown.

Code: Select all

Loop, 100
	Stdout(A_Index, false)	;output to new console with scite check disabled for realtime performance.

Stdout("Hello there.")	;output to new console
name := Stdin("so what's your name?")
Stdout("Hello again... " . name)	;append to console
Sleep 2000
Stdout()	;free console
Sleep 2000
Stdout("Back again")	;output to new console
Sleep 2000
Stdout()

Stdout(output:="", sciteCheck := true){	;output to console	-	sciteCheck reduces Stdout/Stdin performance,so where performance is necessary disable it accordingly
	Global ___console___
	If (sciteCheck && ProcessExist("SciTE.exe") && GetScriptParentProcess() = "SciTE.exe"){	;if script parent is scite,output to scite console & return
		FileAppend, %output%`n, *
		Return
	}																												;CONOUT$ is a special file windows uses to expose attached console output
	( output ? ( !___console___? (DllCall("AttachConsole", "int", -1) || DllCall("AllocConsole")) & (___console___:= true) : "" ) & FileAppend(output . "`n","CONOUT$") : DllCall("FreeConsole") & (___console___:= false) & StdExit() )
}

Stdin(output:="", sciteCheck := true){	;output to console & wait for input & return input
	Global ___console___
	If (sciteCheck && ProcessExist("SciTE.exe") && GetScriptParentProcess() = "SciTE.exe"){	;if script parent is scite,output to scite console & return
		FileAppend, %output%`n, *
		Return
	}
	( output ? ( !___console___? (DllCall("AttachConsole", "int", -1) || DllCall("AllocConsole")) & (___console___:= true) : "" ) & FileAppend(output . "`n","CONOUT$") & (Stdin := FileReadLine("CONIN$",1)) : DllCall("FreeConsole") & (___console___:= false) & StdExit() )
	Return Stdin
}

StdExit(){
	If GetScriptParentProcess() = "cmd.exe"		;couldn't get this: 'DllCall("GenerateConsoleCtrlEvent", CTRL_C_EVENT, 0)' to work so...
		ControlSend, , {Enter}, % "ahk_pid " . GetParentProcess(GetCurrentProcess())
}

FileAppend(str, file){
	FileAppend, %str%, %file%
}

FileReadLine(file,lineNum){
	FileReadLine, retVal, %file%, %lineNum%
	return retVal
}

ProcessExist(procName){
	Process, Exist, % procName
	Return ErrorLevel
}

GetScriptParentProcess(){
	return GetProcessName(GetParentProcess(GetCurrentProcess()))
}

GetParentProcess(PID)
{
	static function := DllCall("GetProcAddress", "ptr", DllCall("GetModuleHandle", "str", "kernel32.dll", "ptr"), "astr", "Process32Next" (A_IsUnicode ? "W" : ""), "ptr")
	if !(h := DllCall("CreateToolhelp32Snapshot", "uint", 2, "uint", 0))
		return
	VarSetCapacity(pEntry, sz := (A_PtrSize = 8 ? 48 : 36)+(A_IsUnicode ? 520 : 260))
	Numput(sz, pEntry, 0, "uint")
	DllCall("Process32First" (A_IsUnicode ? "W" : ""), "ptr", h, "ptr", &pEntry)
	loop
	{
		if (pid = NumGet(pEntry, 8, "uint") || !DllCall(function, "ptr", h, "ptr", &pEntry))
			break
	}
	DllCall("CloseHandle", "ptr", h)
	return Numget(pEntry, 16+2*A_PtrSize, "uint")
}

GetProcessName(PID)
{
	static function := DllCall("GetProcAddress", "ptr", DllCall("GetModuleHandle", "str", "kernel32.dll", "ptr"), "astr", "Process32Next" (A_IsUnicode ? "W" : ""), "ptr")
	if !(h := DllCall("CreateToolhelp32Snapshot", "uint", 2, "uint", 0))
		return
	VarSetCapacity(pEntry, sz := (A_PtrSize = 8 ? 48 : 36)+260*(A_IsUnicode ? 2 : 1))
	Numput(sz, pEntry, 0, "uint")
	DllCall("Process32First" (A_IsUnicode ? "W" : ""), "ptr", h, "ptr", &pEntry)
	loop
	{
		if (pid = NumGet(pEntry, 8, "uint") || !DllCall(function, "ptr", h, "ptr", &pEntry))
			break
	}
	DllCall("CloseHandle", "ptr", h)
	return StrGet(&pEntry+28+2*A_PtrSize, A_IsUnicode ? "utf-16" : "utf-8")
}

GetCurrentProcess()
{
	return DllCall("GetCurrentProcessId")
}
Last edited by CyL0N on 12 Oct 2018, 00:36, edited 11 times in total.
live ? long & prosper : regards
guest3456
Posts: 3463
Joined: 09 Oct 2013, 10:31

Re: Print() & PrintDebug()

03 Oct 2018, 04:45

nice work, i like it
CyL0N wrote:This is method seldom used to display script output for reasons beyond me,with most people deferring to MsgBox,ToolTip & TrayTip commands or Gui's to display output
well, how about this as a reason: why go through all this trouble when those other commands do job easier? what does using the script's listvars window offer that those others don't?

CyL0N
Posts: 211
Joined: 27 Sep 2018, 09:58

Re: Print() & PrintDebug()

03 Oct 2018, 23:42

guest3456 wrote:nice work, i like it
CyL0N wrote:This is method seldom used to display script output for reasons beyond me,with most people deferring to MsgBox,ToolTip & TrayTip commands or Gui's to display output
well, how about this as a reason: why go through all this trouble when those other commands do job easier? what does using the script's listvars window offer that those others don't?
Thanks, i hope you find it useful too, and the main reason i prefer it is that it allows for a large output that would otherwise require a scrolling Gui as well as rapidly changing outputs which Tooltips excel at in a single package,whilst allowing rapid debugging without resorting to log files or a number of Tooltips as PrintDebug preserves previous outputs.
live ? long & prosper : regards
CyL0N
Posts: 211
Joined: 27 Sep 2018, 09:58

Re: Print(), PrintDebug() & Stdout()

05 Oct 2018, 21:16

UPDATE:
  • Added Stdout() to output to a created console output,appending every subsequent output to console...
    Added Stdin() to accept input from console to var...
Last edited by CyL0N on 06 Oct 2018, 00:04, edited 1 time in total.
live ? long & prosper : regards
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: Print(), PrintDebug() & Stdout()

05 Oct 2018, 21:59

Thanks for sharing those functions.
I changed the CONOUT$ to * and running the script from SciTE4AHK is also supported.
CyL0N
Posts: 211
Joined: 27 Sep 2018, 09:58

Re: Print(), PrintDebug() & Stdout()

06 Oct 2018, 00:11

wolf_II wrote:Thanks for sharing those functions.
I changed the CONOUT$ to * and running the script from SciTE4AHK is also supported.
Cheers wolf_II, Replacing CONOUT$ with * kinds of breaks the functionality as CONOUT$ is a special file,so yes it might output to scite console but the created/attached console would be useless not to mention the Stdin() function i added after you posted would be a tad useless as well. It's better i think to use a normal FileAppend, %output%`n, * to output to scite console.

I thought about checking parent process to see if it was scite & ouput to it's console if so,but i couldn't figure out how to also make Stdin() work with that approach, so i abandoned it,unless you know of a way to make both functions work with scite console...
live ? long & prosper : regards
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: Print(), PrintDebug(), Stdout() & Stdin()

06 Oct 2018, 02:30

OK, I see now. Thanks.
... and no, I don't know how to make AHK use the stdin feature of the SciTE console.
CyL0N
Posts: 211
Joined: 27 Sep 2018, 09:58

Re: Print(), PrintDebug(), Stdout() & Stdin()

06 Oct 2018, 02:57

wolf_II wrote:OK, I see now. Thanks.
... and no, I don't know how to make AHK use the stdin feature of the SciTE console.

That's too bad, i updated main post to be compatible with scite & otherwise, stdin() ofcourse doesn't work with scite though...
It checks if parent process is scite to decide where to output...
live ? long & prosper : regards
CyL0N
Posts: 211
Joined: 27 Sep 2018, 09:58

Re: Print(), PrintDebug(), Stdout() & Stdin()

08 Oct 2018, 04:58

Fixed A Performance issue with Stdout/Stdin and scite checking, so either change scite checking defaults if you don't intend to use scite, or disable sciteChecking for every call.

Replaced wmi with DllCall for parent process checking for faster checks...though still slow enough to warrant an option to disable checking.
live ? long & prosper : regards
User avatar
Cerberus
Posts: 172
Joined: 12 Jan 2016, 15:46

Re: Print(), PrintDebug(), Stdout() & Stdin()

10 Oct 2018, 16:09

Very interesting! I've subscribed to this topic. I will probably test this in the future and use it for a linter that I have written for Autohotkey.
CyL0N
Posts: 211
Joined: 27 Sep 2018, 09:58

Re: Print(), PrintDebug(), Stdout() & Stdin()

12 Oct 2018, 00:37

Updated: Fixed to work with scripts being run from console,i.e output to console being run on, StdIn may have some issues though with intermittent gafs when accepting input from existing console, cause unkown.

Will gladly accept solutions for the specified issue with StdIn,which occurs ONLY when script is run from console...
live ? long & prosper : regards
User avatar
eagleDog
Posts: 11
Joined: 28 Aug 2023, 01:00
Contact:

Re: Print(), PrintDebug(), Stdout() & Stdin()

23 Sep 2023, 21:29

This is exactly what I've been looking for, but I can't get it to work so far. I've spent the past several days feverishly attempting to deconstruct the code here, learn about DLL calls, and break off bite-sized pieces. At the most basic level, here is my first main problem so far:

It seems that I should be able to launch a new console window window with `DLLCall("AllocConsole")`, but when I run this, nothing happens. Here is my simplest code:

Code: Select all

  response := DllCall("AllocConsole")
  msgbox % response
This returns a value of 1, which the internet says means that the process was successful. I can also get a return value of 0, with the following:

Code: Select all

  DllCall("AttachConsole", "int", -1)
  response := DllCall("AllocConsole")
  msgbox % response
This returns 0, which I think means that the AHK process successfully attached itself to a console, and therefore failed to subsequently allocate a new console window. In other words, everything seems to be working, but I just can't see the console window, nor can I successfully send a message to an existing console window.

Do you Awesome AHK Forum Friends (AAHKFFs) have any suggestions on how to proceed?

I have reviewed the "What is DLLCall in AHK?" thread (viewtopic.php?t=23925), watched Raptor's excellent videos, and checked out the related Tutorial(https://www.autohotkey.com/board/topic/88313-my-dllcall-tutorial-for-beginnersmessagebox/). My greatest DLL success so far is that I was able to create a MessageBox using the following code:

Code: Select all

DllCall("MessageBox","Uint",0,"Str","This Message is pooped through DLLcall","Str","I typed that title","Uint","0x00000036L")
Thank you all. Best regards and happy wishes. I really love using AHK. I think it is such a wonderful tool. :trollface:
User avatar
eagleDog
Posts: 11
Joined: 28 Aug 2023, 01:00
Contact:

Re: Print(), PrintDebug(), Stdout() & Stdin()

23 Sep 2023, 23:23

__UPDATE__
Oh wow, this is exciting!
My text editor is Sublime Text. It appears that Sublime Text was highjacking the console allocation. But now I've discovered the thing I always hoped for: the ability to log debug information directly to the Sublime Text console!! Hip hip... hooray!!! God bless this thread!! :bravo: :dance: :superhappy:
Image
When I close out of Sublime Text completely, I am able to launch a new console window, as expected, with `DllCall("AllocConsole")`. And bonus: now I can do what I never dreamed of -- sending information directly to my Sublime Text console area.

Hence, the answer to my question was, "Close Sublime Text". And now I shall continue with my quest to receive information from the console. Best regards to all!
User avatar
eagleDog
Posts: 11
Joined: 28 Aug 2023, 01:00
Contact:

Re: Print(), PrintDebug(), Stdout() & Stdin()

24 Sep 2023, 19:03

This thread has been very helpful for me. Big thanks to CyL0N et al.
For output to command line, I also get good results with the following:

Code: Select all

ControlSend, , asdf {Enter}, ahk_class ConsoleWindowClass
For StdIn(), I had no luck with CyL0N's script, but I found a solution from Lexikos on this archived thread: https://www.autohotkey.com/board/topic/33397-screen-capture-in-command-console/. My code below is a summary of the Lexikos solution.

After attaching console, I can retrieve all console contents with the following:

Code: Select all

GetConsoleText() {
  handle := DllCall("CreateFile","str","CONOUT$","uint",0xC0000000
                    ,"uint",7,"uint",0,"uint",3,"uint",0,"uint",0)

  VarSetCapacity(buffer_info, 40, 0)

  DllCall("GetConsoleScreenBufferInfo"
          ,"uint",handle,"uint",&buffer_info)

  ConWinLeft := NumGet(buffer_info, 10, "Short")     ; info.srWindow.Left
  ConWinTop := NumGet(buffer_info, 12, "Short")      ; info.srWindow.Top
  ConWinRight := NumGet(buffer_info, 14, "Short")    ; info.srWindow.Right
  ConWinBottom := NumGet(buffer_info, 16, "Short")   ; info.srWindow.Bottom
  ConWinWidth := ConWinRight - ConWinLeft + 1
  ConWinHeight := ConWinBottom - ConWinTop + 1

  VarSetCapacity(output_text, ConWinWidth * ConWinHeight, 0)

  DllCall("ReadConsoleOutputCharacter","uint",handle
          ,"str",output_text,"uint",1000,"uint",0,"uint*")

  msgbox % output_text
}
I am sharing here, in case these snippets may be helpful to others in the future. :HeHe:

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 253 guests