By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,905 Members | 1,743 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,905 IT Pros & Developers. It's quick & easy.

Marshaling a string (and struct) for call to SendMessage

P: n/a
I am attempting to set the text on a richedit control in another application
using EM_SETTEXTEX:
http://msdn.microsoft.com/library/de..._settextex.asp

I have the following:

[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int
lParam);

[StructLayout(LayoutKind.Sequential)]
public struct SETEXTEX
{
public uint flags;
public uint codepage;
};
private void SetRichEditText(IntPtr hWnd, string text)
{
SETEXTEX setextex = new SETEXTEX();
setextex.codepage = 0;
setextex.flags = 0;
IntPtr ptr =
System.Runtime.InteropServices.Marshal.AllocCoTask Mem(System.Runtime.Interop
Services.Marshal.SizeOf(setextex.GetType()));
System.Runtime.InteropServices.Marshal.StructureTo Ptr(setextex, ptr,
true);
IntPtr sPtr = System.Runtime.InteropServices.Marshal.StringToBST R(text);
Win32API.SendMessage(hWnd, Messages.WM_USER+97, ptr.ToInt32(),
sPtr.ToInt32());
System.Runtime.InteropServices.Marshal.FreeCoTaskM em(ptr);
System.Runtime.InteropServices.Marshal.FreeBSTR(sP tr);
}

This code, while running without error, gives garbage in the richedit
control. If I change the StringToBSTR to StringToCoTaskMemAnsi or
StringToCoTaskMemAuto, then the other program crashes upon calling
SendMessage. Any ideas on what I'm doing wrong here?

--
Adam Clauss
ca*****@tamu.edu
Nov 16 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a
Adam,

You will have to find another way to marshal the string across the
process boundary. When you allocate memory in the local process, the
address that is returned is valid only in the local process. When you
transmit that value across the process boundary (which is what SendMessage
does, it only sends the pointer values, not the values the pointers point
to), the pointer is invalidated, because it is now in a different virtual
address space.

If you want to share some values, you will have to use another
mechanism, such as remoting, sockets, pipes, shared files, etc, etc.
Basically, you need some way of actually sending the bits that you want, and
not pointers to them.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Adam Clauss" <ca*****@tamu.edu> wrote in message
news:eM**************@TK2MSFTNGP10.phx.gbl...
I am attempting to set the text on a richedit control in another application using EM_SETTEXTEX:
http://msdn.microsoft.com/library/de..._settextex.asp
I have the following:

[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

[StructLayout(LayoutKind.Sequential)]
public struct SETEXTEX
{
public uint flags;
public uint codepage;
};
private void SetRichEditText(IntPtr hWnd, string text)
{
SETEXTEX setextex = new SETEXTEX();
setextex.codepage = 0;
setextex.flags = 0;
IntPtr ptr =
System.Runtime.InteropServices.Marshal.AllocCoTask Mem(System.Runtime.Interop Services.Marshal.SizeOf(setextex.GetType()));
System.Runtime.InteropServices.Marshal.StructureTo Ptr(setextex, ptr,
true);
IntPtr sPtr = System.Runtime.InteropServices.Marshal.StringToBST R(text); Win32API.SendMessage(hWnd, Messages.WM_USER+97, ptr.ToInt32(),
sPtr.ToInt32());
System.Runtime.InteropServices.Marshal.FreeCoTaskM em(ptr);
System.Runtime.InteropServices.Marshal.FreeBSTR(sP tr);
}

This code, while running without error, gives garbage in the richedit
control. If I change the StringToBSTR to StringToCoTaskMemAnsi or
StringToCoTaskMemAuto, then the other program crashes upon calling
SendMessage. Any ideas on what I'm doing wrong here?

--
Adam Clauss
ca*****@tamu.edu

Nov 16 '05 #2

P: n/a
Thats... not good. Is there no way to do this through SendMessage? I do not have control over the other app (its actually an
Windows Installer - I am trying to fill some info in on one of the pages). Since I obviously can't modify the installer itself, I
don't think I can use any of the other methods you mentioned can I?

--
Adam Clauss
ca*****@tamu.edu
"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote in message news:OI**************@TK2MSFTNGP12.phx.gbl...
Adam,

You will have to find another way to marshal the string across the
process boundary. When you allocate memory in the local process, the
address that is returned is valid only in the local process. When you
transmit that value across the process boundary (which is what SendMessage
does, it only sends the pointer values, not the values the pointers point
to), the pointer is invalidated, because it is now in a different virtual
address space.

If you want to share some values, you will have to use another
mechanism, such as remoting, sockets, pipes, shared files, etc, etc.
Basically, you need some way of actually sending the bits that you want, and
not pointers to them.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Adam Clauss" <ca*****@tamu.edu> wrote in message
news:eM**************@TK2MSFTNGP10.phx.gbl...
I am attempting to set the text on a richedit control in another

application
using EM_SETTEXTEX:

http://msdn.microsoft.com/library/de..._settextex.asp

I have the following:

[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam,

int
lParam);

[StructLayout(LayoutKind.Sequential)]
public struct SETEXTEX
{
public uint flags;
public uint codepage;
};
private void SetRichEditText(IntPtr hWnd, string text)
{
SETEXTEX setextex = new SETEXTEX();
setextex.codepage = 0;
setextex.flags = 0;
IntPtr ptr =

System.Runtime.InteropServices.Marshal.AllocCoTask Mem(System.Runtime.Interop
Services.Marshal.SizeOf(setextex.GetType()));
System.Runtime.InteropServices.Marshal.StructureTo Ptr(setextex, ptr,
true);
IntPtr sPtr =

System.Runtime.InteropServices.Marshal.StringToBST R(text);
Win32API.SendMessage(hWnd, Messages.WM_USER+97, ptr.ToInt32(),
sPtr.ToInt32());
System.Runtime.InteropServices.Marshal.FreeCoTaskM em(ptr);
System.Runtime.InteropServices.Marshal.FreeBSTR(sP tr);
}

This code, while running without error, gives garbage in the richedit
control. If I change the StringToBSTR to StringToCoTaskMemAnsi or
StringToCoTaskMemAuto, then the other program crashes upon calling
SendMessage. Any ideas on what I'm doing wrong here?

--
Adam Clauss
ca*****@tamu.edu


Nov 16 '05 #3

P: n/a
Hi Adam,

"Adam Clauss" <ca*****@tamu.edu> wrote in message
news:eQ**************@TK2MSFTNGP10.phx.gbl...
Thats... not good. Is there no way to do this through SendMessage? I do not have control over the other app (its actually an Windows Installer - I am trying to fill some info in on one of the pages). Since I obviously can't modify the installer itself, I don't think I can use any of the other methods you mentioned can I?


Just an FYI, if the installation package is an ".msi" file then you
*could* change it. Whether it is practical to do so is another matter, of
course. Windows Installer installation packages are actually stand-alone
databases (rather like Access .mdb files) with a specific set of tables.
There is a COM API for modifying the contents of the tables (Microsoft
Windows Installer Object Library: %windir%\system32\msi.dll).

Regards,
Daniel
Nov 16 '05 #4

P: n/a
Interesting, I'll have to look into that. It could greatly speed up some of what I am doing.

In the meantime, the workaround I just got working (not pretty, nor efficient, but it works) is to just repeatedly send WM_CHAR
messages to the richedit. Seems to have done the job. Fortunately, the strings I am sending are not too long.

--
Adam Clauss
ca*****@tamu.edu
"Daniel Pratt" <ko******************@hotmail.com> wrote in message news:%2****************@TK2MSFTNGP11.phx.gbl...
Hi Adam,

"Adam Clauss" <ca*****@tamu.edu> wrote in message
news:eQ**************@TK2MSFTNGP10.phx.gbl...
Thats... not good. Is there no way to do this through SendMessage? I do

not have control over the other app (its actually an
Windows Installer - I am trying to fill some info in on one of the pages).

Since I obviously can't modify the installer itself, I
don't think I can use any of the other methods you mentioned can I?


Just an FYI, if the installation package is an ".msi" file then you
*could* change it. Whether it is practical to do so is another matter, of
course. Windows Installer installation packages are actually stand-alone
databases (rather like Access .mdb files) with a specific set of tables.
There is a COM API for modifying the contents of the tables (Microsoft
Windows Installer Object Library: %windir%\system32\msi.dll).

Regards,
Daniel

Nov 16 '05 #5

P: n/a
"Adam Clauss" <ca*****@tamu.edu> wrote in message
news:OF**************@TK2MSFTNGP11.phx.gbl...
Interesting, I'll have to look into that. It could greatly speed up some of what I am doing.
In the meantime, the workaround I just got working (not pretty, nor efficient, but it works) is to just repeatedly send WM_CHAR messages to the richedit. Seems to have done the job. Fortunately, the strings I am sending are not too long.

Hi Adam,

Have a look at the WM_SETTEXT and (EM_SETTEXTEX for RTF) messages. And if
you want to replace part of the existing text, check the EM_SETSEL and
EM_REPLACESEL.

Another way of sending a string to this richedit would be to copy it to the
Clipboard and then send the WM_PASTE message to the window. But I do not
recommend this way, because your string may get corrupted by other apps or
user activities.

Regards,

Stoil

--
Adam Clauss
ca*****@tamu.edu
"Daniel Pratt" <ko******************@hotmail.com> wrote in message

news:%2****************@TK2MSFTNGP11.phx.gbl...
Hi Adam,

"Adam Clauss" <ca*****@tamu.edu> wrote in message
news:eQ**************@TK2MSFTNGP10.phx.gbl...
Thats... not good. Is there no way to do this through SendMessage? I
do not have control over the other app (its actually an
Windows Installer - I am trying to fill some info in on one of the
pages). Since I obviously can't modify the installer itself, I
don't think I can use any of the other methods you mentioned can I?


Just an FYI, if the installation package is an ".msi" file then you
*could* change it. Whether it is practical to do so is another matter, of course. Windows Installer installation packages are actually stand-alone
databases (rather like Access .mdb files) with a specific set of tables.
There is a COM API for modifying the contents of the tables (Microsoft
Windows Installer Object Library: %windir%\system32\msi.dll).

Regards,
Daniel



Nov 16 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.