Question on Marshaling

R

Rodger Higgins

I am trying marshal ReadMSgQueue on a Windows CE .NET platform. I am
using the following code:


....
[DllImport("Coredll.dll", SetLastError=true)]
public static extern bool ReadMsgQueue(
int hMsgQ,
out byte[] lpBuffer,
int cbBufferLen,
out byte[] lpNumberOfBytesRead,
int dwTimeout,
out byte[] dwFlags ) ;
....

if ( !MsgQueue.ReadMsgQueue( hReadMsgQueue, out msg, 64, len, 0, flags ) )
{
MessageBox.Show( "Err: " + MsgQueue.GetLastError() ) ;
}
else
{
Received.Items.Add( "OK" ) ;
UnicodeEncoding UEncoder = new UnicodeEncoding() ;
string msgString = UEncoder.GetString( msg, 0, msg.Length ) ;

MessageBox.Show( msgString ) ;
}


The Received.Items.Add causes a general exception if its located after
the call to ReadMsgQueue. It appears to be related to marshaling the
lpBuffer parameter. What am I missing or doing wrong?

Thanks
Rodger Higgins
 
A

Alex Feinman [MVP]

Change the PInvoke definition to:

DllImport("Coredll.dll", SetLastError=true)]
public static extern bool ReadMsgQueue(
int hMsgQ,
byte[] lpBuffer,
int cbBufferLen,
out int lpNumberOfBytesRead,
int dwTimeout,
out int dwFlags ) ;


Adjust your parameters accordingly.
 
R

Rodger Higgins

I tried your suggestion. Did not get the exception. But the message
contents did not appear in the buffer. The only way this will appear is
if I use ref or out. But then memory gets corrupted. I am deplying
this to the Windows CE emulator. I have attached the files...

Rodger Higgins



using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Data;
using System.Text;
using System.Runtime.InteropServices;
using MessageQueue ;

namespace MessageQueueMarshellExample
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class XTalkForm : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox Message;
private System.Windows.Forms.ListBox Received;
private System.Windows.Forms.Button SendBtn;
private System.Windows.Forms.Button Read;
private int hWriteMsgQueue = 0 ;
private int hReadMsgQueue = 0 ;

public XTalkForm()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
MsgQueueOptions mqo = new MsgQueueOptions() ;
mqo.dwSize = Marshal.SizeOf( mqo ) ;
mqo.dwFlags = MsgQueue.MSGQUEUE_ALLOW_BROKEN ;
mqo.dwMaxMessages = 5 ;
mqo.cbMaxMessage = 64 ;
mqo.bReadAccess = false ;
hWriteMsgQueue = MsgQueue.CreateMsgQueue( "Rodger", ref mqo ) ;
if ( hWriteMsgQueue == 0 )
{
MessageBox.Show( "Write Err: " + MsgQueue.GetLastError() ) ;
}

mqo.bReadAccess = true ;
hReadMsgQueue = MsgQueue.CreateMsgQueue( "Rodger", ref mqo ) ;
if ( hReadMsgQueue == 0 )
{
MessageBox.Show( "Read Err: " + MsgQueue.GetLastError() ) ;
}
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Message = new System.Windows.Forms.TextBox();
this.SendBtn = new System.Windows.Forms.Button();
this.Received = new System.Windows.Forms.ListBox();
this.Read = new System.Windows.Forms.Button();
//
// Message
//
this.Message.Location = new System.Drawing.Point(8, 7);
this.Message.Size = new System.Drawing.Size(184, 22);
this.Message.Text = "Message Here";
//
// SendBtn
//
this.SendBtn.Location = new System.Drawing.Point(216, 8);
this.SendBtn.Text = "Send";
this.SendBtn.Click += new System.EventHandler(this.SendBtn_Click);
//
// Received
//
this.Received.Location = new System.Drawing.Point(8, 40);
this.Received.Size = new System.Drawing.Size(184, 142);
//
// Read
//
this.Read.Location = new System.Drawing.Point(216, 40);
this.Read.Text = "Read";
this.Read.Click += new System.EventHandler(this.Read_Click);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
//
// XTalkForm
//
this.ClientSize = new System.Drawing.Size(314, 192);
this.Controls.Add(this.Read);
this.Controls.Add(this.Received);
this.Controls.Add(this.SendBtn);
this.Controls.Add(this.Message);
this.Text = "XTalk";

}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>

static void Main()
{
Application.Run(new XTalkForm());
}

private void SendBtn_Click(object sender, System.EventArgs e)
{
if ( hWriteMsgQueue != 0 )
{
UnicodeEncoding UEncoder = new UnicodeEncoding() ;
byte[] msg = UEncoder.GetBytes( Message.Text ) ;

if ( !MsgQueue.WriteMsgQueue( hWriteMsgQueue, ref msg, msg.Length, 0, 0 ) )
{
MessageBox.Show( "Err: " + MsgQueue.GetLastError() ) ;
}
}
}

private void Read_Click(object sender, System.EventArgs e)
{
if ( hReadMsgQueue != 0 )
{
byte[] msg = new byte[1024] ;
int len = 0 ;
int flags ;


if ( !MsgQueue.ReadMsgQueue( hReadMsgQueue, out msg, 64, out len, 0, out flags ) )
{
MessageBox.Show( "Err: " + MsgQueue.GetLastError() ) ;
}
else
{
Received.Items.Add( "OK" ) ;
UnicodeEncoding UEncoder = new UnicodeEncoding() ;
string msgString = UEncoder.GetString( msg, 0, msg.Length ) ;

MessageBox.Show( msgString ) ;
}
}
}
}
}

using System;
using System.Runtime.InteropServices;

namespace MessageQueue
{
/// <summary>
///
/// </summary>
public class MsgQueue
{
public const int MSGQUEUE_NOPRECOMMIT = 0x00000001 ;
public const int MSGQUEUE_ALLOW_BROKEN = 0x00000002 ;

public const int MSGQUEUE_MSGALERT = 0x00000001 ;

public MsgQueue()
{
//
// TODO: Add constructor logic here
//

}

public static int GetLastError()
{
return Marshal.GetLastWin32Error() ;
}

[DllImport("Coredll.dll", SetLastError=true)]
public static extern int CreateMsgQueue(
string lpMsgQueueName,
ref MsgQueueOptions lpOptions ) ;

[DllImport("Coredll.dll", SetLastError=true)]
public static extern bool WriteMsgQueue(
int hMsgQ,
ref byte[] lpBuffer,
int cbDataSize,
int dwTimeout,
int dwFlags ) ;

[DllImport("Coredll.dll", SetLastError=true)]
public static extern bool ReadMsgQueue(
int hMsgQ,
out byte[] lpBuffer,
int cbBufferLen,
out int lpNumberOfBytesRead,
int dwTimeout,
out int dwFlags ) ;
}

public struct MsgQueueOptions
{
public int dwSize ;
public int dwFlags ;
public int dwMaxMessages ;
public int cbMaxMessage ;
public bool bReadAccess ;
}



}
 
A

Alex Feinman [MVP]

You cannot use ref or out with byte[] parameters as this results in the
address of an internal object (and not the buffer itself) passed to the
unmanaged code.

For an example of using ReadMsgQueue from managed code see my sample of
PM-aware application:
http://www.alexfeinman.com/download.asp?doc=PowerAwareApp.zip



--
Alex Feinman
---
Visit http://www.opennetcf.org
Rodger Higgins said:
I tried your suggestion. Did not get the exception. But the message
contents did not appear in the buffer. The only way this will appear is
if I use ref or out. But then memory gets corrupted. I am deplying
this to the Windows CE emulator. I have attached the files...

Rodger Higgins




----------------------------------------------------------------------------
----


using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Data;
using System.Text;
using System.Runtime.InteropServices;
using MessageQueue ;

namespace MessageQueueMarshellExample
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class XTalkForm : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox Message;
private System.Windows.Forms.ListBox Received;
private System.Windows.Forms.Button SendBtn;
private System.Windows.Forms.Button Read;
private int hWriteMsgQueue = 0 ;
private int hReadMsgQueue = 0 ;

public XTalkForm()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
MsgQueueOptions mqo = new MsgQueueOptions() ;
mqo.dwSize = Marshal.SizeOf( mqo ) ;
mqo.dwFlags = MsgQueue.MSGQUEUE_ALLOW_BROKEN ;
mqo.dwMaxMessages = 5 ;
mqo.cbMaxMessage = 64 ;
mqo.bReadAccess = false ;
hWriteMsgQueue = MsgQueue.CreateMsgQueue( "Rodger", ref mqo ) ;
if ( hWriteMsgQueue == 0 )
{
MessageBox.Show( "Write Err: " + MsgQueue.GetLastError() ) ;
}

mqo.bReadAccess = true ;
hReadMsgQueue = MsgQueue.CreateMsgQueue( "Rodger", ref mqo ) ;
if ( hReadMsgQueue == 0 )
{
MessageBox.Show( "Read Err: " + MsgQueue.GetLastError() ) ;
}
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Message = new System.Windows.Forms.TextBox();
this.SendBtn = new System.Windows.Forms.Button();
this.Received = new System.Windows.Forms.ListBox();
this.Read = new System.Windows.Forms.Button();
//
// Message
//
this.Message.Location = new System.Drawing.Point(8, 7);
this.Message.Size = new System.Drawing.Size(184, 22);
this.Message.Text = "Message Here";
//
// SendBtn
//
this.SendBtn.Location = new System.Drawing.Point(216, 8);
this.SendBtn.Text = "Send";
this.SendBtn.Click += new System.EventHandler(this.SendBtn_Click);
//
// Received
//
this.Received.Location = new System.Drawing.Point(8, 40);
this.Received.Size = new System.Drawing.Size(184, 142);
//
// Read
//
this.Read.Location = new System.Drawing.Point(216, 40);
this.Read.Text = "Read";
this.Read.Click += new System.EventHandler(this.Read_Click);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
//
// XTalkForm
//
this.ClientSize = new System.Drawing.Size(314, 192);
this.Controls.Add(this.Read);
this.Controls.Add(this.Received);
this.Controls.Add(this.SendBtn);
this.Controls.Add(this.Message);
this.Text = "XTalk";

}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>

static void Main()
{
Application.Run(new XTalkForm());
}

private void SendBtn_Click(object sender, System.EventArgs e)
{
if ( hWriteMsgQueue != 0 )
{
UnicodeEncoding UEncoder = new UnicodeEncoding() ;
byte[] msg = UEncoder.GetBytes( Message.Text ) ;

if ( !MsgQueue.WriteMsgQueue( hWriteMsgQueue, ref msg, msg.Length, 0, 0 ) )
{
MessageBox.Show( "Err: " + MsgQueue.GetLastError() ) ;
}
}
}

private void Read_Click(object sender, System.EventArgs e)
{
if ( hReadMsgQueue != 0 )
{
byte[] msg = new byte[1024] ;
int len = 0 ;
int flags ;


if ( !MsgQueue.ReadMsgQueue( hReadMsgQueue, out msg, 64, out len, 0, out flags ) )
{
MessageBox.Show( "Err: " + MsgQueue.GetLastError() ) ;
}
else
{
Received.Items.Add( "OK" ) ;
UnicodeEncoding UEncoder = new UnicodeEncoding() ;
string msgString = UEncoder.GetString( msg, 0, msg.Length ) ;

MessageBox.Show( msgString ) ;
}
}
}
}
}


----------------------------------------------------------------------------
----


using System;
using System.Runtime.InteropServices;

namespace MessageQueue
{
/// <summary>
///
/// </summary>
public class MsgQueue
{
public const int MSGQUEUE_NOPRECOMMIT = 0x00000001 ;
public const int MSGQUEUE_ALLOW_BROKEN = 0x00000002 ;

public const int MSGQUEUE_MSGALERT = 0x00000001 ;

public MsgQueue()
{
//
// TODO: Add constructor logic here
//

}

public static int GetLastError()
{
return Marshal.GetLastWin32Error() ;
}

[DllImport("Coredll.dll", SetLastError=true)]
public static extern int CreateMsgQueue(
string lpMsgQueueName,
ref MsgQueueOptions lpOptions ) ;

[DllImport("Coredll.dll", SetLastError=true)]
public static extern bool WriteMsgQueue(
int hMsgQ,
ref byte[] lpBuffer,
int cbDataSize,
int dwTimeout,
int dwFlags ) ;

[DllImport("Coredll.dll", SetLastError=true)]
public static extern bool ReadMsgQueue(
int hMsgQ,
out byte[] lpBuffer,
int cbBufferLen,
out int lpNumberOfBytesRead,
int dwTimeout,
out int dwFlags ) ;
}

public struct MsgQueueOptions
{
public int dwSize ;
public int dwFlags ;
public int dwMaxMessages ;
public int cbMaxMessage ;
public bool bReadAccess ;
}



}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top