Solved

Console output (STDOut for VB)?

Posted on 2001-08-15
16
647 Views
Last Modified: 2012-06-27
Okay, I wrote a command line program with no forms (just a quick cludge) and I wanted to be able to output to the console some message.

I've searched quite a bit and haven't found anything that will let me print a simple string to the cmdline like I want.  The only way I've been able to do it is to use msgbox, but I don't want any windows involved.  Just return a result by command line.

Is there a simple way to do this that I'm missing?
0
Comment
Question by:Sorklin
  • 5
  • 4
  • 3
  • +3
16 Comments
 
LVL 8

Expert Comment

by:DennisBorg
ID: 6389443
0
 
LVL 20

Expert Comment

by:hes
ID: 6389457
Also take a look here:
http://www.saurik.com/samples/

look at smpConsole
0
 
LVL 38

Expert Comment

by:PaulHews
ID: 6389625
The trouble I've seen with this is that I've been unable to attach to a pre-existing command line window, only start a new console window.  At this point, I have not solved it or seen it solved.
0
 
LVL 8

Expert Comment

by:DennisBorg
ID: 6389870
Good point, Paul.

But how would one determine which pre-existing console window to target? One could have many open at the time, but all would have been spawned by COMMAND.COM or CMD.EXE

-Dennis Borg
0
 
LVL 38

Expert Comment

by:PaulHews
ID: 6390358
That's part of the trouble.  The other part is that VB programs do not have any built in console function, they are compiled as GUI applications, not console apps.  They can allocate a new console easily enough, but there doesn't seem to be anyway to attach to an existing StdIn/StdOut the way one would when starting a program from a batch file or from the command prompt.

This is detailed here:
HOWTO: Attach a Console Window to Your Visual Basic Program

http://support.microsoft.com/support/kb/articles/Q171/6/54.asp
0
 
LVL 38

Expert Comment

by:PaulHews
ID: 6390364
Quote:

If a Visual Basic application is started from a console application, the operating system automatically detaches it from the console, preventing the Visual Basic application from interacting with it. This article does not provide a method to prevent this from happening, but does demonstrate creating a new console window that your application can interact with. It also demonstrates running a console application (batch file, in this case) from Visual Basic, which utilizes the created console.
0
 
LVL 14

Expert Comment

by:wsh2
ID: 6390712
<Movie line; circa 1940s.. "Say it isn't so Joe">

Sad, but true.. <sigh>
0
 
LVL 8

Expert Comment

by:DennisBorg
ID: 6390833
Good info, Paul. Thank you for the input!
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 43

Accepted Solution

by:
TimCottee earned 100 total points
ID: 6391727
Sorklin, there is a solution to this but not an obvious one. Firstly get rid of any allocconsole in your application you won't need this any more as it will spawn an additional console window which is not what you need. Then compile your application as normal but before you run it hack it using the following:

Simply paste this code into a module and then compile to MakeVBCon.EXE. Then with the compiled console application executable do

MakeVBCon MyApplication.exe. This will then run in the original console window in which it was launched.

' ------------------------------------------------------
' MakeConsole.BAS -- Copyright (c) Slightly Tilted Software
' By: L.J. Johnson Date: 11-30-1997
' Comments: Contains MAIN(), plus the function
' which take a standard VB 5.0 EXE ( or VB 6.0 ! )
' and change it to a 32-bit console app
' ------------------------------------------------------
Option Explicit
Option Base 1
DefLng A-Z

Private Const GENERIC_READ As Long = &H80000000
Private Const OPEN_EXISTING As Long = 3&
Private Const FILE_ATTRIBUTE_NORMAL As Long = &H80&

Private Const SCS_32BIT_BINARY = 0&
Private Const SCS_DOS_BINARY = 1&
Private Const SCS_WOW_BINARY = 2&
Private Const SCS_PIF_BINARY = 3&
Private Const SCS_POSIX_BINARY = 4&
Private Const SCS_OS216_BINARY = 5&

Private Const constMsgTitle = "Make Console App"

' ---------------------------------------------
' Windows API calls
' ---------------------------------------------
Public Declare Sub CopyMem _
Lib "kernel32" Alias "RtlMoveMemory" _
(dst As Any, src As Any, ByVal Size As Long)
Private Declare Function CloseHandle _
Lib "kernel32" _
(ByVal hObject As Long) As Long
Private Declare Function CreateFile _
Lib "kernel32" Alias "CreateFileA" _
(ByVal lpFileName As String, _
ByVal dwDesiredAccess As Long, _
ByVal dwShareMode As Long, _
ByVal lpSecurityAttributes As Long, _
ByVal dwCreationDisposition As Long, _
ByVal dwFlagsAndAttributes As Long, _
ByVal hTemplateFile As Long) As Long

Public Sub Main()
Dim strCmd As String
Dim strMsg As String
Dim strRtn As String

strCmd = Command$

If Trim$(strCmd) = "" Then
strMsg = "You must enter the name of a VB 5.0 standard executable file."
MsgBox strMsg, vbExclamation, constMsgTitle
Else
If InStr(1, strCmd, ".", vbTextCompare) = 0 Then
strCmd = strCmd & ".EXE"
End If

If Exists(strCmd) = True Then
strRtn = SetConsoleApp(strCmd)
MsgBox strRtn, vbInformation, constMsgTitle
Else
strMsg = "The file, " & Trim$(strCmd) & ", does not exist."
MsgBox strMsg, vbCritical, constMsgTitle
End If
End If

End Sub

Private Function SetConsoleApp(xstrFileName As String) As String
Dim lngFileNum As Long
Dim ststrMZ_Header As String * 512
Dim strMagic As String * 2
Dim strMagicPE As String * 2
Dim lngNewPE_Offset As Long
Dim lngData As Long
Dim strTmp As String
Const PE_FLAG_OFFSET As Long = 93&
Const DOS_FILE_OFFSET As Long = 25&

' ---------------------------------------------
' See if file actually exists
' ---------------------------------------------
strTmp = Trim$(Dir$(xstrFileName))
If Len(strTmp) = 0 Then
SetConsoleApp = "Failed -- The file, " & xstrFileName & ", does not exist!"
GoTo ExitCheck
End If

' ---------------------------------------------
' Get a free file handle
' ---------------------------------------------
On Error Resume Next
lngFileNum = FreeFile
Open xstrFileName For Binary Access Read Write Shared As lngFileNum

' ---------------------------------------------
' Get the first 512 characters from from file
' ---------------------------------------------
Seek #lngFileNum, 1
Get lngFileNum, , ststrMZ_Header

' ---------------------------------------------
' Look for the "magic header" values "MZ"
' If it doesn't exist, then it's not an EXE file
' ---------------------------------------------
If Mid$(ststrMZ_Header, 1, 2) <> "MZ" Then
SetConsoleApp = "Failed -- File is not an executable file."
GoTo ExitCheck
End If

' ---------------------------------------------
' Check to see if it's a MS-DOS executable
' ---------------------------------------------
CopyMem lngData, ByVal Mid$(ststrMZ_Header, DOS_FILE_OFFSET, 2), 2
If lngData < 64 Then
SetConsoleApp = "Failed -- File is 16-bit MSDOS EXE file."
GoTo ExitCheck
End If

' ---------------------------------------------
' Get the offset for the new .EXE header
' ---------------------------------------------
CopyMem lngNewPE_Offset, ByVal Mid$(ststrMZ_Header, 61, 4), 4

' ---------------------------------------------
' Get the "magic" header (NE, LE, PE)
' ---------------------------------------------
strMagic = Mid$(ststrMZ_Header, lngNewPE_Offset + 1, 2)
strMagicPE = Mid$(ststrMZ_Header, lngNewPE_Offset + 3, 2)

Select Case strMagic

' ---------------------------------------------
' Check for NT format
' ---------------------------------------------
Case "PE"
If strMagicPE <> vbNullChar & vbNullChar Then
SetConsoleApp = "Failed -- File is unknown 32-bit NT executable file."
GoTo ExitCheck
End If

' ---------------------------------------------
' Get the subsystem flags to identify NT
' character-mode
' ---------------------------------------------
lngData = Asc(Mid$(ststrMZ_Header, lngNewPE_Offset + PE_FLAG_OFFSET, 1))
If lngData <> 3 Then
On Error Resume Next
Err.Number = 0
Seek #lngFileNum, lngNewPE_Offset + PE_FLAG_OFFSET
Put lngFileNum, , 3
If Err.Number = 0 Then
SetConsoleApp = "Success -- Converted file to console app."
Else
SetConsoleApp = "Failed -- Error converting to console app: " & Err.Description
End If
Else
SetConsoleApp = "Failed -- Already a console app"
End If

Case Else
SetConsoleApp = "Failed -- Not correct file type."

End Select

ExitCheck:
' ---------------------------------------------
' Close the file
' ---------------------------------------------
Close lngFileNum

On Error GoTo 0

End Function

Public Function Exists(ByVal xstrFullName As String) As Boolean
On Error Resume Next ' Don't accept errors here
Const constProcName As String = "Exists"
Dim lngFileHwnd As Long
Dim lngRtn As Long

' ------------------------------------------
' Open the file only if it already exists
' ------------------------------------------
lngFileHwnd = CreateFile(xstrFullName, _
GENERIC_READ, 0&, _
0&, OPEN_EXISTING, _
FILE_ATTRIBUTE_NORMAL, 0&)

' ------------------------------------------
' If get these specific errors, then
' file doesn't exist
' ------------------------------------------
If lngFileHwnd = 0 Or lngFileHwnd = -1 Then
Exists = False
Else
' Success -- Must close the handle
lngRtn = CloseHandle(lngFileHwnd)
Exists = True
End If

On Error GoTo 0
End Function

Essentially windows is fooled by this rewrite of the executable header into thinking that the application is actually a DOS one not a GUI one. I have used this a number of times to create applications that run in a telnet environment. Accessed by handheld scanners such as Symbol and Telxon running VT220 terminal emulation against the telnet server.
0
 
LVL 8

Expert Comment

by:DennisBorg
ID: 6392462
Thanks, Tim!
0
 
LVL 38

Expert Comment

by:PaulHews
ID: 6392568
Neat hack!
0
 
LVL 1

Author Comment

by:Sorklin
ID: 6392763
Tim, I haven't tried it yet, but I will.  Sounds like what I want.
0
 
LVL 1

Author Comment

by:Sorklin
ID: 6392872
Very neat hack.  Where did you ever figure this one out?
0
 
LVL 43

Expert Comment

by:TimCottee
ID: 6393052
Not my code I freely admit, I found it in an old question posted by mcrider I think. Gave it a go and it worked excellently. It is a handy tool to keep in the arsenal.
0
 
LVL 8

Expert Comment

by:DennisBorg
ID: 6393296
>It is a handy tool to keep in the arsenal.

A very good thing to know!
0
 
LVL 1

Author Comment

by:Sorklin
ID: 6393897
Exactly what this forum is for.  It would take me a thousand years to come up with something like this.  Thanks.
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

If you have ever used Microsoft Word then you know that it has a good spell checker and it may have occurred to you that the ability to check spelling might be a nice piece of functionality to add to certain applications of yours. Well the code that…
Enums (shorthand for ‘enumerations’) are not often used by programmers but they can be quite valuable when they are.  What are they? An Enum is just a type of variable like a string or an Integer, but in this case one that you create that contains…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now