Я весь день бил головой об этом, и я просто не могу разобраться в различной (иногда противоречивой) документации по этому вопросу. Чтобы добавить к путанице, в какой-то момент в течение дня это выполняло (вроде) работу, то есть не бросало ошибку нарушения доступа. Но данные на другом конце трубы были бессмысленными, поэтому я подозреваю, что это только «сработало» случайно.Ошибки, вызывающие WriteFile из визуального базового .net 2010 по именованному каналу
У меня есть программа vb.net (с использованием .net 3.0, поэтому нет поддержки System.IO.NamedPipes :(), которая создает именованный канал и ждет другого приложения для подключения и отправки некоторых данных. В качестве 'ack' , Я тогда хочу, чтобы программа vb отправила обратно общую длину полученного сообщения. Я могу создать канал, дождаться соединения и получить сообщение, но он пытается отправить «ack» с помощью WriteFile
. (ток) определение я использую для WriteFile
основано на соответствующий ReadFile
, который, кажется, работает хорошо:
Declare Function ReadFile Lib "kernel32" (_
ByVal hFile As Integer, _
ByRef lpBuffer As Byte, _
ByVal nNumberOfBytesToRead As Integer, _
ByRef lpNumberOfBytesRead As Integer, _
ByVal lpOverlapped As Integer) _
As Integer
Declare Function WriteFile Lib "kernel32" (_
ByVal hFile As Long, _
ByRef lpBuffer As Byte, _
ByVal nNumberOfBytesToWrite As Integer, _
ByRef lpNumberOfBytesWritten As Integer, _
ByVal lpOverlapped As Integer) _
As Integer
урезанного код (проверка ошибок и отладка печать удалена) выглядят следующим образом:
Dim openMode = PIPE_ACCESS_DUPLEX Or FILE_FLAG_FIRST_PIPE_INSTANCE
Dim pipeMode = PIPE_WAIT Or PIPE_TYPE_MESSAGE Or PIPE_READMODE_MESSAGE
Dim res ' Result of dll calls
pipeN2Q = CreateNamedPipe("\\.\pipe\N2Q", openMode, pipeMode, 10, 1024, 1024, 2000, IntPtr.Zero)
res = ConnectNamedPipe(pipeN2Q, 0)
Dim rxCount As Integer = 0 ' To hold the number of bytes received
Dim txCount As Integer = 0 ' To hold the number of bytes sent
Dim txReq As Integer = 2 ' To hold the number of bytes we're going to ask to be sent during the 'ack'
Dim dataIn(256) As Byte
res = ReadFile(pipeN2Q, dataIn(0), 256, rxCount, Nothing)
Dim recvBuffer As String = System.Text.Encoding.ASCII.GetString(dataIn, 0, rxCount)
Dim dataOut(2) As Byte
dataOut(0) = 42
dataOut(1) = 43
res = WriteFile(pipeN2Q, dataOut(0), txReq, txCount, Nothing)
После того, как код попадает в WriteFile
, он бросает AccessViolationException - «Попытка чтения или записи в защищенную память.» Я предполагаю, что это жалуется параметр dataOut
, но он не дает никаких дальнейших подробностей. Вещи, которые я пробовал до сих пор включают в себя:
- Изменение декларации
WriteFile
так чтоlpBuffer
объявлен:ByVal lpBuffer as IntPtr
- DATAOUT используя Выделение
Marshal.AllocHGlobal(txReq)
и инициализируется с помощьюMarshal.WriteInt16()
- Выделяя большой буфер для
dataOut
(1024 байт) и инициализации их на нули
Чтобы быть ясным, сообщение, полученное из другого приложения, получено отлично и recvBuffer
имеет строку точно как отправлено. Я просто не могу убедить WriteFile сотрудничать (за исключением одного, возможно, случайно, и я не смог повторить его). Я надеюсь, что это просто что-то в декларации или инициализации переменных - какие-то подсказки?
Ваши объявления о плющике плохие. Используйте сайт pinvoke.net, чтобы найти хорошие. –
Спасибо - pinvoke.net был одним из сайтов, на которые я ссылался - хотя у него есть 3 разных подписи для WriteFile, а тип возврата для ReadFile показан как SafeFileHandle, тогда как в MSDN он отображается как Boolean. Поэтому я действительно не доверял этому ... Однако версия с StringBuilder как тип буфера передачи, наконец, позволила мне отправлять чистые данные с обеих сторон, поэтому спасибо за указатель. – dsl101