VB API translating into VBA

M

Marcel

Hi,

I'm trying to use a Named Pipe in Word2003. I will let Word talks via this
pipe with another application that serves as an pipe server. I have this
working in two other programming laguages Xbasic and PureBasic. Now I want
add VBA to it

The API function (Visual Basic version) doesn't work in VBA and let Word
crash is the following:

Public Declare Function CallNamedPipe Lib "kernel32" Alias "CallNamedPipeA"
_
(ByVal lpNamedPipeName As String, _
ByRef lpInBuffer As Any, _
ByVal nInBufferSize As Long, _
ByRef lpOutBuffer As Any, _
ByVal nOutBufferSize As Long, _
ByRef lpBytesRead As Long, _
ByVal nTimeOut As Long) As Long

When I change all the Longs in Integers and call it as an CallNamedPipeA
version it doesn't crash anymore and the communication does something.

Declare Function CallNamedPipeA Lib "kernel32.dll" ( _
ByVal lpNamedPipeName As String, _
lpInBuffer As Any, _
ByVal nInBufferSize As Integer, _
lpOutBuffer As Any, _
ByVal nOutBufferSize As Integer, _
lpBytesRead As Integer, _
ByVal nTimeOut As Integer) As Integer

Both versions do get a connection to the pipe server which is running at
that moment. The ReadFile() action in the server doesn't return with
success, res = 0. The server does work correct in connection to other
programs.

-------------- start of VBA code -----------

Option Explicit

Private Const pipeName As String = "\\.\pipe\mynamedpipe"
Private Const BUFFSIZE = 1024
Private hpipe As Integer
Private myerror As Integer

Public Const INVALID_HANDLE_VALUE As Integer = -1

Declare Function CallNamedPipeA Lib "kernel32.dll" ( _
ByVal lpNamedPipeName As String, _
lpInBuffer As Any, _
ByVal nInBufferSize As Integer, _
lpOutBuffer As Any, _
ByVal nOutBufferSize As Integer, _
lpBytesRead As Integer, _
ByVal nTimeOut As Integer) As Integer

Public Sub CallAPipe()

Dim res As Integer, cbRead As Integer, numBytes As Integer
Dim lpInBuffer As String
Dim lpOutBuffer As String

lpInBuffer = "Some text from Word."
numBytes = Len(lpInBuffer)
lpOutBuffer = String(BUFFSIZE, 0)

res = CallNamedPipeA(pipeName, lpInBuffer, numBytes, lpOutBuffer, BUFFSIZE,
cbRead, 0)

If res = 0 Then
myerror = Err.LastDllError
MsgBox "Error number " & myerror & Error(myerror), vbOKOnly
Else
MsgBox "Ok"
End If
End Sub

-------------- end of vba code -----

Is there someone who has done this before and can point me in the right
direction with this code? All kind of help with this code is appreciated.


Regards,

Marcel
 
T

Tony Jollans

OK, I'm way out of my depth on this one but from a quick check via Google
to MSDN ..


BOOL CallNamedPipe(
LPCTSTR lpNamedPipeName,
LPVOID lpInBuffer,
DWORD nInBufferSize,
LPVOID lpOutBuffer,
DWORD nOutBufferSize,
LPDWORD lpBytesRead,
DWORD nTimeOut
);



Seems to me that doesn't tie in with the definitions you have. Longs in VBA
are single words so I would guess your lengths are not being read correctly



PipeName - String looks good

The two Buffer pointers - Should probably be btye arrays but strings should
also work I think

The two buffer lengths - doubleword isn't a VBA type - you might need to
frig this

Bytes read and TimeOut also need doublewords which again might need a frig -
(halfword) integers certainly don't seem to fit the bill.



I know nothing of pipes so can't test or do the trial and error for you but
a byte array for the pointer) and/or fixed length strings (for the
doublewords) - which you build and interpret yourself - might be needed for
all of them.


Don't know if any of that's any help, but as nobody else is answering I
thought I'd try.
 
M

Marcel

Thanks for your answer Tony,
Seems to me that doesn't tie in with the definitions you have. Longs in
VBA
are single words so I would guess your lengths are not being read
correctly

I checked and double checked it on the Microsoft Site:
C/CPP l, lp, lpz, handle and long is in VBA long (long integer) 4 bytes,
range: -2.147.483.648 tot 2.147.483.64.
C/CPP int is in VBA Integer 2 bytes, range: -32.768 tot 32.767

IMHO the long is a DWORD and integer is a WORD but there can be a
difference.
PipeName - String looks good

The two Buffer pointers - Should probably be byte arrays but strings
should
also work I think

I've examined this and it can be the problem. The original code example
http://support.microsoft.com/default.aspx?scid=kb;en-us;871044 does mention
a byte array. But unfortunately I didn''t understand what they were doing.
;-)

Another point is that in other examples I never saw a byte array and they
used static string buffers.

I'll check the byte arrays.
The two buffer lengths - doubleword isn't a VBA type - you might need to
frig this

Bytes read and TimeOut also need doublewords which again might need a
frig -
(halfword) integers certainly don't seem to fit the bill.



I know nothing of pipes so can't test or do the trial and error for you
but
a byte array for the pointer) and/or fixed length strings (for the
doublewords) - which you build and interpret yourself - might be needed
for
all of them.
Don't know if any of that's any help, but as nobody else is answering I
thought I'd try.


Thanks Tony, your help is appreciated.
 
M

Marcel

The code example I mentioned was VB .Net. When to use it in Word VBA you
have to keep the next thing in mind:

Caution If you are interfacing with components written in Visual Basic
version 6.0, for example Automation or COM objects, keep in mind that
Integer has a different data width (16 bits) in Visual Basic 6.0. If you are
passing a 16-bit argument to such a component, declare it as Short instead
of Integer in Visual Basic .NET.

Again a step nearer to the solution.

Marcel
 
T

Tony Jollans

A bit different. Glad you're found a solution though - because I would have
been struggling :)

I agree l, lp, lpsz etc. are (VBA) longs - it is the DWORDS I think are the
problem. The trouble with some newer APIs is the VB.NET data types - Short
(=VBA Integer), Integer (=VBA Long) and Long (=not in VBA) - I think!
 
M

Marcel

The byte arrays did it.

I can't simply pass a string to the function. I have to put each character
in a byte array.?!?! Pass the array and it works. I got an VBA example from
the recieving side. I build one for the sending side. Now it works. However
I have to do this only for the VBA code. In the other program (Xbasic) I can
simply create a static string array and it works.
 
T

Tony Jollans

I've never completely got to grips with what happens when but it's all to do
with whether or not Unicode strings get converted behind the scenes by VBA.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top