System.ExecutionEngineException during a P/Invoke call

T

Tom Hellstrom

Hello, I'm trying to make a program that talks to the printerspooler in .net.
Currently the only way seems to be to go through P/Invoke calls to the win32
API. Thing is I get this error when I try to retrieve a job from the spooler.

An unhandled exception of type 'System.ExecutionEngineException' occurred.

The offending code in question is in C#:

int antalBytes = 0;
JobInfo1 pJob = new JobInfo1();
GetJob(printerhandle, jobid, 1, ref pJob, 0, out antalBytes);
GetJob(printerhandle, jobid, 1, ref pJob, antalBytes, out antalBytes);

It's the second call to GetJob that goes wrong apparently. The first call to
GetJob just fills out antalBytes with the number of bytes needed for the second
call. The second call fills in pJob (a struct) with various data, both int's
and strings. The thing is that in the debugger I can look into the struct
after the call, and all fields are populated with the correct data (or atleast
it looks like correct data).

I've found something about a bug in .net that might be related, not sure though.
http://support.microsoft.com/default.aspx?scid=kb;en-us;327106

I've tried to Marshal the strings as:
[MarshalAs(UnmanagedType.LPStr)] public String pPrinterName;
and:
[MarshalAs(UnmanagedType.LPTStr)] public String pPrinterName;
and:
public string pPrinterName;

all give the error. I'm not even sure that is the problem.

Some additional code that might be interesting:

[DllImport("winspool.drv", EntryPoint="GetJobA",
SetLastError=true, CharSet=CharSet.Ansi,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool GetJob(
int hPrinter, // handle to printer
int JobId, // job identifier
int Level, // information level
ref JobInfo1 pJob, // job to return
int cbBuf, // bytes in array
out int pcbNeeded // bytes received or required
);

and some info on GetJob:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/prntspol_2uci.asp

Any ideas?
 
M

Mattias Sjögren

Tom,
It's the second call to GetJob that goes wrong apparently. The first call to
GetJob just fills out antalBytes with the number of bytes needed for the second
call. The second call fills in pJob (a struct) with various data, both int's
and strings.

Right, but you're claiming that your structure is antalBytes bytes
large in the second call, when it most likely isn't (antalBytes
includes the space needed for the strings). Since antalBytes can vary,
you need to dynamically allocate enough memory with one of the
Marshal.Alloc* methods, pass that buffer to the API, and then retrieve
the structure with Marshal.PtrToStructure.




Mattias
 
T

Tom Hellström

Mattias Sjögren said:
Tom,


Right, but you're claiming that your structure is antalBytes bytes
large in the second call, when it most likely isn't (antalBytes
includes the space needed for the strings). Since antalBytes can vary,
you need to dynamically allocate enough memory with one of the
Marshal.Alloc* methods, pass that buffer to the API, and then retrieve
the structure with Marshal.PtrToStructure.




Mattias

Thank you thank you thank you!

Using Marshal.AllocHGlobal solved the problem.

Excellent advise.

///. Tom H
 

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