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 wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Shell Wait 16 Bit

Status
Not open for further replies.

robctech

IS-IT--Management
Oct 12, 2001
114
CA
Ok I'm gonna try and explain this a little better this time. I have posted one message but none of the responses have been able to help me.

Details:

I have a program writtine in vb which sits and waits for a command via TCP/IP. When it receives the proper command it launches an application in a dos window which is a 16 bit application. I need my code to wait until the 16 bit program is completed before it continues as well I need to read what the 16bit program puts to the console.

Tried So Far:
I have tried using all the examples I have found with the following results

ReadFile - This doesn't work until the program is complete and hangs the system
ReadConsole - Doesn't seem to work at all
ReadConsoleOutputChar - this works providing I launch my program after using AllocConsole..but when I use my API to launch the console I can't read it.
The code below is ALMOST what I need...it uses AllocConsole and fires my app and even waits until it is complete but it will not close the console once I have run my app inside it.
If I can figure a way to get it to close the console that would be it

Code:
Public Function ExecCmd(ByVal cmdline$, ByVal SixteenBitApp As Boolean, Optional ByVal PathChange As String)
   Dim proc As PROCESS_INFORMATION
   Dim start As STARTUPINFO
   Dim BuildDirChange As String
   Dim ReadingProgress As Long

    ReadCMDFileCommands IIf(Right(PathChange, 1) = "\", PathChange, PathChange & "\") & _
        Right(cmdline, InStr(StrReverse(cmdline), " ") - 1)

    If AllocConsole() Then
        ProcessConsole = GetStdHandle(STD_OUTPUT_HANDLE)
        If ProcessConsole = 0 Then MsgBox "Couldn't allocate STDOUT"
    Else
        MsgBox "Couldn't allocate console"
    End If
   ' Start the shelled application:
    start.cb = Len(start)

   '//Lets see if we should change directories
    If Len(PathChange) Then ChDir PathChange
    If SixteenBitApp Then cmdline = "cmd /c" & cmdline '& " > cmdlogtest.txt"
    If SixteenBitApp And InStr(cmdline, "POSTODB") > 0 Then _
        cmdline = "cmd /c" & cmdline
    ret& = CreateProcessA(vbNullString, cmdline$, 0&, 0&, 1&, _
    NORMAL_PRIORITY_CLASS, 0&, vbNullString, start, proc)
    ' Wait for the shelled application to finish:
ContinueToWait:
    Read_ConsoleInformation CurPosition
    DoEvents
    ret& = WaitForSingleObject(proc.hProcess, 1)
    DoEvents
    If ret& <> 0 Then GoTo ContinueToWait
    GetExitCodeProcess proc.hProcess, ret&
    CloseHandle proc.hThread
    CloseHandle proc.hProcess
    MsgBox &quot;Console Should Now Close&quot;
    CloseHandle ProcessConsole
    FreeConsole
    ExecCmd = ret&
End Function


Private Sub Read_ConsoleInformation(ReadFromTo As COORD)
    Dim varConsoleGrab As CONSOLE_SCREEN_BUFFER_INFO
    Dim ReadBuffer As String
    Dim ConCharsRead As Long
    Dim StartReadFrom As Long
    Dim ReaderLoop As Long

    GetConsoleScreenBufferInfo ProcessConsole, varConsoleGrab
    '//First Lets Compare The Positions
    Status_Window &quot;Trying to read console&quot;
    ReadBuffer = Space(varConsoleGrab.dwSize.y * varConsoleGrab.dwSize.x)
    ReadConsoleOutputCharacter ProcessConsole, ByVal ReadBuffer, Len(ReadBuffer), 0, ConCharsRead
    If StoreBuffer <> ReadBuffer Then
        ParseAndDisplay ReadBuffer
        StoreBuffer = ReadBuffer
    End If
    ReadFromTo = varConsoleGrab.dwCursorPosition
End Sub

Private Sub ParseAndDisplay(NewData As String, Optional ConBufSize As Long = 80)
    Dim ParseDataString As Integer
    Dim DisplayIt As String
    
    For ParseDataString = 1 To Len(NewData) Step ConBufSize
        DisplayIt = RTrim(Mid(NewData, ParseDataString, ConBufSize))
        If DisplayIt <> RTrim(Mid(StoreBuffer, ParseDataString, ConBufSize)) And Not EliminatePanasonicSession(DisplayIt) Then
            If Len(RTrim(DisplayIt)) > 0 Then
                Status_Window chkTransfering(DisplayIt)
            End If
            DoEvents
        End If
    Next ParseDataString
End Sub
 
u may be able to use strongms excelent code from thread222-255803 to use pipes to and from the console (with regard to reading the console, and to some extent waiting for the console to complete)!

hope this helps in some way (but if not, it still makes good reading)

good luck

If somethings hard to do, its not worth doing - Homer Simpson
------------------------------------------------------------------------
A General Guide To Excel in VB FAQ222-3383
The Great Date Debate Thread222-368305
File Formats Galore @ or
 
I have already tried strongms example and 1st unfortunatly it always hung on me...and secondly I have tried using the createpipe etc still with no luck. Strongm if you are reading this and have some time to help me I'll send you the entire code file to see if you can make it work. I am in a crunch for this however as we need to move on to phase 2 of this project and this 1 damn thing is holding me up.
 
Ok, A little additional information. I have tried all the examples I have found and still haven't been able to solve the problem. However I have been able to determine that it is only 16Bit programs that cause the problem. If you run any command like dir or a batch file it works great exactly as it should. However if you fire any 16Bit program such as Edit.com even from a batch file it hangs. I am on a 2000 system so not sure if its on all operating systems but on nt and 2000 it is. Please can any one help me figure this one out. And believe me if I find the problem I will be posting it here.
 
Ok the first clue I have found to the problem is that since my console is fireing a 16bit program it loads ntvdm.exe. If I go into my processes and end ntvdm.exe process my console window closes. So I am assuming (bad fraze but what else do I use) that its something to do with the ntvdm that is causing the problem
 
im guessing u have already read this article (and im assuming it is relevant to your problem)

but just in case


it is a link provided by someone at expert-exchange (admitably a c++ question but like i said it seems relevant (see jkr's final post))

hope this is of use to somebody!

If somethings hard to do, its not worth doing - Homer Simpson
------------------------------------------------------------------------
A General Guide To Excel in VB FAQ222-3383
The Great Date Debate Thread222-368305
File Formats Galore @ or
 
Hi,
I am currently trying to write an application in Delphi (Pascal) that will timeout a 16 bit application. I understand your frustration and I am starting to conclude that there is not a good way to do it. I first had trouble getting the CreateProcess to return a processid that I could use to compare with my process list. I found that by using the &quot;CREATE_SEPARATE_WOW_VDM&quot; in the Process Creation Flag it finally returns all the processids in the Process Information object. The second problem was with the &quot;WaitForInputIdle&quot; function. It would randomly return false return codes on 16 bit applications. I found that by putting a small sleep (100ms or less) between The CreateProcess and the WaitForInputIdle I was finally able to get it to return a consistant value. At that point I was able to get a true return code. If it ended in error or exceeded the max wait time I inserted another small sleep before starting further processing. I am finally able to timeout both 16 bit and 32 bit applications but am I happy with the code....NO. If you find a better solution please let me know. Hope this helps.
 
Sendkeys, anyone?
Code:
Set Timer.Interval 'and timeout in milliseconds
Private Sub Timer_Timer()
SendKeys &quot;%F x&quot; 'or whatever exit keys the program requires
SendKeys &quot;exit&quot;
End Sub
The only problem with this is if the user removes focus from your 16-bit program.
Crystalinity
 
I'm facing the same problem - ntvdm.exe hangs and console window remains open. I'm using VC++ 6.0 on Win2000 Prof Service Pack 2.

Sample code is given below. If I call below function from inside a Windows Console application (main), everything works OK. But, if I call this function from a Windows application (WinMain), ntvdm.exe hangs and console window remains open.

void TestConsole()
{
BOOL bAllocConsoleStatus = AllocConsole();

// Holds child process information
STARTUPINFO si;

// Holds child process information
PROCESS_INFORMATION pi;

ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );

// Start the child process.
if( !CreateProcess( NULL, // module name
"edit.com",
NULL,
NULL,
FALSE,
0, // Creation flags
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi ) // Pointer to PROCESS_INFORMATION structure.
)
{
return;
}

Sleep(3000);

WaitForSingleObject( pi.hProcess, INFINITE );

Sleep(5000);

// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );

if (bAllocConsoleStatus == TRUE)
bAllocConsoleStatus = FreeConsole();
}

The problem "robctech" described is exactly the same, but the code is VB.

Please let me know whether you were able to fix this problem? Is this a Microsoft bug?

Thanks!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top