Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как? / 25 сообщений из 49, страница 1 из 2
10.02.2015, 12:29
    #38875759
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
Я для передачи команд (строк) между приложениями использую два IPC-метода:
1) Mailslot
2) SendMessage(WM_COPYDATA) -сейчас почти нигде не оставил в пользу первого

В переписываемом .Net приложении я делаю упор на Юникод, т.е. все API декларируются
Код: vbnet
1.
Declare Unicode Function ...Alias "...W"


все структуры с намеком на строки
Код: vbnet
1.
  <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>



Чтение /запись в MailSlot базируется на ф-циях ReadFile/WriteFile. В случае WM_COPYDATA передается структура COPYDATASTRUCT.
И в том и другом случае речь идет о передаче НАБОРА БАЙТОВ а не строк, поэтому в оригинале нет отдельных определений "A" и "W"

Вот собственно не знаю как поступить.

Могу оставаться в ANSI (для этих методов):

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
'MailSlot
  Public Declare Function ReadFile Lib "kernel32" ( _
   ByVal hFile As IntPtr, _
   ByVal lpBuffer As String, _
   ByVal nNumberOfBytesToRead As Integer, _
   ByRef lpNumberOfBytesRead As Integer, _
   ByVal lpOverlapped As IntPtr) As Boolean 'два крайних параметра -Optional
  Public Declare Function WriteFile Lib "kernel32" ( _
   ByVal hFile As IntPtr, _
   ByVal lpBuffer As String, _
   ByVal nNumberOfBytesToWrite As Integer, _
   ByRef lpNumberOfBytesWritten As Integer, _
   ByVal lpOverlapped As IntPtr) As Boolean

'SendMessage(WM_COPYDATA)
  <StructLayout(LayoutKind.Sequential)>
  Public Structure COPYDATASTRUCT
    Dim dwData As IntPtr ' additional 32 bit data to pass
    Dim cbData As Integer ' length in bytes of data pointed by lpData
    Dim lpData As String ' pointer to data to be passed to the receiving app. '<MarshalAs(UnmanagedType.LPStr)>
  End Structure



Могу "мигрировать на Юникод"
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
'MailSlot
  Public Declare Unicode Function ReadFile Lib "kernel32" ( _
   ByVal hFile As IntPtr, _
   ByVal lpBuffer As String, _
   ByVal nNumberOfBytesToRead As Integer, _
   ByRef lpNumberOfBytesRead As Integer, _
   ByVal lpOverlapped As IntPtr) As Boolean 'два крайних параметра -Optional
  Public Declare Unicode Function WriteFile Lib "kernel32" ( _
   ByVal hFile As IntPtr, _
   ByVal lpBuffer As String, _
   ByVal nNumberOfBytesToWrite As Integer, _
   ByRef lpNumberOfBytesWritten As Integer, _
   ByVal lpOverlapped As IntPtr) As Boolean

'SendMessage(WM_COPYDATA)
   <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
  Public Structure COPYDATASTRUCT
    Dim dwData As IntPtr ' additional 32 bit data to pass
    Dim cbData As Integer ' length in bytes of data pointed by lpData
    Dim lpData As String ' pointer to data to be passed to the receiving app. '<MarshalAs(UnmanagedType.LPStr)>
  End Structure



Сложность выбора еще в том, что у меня есть C++(ANSI) -модуль, в котором также присутствует MailSlot , он обменивается c VB.Net -приложением (только EN-строки), но это же VB.Net обменивается с другим VB.Net.
Если посылать раздельно ANSI/Unicode (в разные приложения) можно без проблем, то приемник один (т.е. в него нельзя слать ANSI/Unicode кашу).

VB.Net компоненты могут передавать меж собой "русские" (не-EN) тексты.
От требования к системе: русский язык для не-юникод программ для "русской версии" я хочу отказаться.

Если я оставлю ANSI в этом вопросе, не получу ли я проблем с передачей русского текста (при отключенной поддержке для не-Юникод программ)? Комп то вроде по любому один и тот же. Как закодирует, так и раскодирует.
Как тут посоветуете поступить?


И еще.
Конечно не стоит мешать API с .Net,
хотя бы в случае с mailslot,
нельзя как-то заменить ReadFile/WriteFile на StreamWriter/Reader?
Т.е. явно задавать/определять кодировку при чтении записи в файл (т.е в Mailslot) UTF8 с флагом или как там его(недавно обсуждали)/Default ANSI, handle mailslot-а известен.???
...
Рейтинг: 0 / 0
10.02.2015, 12:34
    #38875779
Konst_One
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
base64 кодируй при отправке, при приёме декодируй
...
Рейтинг: 0 / 0
10.02.2015, 13:17
    #38875852
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
маршаллинг прарметров явно задай (как массив байтов с указаием параметра-длины) ,
буферу будет насрать на вызов A или U

Дмитрий77От требования к системе: русский язык для не-юникод программ для "русской версии" я хочу отказаться.
это правильно

Дмитрий77нельзя как-то заменить ReadFile/WriteFile на StreamWriter/Reader?
Т.е. явно задавать/определять кодировку при чтении записи в файл (т.е в Mailslot) UTF8 с флагом или как там его(недавно обсуждали)/Default ANSI, handle mailslot-а известен.???
никакого смысла. получил пакет в виде набора байтов - интерпретируй как хочешь, поток не поможет

можно рассмотреть вариант - во всех приложениях использовать UTF-8
...
Рейтинг: 0 / 0
10.02.2015, 13:54
    #38875899
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
Дмитрий77, при работе с набором байтов разницы между ANSI и Unicode не будет. Однако по моему ты неправильно объявил ReadFile/WriteFile/COPYDATASTRUCT. Ты говоришь об обмена байтами, а используешь тип String для lpBuffer/lpData. По моему там должен быть IntPtr т.к. в С/С++ они объявлены как LPVOID.
...
Рейтинг: 0 / 0
10.02.2015, 14:07
    #38875921
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
Давайте про mailslot только рассуждать чтоб не путаться.

Ну, насколько я понимаю,
что если
1) строка "русская"
2) язык системы для не-юникода - "китайский"
3) WriteFile и ReadFile декларированы как ANSI т.е. (...ByVal lpBuffer As String)
то на выходе все таки получим фигню а не "русский".
Т.е. не сумеет он в общем случае кодировать в ANSI и декодировать из ANSI.
Так? Т.е. все-таки передавать надо Unicode?


>маршаллинг прарметров явно задай
Какая разница в данном случае написать слово Unicode перед ф-цией или лепить <Marshall.> перед as String?.
Задекларировав функции как Declare Unicode Function , ну или прописав маршалинг параметров как Юникод я эту задачу решаю (передается Юникод хз там в какой кодировке согласно API понятиям но без искажений). Естественно хочется As String для простоты использования.
===
Но остается тогда нерешенной следующая задача:
Предположим есть exe, есть mailslot.
Одно приложение шлет в него ANSI (C++, только EN, переписывать/перекомпилировать на Unicode не буду).
Другое приложение шлет в него Unicode.
Как извернуться (с единственным mailslot)?

Объясню почему я вспомнил про StreamWriter/Reader.
Потому что mailslot -по сути файл с операциями записи чтения в него.
В StreamWriter/Reader есть параметр Encoder, применяя который можно задать BOM (явное указание UTF8 например).
Т.е. нельзя ли эту автоматику как то присобачить?
Приходит строка с BOM -конвертируется из UTF8, без BOM -значит ANSI.
Хотя опять же, не уверен. BOM же в начало файла ставится а как это на MailSlot переложить...

Функции для MailSlot у меня со времен VB6 такие, декларации для ANSI и Unicode я привел выше.

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
  Public Function MailSlotReadFirst(ByRef m_Message As String, ByRef m_MsgCount As Integer) As Boolean
    'ПРИЕМНИК(сервер) ф-ция читает первое сообщение если есть
    'возвращает True, если есть хотя бы одно и оно было прочитано
    'm_Message (Out)-текст сообщения, если прочли
    'm_MsgCount -к-во сообщений оставшихся после чтения (без учета прочитанного)

    MailSlotReadFirst = False

    Dim lBufferSize As Integer
    m_Message = ""
    m_MsgCount = 0
    GetMailslotInfo(hMailSlotHandle, 0, lBufferSize, m_MsgCount, 0)
    If m_MsgCount > 0 Then
      Dim sBuffer As String
      ' Create a buffer
      sBuffer = StrDup(lBufferSize, Chr(0))

      ' Read data: optional параметры ф-ции не используем
      If ReadFile(hMailSlotHandle, sBuffer, lBufferSize, 0, IntPtr.Zero) Then
        m_Message = sBuffer
        m_MsgCount = m_MsgCount - 1
        MailSlotReadFirst = True
      End If
    End If
  End Function

  Public Function SendMessageToMailSlot(ByVal sMessage As String, ByVal sMailSlot As String, _
   Optional ByVal CPP As Boolean = False) As Boolean
    'ПЕРЕДАТЧИК(клиент)ф-ция отправляет сообщение sMessage серверу с именем sMailSlot
    'если сервер не запущен, то сообщение не отправляется
    Dim hFile As IntPtr
    Dim m_tSA As SECURITY_ATTRIBUTES

    hFile = CreateFile(sMailSlot, _
                       GENERIC_WRITE, _
                       FILE_SHARE_READ, _
                       m_tSA, _
                       OPEN_EXISTING, _
                       FILE_ATTRIBUTE_NORMAL, _
                       IntPtr.Zero)
    If hFile = INVALID_HANDLE_VALUE Then Return False

    If CPP Then
      SendMessageToMailSlot = WriteFile(hFile, sMessage, Strings.Len(sMessage) + 1, 0, IntPtr.Zero) 'добавляем '\0'
    Else
      SendMessageToMailSlot = WriteFile(hFile, sMessage, Strings.Len(sMessage), 0, IntPtr.Zero) 'при отправке в VB не добавляем '\0'
    End If
    CloseHandle(hFile)
  End Function



Видимо надо тест-проект создавать и играться.
...
Рейтинг: 0 / 0
10.02.2015, 14:16
    #38875933
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
bazileДмитрий77, при работе с набором байтов разницы между ANSI и Unicode не будет. Однако по моему ты неправильно объявил ReadFile/WriteFile/COPYDATASTRUCT. Ты говоришь об обмена байтами, а используешь тип String для lpBuffer/lpData. По моему там должен быть IntPtr т.к. в С/С++ они объявлены как LPVOID.
Ты абсолютно прав. В оригинале там конечно байты, а не строки. По этой причине в ReadFile/WriteFile/COPYDATASTRUCT и нет деления на "A" и "W".
Но я то знаю что я работаю ТОЛЬКО со строками. Поэтому могу довериться автоматике/маршалингу.
Если объявлю ReadFile/WriteFile как Unicode -буду передавать Unicode-строки, если ANSI -то ANSI. главное чтоб одинаково для Read и Write.
...
Рейтинг: 0 / 0
10.02.2015, 14:20
    #38875942
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
Дмитрий773) WriteFile и ReadFile декларированы как ANSI т.е. (...ByVal lpBuffer As String)
ну не надо буфер как строку передавать- передавай байты.
...
Рейтинг: 0 / 0
10.02.2015, 14:49
    #38875974
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
Дмитрий77Но остается тогда нерешенной следующая задача:
Предположим есть exe, есть mailslot.
Одно приложение шлет в него ANSI (C++, только EN, переписывать/перекомпилировать на Unicode не буду).
Другое приложение шлет в него Unicode.
Как извернуться (с единственным mailslot)?

Объясню почему я вспомнил про StreamWriter/Reader.
Потому что mailslot -по сути файл с операциями записи чтения в него.
В StreamWriter/Reader есть параметр Encoder, применяя который можно задать BOM (явное указание UTF8 например).
Т.е. нельзя ли эту автоматику как то присобачить?
Раз ты контролиуешь обе стороны обмена, то можно. При наличии ВОМ класс StreamReader игнорирует переданную ему кодировку и использует кодировку указанную через BOM. Сам массив данных можно трактовать как поток с помощью MemoryStream. Передавать при этом мы будем всегда массив байтов. Код фукнций подготовки данных и их чтения на стороне .NEТ можно организовать примерно так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Function StringToBytes(ByVal text As String) As Byte()
	Dim utf8 As New UTF8Encoding(True) ' Указываем всегда использовать BOM
	Return utf8.GetBytes(text)
End Function

Function BytesToString(ByVal data() As Byte) As String
	Using mstream As New MemoryStream(data)
		Using reader As New StreamReader(mstream, Encoding.Default)
			return reader.ReadToEnd()
		End Using
	End Using
End Function
...
Рейтинг: 0 / 0
10.02.2015, 15:22
    #38876015
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
Изопропилну не надо буфер как строку передавать- передавай байты.
А что это даст кроме гимора с конвертацией в байты и обратно?
Я ж все равно не угадаю юникодные это байты или ANSI (если мне приходят "наборы двух типов", а чтобы понять от кого пришло надо прочесть чего там написано, а не зная ANSI или Unicode и не прочтешь, если только собственные "байт-метки" ставить, но это уже маразм).

По хорошему декларировать все как Юникод (As String) и все типа в шоколаде.
Это если не выходя за пределы .Net. Это я сделаю, это работает.

Но что тогда делать с C++ которое отправляет и принимает ANSI.
Причем сам C++ проект -чистое ANSI и Юникод там нафиг не нужен (для всего проекта).

Код там такой:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
'прием
  char buffer[1000];
  DWORD NumberOfBytesRead;
  for (;;)
  {
    if (ReadFile(hMailSlotHandle, buffer, 1000, &NumberOfBytesRead, NULL)!=0) {
      buffer[NumberOfBytesRead]='\0'; //отсекаем мусор -не надо, надо '\0' добавлять к сообщению
      PString str_message =  PString((LPCTSTR)buffer);
...


'отправка
BOOL SendMessageToMailSlot(LPCTSTR lpszMessage, LPCTSTR SlotName)
{
  HANDLE hFile;

  hFile = CreateFile(SlotName,
   GENERIC_WRITE,
   FILE_SHARE_READ,
   (LPSECURITY_ATTRIBUTES) NULL,
   OPEN_EXISTING,
   FILE_ATTRIBUTE_NORMAL,
   (HANDLE) NULL);
  if (hFile == INVALID_HANDLE_VALUE)
    return FALSE;

  BOOL fResult;
  DWORD cbWritten; 
  fResult = WriteFile(hFile, 
   lpszMessage,
   (DWORD) lstrlen(lpszMessage)*sizeof(TCHAR),
   &cbWritten,
   (LPOVERLAPPED) NULL);
  CloseHandle(hFile);
  return fResult;
}

'Ну например...
      std::string buffer;
...
      SendMessageToMailSlot(TEXT(buffer.c_str()),
       TEXT("\\\\.\\mailslot\\MailSlotMyName"));



Вот как эти две "функции" переписать на прием/отправку именно Юникода? При том что весь проект в ANSI.
...
Рейтинг: 0 / 0
10.02.2015, 15:41
    #38876042
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
bazile,

т.е. я правильно понимаю, что при отправке юникод сообщения(UTF-8) я BOM добавляю в начало КАЖДОГО сообщения (массива байтов) - т.е на этапе формирования именно массива байтов?
Соответственно если надо отправить в ANSI, то делаю массив с кодировкой .Default?
А на обратном пути автоматика на основании наличия/отсутствия BOM?
При этом конечно ReadFile/WriteFile декларирую однозначно с массивом байтов (IntPtr, надо смотреть) - инвариантно для обоих случаев - как в оригинале.

Ну по крайне мере чутье не обмануло. Хотя я имел ввиду запись BOM в MailSlot (интерпретируя его как файл).
Идея дошла. Спасибо. Пошел делать тест-проект, играться и переписывать свои ф-ции.
...
Рейтинг: 0 / 0
10.02.2015, 16:02
    #38876072
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
Дмитрий77т.е. я правильно понимаю, что при отправке юникод сообщения(UTF-8) я BOM добавляю в начало КАЖДОГО сообщения (массива байтов) - т.е на этапе формирования именно массива байтов?
Соответственно если надо отправить в ANSI, то делаю массив с кодировкой .Default?
А на обратном пути автоматика на основании наличия/отсутствия BOM?
Да.

Дмитрий77Хотя я имел ввиду запись BOM в MailSlot (интерпретируя его как файл).
Никто не мешает тебе написать класс MailSlotStream инкапсулирующий всю эту логику.
...
Рейтинг: 0 / 0
10.02.2015, 16:24
    #38876119
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
bazileДмитрий77Хотя я имел ввиду запись BOM в MailSlot (интерпретируя его как файл).
Никто не мешает тебе написать класс MailSlotStream инкапсулирующий всю эту логику.
Не-не, здесь нет никакой здравой логики. Я то хотел по hMailSlotHandle открыть его как файл и использовать StreamWriter/Reader, ВМЕСТО ReadFile/WriteFile , возможно частично сделать что-то здесь можно, например указав "\\.\mailslot\MailSlotMyName" в качестве пути к файлу (на запись возможно да, если атрибуты - аналог CreateFile подберу), но я сомневаюсь что что-то путное выйдет. Короче счас попробую твою идею с подготовкой/чтением массива байтов + родные ReadFile/WriteFile.
А уж потом посмотрю можно ли ему сообщение послать чисто через StreamWriter.
...
Рейтинг: 0 / 0
10.02.2015, 16:48
    #38876168
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
Дмитрий77его как файл и использовать StreamWriter/Reader, ВМЕСТО ReadFile/WriteFile ,


это НИКАК не влияет на решение задачи ( кодировку текста)
...
Рейтинг: 0 / 0
10.02.2015, 17:23
    #38876211
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
Дмитрий77Не-не, здесь нет никакой здравой логики.
"Спасибо" за высокую оценку. В моем понимании это наоборот прекрасно укладывается в .NET логику. Ты хочешь работать с mailslot через StreamWriter который умеет оборачиваться вокруг другого потока. Т.к. в нет класса наследника Stream который умеет работать с MailSlot, то значит можно написать свой класс для этой задачи.

Дмитрий77Я то хотел по hMailSlotHandle открыть его как файл и использовать StreamWriter/Reader, ВМЕСТО ReadFile/WriteFile
Конструктор FileStream позволяет передать дескриптор уже открытого потока. Затем FileStream можно передать StreamWriter/Reader. Попробуй так.
...
Рейтинг: 0 / 0
10.02.2015, 18:10
    #38876277
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
bazile
Код: vbnet
1.
2.
3.
4.
Function StringToBytes(ByVal text As String) As Byte()
	Dim utf8 As New UTF8Encoding(True) ' Указываем всегда использовать BOM
	Return utf8.GetBytes(text)
End Function

Так не хочет BOM к массиву пре-приписывать.

Вроде вот так получается (до конца еще не доделал):
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
   Dim buffer As Byte()
    If bUTF8 Then 'отправлять Юникод
      Dim utf8 As New System.Text.UTF8Encoding(True) ' Указываем всегда использовать BOM
      Dim pre As Byte() = utf8.GetPreamble 'если только ручками BOM дописывать
      Dim body As Byte() = utf8.GetBytes(sMessage)
      ReDim buffer(0 To pre.Length + body.Length - 1)
      Array.Copy(pre, buffer, pre.Length)
      Array.Copy(body, 0, buffer, pre.Length, body.Length)


Проще нельзя этот BOM приписать?
...
Рейтинг: 0 / 0
10.02.2015, 18:57
    #38876298
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
Дмитрий77Проще нельзя этот BOM приписать?
можно
...
Рейтинг: 0 / 0
10.02.2015, 19:56
    #38876325
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
ИзопропилДмитрий77Проще нельзя этот BOM приписать?
можно
Ты вот это имел ввиду?
Код: vbnet
1.
2.
      buffer = _
       System.Text.Encoding.UTF8.GetPreamble().Concat(System.Text.Encoding.UTF8.GetBytes(sMessage)).ToArray


Это на .Net2 не фурычит, а я как ты возможно помнишь не рискну отказываться хотя бы от совместимости кода.

Или что-то другое имелось в виду?
...
Рейтинг: 0 / 0
10.02.2015, 21:56
    #38876386
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
Ну вот вроде допилил, все типа работает:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
Public Class Form1

  Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    MakeMailSlot("\\.\mailslot\MailSlotMyName")
  End Sub

  Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
    CloseMailSlot() 'необх. нет, т.к. он уничтожится по любому вместе с закрытием приложения
  End Sub

'я беру интервал 1 секунда  
Private Sub TimerMailSlot_Tick(sender As Object, e As EventArgs) Handles TimerMailSlot.Tick
    ReadApplyMessages_MailSlot()
  End Sub

  Public Sub ReadApplyMessages_MailSlot()
    Dim the_str As String = vbNullString
    Dim the_msgCount As Integer
    Do
      If MailSlotReadFirst(the_str, the_msgCount) Then
        '---обработка сообщения---
        MsgBox(the_str)
        '---обработка сообщения---
        If the_msgCount = 0 Then Exit Do
      Else
        Exit Do
      End If
    Loop
  End Sub

  Private Sub ButtonSendANSI_Click(sender As Object, e As EventArgs) Handles ButtonSendANSI.Click
    SendMessageToMailSlot(TextBoxToSend.Text, "\\.\mailslot\MailSlotMyName", False)
  End Sub

  Private Sub ButtonSendUTF8_Click(sender As Object, e As EventArgs) Handles ButtonSendUTF8.Click
    SendMessageToMailSlot(TextBoxToSend.Text, "\\.\mailslot\MailSlotMyName", True)
  End Sub
End Class



Module MailSlots
  Public Structure SECURITY_ATTRIBUTES
    Dim nLength As Integer
    Dim lpSecurityDescriptor As IntPtr
    Dim bInheritHandle As Boolean
  End Structure

  'File Attribute Constants
  Public Const FILE_ATTRIBUTE_NORMAL = &H80

  Public ReadOnly INVALID_HANDLE_VALUE As IntPtr = New IntPtr(-1)

  'File Management Functions

  'dwDesiredAccess - The requested access to the file or device, which can be summarized as read, write, both...
  Public Const GENERIC_WRITE = &H40000000
  'dwShareMode - The requested sharing mode of the file or device
  Public Const FILE_SHARE_READ = &H1
  'dwCreationDisposition -An action to take on a file or device that exists or does not exist.
  Public Const OPEN_EXISTING = 3

  Public Declare Unicode Function CreateFile Lib "kernel32" _
   Alias "CreateFileW" ( _
   ByVal lpFileName As String, _
   ByVal dwDesiredAccess As Integer, _
   ByVal dwShareMode As Integer, _
   ByRef lpSecurityAttributes As SECURITY_ATTRIBUTES, _
   ByVal dwCreationDisposition As Integer, _
   ByVal dwFlagsAndAttributes As Integer, _
   ByVal hTemplateFile As IntPtr) As IntPtr

  Public Declare Function ReadFile Lib "kernel32" ( _
   ByVal hFile As IntPtr, _
   ByVal lpBuffer As Byte(), _
   ByVal nNumberOfBytesToRead As Integer, _
   ByRef lpNumberOfBytesRead As Integer, _
   ByVal lpOverlapped As IntPtr) As Boolean 'два крайних параметра -Optional
  Public Declare Function WriteFile Lib "kernel32" ( _
   ByVal hFile As IntPtr, _
   ByVal lpBuffer As Byte(), _
   ByVal nNumberOfBytesToWrite As Integer, _
   ByRef lpNumberOfBytesWritten As Integer, _
   ByVal lpOverlapped As IntPtr) As Boolean

  'Mailslot Functions
  Public Declare Unicode Function CreateMailslot Lib "kernel32" _
   Alias "CreateMailslotW" ( _
   ByVal lpName As String, _
   ByVal nMaxMessageSize As Integer, _
   ByVal lReadTimeout As Integer, _
   ByRef lpSecurityAttributes As SECURITY_ATTRIBUTES) As IntPtr
  Public Declare Function GetMailslotInfo Lib "kernel32" ( _
   ByVal hMailslot As IntPtr, _
   ByRef lpMaxMessageSize As Integer, _
   ByRef lpNextSize As Integer, _
   ByRef lpMessageCount As Integer, _
   ByRef lpReadTimeout As Integer) As Boolean

  'Handle and Object Functions
  Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As IntPtr) As Boolean

  Public hMailSlotHandle As IntPtr

  Public Function MakeMailSlot(ByVal lpszSlotName As String) As Boolean
    'ПРИЕМНИК(сервер) ф-ция создает MailSlot с именем lpszSlotName
    'невозможно создать более одного MailSlot с заданным именем
    Dim m_tSA As SECURITY_ATTRIBUTES

    If Strings.Len(lpszSlotName) = 0 Then
      ' No slotname
      hMailSlotHandle = INVALID_HANDLE_VALUE
      MakeMailSlot = False
      Exit Function
    End If

    ' The handle to the slot
    hMailSlotHandle = CreateMailslot(lpszSlotName, 0, 0, m_tSA)

    MakeMailSlot = (hMailSlotHandle <> INVALID_HANDLE_VALUE)
  End Function

  Public Sub CloseMailSlot()
    'ПРИЕМНИК(сервер) ф-ция уничтожает MailSlot
    'При этом все непрочитанные сообщения также уничтожаются
    'При закрытии приложения (включая принудительное типа End Task/kill) MailSlot и сообщения также уничтожатся
    If hMailSlotHandle <> INVALID_HANDLE_VALUE Then
      CloseHandle(hMailSlotHandle)
      hMailSlotHandle = INVALID_HANDLE_VALUE
    End If
  End Sub

  Public Function MailSlotReadFirst(ByRef m_Message As String, ByRef m_MsgCount As Integer) As Boolean
    'ПРИЕМНИК(сервер) ф-ция читает первое сообщение если есть
    'возвращает True, если есть хотя бы одно и оно было прочитано
    'm_Message (Out)-текст сообщения, если прочли
    'm_MsgCount -к-во сообщений оставшихся после чтения (без учета прочитанного)

    MailSlotReadFirst = False

    Dim lBufferSize As Integer
    m_Message = ""
    m_MsgCount = 0
    GetMailslotInfo(hMailSlotHandle, 0, lBufferSize, m_MsgCount, 0)
    If m_MsgCount > 0 Then
      Dim sBuffer(lBufferSize - 1) As Byte

      ' Read data: optional параметры ф-ции не используем
      If ReadFile(hMailSlotHandle, sBuffer, lBufferSize, 0, IntPtr.Zero) Then
        Using mstream As New IO.MemoryStream(sBuffer)
          Using reader As New IO.StreamReader(mstream, System.Text.Encoding.Default, True)
            m_Message = reader.ReadToEnd()
          End Using
        End Using
        m_MsgCount = m_MsgCount - 1
        MailSlotReadFirst = True
      End If
    End If
  End Function

  Public Function SendMessageToMailSlot(ByVal sMessage As String, ByVal sMailSlot As String, _
   Optional ByVal bUTF8 As Boolean = True, Optional ByVal CPP As Boolean = False) As Boolean
    'ПЕРЕДАТЧИК(клиент)ф-ция отправляет сообщение sMessage серверу с именем sMailSlot
    'если сервер не запущен, то сообщение не отправляется
    'bUTF8 -кодировать в UTF8 CPP-если true, то добавлять '\0' в конце
    Dim hFile As IntPtr
    Dim m_tSA As SECURITY_ATTRIBUTES

    hFile = CreateFile(sMailSlot, _
                       GENERIC_WRITE, _
                       FILE_SHARE_READ, _
                       m_tSA, _
                       OPEN_EXISTING, _
                       FILE_ATTRIBUTE_NORMAL, _
                       IntPtr.Zero)
    If hFile = INVALID_HANDLE_VALUE Then Return False

    If CPP Then sMessage = sMessage & Chr(0) 'при отправке в VB не добавляем '\0'

    Dim buffer As Byte()
    If bUTF8 Then 'отправлять Юникод
      'Указываем всегда использовать BOM
      Dim pre As Byte() = System.Text.Encoding.UTF8.GetPreamble()
      Dim body As Byte() = System.Text.Encoding.UTF8.GetBytes(sMessage)
      ReDim buffer(pre.Length + body.Length - 1)
      Array.Copy(pre, buffer, pre.Length)
      Array.Copy(body, 0, buffer, pre.Length, body.Length)
      'System.Text.Encoding.UTF8.GetPreamble().Concat(System.Text.Encoding.UTF8.GetBytes(sMessage)).ToArray
    Else 'отправлять ANSI
      buffer = System.Text.Encoding.Default.GetBytes(sMessage)
    End If

    SendMessageToMailSlot = WriteFile(hFile, buffer, buffer.Length(), 0, IntPtr.Zero)
    CloseHandle(hFile)
  End Function
End Module



Bazile, спасибо.

bazileКонструктор FileStream позволяет передать дескриптор уже открытого потока. Затем FileStream можно передать StreamWriter/Reader. Попробуй так.
Там все методы с Intptr первым параметром "устаревшие" (компилятор подчеркивает).
Я попробовал интереса ради. Типа через задницу работает (отправка), но при этом вместо одного сообщения отправляется 2, первое пустое, а нужное приходит с задержкой в несколько секунд, уж не знаю чего там эта муть делает.
При попытке подсунуть имя mailslot-а в FileStream или StreamWriter всегда имеем:
Дополнительные сведения: FileStream не открывает устройства Win32, такие как логические диски и ленточные накопители. Избегайте использования "\\.\" в пути.

Через API WriteFile/ReadFile все работает как и положено четко.
Данный совет приписывать BOM к массиву байтов озвученную проблему "автоматики при приеме" решил.

====

По mailslot у меня один наверно вопрос еще.
Я использую таймер который запускает ф-цию ReadApplyMessages_MailSlot() раз в секунду (в коде формы, код под спойлером).
Т.е. время ожидания и обработки сообщения может затянуться (максимум на 1 секунду).
В принципе для моих целей это приемлимо, но все же.
В VB6 к сожалению с многопоточностью хреново.

По хорошему это надо крутить циклом в отдельном потоке.
Не подскажете как в .Net лучше сделать?
Есть еще опасения что при выполнении команд буду нарываться на ошибки типа "вы пытаетесь дорваться до чего-то что было создано в другом потоке", посему особо не горю желанием такие штуки сгоряча и без опыта имплементировать.
...
Рейтинг: 0 / 0
11.02.2015, 00:17
    #38876447
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
Дмитрий77Или что-то другое имелось в виду?
да
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
            MemoryStream m = new MemoryStream();
            using (StreamWriter w = new StreamWriter(m, Encoding.UTF8))
            {
                w.Write("bla-bla");
                w.Flush();
                long sz = m.Length;
                byte[] buf = m.GetBuffer();
            }

...
Рейтинг: 0 / 0
11.02.2015, 00:21
    #38876448
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
Дмитрий77Есть еще опасения что при выполнении команд буду нарываться на ошибки типа "вы пытаетесь дорваться до чего-то что было создано в другом потоке"

настоящий программист документацию не читает
...
Рейтинг: 0 / 0
11.02.2015, 08:07
    #38876535
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
ИзопропилДмитрий77Или что-то другое имелось в виду?да
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
            MemoryStream m = new MemoryStream();
            using (StreamWriter w = new StreamWriter(m, Encoding.UTF8))
            {
                w.Write("bla-bla");
                w.Flush();
                long sz = m.Length;
                byte[] buf = m.GetBuffer();
            }


Уже подумал о том что MemoryStream можно использовать обратно с StreamWriter (по аналогии с распаковкой в строку).
Спасибо за код.

Тогда лучше думаю так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
    Dim buffer As Byte()
    Using mstream As New IO.MemoryStream()
      Using writer As New IO.StreamWriter(mstream, IIf(bUTF8, System.Text.Encoding.UTF8, System.Text.Encoding.Default))
        writer.Write(sMessage)
        writer.Flush()
        buffer = mstream.ToArray()
      End Using
    End Using



Иначе придется обрезать лишнее:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    Dim buffer As Byte()
    Using mstream As New IO.MemoryStream()
      Using writer As New IO.StreamWriter(mstream, IIf(bUTF8, System.Text.Encoding.UTF8, System.Text.Encoding.Default))
        writer.Write(sMessage)
        writer.Flush()
        buffer = mstream.GetBuffer()
        ReDim Preserve buffer(mstream.Length - 1)
        buffer = mstream.ToArray()
      End Using
    End Using



ИзопропилДмитрий77Есть еще опасения что при выполнении команд буду нарываться на ошибки типа "вы пытаетесь дорваться до чего-то что было создано в другом потоке"

настоящий программист документацию не читает

По MailSlot я документацию читал и примеры смотрел. Иначе б этот вопрос не возник.
Просто это делалось под VB6 и таймер был выбран как наиболее разумный способ чтения MailSlot (VB6 при создании потока через API крашит, поэтому научился обходиться без них).

.Net документацию по потокам - нет, не читал пока. Насколько понимаю, тема не очень тривиальная и с ней надо разбираться отдельно. Так что пока оставлю ту логику что есть, вопрос снимаю.
...
Рейтинг: 0 / 0
11.02.2015, 08:18
    #38876538
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
Вызов метода в UI потоке - control.Invoke - ничего сложного, код в форме от таймерного отличаться не будет

Массив из memoryStream - не твой - просто скопируй нужное количество байтов в свой массив
...
Рейтинг: 0 / 0
11.02.2015, 09:00
    #38876561
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
ИзопропилМассив из memoryStream - не твой - просто скопируй нужное количество байтов в свой массив
Ну.
А разве buffer = mstream.ToArray() именно это и не делает в одну строчку?
Просто все копирования mstream.GetBuffer() с учетом mstream.Length -оно ни чуть не менее муторней чем тупое сложение массивов System.Text.Encoding.UTF8.GetPreamble() и System.Text.Encoding.UTF8.GetBytes(sMessage) - изначальный вариант

ИзопропилВызов метода в UI потоке - control.Invoke - ничего сложного, код в форме от таймерного отличаться не будет
Что значит не будет? Получил я message, мне например надо: нажать кнопку на форме, выгрузить форму, поменять надпись на форме... выполнить какую нибудь public function из модуля, которая на эту форму ссылается и т.п. Это хорошо еще если я к этой форме только в режиме чтения обращаюсь, или просто какие-то левые дела в этом ново-потоке делаю.
А в общем случае это надо переписывать код, с отработкой заново всех потенциальных глюков.
Не, давай забьем пока эту тему.
...
Рейтинг: 0 / 0
11.02.2015, 10:28
    #38876645
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
Дмитрий77Что значит не будет?
Есть форме(контроле) метод.

без разницы - из таймера Invoke делать или из другого потока. Нет никаких глюков. В UI потоке будет вызываться
...
Рейтинг: 0 / 0
11.02.2015, 13:25
    #38876935
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как?
Вроде вот с WM_COPYDATA сделал по аналогии:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
Imports System.Runtime.InteropServices

Module ModuleCopyData
  Public Const WM_COPYDATA = &H4A

  <StructLayout(LayoutKind.Sequential)>
  Public Structure COPYDATASTRUCT
    Dim dwData As IntPtr ' additional 32 bit data to pass
    Dim cbData As Integer ' length in bytes of data pointed by lpData
    Dim lpData As IntPtr 'Byte() ' pointer to data to be passed to the receiving app. 
  End Structure

  Public Declare Unicode Function SendMessage_COPYDATASTRUCT Lib "user32" Alias "SendMessageW" _
   (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByRef lParam As COPYDATASTRUCT) As Integer

  Public Sub SendMessageCopyData(ByVal dwData As Integer, ByVal sMessage As String, ByVal hwndTarget As IntPtr, _
   Optional ByVal bUTF8 As Boolean = True, Optional ByVal AddZero As Boolean = False)
    'dwData -тип сообщения (например номер команды)
    'sMessage -текстовое сообщение
    'hwndTarget -окно - получатель сообщения
    'bUTF8 -кодировать в UTF8; AddZero-если true, то добавлять '\0' в конце

    If AddZero Then sMessage = sMessage & Chr(0) 'в VB6 при приеме иногда читал байты по указателю до символа '\0'

    Dim buffer As Byte()
    Using mstream As New IO.MemoryStream()
      Using writer As New IO.StreamWriter(mstream, IIf(bUTF8, System.Text.Encoding.UTF8, System.Text.Encoding.Default))
        writer.Write(sMessage)
        writer.Flush()
        buffer = mstream.ToArray()
      End Using
    End Using
    Dim cds As New COPYDATASTRUCT
    cds.dwData = CType(dwData, IntPtr) 'идентифицирует тип передаваемых данных
    cds.cbData = buffer.Length
    Dim lpData As IntPtr = Marshal.AllocHGlobal(buffer.Length)
    Marshal.Copy(buffer, 0, lpData, buffer.Length)
    cds.lpData = lpData

    Call SendMessage_COPYDATASTRUCT(hwndTarget, WM_COPYDATA, hwndTarget, cds)

    Marshal.FreeHGlobal(lpData)

  End Sub

End Module

'=====

Imports System.Runtime.InteropServices

Public Class Form1
  Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    'Debug.WriteLine(m.ToString())

    Select Case m.Msg
      Case WM_COPYDATA
        Dim the_str As String
        Dim cds As COPYDATASTRUCT = CType(Marshal.PtrToStructure(m.LParam, GetType(COPYDATASTRUCT)), COPYDATASTRUCT)
        Dim buffer(cds.cbData - 1) As Byte
        Marshal.Copy(cds.lpData, buffer, 0, cds.cbData)
        Using mstream As New IO.MemoryStream(buffer)
          Using reader As New IO.StreamReader(mstream, System.Text.Encoding.Default, True)
            the_str = reader.ReadToEnd()
          End Using
        End Using
        MsgBox(the_str & ";len=" & Strings.Len(the_str))
      Case Else
    End Select

    ' Forward message to base WndProc.
    MyBase.WndProc(m)
  End Sub

  Private Sub ButtonSendMeANSI_Click(sender As Object, e As EventArgs) Handles ButtonSendMeANSI.Click
    SendMessageCopyData(1, TextBoxSendMeANSI.Text, Me.Handle, False, False)
  End Sub

  Private Sub ButtonSendMeUNI_Click(sender As Object, e As EventArgs) Handles ButtonSendMeUNI.Click
    SendMessageCopyData(2, TextBoxSendMeUNI.Text, Me.Handle, True, False)
  End Sub
End Class



Но у меня получилось только с Dim lpData As IntPtr + Marshal.AllocHGlobal + Marshal.FreeHGlobal

А упрощенный вариант почему-то не работает.
Код: vbnet
1.
2.
3.
4.
5.
6.
  <StructLayout(LayoutKind.Sequential)>
  Public Structure COPYDATASTRUCT
    Dim dwData As IntPtr ' additional 32 bit data to pass
    Dim cbData As Integer ' length in bytes of data pointed by lpData
    Dim lpData As Byte() ' pointer to data to be passed to the receiving app.
  End Structure

Собственно код:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
  Public Structure COPYDATASTRUCT
    Dim dwData As IntPtr ' additional 32 bit data to pass
    Dim cbData As Integer ' length in bytes of data pointed by lpData
    Dim lpData As Byte() ' pointer to data to be passed to the receiving app.
  End Structure

  Public Sub SendMessageCopyData(ByVal dwData As Integer, ByVal sMessage As String, ByVal hwndTarget As IntPtr, _
   Optional ByVal bUTF8 As Boolean = True, Optional ByVal AddZero As Boolean = False)
    'dwData -тип сообщения (например номер команды)
    'sMessage -текстовое сообщение
    'hwndTarget -окно - получатель сообщения
    'bUTF8 -кодировать в UTF8; AddZero-если true, то добавлять '\0' в конце

    If AddZero Then sMessage = sMessage & Chr(0) 'в VB6 при приеме иногда читал байты по указателю до символа '\0'

    Dim cds As New COPYDATASTRUCT
    Using mstream As New IO.MemoryStream()
      Using writer As New IO.StreamWriter(mstream, IIf(bUTF8, System.Text.Encoding.UTF8, System.Text.Encoding.Default))
        writer.Write(sMessage)
        writer.Flush()
        cds.lpData = mstream.ToArray()
      End Using
    End Using
    cds.dwData = CType(dwData, IntPtr) 'идентифицирует тип передаваемых данных
    cds.cbData = cds.lpData.Length

    Call SendMessage_COPYDATASTRUCT(hwndTarget, WM_COPYDATA, hwndTarget, cds)

  End Sub

'---
  Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    'Debug.WriteLine(m.ToString())

    Select Case m.Msg
      Case WM_COPYDATA
        Dim the_str As String
        Dim cds As COPYDATASTRUCT = CType(Marshal.PtrToStructure(m.LParam, GetType(COPYDATASTRUCT)), COPYDATASTRUCT)
        Using mstream As New IO.MemoryStream(cds.lpData)
          Using reader As New IO.StreamReader(mstream, System.Text.Encoding.Default, True)
            the_str = reader.ReadToEnd()
          End Using
        End Using
        MsgBox(the_str & ";len=" & Strings.Len(the_str))
      Case Else
    End Select

    ' Forward message to base WndProc.
    MyBase.WndProc(m)
  End Sub


Т.е. он работает, но если посылать сообщение своему окну.
А если чужому, то lpData As Byte() в target не читается (ptr получает а содержимое отсутствует).

Для сравнения
Если писать Dim lpData As String, то работает (с оговоркой про ANSI/Unicode естественно)

В Mailslot+ReadFile/WriteFile,
ByVal lpBuffer As Byte() на ура прокатило без всяких IntPtr.

Где напортачил в нижнем коде? М.б.
<MarshalAs(UnmanagedType. ???> Dim lpData As Byte() какой нибудь надо подставить?
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Mailslot /SendMessage(WM_COPYDATA). Передача строк. Unicode или ANSI или все равно как? / 25 сообщений из 49, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]