James Reynolds 01-19-2008, 03:12 PM Well, I have a similar problem... And I search much, but not find the solution...
I need to open with a Shell a Ms-Dos program that is not developed by my...
And this Ms-Dos program calculate much time and while calculating show some results...
Because this the redirection not is my solution, the redirection work when the program end, and I need to know the results while calculating and I decide when finish the Ms-Dos program - I know the hwnd of the Ms-Dos Window and use WM_CLOSE -...
How to get the complete buffer of the Console - the console have a limit, when this limit are reached, the first line are deleted, not is problem, this ms-dos program update the data with the new results, I need to get the output complete that the console have at any time - of this Ms-Dos program at any time???
Thanks in advance if any know a solution...
dilettante 01-19-2008, 03:34 PM You can use the redirection and output any dos text output to a file.
This isn't strictly true. Many programs like Edit and Windows' FTP don't send output to standard I/O streams. They use Console Device I/O which works directly against Console buffers. Simpler StdIO programs work in a shell because the shell mediates between the program's streams and the Console Device.
If this "DOS program" you have does use StdIO though you might consider using API calls yourself, the WScript.Exec() method, or something like my ShellPipe UserControl which is included and demonstrated in the attachment at http://www.xtremevbtalk.com/showpost.php?p=1257894
James Reynolds 01-19-2008, 06:33 PM This isn't strictly true. Many programs like Edit and Windows' FTP don't send output to standard I/O streams. They use Console Device I/O which works directly against Console buffers. Simpler StdIO programs work in a shell because the shell mediates between the program's streams and the Console Device.
If this "DOS program" you have does use StdIO though you might consider using API calls yourself, the WScript.Exec() method, or something like my ShellPipe UserControl which is included and demonstrated in the attachment at http://www.xtremevbtalk.com/showpost.php?p=1257894
A little complex hehe... I not understand why Microsoft not create a simple function how GetCmdBuffer(hwndCMD)... Very complicated know the text into a cmd console... Grrrr...
I not know almost nothing about script, I test how this in your UserControl (Very thanks for you answer and message):
spResult = spWorker(0).Run("c:\a.exe")
But not work, not open the a.exe, I need to put "c:\a.exe" in a script???
dilettante 01-19-2008, 07:23 PM No, the scripts are just an example instead of including a second EXE in there to be the child process.
Are you sure it did not run your a.exe program? Was there any error?
When you run a child process in this way it doesn't open any console window. Is that what you were expecting? You won't "see it" running except in Task Manager. You control the child process solely through your VB program.
Is it possible your a.exe ran but was hung waiting for input? If it wants input your VB program must send some to it.
dilettante 01-19-2008, 08:06 PM Maybe this simpler example will help you.
It automates an instance of cmd.exe from a VB program to produce a sort of "console in a window." Perhaps just change where it runs the child program to run this "DOS program" of yours and test it?
James Reynolds 01-20-2008, 01:59 AM Ok, sorry, I go to sleep, very thanks for your time, at now I test...!!!
James Reynolds 01-20-2008, 02:56 AM Well, work good, for run a program a write, for example:
With spCmd
.Run "cmd /c c:\air.exe"
End With
Nice!!! If you have a button for send a donation, let me know, really...
But, well, is a very good code, but a little complex for only know where text are in the cmd console, not are a more better way???, run the ms-dos program visible and set the left or top value to -100000 for example, and retrieve only the buffer of the console of this program while program calculate???
Is more elegant a code how this, not interact with the ms-dos program, only retrieve the value of the buffer of the console...
Not is possible only retrieve the buffer without redirect or capture the ms-dos program???
I know the hwnd handle of the console open by the ms-dos program because I know the title of the window and with FindWIndow I localize...
Thanks dilletante for your time... Very thanks... Carrying 2 days looking for a code that, I think, should be more easy - only retireve the buffer of a console -, it is important because many ms-dos programs provides a very important data...
dilettante 01-20-2008, 07:04 AM Well I'm glad you have it working. I'm not sure why you have to run a command shell to run this air.exe program... that seems entirely redundant.
Don't worry about any donation, I appreciate the thought but ShellPipe isn't really of the quality or complexity to deserve it. I made it for myself and I get lots of use out of it for my own projects.
I'm a little surprised you find the code "complex" though. ShellPipe is actually quite simple and doesn't do anything tricky at all. It is pretty much "by the book" code for starting a child process and redirecting its I/O through anonymous pipes. As controls go it is really pretty basic when compared to even the TextBox control, let alone something like the Winsock or Inet controls.
Grabbing a console window's hWnd through FindWindow strikes me as complicated and hackish. It also very much "goes against the book" as a reliable and secure technique. Rummaging through open windows hoping to stumble on the one you want by its Caption contents... very bad:
Why FindWindow doesn't work (http://www.developerfusion.co.uk/show/1716/5/).
James Reynolds 01-20-2008, 09:19 AM Well dilletante, a program in windows have much child windows, textbox, commands buttons, lists, many, but a program in ms-dos only have one thing, the console, because this I think possible more easy code, how a simple function, for example:
GetBufferCdm(hwndCMD)
I think Microsoft should have made easier, because that a ms-dos console only have in reality one child window, similar to a textbox...
For example, in the console functions:
http://msdn2.microsoft.com/en-us/library/ms682073(VS.85).aspx
Are this: GetConsoleFontSize
Why not is possible retrieve the content of the console but yes the fontsize used by this content???
I think is possible retrieve the buffer content using functions how:
ReadConsoleOutputCharacter
http://msdn2.microsoft.com/en-us/library/ms684969(VS.85).aspx
James Reynolds 01-20-2008, 09:28 AM Here is a good topic, but in Russian hehe:
http://www.sql.ru/forum/actualthread.aspx?bid=22&tid=512514&pg=2
The title (google translation) is: Reading the results of the console application
James Reynolds 01-20-2008, 09:35 AM Well, the program air.exe check the networks all the time, doing the quality, power, name, etc... Is a continuous process...
dilettante 01-20-2008, 09:53 AM I think you are confusing two different things: Consoles and StdIO.
Yes, a program can allocate a Console and use the Console I/O API calls to handle input and output. Some programs do just that.
Most command line programs do not have a Console or a console window. They use the StdIO streams to communicate.
By default a program compiled for Windows' "Console Subsystem" will get a "free" Console if it is run without the standard I/O streams redirected. If you run the program via a command shell like Cmd.exe, the shell does two things: (a.) it allows its own Console to be inherited by the child process, and (b.) it redirects the StdIO streams of the child process back to itself via anonymous pipes and does the Console I/O on the behalf of the child.
To get to the Console you can't attack it from the window used to display the Console. You have to have a handle to the Console and this isn't exposed through the window.
These sorts of programs can run without the windowing subsystem and GUI shell active at all. In such cases the Console needs access directly to the screen and takes it over. Windows ends up looking like "DOS." This is not the same as running with a Console window set to "full screen" mode but looks similar.
VB programs are compiled and linked for the Windows Subsystem. /SUBSYSTEM (Specify Subsystem) (http://msdn2.microsoft.com/en-us/library/fcc1zstk.aspx) shows where this is set. In VB you don't have this available as a Project Property though, it always sets "Windows." It is possible to relink a formless VB program for the Console subsystem, and it has a few uses.
It is quite possible for a VB program compiled for the GUI (Windows) subsystem to allocate a Console and have it inherited by a child process. People do it all the time.
The VB program could then "hook" Console Device I/O via SetWinEventHook() (http://msdn2.microsoft.com/en-us/library/ms696160(VS.85).aspx).
But this carries a lot of baggage:
You have to have a Console lying around. This is entirely unnecessary overhead.
The Console I/O appears on the user's screen. Do you want that? Why?
The process is a lot more complicated and a lot more work than simply redirecting the standard streams to anonymous pipes and doing pipe I/O in your VB program.
At the end of the day you can insert the logic into your program inline, or you can use something like my ShellPipe control. I really don't see the problem here, and it's standard practice anyway.
ShellPipe is doing things the easy way.
James Reynolds 01-20-2008, 12:21 PM Well Dilletante one of me problems are I not understand well English...
I test - I read after in deep your last message - the code of the Russians, and go well also!!! Not is exactly I think but work also - I understand the HWnd of the Console Window not to do the buffer, but I think Microsoft could have made a simple function to read the console screen buffer according to their hwnd (in deep of the function Ms develop any) but the need to read the console buffer can be very much by many programmers, would have been a great help simplify this process -...
I go to make a winrar with the code of the Russians and upload to the forum, the code call an (any you write) ms-dos program and after, with a timer, check the buffer of the console...
I read also in deep your last message Dilletante... Thanks another time...
James Reynolds 01-20-2008, 12:27 PM At the end of the day you can insert the logic into your program inline, or you can use something like my ShellPipe control. I really don't see the problem here, and it's standard practice anyway.
ShellPipe is doing things the easy way.
Your code work very well also, but I search for a more little code, overalls not interact directly with the ms-dos program, only retrieve the screen buffer, the code of the russians also not are how this, but a little, I search a code that only retrieve the buffer of the ms-dos program, and the ms-dos program work independent totally, I not know if this is possible...
James Reynolds 01-20-2008, 12:34 PM A little example Dilletante:
Suppose we need to check what ms-dos programs are running in Windows and retrieve the buffer of the console of all the ms-dos program running, not our WIndows program run the ms-dos program...
Is possible???
James Reynolds 01-20-2008, 01:06 PM The Example of the Russian Forum...
http://www.sql.ru/forum/actualthread.aspx?bid=22&tid=512514&pg=2
xer0syk0 01-20-2008, 08:15 PM This piece of code will do wonders for you:
http://www.xtremevbtalk.com/showthread.php?t=129103
Simply import the .cls file into your project, and copy paste the code from the main post into your project.
James Reynolds 01-20-2008, 09:09 PM Interesting and very nice code also!!! xer0syk0.
But a little complex also. And run the Ms-Dos App also.
The Russians code work how this in resume:
http://www.xtremevbtalk.com/attachment.php?attachmentid=27845&d=1200859594
- 1 pass:
If AllocConsole() Then
hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE)
End if
- 2 Pass -> Run the Ms-Dos App and a Do-Loop Checking the End of the Ms-Dos App with a DoEvents in middle:
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 1, Shell(AppToRun, vbHide))
Do
'Get the status of the process
GetExitCodeProcess hProcess, RetVal
DoEvents
'Loop while the process is active
Loop While RetVal = STILL_ACTIVE
- 3 Pass -> Check with a Timer the Buffer or Console Output:
fsuccess = GetConsoleScreenBufferInfo(hConsoleOut, csScreenBuffer)' (This is the Important Code, appear to be that with hConsoleOut is Possible retrieve the Buffer)
'non-zero result is a success
ConsoleBoundary = csScreenBuffer.srWindow
Dim lineMessage As String * 80
readLength = 80
XPos = 0
YPos = 0
Text1.Text = ""
'???????????????? ?????? ???? ??????? ?? ?????? ?????
For YPos = 0 To ConsoleBoundary.Bottom
def = ReadConsoleOutputCharacter(hConsoleOut, lineMessage, readLength, YPos * 65536, vbNull)
If Trim(lineMessage) <> "" Then
Text1.Text = Text1.Text & Trim(lineMessage) & vbCrLf
End If
Next YPos
Well, me question is, if the Ms-Dos app is Running before our Exe Run, not our Exe Run the Ms-Dos App, how is possible to go directly to the 3 Pass???
Appear to be only is necessary know the hConsoleOut, but I not understand well the first Pass, the Pass that retrieve the hConsoleOut.
When I check all the codes (Dilletante, xer0syk0 and Russians), all Call the Ms-Dos program and I have the problem that the Ms-Dos program some times Remains active when I close or if I close, close the VB6 also, because interact or capture directly the Ms-Dos App do strange situations, I believe the more elegant and not problematic code are a code that how the 3 pass, only retrieve the console output.
How to know the hConsoleOut of a Ms-Dos program running before our aplication run...?
Very thanks Dilletante and xer0syk0... And all...
dilettante 01-20-2008, 09:37 PM It looks like the code above only gets information from the VB program's own console, the console allocated in step 1.
I have no idea how you might hijack the console of another process. Why would you even want to? Sounds like a security risk.
My guess is that this code allocates a console in the VB program, then starts a child process, and then "scrapes" that console to get the output from the child process (which inherits the VB program's explictly allocated console).
Another thing that Windows does not expose in a clear way is that related processes run as Windows jobs. Normally child processes are part of the parent program's process family, another name for job. But a process can start a new process as a new job. This is called a detached process and will get its own console that the parent cannot touch. It also gets its own set of environment variables.
I don't think that a process in one job can get to the console in another job.
James Reynolds 01-21-2008, 04:10 AM Sounds like a security risk.
Yes, all the 3 codes do strange responses of the ms-dos program, Windows not are very stable, the more better code is the code not interact much with other programs... In the tests, if I press Ctrl ^ C for end the console, also the VB project close automatic, dissapear, if press the Stop button in the toolbar of Visual Basic, after pres Ctrl+Alt+End appear the Ms-DOs program are running in process tab... Interact directly with another program requires after much checks, is more better the Ms-DOs program go independent, only know the the way for retrieve the buffer...
I don't think that a process in one job can get to the console in another job.
But nothing is impossible, must be a way to find that hConsoleOut... There should be the possibility of obtaining the buffer of an open console...
James Reynolds 01-21-2008, 05:02 AM Well, exists GetConsoleWindow()
http://msdn2.microsoft.com/en-us/library/ms683175(VS.85).aspx
But not exists the inverse hehe, for example, GetConsoleHandleFromWindow(hwnd)...
James Reynolds 01-21-2008, 08:08 AM Unfortunate, because would be ideal to get the console buffer without problems of capturing or redirect or many other options, only retrieve the console buffer of any Ms-Dos program...
Because with this is very very very easy - with the codes send in this topic also is possible, but not perfect and elegant code, perfect are not interact nothing with the Ms-Dos process only retrieve the console buffer and go out of the Ms-Dos process - manage much information of many cmd commands how cmd ipconfig /all, much commands of cmd and ms-dos programs have deep information that are good obtain and manage in a simple VB program...
And also is possible are interesting for a situation that a ms-dos program is run before our application run and is needed retrieve your console buffer...
I continue searching the code, I today consult in other forums, if I find, I put here with example code for others programmers with same problem...
And if any find a solution, please, write here!!!
Thanks!!!
James Reynolds 01-21-2008, 08:22 AM Possible is possible, evident, here is an example, with not source code - unfortunately -:
http://www.xtremevbtalk.com/showthread.php?t=119379
Here the download program:
http://www.skesoft.com/download/textcatch.zip
Capture the console buffer of any ms-dos windows program executing in windows...
James Reynolds 01-21-2008, 08:27 AM Well, the code!!!!!!!!!!!!!!!!!!!!
Here is a code that from a hwnd window retrive the console buffer!!! Thanks to binarypoet user!!!
http://www.xtremevbtalk.com/showthread.php?t=119379
And here Source Code, at END ufffffffff:
http://www.skesoft.com/tclib/samples.htm
For Visual Basic:
http://www.skesoft.com/tclib/sample/VBSample.zip
James Reynolds 01-21-2008, 08:40 AM Grrr the code are in a dll... hehe... I consult the author if is possible know how make this...
|