Solved

ReadFile API

Posted on 2004-03-28
7
1,100 Views
Last Modified: 2012-05-04
I am using readfile api to read from a pipe however if there is no data in the pipe, it will just hang until data arrives, is there a way to just check the pipe for data instead of reading to prevent the hanging.


Please look at:
http://oldlook.experts-exchange.com:8080/Programming/Programming_Languages/Visual_Basic/Q_20934771.html



I will award points for both questions if I can get an answer.
0
Comment
Question by:BrianGEFF719
7 Comments
 
LVL 8

Expert Comment

by:plq
ID: 10701954
Use WaitForSingleObject but dont put INFINITE in that parameter, just wait a couple of milliseconds
0
 
LVL 19

Author Comment

by:BrianGEFF719
ID: 10702254
What does WaitForSingle object do?
0
 
LVL 26

Expert Comment

by:EDDYKT
ID: 10703580
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 26

Expert Comment

by:EDDYKT
ID: 10703598
ie

Public Type COMMTIMEOUTS
        ReadIntervalTimeout As Long
        ReadTotalTimeoutMultiplier As Long
        ReadTotalTimeoutConstant As Long
        WriteTotalTimeoutMultiplier As Long
        WriteTotalTimeoutConstant As Long
End Type
Public Declare Function SetCommTimeouts Lib "kernel32.dll" _
 (ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS ) _
 As Long
0
 
LVL 4

Accepted Solution

by:
sokolovsky earned 500 total points
ID: 10703810
The answer is simple:

Declare Function PeekNamedPipe Lib "kernel32" ( _
ByVal hNamedPipe As Long, _
lpBuffer As Any, _
ByVal nBufferSize As Long, _
lpBytesRead As Long, _
lpTotalBytesAvail As Long, _
lpBytesLeftThisMessage As Long _
) As Long

Set lpBuffer to ByVal 0& (we only want to check). So, nBufferSize = 0,  lpBytesRead, lpTotalBytesAvail and lpBytesLeftThisMessage - your variables, after function call will be filled with values.
If lpTotalBytesAvail > 0 - there is some unread data in pipe.
Before calling to ReadFile check for new data in pipe.

Sample Listing:

Option Explicit
Private Type SECURITY_ATTRIBUTES
    nLength As Long
    lpSecurityDescriptor As Long
    bInheritHandle As Long
End Type

Private Type STARTUPINFO
    cb As Long
    lpReserved As Long
    lpDesktop As Long
    lpTitle As Long
    dwX As Long
    dwY As Long
    dwXSize As Long
    dwYSize As Long
    dwXCountChars As Long
    dwYCountChars As Long
    dwFillAttribute As Long
    dwFlags As Long
    wShowWindow As Integer
    cbReserved2 As Integer
    lpReserved2 As Long
    hStdInput As Long
    hStdOutput As Long
    hStdError As Long
End Type

Private Type PROCESS_INFORMATION
    hProcess As Long
    hThread As Long
    dwProcessId As Long
    dwThreadId As Long
End Type

Private Type PIPE
    hReadPipe As Long
    hWritePipe As Long
End Type

Private Const INFINITE = -1&

Private Const NORMAL_PRIORITY_CLASS = &H20&
Private Const CREATE_NEW_CONSOLE = &H10

Private Const STARTF_USESHOWWINDOW = &H1
Private Const STARTF_USESIZE = &H2
Private Const STARTF_USEPOSITION = &H4
Private Const STARTF_USECOUNTCHARS = &H8
Private Const STARTF_USEFILLATTRIBUTE = &H10
Private Const STARTF_RUNFULLSCREEN = &H20
Private Const STARTF_FORCEONFEEDBACK = &H40
Private Const STARTF_FORCEOFFFEEDBACK = &H80
Private Const STARTF_USESTDHANDLES = &H100

Private Const SW_HIDE = 0
Private Const SW_SHOWNORMAL = 1
Private Const SW_NORMAL = 1
Private Const SW_SHOWMINIMIZED = 2
Private Const SW_SHOWMAXIMIZED = 3
Private Const SW_MAXIMIZE = 3
Private Const SW_SHOWNOACTIVATE = 4
Private Const SW_SHOW = 5
Private Const SW_MINIMIZE = 6
Private Const SW_SHOWMINNOACTIVE = 7
Private Const SW_SHOWNA = 8
Private Const SW_RESTORE = 9
Private Const SW_SHOWDEFAULT = 10
Private Const SW_MAX = 10

Private Const INVALID_HANDLE_VALUE = -1

Private Const STILL_ACTIVE = &H103&

Private Declare Function CreatePipe Lib "kernel32" _
 (phReadPipe As Long, phWritePipe As Long, lpPipeAttributes _
 As SECURITY_ATTRIBUTES, ByVal nSize As Long) As Long

Private Declare Function ReadFile Lib "kernel32" _
 (ByVal hFile As Long, ByVal lpBuffer As String, _
 ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead _
 As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function WriteFile Lib "kernel32" _
 (ByVal hFile As Long, ByVal lpBuffer As String, _
 ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten _
 As Long, lpOverlapped As Any) As Long

Private Declare Function CreateProcess Lib "kernel32" _
 Alias "CreateProcessA" (ByVal lpApplicationName As Long, _
 ByVal lpCommandLine As String, lpProcessAttributes As Any, _
 lpThreadAttributes As Any, ByVal bInheritHandles As _
 Long, ByVal dwCreationFlags As Long, ByVal lpEnvironment _
 As Long, ByVal lpCurrentDirectory As Long, lpStartupInfo _
 As Any, lpProcessInformation As Any) As Long

Private Declare Function GetExitCodeProcess Lib _
 "kernel32" (ByVal hProcess As Long, lpExitCode _
 As Long) As Long
Private Declare Function TerminateProcess Lib _
 "kernel32" (ByVal hProcess As Long, ByVal uExitCode _
 As Long) As Long

Private Declare Function GetStdHandle Lib "kernel32" _
 (ByVal nStdHandle As Long) As Long
Private Declare Function SetStdHandle Lib "kernel32" _
 (ByVal nStdHandle As Long, ByVal nHandle As Long) As Long

Private Declare Function CloseHandle Lib "kernel32" _
 (ByVal hObject As Long) As Long

Private Declare Function PeekNamedPipe Lib "kernel32" _
 (ByVal hNamedPipe As Long, lpBuffer As Any, ByVal _
 nBufferSize As Long, lpBytesRead As Long, _
 lpTotalBytesAvail As Long, lpBytesLeftThisMessage _
 As Long) As Long

Private pipeOut As PIPE, pipeIn As PIPE

Private Process As PROCESS_INFORMATION

Private mvarCommandLine As String
Private mvarRunning As Boolean

Public Sub Terminate()
    TerminateProcess Process.hProcess, 0
    CloseHandle Process.hProcess
    CloseHandle Process.hThread
    CloseHandle pipeIn.hReadPipe
    CloseHandle pipeIn.hWritePipe
    CloseHandle pipeOut.hReadPipe
    CloseHandle pipeOut.hWritePipe
   
    mvarRunning = False
End Sub

Public Function Read(Optional ByVal Bytes As Long = -1)
                                                As String
    Dim tBytesR As Long, Buffer As String
    Dim tBytesA As Long, tMsg As Long
    Dim I As Long, Result As Long
    Dim ReturnStr As String
   
    If Not mvarRunning Then Exit Function
   
    Result = PeekNamedPipe(pipeErr.hReadPipe, ByVal 0&, 0, _
             tBytesR, tBytesA, tMsg)

    If Result <> 0 And tBytesA > 0 Then
        Buffer = String(tBytesA, " ")
        Result = ReadFile(pipeOut.hReadPipe, Buffer, _
                  IIf(Bytes = -1, Len(Buffer), _
            Bytes), tBytesR, ByVal 0&)
        If Result = 0 Then _
            Err.Raise vbObjectError + 504, "DOSShell Class", _
            "Error: ReadFile failed. " & Err.LastDllError
        ReturnStr = Left(Buffer, tBytesR)
        Read = DOSDecode(ReturnStr)
    End If
End Function

Public Function Write(ByVal Data As String) As Long
    Dim tBytesW As Long
    Dim I As Long, Result As Long

    If Not Right(Data, 2) = Chr(13) & Chr(10) Then _
             Data = Data & Chr(13) & Chr(10)

    Result = WriteFile(pipeIn.hWritePipe, Data, _
              Len(Data), tBytesW, ByVal 0&)
    If Result = 0 Then _
        Err.Raise 503, "DOSWrite", "Error: WriteFile failed. " _
                       & Err.LastDllError
    Result = FlushFileBuffers(pipe.hWritePipe)
    If Result = 0 Then _
        Err.Raise vbObjectError + 507, "DOSShell Class", _
         "Error: FlushFileBuffers failed. " & Err.LastDllError
   
    WriteIn = Len(Data) - 1
End Function

Public Function Execute(Optional ByVal CommandLine As _
           String = "") As Long
    Dim Result As Long
    Dim StartInfo As STARTUPINFO
    Dim Attribs As SECURITY_ATTRIBUTES
    Dim tIn As Long, tOut As Long
   
    On Error GoTo ErrHandler
   
    If CommandLine <> "" Then mvarCommandLine = CommandLine
   
    Attribs.nLength = Len(Attribs)
    Attribs.bInheritHandle = 1;
    Attribs.lpSecurityDescriptor = 0&
   
    Result = CreatePipe(pipeIn.hReadPipe, pipeIn.hWritePipe, _
 Attribs, ByVal 0&)
    If Result = 0 Then _
        Err.Raise vbObjectError + 501, "DOSShell Class", _
 "Error: CreatePipe failed. " & Err.LastDllError
   
    Result = CreatePipe(pipeOut.hReadPipe, pipeOut.hWritePipe, _
 Attribs, ByVal 0&)
    If Result = 0 Then _
        Err.Raise vbObjectError + 501, "DOSShell Class", _
 "Error: CreatePipe failed. " & Err.LastDllError
       
    StartInfo.cb = Len(StartInfo)
    StartInfo.hStdInput = pipeIn.hReadPipe
    StartInfo.hStdOutput = pipeOut.hWritePipe
    StartInfo.hStdError = pipeOut.hWritePipe
    StartInfo.dwFlags = STARTF_USESTDHANDLES + _
                              STARTF_USESHOWWINDOW
    StartInfo.wShowWindow = SW_HIDE

    Result = CreateProcess(0&, mvarCommandLine, Attribs, _
 Attribs, ByVal 1&, CREATE_NEW_CONSOLE, ByVal 0&, ByVal _
 0&, StartInfo, Process)
 
    If Result = 0 Then _
        Err.Raise vbObjectError + 502, "DOSShell Class", _
 "Error: CreateProcess failed. " & Err.LastDllError
   
    Execute = 1
    mvarRunning = True
    Exit Function

ErrHandler:
    Execute = Err.Number
   
End Function

Public Property Get Running() As Boolean
    Dim ExitCode As Long
    If Not mvarRunning Then
        Running = False
    Else
        GetExitCodeProcess Process.hProcess, ExitCode
        Running = (ExitCode = STILL_ACTIVE)
    End If
End Property

Public Property Let CommandLine(ByVal vData As String)
    mvarCommandLine = vData
End Property

Public Property Get CommandLine() As String
    CommandLine = mvarCommandLine
End Property

Private Function DOSDecode(ByVal Str As String) As String
    Dim I As Long

    For I = 239 To 192 Step -1
        Str = Replace(Str, Chr(I), Chr(I + 16))
    Next I

    For I = 191 To 128 Step -1
        Str = Replace(Str, Chr(I), Chr(I + 64))
    Next I
    Str = Replace(Str, Chr(0), "")

    DOSDecode = Str
End Function
0
 
LVL 19

Author Comment

by:BrianGEFF719
ID: 10709152
its not a named pipe, its an anonymous pipe.


-Brian
0
 
LVL 19

Author Comment

by:BrianGEFF719
ID: 10709187
sokolovsky!!! YOU ARE THE MAN! You saved my ass. Thank you so much
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

I’ve seen a number of people looking for examples of how to access web services from VB6.  I’ve been using a test harness I built in VB6 (using many resources I found online) that I use for small projects to work out how to communicate with web serv…
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…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
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…

744 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

11 Experts available now in Live!

Get 1:1 Help Now