EnumMonitors in c#

B

Brad M

Hi there,

I am trying to retrieve a list of installed printer port monitors, this
was relatively easy in c++, but I can't seem to figure out the API call
in c#.

From MSDN the API call is...

BOOL EnumMonitors(
LPTSTR pName, // [in] server name
DWORD Level, // [in] information level
LPBYTE pMonitors, // [out] monitor information buffer
DWORD cbBuf, // [in] size of monitor information buffer
LPDWORD pcbNeeded, // [out] bytes received or required
LPDWORD pcReturned // [out] number of monitors received
);

So I have translated this into c#(probably incorrectly) as...

[DllImport("winspool.drv", CharSet=CharSet.Auto,SetLastError=true)]
private static extern bool EnumMonitors(string pName, uint Level,
[Out] out byte[] pMonitors,uint cbBuf,
[Out] out uint cbNeeded,
[Out] out uint cbReturned);

I could be way off here, but I have been successfull at getting most of
the other printer API calls working this way.

Then try and call it...

byte[] buff = new byte[4098];
uint b,n,r;
b=4098;
n=0;
r=0;

if (!EnumMonitors(null,1,out buff,b,out n,out r))
{
System.ComponentModel.Win32Exception error = new
System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
Console.WriteLine(error.Message);
}
else
{
Console.WriteLine("Success");
}

This just seems to hang and not return...

I am not sure if I should use byte[] for pMonitors or create a new
struct for MONITOR_INFO_1.

Anyone out there like to point me in the right direction?



Regards,

Brad
 
M

Mattias Sjögren

[DllImport("winspool.drv", CharSet=CharSet.Auto,SetLastError=true)]
private static extern bool EnumMonitors(string pName, uint Level,
[Out] out byte[] pMonitors,uint cbBuf,
[Out] out uint cbNeeded,
[Out] out uint cbReturned);

Remove the out modifier on the pMonitors parameter.

I am not sure if I should use byte[] for pMonitors or create a new
struct for MONITOR_INFO_1.

Personally I'd use IntPtr as the pMonitors parameter type, then pass
in a buffer allocated with Marshal.Alloc*. Retrieve array elements
from the buffer with Marshal.PtrToStructure.



Mattias
 
B

Brad M

I think I am getting lost here, I have added the following structure...

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
private struct MONITOR_INFO_1
{
public string pName;
}

I am allocating some memory using

IntPtr buff = Marshal.AllocHGlobal((IntPtr)4098);

and then running...

uint b,n,r;
b=4098;
n=0;
r=0;
if (!EnumMonitors(null,1,ref buff,b,out n,out r))
{
System.ComponentModel.Win32Exception error = new
System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
Console.WriteLine(error.Message);
}
else
{
MONITOR_INFO_1[] m = new MONITOR_INFO_1[100];
Marshal.PtrToStructure(buff,m);
foreach (MONITOR_INFO_1 i in m)
{
Console.WriteLine(i.pName);
}
}
Marshal.FreeHGlobal(buff);

still no luck - I don't think I am correctly using
Marshal.PtrToStructure :-(




[DllImport("winspool.drv", CharSet=CharSet.Auto,SetLastError=true)]
private static extern bool EnumMonitors(string pName, uint Level,
[Out] out byte[] pMonitors,uint cbBuf,
[Out] out uint cbNeeded,
[Out] out uint cbReturned);


Remove the out modifier on the pMonitors parameter.


I am not sure if I should use byte[] for pMonitors or create a new
struct for MONITOR_INFO_1.


Personally I'd use IntPtr as the pMonitors parameter type, then pass
in a buffer allocated with Marshal.Alloc*. Retrieve array elements
from the buffer with Marshal.PtrToStructure.



Mattias
 
M

Mattias Sjögren

MONITOR_INFO_1[] m = new MONITOR_INFO_1[100];
Marshal.PtrToStructure(buff,m);

Unfortunately it's not that easy. You have to read element by element
with PtrToStructure, and increment the pointer by
Marshal.SizeOf(typeof(MONITOR_INFO_1)) for each.



Mattias
 

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