How do i get the printer status

G

Gordon Truslove

I've been trying to get the printer status using GetPrinter and
Printer_Info_2

I'm getting closer, but it still fails.

Error 122 - The data area passed to a system call is too small.
---------------------------------------------------------------
[StructLayout( LayoutKind.Sequential,CharSet=CharSet.Auto)]

public struct PRINTERINFO2

{

[MarshalAs(UnmanagedType.LPTStr)]public string pServerName;

[MarshalAs(UnmanagedType.LPTStr)]public string pPrinterName;

[MarshalAs(UnmanagedType.LPTStr)]public string pShareName;

[MarshalAs(UnmanagedType.LPTStr)]public string pPortName;

[MarshalAs(UnmanagedType.LPTStr)]public string pDriverName;

[MarshalAs(UnmanagedType.LPTStr)]public string pComment;

[MarshalAs(UnmanagedType.LPTStr)]public string pLocation;

public IntPtr pDevMode;

[MarshalAs(UnmanagedType.LPTStr)]public string pSepFile;

[MarshalAs(UnmanagedType.LPTStr)]public string pPrintProcessor;

[MarshalAs(UnmanagedType.LPTStr)]public string pDatatype;

[MarshalAs(UnmanagedType.LPTStr)]public string pParameters;

public IntPtr pSecurityDescriptor;

public int Attributes;

public int Priority;

public int DefaultPriority;

public int StartTime;

public int UntilTime;

public int Status;

public int cJobs;

public int AveragePPM;

}

public class Printer

{

[ DllImport( "winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=false,

CallingConvention=CallingConvention.StdCall )]

public static extern long OpenPrinter(string pPrinterName,ref IntPtr
phPrinter, int pDefault);

[ DllImport(

"winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=true,

CallingConvention=CallingConvention.StdCall )]

public static extern long ClosePrinter(IntPtr hPrinter);

[ DllImport(

"winspool.drv" ,CharSet=CharSet.Auto)]

public static extern bool GetPrinter(IntPtr hPrinter,int Level,ref
PRINTERINFO2 pPrinter,int cbBuf,ref int pcbNeeded);

}

public class App

{

public static void Main ()

{

System.IntPtr lhPrinter=new System.IntPtr();

Printer.OpenPrinter("Epson EPL-5700",ref lhPrinter,0);

PRINTERINFO2 PI=new PRINTERINFO2();

int Need=0;

Console.WriteLine(Printer.GetPrinter(lhPrinter,2,ref
PI,Marshal.SizeOf(PI),ref Need));


Console.WriteLine("Error "+Marshal.GetLastWin32Error());


Printer.ClosePrinter(lhPrinter);

Console.ReadLine();

}

}
 
N

Nicholas Paldino [.NET/C# MVP]

Gordon,

Looking into this some more, the correct way to call GetPrinter is to
first make a call to see how big the buffer will be for the call.
Apparently, the pointers in the structure point to the areas right after the
structure itself. Because of this, you will have to take a different
approach.

First, you will have to find out how much memory you need. You do that
with a call to GetPrinter initially:

// Get the number of bytes needed.
Printer.GetPrinter(lhPrinter, 2, IntPtr.Zero, 0, ref Need);

Notice that I changed the declaration of the function so that the third
parameter takes an IntPtr. At this point, Need should have the number of
bytes needed. You can then allocate the memory needed.

// Allocate that in unmanaged memory.
IntPtr pintStruct = Marshal.AllocCoTaskMem(Need);

At this point, you can call GetPrinter again, getting the information:

// Now make the call again and get the bytes in memory.
int SizeOf = Need;
Printer.GetPrinter(lhPrinter, 2, pintStruct, SizeOf, ref Need);

Now you can marshal the structure from unmanaged memory:

// Now marshal the structure manually.
PI = (PRINTERINFO2) Marshal.PtrToStructure(pintStruct,
typeof(PRINTERINFO2));

At this point, all you have to do is free the unmanaged memory:

// Deallocate the memory.
Marshal.FreeCoTaskMem(pintStruct);

Mind you there is no error handling in this code. I'll leave that to
you.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Gordon Truslove said:
I've been trying to get the printer status using GetPrinter and
Printer_Info_2

I'm getting closer, but it still fails.

Error 122 - The data area passed to a system call is too small.
---------------------------------------------------------------
[StructLayout( LayoutKind.Sequential,CharSet=CharSet.Auto)]

public struct PRINTERINFO2

{

[MarshalAs(UnmanagedType.LPTStr)]public string pServerName;

[MarshalAs(UnmanagedType.LPTStr)]public string pPrinterName;

[MarshalAs(UnmanagedType.LPTStr)]public string pShareName;

[MarshalAs(UnmanagedType.LPTStr)]public string pPortName;

[MarshalAs(UnmanagedType.LPTStr)]public string pDriverName;

[MarshalAs(UnmanagedType.LPTStr)]public string pComment;

[MarshalAs(UnmanagedType.LPTStr)]public string pLocation;

public IntPtr pDevMode;

[MarshalAs(UnmanagedType.LPTStr)]public string pSepFile;

[MarshalAs(UnmanagedType.LPTStr)]public string pPrintProcessor;

[MarshalAs(UnmanagedType.LPTStr)]public string pDatatype;

[MarshalAs(UnmanagedType.LPTStr)]public string pParameters;

public IntPtr pSecurityDescriptor;

public int Attributes;

public int Priority;

public int DefaultPriority;

public int StartTime;

public int UntilTime;

public int Status;

public int cJobs;

public int AveragePPM;

}

public class Printer

{

[ DllImport( "winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=false,

CallingConvention=CallingConvention.StdCall )]

public static extern long OpenPrinter(string pPrinterName,ref IntPtr
phPrinter, int pDefault);

[ DllImport(

"winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=true,

CallingConvention=CallingConvention.StdCall )]

public static extern long ClosePrinter(IntPtr hPrinter);

[ DllImport(

"winspool.drv" ,CharSet=CharSet.Auto)]

public static extern bool GetPrinter(IntPtr hPrinter,int Level,ref
PRINTERINFO2 pPrinter,int cbBuf,ref int pcbNeeded);

}

public class App

{

public static void Main ()

{

System.IntPtr lhPrinter=new System.IntPtr();

Printer.OpenPrinter("Epson EPL-5700",ref lhPrinter,0);

PRINTERINFO2 PI=new PRINTERINFO2();

int Need=0;

Console.WriteLine(Printer.GetPrinter(lhPrinter,2,ref
PI,Marshal.SizeOf(PI),ref Need));


Console.WriteLine("Error "+Marshal.GetLastWin32Error());


Printer.ClosePrinter(lhPrinter);

Console.ReadLine();

}

}
 
G

Gordon Truslove

Great. I'm getting there. You can only check the status when the printer is
trying to print. Otherwise you just get status=0. So i'm working on some
kind of monitoring sysytem now.

Thanks.

Nicholas Paldino said:
Gordon,

Looking into this some more, the correct way to call GetPrinter is to
first make a call to see how big the buffer will be for the call.
Apparently, the pointers in the structure point to the areas right after the
structure itself. Because of this, you will have to take a different
approach.

First, you will have to find out how much memory you need. You do that
with a call to GetPrinter initially:

// Get the number of bytes needed.
Printer.GetPrinter(lhPrinter, 2, IntPtr.Zero, 0, ref Need);

Notice that I changed the declaration of the function so that the third
parameter takes an IntPtr. At this point, Need should have the number of
bytes needed. You can then allocate the memory needed.

// Allocate that in unmanaged memory.
IntPtr pintStruct = Marshal.AllocCoTaskMem(Need);

At this point, you can call GetPrinter again, getting the information:

// Now make the call again and get the bytes in memory.
int SizeOf = Need;
Printer.GetPrinter(lhPrinter, 2, pintStruct, SizeOf, ref Need);

Now you can marshal the structure from unmanaged memory:

// Now marshal the structure manually.
PI = (PRINTERINFO2) Marshal.PtrToStructure(pintStruct,
typeof(PRINTERINFO2));

At this point, all you have to do is free the unmanaged memory:

// Deallocate the memory.
Marshal.FreeCoTaskMem(pintStruct);

Mind you there is no error handling in this code. I'll leave that to
you.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Gordon Truslove said:
I've been trying to get the printer status using GetPrinter and
Printer_Info_2

I'm getting closer, but it still fails.

Error 122 - The data area passed to a system call is too small.
---------------------------------------------------------------
[StructLayout( LayoutKind.Sequential,CharSet=CharSet.Auto)]

public struct PRINTERINFO2

{

[MarshalAs(UnmanagedType.LPTStr)]public string pServerName;

[MarshalAs(UnmanagedType.LPTStr)]public string pPrinterName;

[MarshalAs(UnmanagedType.LPTStr)]public string pShareName;

[MarshalAs(UnmanagedType.LPTStr)]public string pPortName;

[MarshalAs(UnmanagedType.LPTStr)]public string pDriverName;

[MarshalAs(UnmanagedType.LPTStr)]public string pComment;

[MarshalAs(UnmanagedType.LPTStr)]public string pLocation;

public IntPtr pDevMode;

[MarshalAs(UnmanagedType.LPTStr)]public string pSepFile;

[MarshalAs(UnmanagedType.LPTStr)]public string pPrintProcessor;

[MarshalAs(UnmanagedType.LPTStr)]public string pDatatype;

[MarshalAs(UnmanagedType.LPTStr)]public string pParameters;

public IntPtr pSecurityDescriptor;

public int Attributes;

public int Priority;

public int DefaultPriority;

public int StartTime;

public int UntilTime;

public int Status;

public int cJobs;

public int AveragePPM;

}

public class Printer

{

[ DllImport( "winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=false,

CallingConvention=CallingConvention.StdCall )]

public static extern long OpenPrinter(string pPrinterName,ref IntPtr
phPrinter, int pDefault);

[ DllImport(

"winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=true,

CallingConvention=CallingConvention.StdCall )]

public static extern long ClosePrinter(IntPtr hPrinter);

[ DllImport(

"winspool.drv" ,CharSet=CharSet.Auto)]

public static extern bool GetPrinter(IntPtr hPrinter,int Level,ref
PRINTERINFO2 pPrinter,int cbBuf,ref int pcbNeeded);

}

public class App

{

public static void Main ()

{

System.IntPtr lhPrinter=new System.IntPtr();

Printer.OpenPrinter("Epson EPL-5700",ref lhPrinter,0);

PRINTERINFO2 PI=new PRINTERINFO2();

int Need=0;

Console.WriteLine(Printer.GetPrinter(lhPrinter,2,ref
PI,Marshal.SizeOf(PI),ref Need));


Console.WriteLine("Error "+Marshal.GetLastWin32Error());


Printer.ClosePrinter(lhPrinter);

Console.ReadLine();

}

}
 
G

Gordon Truslove

OK if anybody ever needs this. You can check the status by using
job=StartDocPrinter then StartPagePrinter then getprinter which will return
a status code, you can then remove the job usint setjob. This doesn't work
if another app has queued a job before this one.

Gordon Truslove said:
Great. I'm getting there. You can only check the status when the printer is
trying to print. Otherwise you just get status=0. So i'm working on some
kind of monitoring sysytem now.

Thanks.

message news:[email protected]...
Gordon,

Looking into this some more, the correct way to call GetPrinter is to
first make a call to see how big the buffer will be for the call.
Apparently, the pointers in the structure point to the areas right after the
structure itself. Because of this, you will have to take a different
approach.

First, you will have to find out how much memory you need. You do that
with a call to GetPrinter initially:

// Get the number of bytes needed.
Printer.GetPrinter(lhPrinter, 2, IntPtr.Zero, 0, ref Need);

Notice that I changed the declaration of the function so that the third
parameter takes an IntPtr. At this point, Need should have the number of
bytes needed. You can then allocate the memory needed.

// Allocate that in unmanaged memory.
IntPtr pintStruct = Marshal.AllocCoTaskMem(Need);

At this point, you can call GetPrinter again, getting the information:

// Now make the call again and get the bytes in memory.
int SizeOf = Need;
Printer.GetPrinter(lhPrinter, 2, pintStruct, SizeOf, ref Need);

Now you can marshal the structure from unmanaged memory:

// Now marshal the structure manually.
PI = (PRINTERINFO2) Marshal.PtrToStructure(pintStruct,
typeof(PRINTERINFO2));

At this point, all you have to do is free the unmanaged memory:

// Deallocate the memory.
Marshal.FreeCoTaskMem(pintStruct);

Mind you there is no error handling in this code. I'll leave that to
you.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Gordon Truslove said:
I've been trying to get the printer status using GetPrinter and
Printer_Info_2

I'm getting closer, but it still fails.

Error 122 - The data area passed to a system call is too small.
---------------------------------------------------------------
[StructLayout( LayoutKind.Sequential,CharSet=CharSet.Auto)]

public struct PRINTERINFO2

{

[MarshalAs(UnmanagedType.LPTStr)]public string pServerName;

[MarshalAs(UnmanagedType.LPTStr)]public string pPrinterName;

[MarshalAs(UnmanagedType.LPTStr)]public string pShareName;

[MarshalAs(UnmanagedType.LPTStr)]public string pPortName;

[MarshalAs(UnmanagedType.LPTStr)]public string pDriverName;

[MarshalAs(UnmanagedType.LPTStr)]public string pComment;

[MarshalAs(UnmanagedType.LPTStr)]public string pLocation;

public IntPtr pDevMode;

[MarshalAs(UnmanagedType.LPTStr)]public string pSepFile;

[MarshalAs(UnmanagedType.LPTStr)]public string pPrintProcessor;

[MarshalAs(UnmanagedType.LPTStr)]public string pDatatype;

[MarshalAs(UnmanagedType.LPTStr)]public string pParameters;

public IntPtr pSecurityDescriptor;

public int Attributes;

public int Priority;

public int DefaultPriority;

public int StartTime;

public int UntilTime;

public int Status;

public int cJobs;

public int AveragePPM;

}

public class Printer

{

[ DllImport( "winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=false,

CallingConvention=CallingConvention.StdCall )]

public static extern long OpenPrinter(string pPrinterName,ref IntPtr
phPrinter, int pDefault);

[ DllImport(

"winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=true,

CallingConvention=CallingConvention.StdCall )]

public static extern long ClosePrinter(IntPtr hPrinter);

[ DllImport(

"winspool.drv" ,CharSet=CharSet.Auto)]

public static extern bool GetPrinter(IntPtr hPrinter,int Level,ref
PRINTERINFO2 pPrinter,int cbBuf,ref int pcbNeeded);

}

public class App

{

public static void Main ()

{

System.IntPtr lhPrinter=new System.IntPtr();

Printer.OpenPrinter("Epson EPL-5700",ref lhPrinter,0);

PRINTERINFO2 PI=new PRINTERINFO2();

int Need=0;

Console.WriteLine(Printer.GetPrinter(lhPrinter,2,ref
PI,Marshal.SizeOf(PI),ref Need));


Console.WriteLine("Error "+Marshal.GetLastWin32Error());


Printer.ClosePrinter(lhPrinter);

Console.ReadLine();

}

}
 

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