0

Good afternoon,

I am attempting to use SendMessage to pass a string from a VB6 EXE, to a .NET 2013 EXE. I know that the message is getting in to the .NET EXE, because I'm able to set a breakpoint on it and it comes up when I call SendMessage from the VB6 EXE. The problem I am having is retrieving the string.

This is how I am attempting to do it:

VB6 Code:

Option Explicit

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dest As Any, Source As Any, ByVal bytes As Long)
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Long, ByVal msg As Long, wParam As Long, lParam As Any) As Long

Private Const APPVIEWER_OPEN = &H400

Private Sub Command1_Click()
  Dim hwndAppViewer As Long
  Dim bytBuffer(1 To 255) As Byte
  Dim sParams As String
  Dim lStringAddress As Long

  hwndAppViewer = FindWindow(vbNullString, "DotNetReceiver")

  If hwndAppViewer > 0 Then
    sParams = "STRINGDATA"
    CopyMemory bytBuffer(1), sParams, Len(sParams)
    lStringAddress = VarPtr(bytBuffer(1))
    SendMessage hwndAppViewer, APPVIEWER_OPEN, Me.hwnd, lStringAddress
  End If
End Sub

Here is the .NET code:

Imports System.Runtime.InteropServices

Public Class Form1
  Protected Overrides Sub WndProc(ByRef m As Message)
    Dim sPolicyInformation As String

    If m.Msg = &H400 Then
      sPolicyInformation = Marshal.PtrToStringAnsi(m.LParam)
    Else
      MyBase.WndProc(m)
    End If
  End Sub
End Class

The problem comes when I try and retrieve the string. I am getting a blank string. I noticed that the number in the VB6 lStringAddress and the number in .NET m.lParam are completely different, so I must be missing something about how I'm passing the address through lParam.

Any ideas what I might be missing?

Thank you.

3
  • To do what you want, I believe you need to use the RegisterWindowMessage function (see: msdn.microsoft.com/en-us/library/windows/desktop/…) to get a message number that may be transfered between applications. Then you would use PostMessage to HWND_BROADCAST (&HFFFF) to send the message. Both apps need to call RegisterWindowMessage with the same key to get the message number to watch for. Commented Jun 23, 2015 at 0:49
  • Instead of using SendMessage to shuffle around pointers to address space, you might consider using the WM_COPYDATA message instead, which is better suited to this case. Commented Jun 23, 2015 at 0:56
  • 1
    Pointers are only meaningful in their owning process address space. You need to marshal the data. WM_COPYDATA is your guy. Commented Jun 23, 2015 at 4:10

1 Answer 1

1

You are sending an ANSI string to VB.NET. VB6 was designed for all MS's OSs and 9x wasn't unicode. So all strings passed to API calls will be converted to ANSI. Windows will convert that ANSI string to unicode for the VB.NET program when it recieves it.

Use the sendmessagew function and send the first element of a byte array that's null terminated.

Dim MyStr() as byte
MyStr = "cat" & chrw(0)

The pass only the first element to SendMessageW ie MyStr(0). Windows API uses null terminated C strings. COM and VB6 use BStr (a size header and a non null terminated string).

When passing strings by ref you pass the address of the header. When passing by value you pass the address of the first character (making it a c string if you tack a null on the end).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.