With a lot a certain amount of difficulty...
The problem is that VB applications compile as GUI applications, not console applications. During process startup, a VB application is foreceably disassociated from any console that might have launched it, and STDIN, STDOUT and STDERR are removed.
Now AllocConsole, which you've probably seen in the other thread(s) that you mention, kind of addresses this in that it creates a new console, and gives the missing standard streams - which point to this new console - back to VB
OK, well, how do you get something similar to work with an already existing console? Sadly, you can't (well, prior to XP). Even if you do something like a FindWindow to locate the console, there's no way to attach to it (Well, XP has an AttachConsole API, but no prior version of Windows does)
The lateral thinking method of dealing with this involves considering the fact that the problem is caused by that nasty initial startup code (which runs before any of your VB code). If there was some way of stopping the detachment of the launching console and the removal of the standard streams then all would be well.
Now in C++ there are compiler options that allow you to specify whether you want a console app or a GUI app. Unfortunately, MS designed VB as a closed environment so we can't make a similar choice. Does this stop us? Not necessarily. Making that choice in C++ may simply make some changes in the programs exe header.
A little bit of investigation reveals that it changes 1 byte, and if we could make the same change then we would have a VB console app!
So here's some self-modifying code that does just that (note that since it modifies a byte in the PE header it will only work on compiled applications):
[tt]
Option Explicit
Public Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" (dst As Any, src As Any, ByVal Size As Long)
Public Sub Main()
' Is this app a console app? If it is not, then make a version that
' is and shell it instead
If Not AmIConsole Then
MsgBox "Converting into console application"
MakeConsoleVersion
Shell App.EXEName + "_iac.exe"
End
Else
' Whatever you want to do with your console app
End If
End Sub
Private Function SetConsoleApp(strFile As String) As Boolean
Dim hFile As Long
Dim strMZ_Header As String * 512
Dim lNewPE_Offset As Long
Const PE_FLAG_OFFSET As Long = 93&
Const DOS_FILE_OFFSET As Long = 25&
' Get the header
hFile = FreeFile
Open strFile For Binary Access Read Write As hFile
Seek #hFile, 1
Get hFile, , strMZ_Header
CopyMem lNewPE_Offset, ByVal Mid$(strMZ_Header, 61, 4), 4
' Rewrite the Application type byte to indicate console application
Seek #hFile, lNewPE_Offset + PE_FLAG_OFFSET
Put hFile, , 3
' Clean up
Close hFile
SetConsoleApp = True
End Function
Private Function MakeConsoleVersion()
FileCopy App.EXEName + ".exe", App.EXEName + "_iac.exe"
SetConsoleApp App.EXEName + "_iac.exe"
End Function
' Function that checks whether current VB application is a console app
Private Function AmIConsole() As Boolean
Dim hFile As Long
Dim strMZ_Header As String * 512
Dim lNewPE_Offset As Long
Dim lData As Long
Const PE_FLAG_OFFSET As Long = 93&
Const DOS_FILE_OFFSET As Long = 25&
hFile = FreeFile
Open App.EXEName & ".exe" For Binary Access Read As hFile
Seek #hFile, 1
Get hFile, , strMZ_Header
Close hFile
CopyMem lNewPE_Offset, ByVal Mid$(strMZ_Header, 61, 4), 4
lData = Asc(Mid$(strMZ_Header, lNewPE_Offset + PE_FLAG_OFFSET, 1))
If lData = 3 Then
AmIConsole = True
MsgBox "This is a console application"
End If
End Function