Marshal Win32 API EnumPorts Printer 
Author Message
 Marshal Win32 API EnumPorts Printer

Dear community,
I read a lot about marshaling, pinvoke, etc. but I can't see the trees
in the forest....

My problem:
would like enum local printer ports with Win32 API call: EnumPorts.
There are nice PORT_INFO structs with data. In VC++ I have to call
EnumPorts twice. First to get the size of returned buffer, and second
to get the filled buffer, type cast and finish.

How doest it work in C#?
Does anyone help me with this problem?

Thank you
Micha

Here a code snip - (incomplete)

[StructLayout(LayoutKind.Sequential)]  
public struct PORT_INFO_1
{
        [MarshalAs(UnmanagedType.LPTStr)]
        public string pName;

Quote:
}

[DllImport("winspool.drv")]
static extern bool EnumPorts(string pName, int level,
[MarshalAs(UnmanagedType.Struct)] ref PORT_INFO_1 pi, int cbBuf, out
int pcbNeeded, out int pcReturned);

public bool GetPorts(out ArrayList portslist)
{
        int pcReturned;
        int pcbNeeded;
        PORT_INFO_1 pi = new PORT_INFO_1();

        // first call to get the size of returnd buffer (pcbNeeded)    
        EnumPorts(null, 1, ref pi, 0, out pcbNeeded, out pcReturned);

        // second call to get filled struct -> here
        // error "System.ExecutionEngineException"            
        EnumPorts(null, 1, ref pi, pcbNeeded, out pcbNeeded, out pcReturned);



Tue, 02 Nov 2004 17:46:07 GMT  
 Marshal Win32 API EnumPorts Printer
Michael,

microsoft.public.dotnet.framework.interop is a better group for
P/Invoke questions.

Since the function returns a variable amount of data, the best
solution is probably to declare the array parameter as an IntPtr. You
then allocate a chunk of unmanaged memory with Marshal.AllocHGlobal(),
call the function, then use Marshal.PtrToStructure() to reatrieve each
array member after the call.

Mattias

===
Mattias Sj?gren (VB MVP)

http://www.msjogren.net/dotnet/



Tue, 02 Nov 2004 19:20:26 GMT  
 Marshal Win32 API EnumPorts Printer
Mattias,
thank you - this was the key...

The solution is:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]  
struct PORT_INFO_1
{
        [MarshalAs(UnmanagedType.LPTStr)]
        public string pName;

Quote:
}

[DllImport("winspool.drv", CharSet=CharSet.Auto)]
static extern bool EnumPorts(string pName, int level, IntPtr bufptr,
int cbBuf, out int pcbNeeded, out int pcReturned);

...

int pcReturned = 0;
int pcbNeeded = 0;
IntPtr outb = IntPtr.Zero;

EnumPorts(null, 1, outb, 0, out pcbNeeded, out pcReturned);
outb = Marshal.AllocHGlobal(pcbNeeded+1);
EnumPorts(null, 1, outb, pcbNeeded, out pcbNeeded, out pcReturned);
PORT_INFO_1[] manyArr = new PORT_INFO_1[pcReturned];

IntPtr current = outb;
for (int i=0; i<pcReturned; i++)
{
        manyArr[i] = (PORT_INFO_1) Marshal.PtrToStructure(current,
typeof(PORT_INFO_1));
        current=(IntPtr)((int)current+Marshal.SizeOf(typeof(PORT_INFO_1)));

Quote:
}

Marshal.FreeHGlobal(outb);
...

Micha



Sat, 06 Nov 2004 17:29:16 GMT  
 
 [ 3 post ] 

 Relevant Pages 

1. Problems Setting the Default printer with Win32 API SDK

2. Marshal..marshaling..

3. EnumPort?

4. REWARD OFFERED --Win32 printer scaling problem

5. Print on Irda printer throught win32

6. PRINTER API under NT4 & VC5

7. How to Get Printer/Job Status by Win API

8. How to Get Printer/Job Status by Win API

9. win API: NT/Win95 printer compatibilty problems

10. Windows 32 API calls - Printers -

11. ::PostMessage Win32 API equivalent??

12. .NET classes win32 api reference

 

 
Powered by phpBB® Forum Software