1

I have Win7 64bit. In my project, I'm using Win API functions from user32.dll for DDE communication. In MS VS2008, everything worked without problems, but now I'm trying to upgrade project to MS VS2012 (on the same PC and OS) and API function call leads to program crash.

It is specifically this function:

[DllImport("user32.dll", EntryPoint = "DdeAccessData", CharSet = CharSet.Ansi)]
    internal static extern string DdeAccessDataString(IntPtr p, out int datasize);

And it's call:

string result = Dde.DdeAccessDataString(da, out datasize);

I'm trying to debug it someway, but without success. I'm only able to to get message, that "Windows has triggered a breakpoint" on this line.

Can you suggest any approach how make it working?

Majak
  • 1,543
  • 1
  • 14
  • 28
  • Either x86 either x64 doesn't work in VS2012 build. – Majak Sep 21 '15 at 16:07
  • I forgot to mention that at the first, I tried to build it in VS2012 without .net framework change as .net 3.0 was previously set in VS2008 project settings. Unfortunately this also didn't help. – Majak Sep 21 '15 at 17:01
  • That's **very** strange... when you target .net framework 3.0 from VS2012 [you are actually using the VS2008 or VS2010 toolchain behind the scenes](http://stackoverflow.com/questions/2921702/change-c-cli-project-to-another-framework-than-4-0-with-vs2010). – yms Sep 21 '15 at 17:06
  • 4
    [DdeAccessData](https://msdn.microsoft.com/en-us/library/windows/desktop/ms648740.aspx) doesn't return a string, but a pointer to a byte array. The marshaler has no way of knowing, that the `LPBYTE` return value, and the `LPDWORD` size are somehow related. If you want to implement a utility function, that returns a `string` where appropriate, write a wrapper around it. Don't rely on the marshaler to fix up your bugs. – IInspectable Sep 21 '15 at 17:17

1 Answers1

1

You cannot use the return value of DdeAccessData directly, since the marshaller does not have a way to know the size of the data that is being returned.

I have not tested this, but something you can try instead is to use IntPtr as return value:

[DllImport("user32.dll", EntryPoint = "DdeAccessData")]
    internal static extern IntPtr DdeAccessData(IntPtr p, out int datasize);

Then use Marshal.ReadByte to retrieve the data.

IntPtr ptrByteArray = Dde.DdeAccessDataString(da, out datasize);
byte[] data = new byte[datasize];
for(int i =0; i < datasize; i++)
{
    data[i] = Marshal.ReadByte(ptrByteArray, i);
}
string result = System.Text.Encoding.ASCII.GetString(data);

You need to call DdeUnaccessData once you are done.

Dde.DdeUnaccessData(da);
yms
  • 10,361
  • 3
  • 38
  • 68