Page 1 of 1

Read windows console already open [Resolved]

Posted: Thu Nov 14, 2019 1:25 pm
by Kwai chang caine
Hello at all :D

Someone know a way to read the text into the console windows already visible

Have a good day

Re: Read windows console already open

Posted: Thu Nov 14, 2019 1:45 pm
by infratec
First idea:

emulate ctrl-a ctrl-c
Then it is in clipboard :mrgreen:

Second idea:
https://devblogs.microsoft.com/powershe ... le-screen/

Re: Read windows console already open

Posted: Thu Nov 14, 2019 2:30 pm
by Kwai chang caine
Hello INFRATEC :D

Even with CTRL A + CTR C that not works :lol:

And for powershell ....i try to understand :oops:

Re: Read windows console already open

Posted: Thu Nov 14, 2019 3:31 pm
by Kwai chang caine
For Powershell i have understand, but apparently that return the content of the "Powershell console" not "windows console" :|

Re: Read windows console already open

Posted: Thu Nov 14, 2019 6:09 pm
by CELTIC88
:D hi @Kwai chang caine
for you :lol:

Code: Select all

;exemple to get any console text  by  Handle using UI Automation 

;https://en.wikipedia.org/wiki/Microsoft_UI_Automation

EnableExplicit
Macro DEFINE_GUID(name, l1, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
	DataSection
		name:
		Data.l $l1
		Data.w $w1, $w2
		Data.b $b1, $b2, $b3, $b4, $b5, $b6, $b7, $b8
	EndDataSection
EndMacro

DEFINE_GUID(IID_IUIAutomation,            30cbe57d, d9d0, 452a, ab, 13, 7a, c5, ac, 48, 25, ee);
DEFINE_GUID(CLSID_CUIAutomation,          ff48dba4, 60ef, 4201, aa, 87, 54, 10, 3e, ef, 59, 4e);

Interface IUIAutomation Extends IUnknown
	CompareElements()
	CompareRuntimeIds()
	GetRootElement()
	ElementFromHandle(hwnd,*Element)
	ElementFromPoint()
	GetFocusedElement()
	GetRootElementBuildCache()
	ElementFromHandleBuildCache()
	ElementFromPointBuildCache()
	GetFocusedElementBuildCache()
	CreateTreeWalker()
	ControlViewWalker()
	ContentViewWalker()
	RawViewWalker()
	RawViewCondition()
	ControlViewCondition()
	ContentViewCondition()
	CreateCacheRequest()
	CreateTrueCondition()
	CreateFalseCondition()
	CreatePropertyCondition(int,val.p-variant,ptr)
	;...
EndInterface

Interface IUIAutomationElement Extends IUnknown
	SetFocus()
	GetRuntimeId()
	FindFirst(long,ptr,ptr)
	FindAll()
	FindFirstBuildCache()
	FindAllBuildCache()
	BuildUpdatedCache()
	GetCurrentPropertyValue()
	GetCurrentPropertyValueEx()
	GetCachedPropertyValue()
	GetCachedPropertyValueEx()
	GetCurrentPatternAs()
	GetCachedPatternAs()
	GetCurrentPattern(long,ptr)
	;....
EndInterface

Interface UIAutomationTextPattern Extends IUnknown
	RangeFromPoint()
	RangeFromChild()
	GetSelection()
	GetVisibleRanges()
	DocumentRange(ptr)
	SupportedTextSelection()
EndInterface

Interface IUIAutomationTextRange Extends IUnknown
	Clone()
	Compare()
	CompareEndpoints()
	ExpandToEnclosingUnit()
	FindAttribute()
	FindText()
	GetAttributeValue()
	GetBoundingRectangles()
	GetEnclosingElement()
	GetText(long,*str)
	;...
EndInterface

Macro FreeObj(Inter)
	If Inter
		Inter\Release()
	EndIf
EndMacro

Macro GoError(val, laberror, debugtext)
	If val <> 0
		Debug debugtext
		Goto laberror
	EndIf
EndMacro

#UIA_NamePropertyId=30005
#TreeScope_Descendants=4
#UIA_TextPatternId=10014

CoInitialize_(0)

Procedure.s UIAutomation_GetConsoleCurrentText(hwndconsole)
	Protected vr.variant\vt = #VT_BSTR
	vr\bstrVal = SysAllocString_("Text Area") ;  control id
	
	Protected pAuto.IUIAutomation,
	          oElement.IUIAutomationElement,
	          pCondition0.IUnknown,
	          oDocument1.IUIAutomationElement,
	          oDocumentRange.IUIAutomationTextRange,
	          oTextPattern1.UIAutomationTextPattern,
	          *bstr_text, sReturn.s
	
	GoError(CoCreateInstance_(?CLSID_CUIAutomation, 0,#CLSCTX_INPROC_SERVER, ?IID_IUIAutomation, @pAuto),l_error,
	        "error create CUIAutomation object ")
	GoError(pAuto\ElementFromHandle(hwndconsole, @oElement),l_error,
	        "error the handle of console not exist !")
	GoError(pAuto\CreatePropertyCondition(#UIA_NamePropertyId, vr,@pCondition0 ),l_error,
	        "error create condition obj")
	GoError(oElement\FindFirst(#TreeScope_Descendants, pCondition0, @oDocument1),l_error,
	        "error get control !!")	
	GoError(oDocument1\GetCurrentPattern(#UIA_TextPatternId, @oTextPattern1),l_error,
	        "error get TextPattern obj")
	GoError(oTextPattern1\DocumentRange(@oDocumentRange),l_error,
	        "error get Document range")
	GoError(oDocumentRange\GetText(-1, @*bstr_text),l_error,
	        "errr get control text !!")
	
	If *bstr_text
		sReturn = PeekS(*bstr_text)
	EndIf
	
	l_error:
	If *bstr_text : SysFreeString_(*bstr_text) : EndIf
	If vr\bstrVal : SysFreeString_(vr\bstrVal) : EndIf
	FreeObj(pAuto)
	FreeObj(oElement)
	FreeObj(pCondition0)
	FreeObj(oDocument1)
	FreeObj(oDocumentRange)
	FreeObj(oTextPattern1)
	
	ProcedureReturn ReplaceString(sReturn , #CRLF$ + #CRLF$+ #CRLF$, "")
EndProcedure

Debug UIAutomation_GetConsoleCurrentText(FindWindow_("ConsoleWindowClass", #Null))


Re: Read windows console already open

Posted: Thu Nov 14, 2019 6:21 pm
by CELTIC88
!remove

Re: Read windows console already open

Posted: Fri Nov 15, 2019 11:10 am
by RASHAD
Very good one CELTIC88
Thanks

Simple one (If it is OK :) )

Code: Select all

Import "kernel32.lib"
  AttachConsole( processID )
EndImport

hConsole = FindWindow_("ConsoleWindowClass",0)
GetWindowThreadProcessId_(hConsole,@procID)
AttachConsole(procID)

nBytes.i
sScreen.s
sBuffer.s
SBI.CONSOLE_SCREEN_BUFFER_INFO
hCons = GetStdHandle_(#STD_OUTPUT_HANDLE)

If hCons
  GetConsoleScreenBufferInfo_(hCons, @SBI)
  dwSizeX = PeekW(@SBI\dwSize)
  dwSizeY = PeekW(@SBI\dwSize + 2)
  For line = 0 To 500
    sBuffer = Space(dwSizeX)
    If ReadConsoleOutputCharacter_(hCons, @sBuffer, Len(sBuffer), Line*$10000, @nBytes)
      Debug Left(sBuffer, nBytes)
    EndIf
  Next
EndIf
FreeConsole_()

Re: Read windows console already open

Posted: Fri Nov 15, 2019 11:55 am
by infratec
Sh..

I tried it already yesterday with nearly the same code like Rashad, but it failed.
I used

Code: Select all

ReadConsoleOutputCharacter_(hStdOut, *Buffer, ConsoleScreenBufferInfo\srWindow\right, ReadCoord, @nBytes)
instead of

Code: Select all

ReadConsoleOutputCharacter_(hStdOut, *Buffer, ConsoleScreenBufferInfo\srWindow\right, PeekL(@ReadCoord), @nBytes)
And I still don't know why it fails.
Here is my 'working' version, with the fix like Rashad did it.

Code: Select all

EnableExplicit

#OnlyVisible = #True

Import "kernel32.lib"
  AttachConsole(processID.l)
EndImport


Define hConsole.i, processID.i, hStdOut.i, NumberOfChars.l, Y.i
Define ConsoleScreenBufferInfo.CONSOLE_SCREEN_BUFFER_INFO
Define *Buffer
Define ReadCoord.COORD
Define X$

hConsole = FindWindow_("ConsoleWindowClass", #Null)
If hConsole
  GetWindowThreadProcessId_(hConsole, @processID)
  If AttachConsole(processID)
    hStdOut = GetStdHandle_(#STD_OUTPUT_HANDLE)
    If hStdOut
      If GetConsoleScreenBufferInfo_(hStdOut, @ConsoleScreenBufferInfo)
        
        *Buffer = AllocateMemory((ConsoleScreenBufferInfo\srWindow\right + 1) * SizeOf(Character), #PB_Memory_NoClear)
        If *Buffer
          ReadCoord\x = 0
          
          X$ = "    "
          For Y = 0 To ConsoleScreenBufferInfo\srWindow\right
            X$ + Right(Str(Y), 1)
          Next Y
          Debug X$
          
        CompilerIf #OnlyVisible              
          For Y = ConsoleScreenBufferInfo\srWindow\top To ConsoleScreenBufferInfo\srWindow\bottom
        CompilerElse
          For Y = 0 To ConsoleScreenBufferInfo\srWindow\bottom
        CompilerEndIf
            ReadCoord\y = Y
            If ReadConsoleOutputCharacter_(hStdOut, *Buffer, ConsoleScreenBufferInfo\srWindow\right + 1, PeekL(@ReadCoord), @NumberOfChars)
              Debug RSet(Str(Y), 3) + " " + PeekS(*Buffer, NumberOfChars)
            EndIf
          Next Y
          
          FreeMemory(*Buffer)
        EndIf
      EndIf
    EndIf
    FreeConsole_()
  EndIf
EndIf

Re: Read windows console already open

Posted: Fri Nov 15, 2019 12:35 pm
by RASHAD
Hi Bernd
Sometime I am lucky with PB :)

You need the coordinates of first cell to read from
MakeLong(x,y)

I prefer your using of ReadConsoleOutputCharacter_()

Code: Select all

ReadConsoleOutputCharacter_(hStdOut, *Buffer, ConsoleScreenBufferInfo\srWindow\right, ReadCoord\y << 16 | ReadCoord\x, @nBytes)

Re: Read windows console already open

Posted: Fri Nov 15, 2019 12:47 pm
by RASHAD
Something wrong with your last update Bernd (1 st. Line)
Go back :D

Re: Read windows console already open

Posted: Fri Nov 15, 2019 3:24 pm
by infratec
The first line
0123456789012345678901234567890123456789
is generated 'by hand', only to show the coordinates.

Code: Select all

          X$ = "    "
          For Y = 0 To ConsoleScreenBufferInfo\srWindow\right
            X$ + Right(Str(Y), 1)
          Next Y
          Debug X$

Re: Read windows console already open

Posted: Fri Nov 15, 2019 7:16 pm
by infratec
A bit speed optimized (I hope)

Code: Select all

EnableExplicit

#OnlyVisible = #False

Import "kernel32.lib"
  AttachConsole(processID.l)
EndImport


Define hConsole.i, processID.i, hStdOut.i, NumberOfChars.l, Y.i
Define ConsoleScreenBufferInfo.CONSOLE_SCREEN_BUFFER_INFO
Define *Buffer
Define ReadCoord.COORD
Define X$

hConsole = FindWindow_("ConsoleWindowClass", #Null)
If hConsole
  GetWindowThreadProcessId_(hConsole, @processID)
  If AttachConsole(processID)
    hStdOut = GetStdHandle_(#STD_OUTPUT_HANDLE)
    If hStdOut
      If GetConsoleScreenBufferInfo_(hStdOut, @ConsoleScreenBufferInfo)
        
        CompilerIf #OnlyVisible
          
          *Buffer = AllocateMemory((ConsoleScreenBufferInfo\srWindow\right + 1) * (ConsoleScreenBufferInfo\srWindow\bottom + 1) * SizeOf(Character), #PB_Memory_NoClear)
          If *Buffer
            ReadCoord\x = 0
            ReadCoord\y = ConsoleScreenBufferInfo\srWindow\top
            
            If ReadConsoleOutputCharacter_(hStdOut, *Buffer, (ConsoleScreenBufferInfo\srWindow\right + 1) * (ConsoleScreenBufferInfo\srWindow\bottom + 1), PeekL(@ReadCoord), @NumberOfChars)
              
              X$ = "    "
              For Y = 0 To ConsoleScreenBufferInfo\srWindow\right
                X$ + Right(Str(Y), 1)
              Next Y
              Debug X$
              
              For Y = 0 To ConsoleScreenBufferInfo\srWindow\bottom - ConsoleScreenBufferInfo\srWindow\top
                Debug RSet(Str(Y), 3) + " " + PeekS(*Buffer + (Y * (ConsoleScreenBufferInfo\srWindow\right + 1) * SizeOf(Character)), ConsoleScreenBufferInfo\srWindow\right + 1)
              Next Y
            EndIf
            FreeMemory(*Buffer)
          EndIf
          
        CompilerElse
          
          *Buffer = AllocateMemory((ConsoleScreenBufferInfo\srWindow\right + 1) * (ConsoleScreenBufferInfo\dwSize\y + 1) * SizeOf(Character), #PB_Memory_NoClear)
          If *Buffer
            ReadCoord\x = 0
            ReadCoord\y = 0
            
            If ReadConsoleOutputCharacter_(hStdOut, *Buffer, (ConsoleScreenBufferInfo\srWindow\right + 1) * (ConsoleScreenBufferInfo\dwSize\y + 1), PeekL(@ReadCoord), @NumberOfChars)
              
              X$ = "    "
              For Y = 0 To ConsoleScreenBufferInfo\srWindow\right
                X$ + Right(Str(Y), 1)
              Next Y
              Debug X$
              
              For Y = 0 To ConsoleScreenBufferInfo\srWindow\bottom
                Debug RSet(Str(Y), 3) + " " + PeekS(*Buffer + (Y * (ConsoleScreenBufferInfo\srWindow\right + 1) * SizeOf(Character)), ConsoleScreenBufferInfo\srWindow\right + 1)
              Next Y
            EndIf
            FreeMemory(*Buffer)
          EndIf
          
        CompilerEndIf
        
      EndIf
    EndIf
    FreeConsole_()
  EndIf
EndIf

Re: Read windows console already open

Posted: Sun Nov 17, 2019 7:24 pm
by Kwai chang caine
I try with W10 x64 / v5.70 x86

Waaaaooouuhh !!!! all my friends in the same thread :shock:

Image

Thanks a lot for all your splendids and powerfull code
8)
it's christmas before christmas

About christmas snow :?
Excuse me for the late answer, but in my department of France there are so much snow than all cables are fall and i have no electricity, no phone and the emetor not works too so no GSM since three days ago.
All my house is under battery 12V, in fact like if i'm into a motorhome :mrgreen:
And today, always not electricity, but just one gsm works...so my first reflex..is come see all my friends in own love PB forum :D

So i have tested all your jewel codes:

The CELTIC code works fine
The little code of RASHAD too
The first INFRATEC code works here
The last INFRATEC code works perfectly and furthermore with line number 8)

I LOVE YOU ALL
Image

Have the very good day of the world !!!!