Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations derfloh on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

EXE Return Value 3

Status
Not open for further replies.

Quros

Programmer
May 31, 2001
20
GB
Hi,

Can I return a value from a Visual Basic executable - as I can in a C executable - for trapping errors in a batch script for example?

Regards,

Quros.

 
Negative, at least not upto VB6. I don't know about VB.net Anything is possible, the problem is I only have one lifetime.
 
Ok, the big problem in returning an errorlevel from a VB app to a commandline that launches it is that VB applications deliberately detach themselves from the launching commandline (and kill off STDIN, STDOUT and STDERR). This is also the reason you can't echo text back from a VB app to the launching commandline.

So, the trick is to convert the VB app from a pure GUI application into a console application. With C++, for example, there is command line option you can give to the linker to do this. But the compile cycle in VB is closed, so you can't do this. However, it transpires that all the linker option does is modify one byte in the executable's header.

So we can try to do the same thing.
The following code creates a console version copy of a compiled VB program. That copy can then be launched from the commandline and returns (in this case) an errorlevel of 5
[tt]
Option Explicit

Public Declare Sub ExitThread Lib "kernel32" (ByVal dwExitCode As Long)

Public Declare Sub CopyMem _
Lib "kernel32" Alias "RtlMoveMemory" (dst As Any, src As Any, ByVal Size As Long)
Public Const PE_FLAG_OFFSET As Long = 93&
Public Const DOS_FILE_OFFSET As Long = 25&

Public Sub Main()
If Not AmIConsole Then
SetConsoleApp
Else
ExitThread 5 ' Don't run this line in the IDE
End If
End Sub

Private Function SetConsoleApp() As String
Dim strFile As String
Dim lngFileNum As Long
Dim ststrMZ_Header As String * 512
Dim lngNewPE_Offset As Long

' Make a copy
FileCopy App.EXEName & ".exe", App.EXEName & ".console.exe"
strFile = App.EXEName & ".console.exe"

' Locate and modify byte in PE header
lngFileNum = FreeFile
Open strFile For Binary Access Read Write Shared As lngFileNum
Seek #lngFileNum, 1
Get lngFileNum, , ststrMZ_Header
CopyMem lngNewPE_Offset, ByVal Mid$(ststrMZ_Header, 61, 4), 4
Seek #lngFileNum, lngNewPE_Offset + PE_FLAG_OFFSET
Put lngFileNum, , 3 'Turn exe copy into console application
Close lngFileNum

End Function

Private Function AmIConsole() As Boolean
Dim strFile As String
Dim lngFileNum As Long
Dim ststrMZ_Header As String * 512
Dim lngNewPE_Offset As Long
Dim lngData As Long

' Make a copy
strFile = App.EXEName & ".exe"

' Locate and query type of current exe in PE header
lngFileNum = FreeFile
Open strFile For Binary Access Read Shared As lngFileNum
Seek #lngFileNum, 1
Get lngFileNum, , ststrMZ_Header
CopyMem lngNewPE_Offset, ByVal Mid$(ststrMZ_Header, 61, 4), 4
lngData = Asc(Mid$(ststrMZ_Header, lngNewPE_Offset + PE_FLAG_OFFSET, 1))

If lngData = 3 Then
AmIConsole = True
Else
AmIConsole = False
End If

Close lngFileNum

End Function
 
Public Declare Sub ExitProcess Lib "kernel32" (ByVal uExitCode As Long)
 
CajunCenturion gets a star for a good technical solution.

Pehon gets a star for a simple solution (and for making me chuckle).

:)
Must think of a witty signature
 
D'oh. I just read one of CajunCenturion's posts. Of course I mean strongm :)
Must think of a witty signature
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top