Solved

ReadFile API

Posted on 2004-03-28
7
1,113 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
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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…
Background What I'm presenting in this article is the result of 2 conditions in my work area: We have a SQL Server production environment but no development or test environment; andWe have an MS Access front end using tables in SQL Server but we a…
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…
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…

828 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