- Has anybody set #Warn to StdOut mode, and been able to retrieve that output from another script?
- Can this be done via AttachConsole and GetStdHandle? As in this scipt. (I couldn't get it to work.) Thanks.
GitHub - joedf/LibCon.ahk: LibCon - AutoHotkey Library For Console Support
https://github.com/joedf/LibCon.ahk
#Warn: get StdOut from another script
#Warn: get StdOut from another script
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: #Warn: get StdOut from another script
Hi jeeswg, some small success, still working at it.
Needs stdout2var.ahk, included.
1) warntest.ahk
2) warn.ahk (this is basically ripped off from the docs for #warn)
3) stdout2var.ahk (from here, I think )
burque505
Needs stdout2var.ahk, included.
1) warntest.ahk
Code: Select all
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#Include stdout2var.ahk
msgbox % StdOutStream("autohotkey.exe warn.ahk")
Code: Select all
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#Warn, All, StdOut ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
g := 1
ShowG() { ; The warning is displayed even if the function is never called.
;global g ; <-- This is required to access the global variable.
MsgBox % g ; Without the declaration, "g" is an empty local variable.
}
Spoiler
Regards,burque505
Re: #Warn: get StdOut from another script
A console is used to display output or get input from the user, not to direct output from one process to another. An application can be associated with a console and yet have stdout directed elsewhere. Scripts and other GUI (not console) applications do not have a console by default. You cannot attach to the console of a process that does not have a console.
Even if you were to attach both scripts to the same console, I do not think you can read console output as a stream. Console output buffers are designed to be written into, with that data being displayed in the console window. If you read from the console (CON), you get the user's input, not the program's output. To get the contents of a console, you need to use a function like ReadConsoleOutput, providing the character position to read from.
There is no difference between retrieving stdout from a script with #Warn and retrieving stdout from any other process. There are numerous examples on the forums, and even some in the documentation:These examples rely on WScript.Shell, which does not support Unicode output. If that's not an issue, I would suggest using WScript.Shell directly rather than using these functions as-is. Otherwise, I would suggest using one of the functions found on the forum, or rolling your own with CreateProcess, CreatePipe, etc.
Even if you were to attach both scripts to the same console, I do not think you can read console output as a stream. Console output buffers are designed to be written into, with that data being displayed in the console window. If you read from the console (CON), you get the user's input, not the program's output. To get the contents of a console, you need to use a function like ReadConsoleOutput, providing the character position to read from.
There is no difference between retrieving stdout from a script with #Warn and retrieving stdout from any other process. There are numerous examples on the forums, and even some in the documentation:
Code: Select all
; Using ExecScript from the docs/Run examples:
MsgBox % ExecScript("#Warn All, StdOut`na:=b+1")
; Using RunWaitOne from the docs/Run examples:
FileAppend % "#Warn All, StdOut`na:=b+1", temp.ahk
MsgBox % RunWaitOne("""" A_AhkPath """ temp.ahk")
FileDelete temp.ahk
Re: #Warn: get StdOut from another script
- Thanks for the ideas.
- I had thought of ExecScript and RunWaitOne, however, those require that the script that monitors another script, also launches that script.
- So, if it's possible, a monitor script that can retrieve the StdOut from a pre-existing script, would be useful.
- I had thought of ExecScript and RunWaitOne, however, those require that the script that monitors another script, also launches that script.
- So, if it's possible, a monitor script that can retrieve the StdOut from a pre-existing script, would be useful.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: #Warn: get StdOut from another script
Why not have a script 'monitor' itself...
Code: Select all
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#Warn All, Stdout ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
a := b+1
If !InStr(ScriptArg(), "ErrorStdOut"){ ;reload script if run without ErrorStdOut...
rP = "%A_AhkPath%" /ErrorStdOut "%A_ScriptFullPath%"
StdOutStream( rP, "StdOutStream_Callback" )
MsgBox, The Original Instance, Now the Monitoring Instance will only exit once Monitored instance is dead...
ExitApp
}
x := y+1
FileAppend, `n Sth... Else, *
StdOutStream_Callback( data, n ) { ;example func
Static D
If n
ToolTip % D .= data
Else
Return "DONE" . ( D := "" )
}
ScriptArg(){
wmi := ComObjGet("winmgmts:")
,queryEnum := wmi.ExecQuery("" . "Select * from Win32_Process where ProcessId=" . DllCall("GetCurrentProcessId"))._NewEnum() ; query to retrieve matching process(es).
return ( queryEnum[process] ? process.CommandLine : "" ) ; return first matching process.
}
StdOutStream( sCmd, Callback := "", WorkingDir:=0, ByRef ProcessID:=0) { ; Modified : maz-1 https://gist.github.com/maz-1/768bf7938e533907d54bff276db80904
Static StrGet := "StrGet" ; Modified : SKAN 31-Aug-2013 http://goo.gl/j8XJXY
; Thanks to : HotKeyIt http://goo.gl/IsH1zs
; Original : Sean 20-Feb-2007 http://goo.gl/mxCdn
tcWrk := WorkingDir=0 ? "Int" : "Str"
DllCall( "CreatePipe", UIntP,hPipeRead, UIntP,hPipeWrite, UInt,0, UInt,0 )
DllCall( "SetHandleInformation", UInt,hPipeWrite, UInt,1, UInt,1 )
If A_PtrSize = 8
{
VarSetCapacity( STARTUPINFO, 104, 0 ) ; STARTUPINFO ; http://goo.gl/fZf24
NumPut( 68, STARTUPINFO, 0 ) ; cbSize
NumPut( 0x100, STARTUPINFO, 60 ) ; dwFlags => STARTF_USESTDHANDLES = 0x100
NumPut( hPipeWrite, STARTUPINFO, 88 ) ; hStdOutput
NumPut( hPipeWrite, STARTUPINFO, 96 ) ; hStdError
VarSetCapacity( PROCESS_INFORMATION, 24 ) ; PROCESS_INFORMATION ; http://goo.gl/b9BaI
}
Else
{
VarSetCapacity( STARTUPINFO, 68, 0 )
NumPut( 68, STARTUPINFO, 0 )
NumPut( 0x100, STARTUPINFO, 44 )
NumPut( hPipeWrite, STARTUPINFO, 60 )
NumPut( hPipeWrite, STARTUPINFO, 64 )
VarSetCapacity( PROCESS_INFORMATION, 16 )
}
;Tip for struct calculation
; Any member should be aligned to multiples of its size
; Full size of structure should be multiples of the largest member size
;============================================================================
;
; x64
; STARTUPINFO
; offset size comment
;DWORD cb; 0 4
;LPTSTR lpReserved; 8 8(A_PtrSize) aligned to 8-byte boundary (4 + 4)
;LPTSTR lpDesktop; 16 8(A_PtrSize)
;LPTSTR lpTitle; 24 8(A_PtrSize)
;DWORD dwX; 32 4
;DWORD dwY; 36 4
;DWORD dwXSize; 40 4
;DWORD dwYSize; 44 4
;DWORD dwXCountChars; 48 4
;DWORD dwYCountChars; 52 4
;DWORD dwFillAttribute; 56 4
;DWORD dwFlags; 60 4
;WORD wShowWindow; 64 2
;WORD cbReserved2; 66 2
;LPBYTE lpReserved2; 72 8(A_PtrSize) aligned to 8-byte boundary (2 + 4)
;HANDLE hStdInput; 80 8(A_PtrSize)
;HANDLE hStdOutput; 88 8(A_PtrSize)
;HANDLE hStdError; 96 8(A_PtrSize)
;
;ALL : 96+8=104=8*13
;
; PROCESS_INFORMATION
;
;HANDLE hProcess 0 8(A_PtrSize)
;HANDLE hThread 8 8(A_PtrSize)
;DWORD dwProcessId 16 4
;DWORD dwThreadId 20 4
;
;ALL : 20+4=24=8*3
;============================================================================
; x86
; STARTUPINFO
; offset size
;DWORD cb; 0 4
;LPTSTR lpReserved; 4 4(A_PtrSize)
;LPTSTR lpDesktop; 8 4(A_PtrSize)
;LPTSTR lpTitle; 12 4(A_PtrSize)
;DWORD dwX; 16 4
;DWORD dwY; 20 4
;DWORD dwXSize; 24 4
;DWORD dwYSize; 28 4
;DWORD dwXCountChars; 32 4
;DWORD dwYCountChars; 36 4
;DWORD dwFillAttribute; 40 4
;DWORD dwFlags; 44 4
;WORD wShowWindow; 48 2
;WORD cbReserved2; 50 2
;LPBYTE lpReserved2; 52 4(A_PtrSize)
;HANDLE hStdInput; 56 4(A_PtrSize)
;HANDLE hStdOutput; 60 4(A_PtrSize)
;HANDLE hStdError; 64 4(A_PtrSize)
;
;ALL : 64+4=68=4*17
;
; PROCESS_INFORMATION
;
;HANDLE hProcess 0 4(A_PtrSize)
;HANDLE hThread 4 4(A_PtrSize)
;DWORD dwProcessId 8 4
;DWORD dwThreadId 12 4
;
;ALL : 12+4=16=4*4
If ! DllCall( "CreateProcess", UInt,0, UInt,&sCmd, UInt,0, UInt,0 ; http://goo.gl/USC5a
, UInt,1, UInt,0x08000000, UInt,0, tcWrk, WorkingDir
, UInt,&STARTUPINFO, UInt,&PROCESS_INFORMATION )
{
DllCall( "CloseHandle", UInt,hPipeWrite )
DllCall( "CloseHandle", UInt,hPipeRead )
DllCall( "SetLastError", Int,-1 )
Return ""
}
hProcess := NumGet( PROCESS_INFORMATION, 0 )
hThread := NumGet( PROCESS_INFORMATION, A_PtrSize )
ProcessID:= NumGet( PROCESS_INFORMATION, A_PtrSize*2 )
DllCall( "CloseHandle", UInt,hPipeWrite )
AIC := ( SubStr( A_AhkVersion, 1, 3 ) = "1.0" ) ; A_IsClassic
VarSetCapacity( Buffer, 4096, 0 ), nSz := 0
While DllCall( "ReadFile", UInt,hPipeRead, UInt,&Buffer, UInt,4094, UIntP,nSz, Int,0 ) {
tOutput := ( AIC && NumPut( 0, Buffer, nSz, "Char" ) && VarSetCapacity( Buffer,-1 ) )
? Buffer : %StrGet%( &Buffer, nSz, "CP0" ) ; formerly CP850, but I guess CP0 is suitable for different locales
Isfunc( Callback ) ? %Callback%( tOutput, A_Index ) : sOutput .= tOutput
}
DllCall( "GetExitCodeProcess", UInt,hProcess, UIntP,ExitCode )
DllCall( "CloseHandle", UInt,hProcess )
DllCall( "CloseHandle", UInt,hThread )
DllCall( "CloseHandle", UInt,hPipeRead )
DllCall( "SetLastError", UInt,ExitCode )
VarSetCapacity(STARTUPINFO, 0)
VarSetCapacity(PROCESS_INFORMATION, 0)
Return Isfunc( Callback ) ? %Callback%( "", 0 ) : sOutput
}
live ? long & prosper : regards
Re: #Warn: get StdOut from another script
A "pre-existing" script has already sent all of its load-time warnings to stdout, probably discarding them since stdout hasn't been directed anywhere.
Re: #Warn: get StdOut from another script
- Thanks CyL0N, I'll take a look.
- Thanks lexikos.
- It looks like OutputDebug will be the way to go, so that one script can handle all errors.
- I'm currently using DebugView, (it gathers text in a listview control,) but I'd like to remove the dependency on it. This script is almost complete:
retrieve OutputDebug text - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=58069
- I've found it difficult to find good info for StdIn/StdOut, as evidenced by the 3 queries here: Maxima CAS (wxMaxima): run via the command line - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=56032
- It would be a good subject for a mini-tutorial, to get a fuller understanding.
- Does anyone use StdOut with #Warn? The approach seems to have some limitations, at least for what I'm trying to do, maybe I missed something.
- Although /ErrorStdOut has been very useful e.g.:
numbers/strings in expressions - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 37&t=55905
- Thanks lexikos.
- It looks like OutputDebug will be the way to go, so that one script can handle all errors.
- I'm currently using DebugView, (it gathers text in a listview control,) but I'd like to remove the dependency on it. This script is almost complete:
retrieve OutputDebug text - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=58069
- I've found it difficult to find good info for StdIn/StdOut, as evidenced by the 3 queries here: Maxima CAS (wxMaxima): run via the command line - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=56032
- It would be a good subject for a mini-tutorial, to get a fuller understanding.
- Does anyone use StdOut with #Warn? The approach seems to have some limitations, at least for what I'm trying to do, maybe I missed something.
- Although /ErrorStdOut has been very useful e.g.:
numbers/strings in expressions - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 37&t=55905
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: #Warn: get StdOut from another script
jeeswg said:
(I still think StdOut2Var as used in my example above and CyLON's as well might prove useful for your purposes.)
The needed files should be in the ZIP attached.
Regards,
burque505
The example below, although I don't believe it meets your needs exactly, might still be useful. It's referencing libraries by FanaticGuru ("GuiVar.ahk"), Relayer ("GuiVar_Class.ahk"), and modified slightly from the example scripts given. Script_1 does NOT retrieve StdOut from a "pre-existing" script, but it does send and receive information from Script_2, manually launched within 10 seconds AFTER Script_1 (and not BY Script_1, although the original script "Script#1) did launch Script#2).- I had thought of ExecScript and RunWaitOne, however, those require that the script that monitors another script, also launches that script.
- So, if it's possible, a monitor script that can retrieve the StdOut from a pre-existing script, would be useful.
(I still think StdOut2Var as used in my example above and CyLON's as well might prove useful for your purposes.)
The needed files should be in the ZIP attached.
Regards,
burque505