.NET Forum / .NET Framework / Interop / April 2004
SetPrinter Call
|
|
Thread rating:  |
Frank Jones - 24 Apr 2004 00:51 GMT We are trying to pause a printer from C# or VB code using the Win32 printer API's in the winspool.drv. We are having varying degrees of success. With the following VB code, the OpenPrinter call works, but we get an access denied error message upon calling SetPrinter. I have auditing turned on the printer and get no failure audits, so it is hard to imagine that this error message is correct
Dim strPrinterName As Strin strPrinterName = "Translator Image Printer Dim lngReturn As Lon Dim hPrinter As Lon Dim printDefaults As PRINTER_DEFAULT printDefaults.DesiredAccess = PRINTER_ALL_ACCES lngReturn = OpenPrinterA(strPrinterName, hPrinter, printDefaults If lngReturn <> 1 Or Err.LastDllError <> 0 The MsgBox "Could not open printer! En End I lngReturn = SetPrinterA(hPrinter, 0, 0, PrinterControlCodes.PrinterControlPause If lngReturn <> 1 Or Err.LastDllError <> 0 The Dim LangOptions As Lon LangOptions = &H Dim buffer As Strin buffer = Space(256 lngReturn = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0&, Err.LastDllError, LangOptions, buffer, Len(buffer), 0& MsgBox "Could not set printer: " & buffe End I lngReturn = ClosePrinter(hPrinter If lngReturn <> 1 The MsgBox "Could not close printer! End I
In the C# world, we cannot even get the OpenPrinter call to work. It always returns with 0 and the Marshal.GetLastWin32Error() returns 87. The following C# code is where we are having issues
string printerName = "Translator Image Printer" PrinterDefaults defaults = new PrinterDefaults() defaults.DesiredAccess = PrinterAccessRights.PRINTER_ALL_ACCESS
int printerHandle = 0 int returnValue = OpenPrinterA(printerName, printerHandle, defaults) if (returnValue == 1 Assert.AreEqual(0, Marshal.GetLastWin32Error(), String.Format("Marshal error #{0}: Could not open printer {1}", Marshal.GetLastWin32Error(), printerName)) els Assert.Fail(String.Format("Last error: {0}", Marshal.GetLastWin32Error()))
returnValue = SetPrinterA(printerHandle, 0, 0, PrinterControlCommands.PRINTER_CONTROL_PAUSE); //(both Level and Buffer are empty to send commands if (returnValue == 1 Assert.AreEqual(0, Marshal.GetLastWin32Error(), String.Format("Marshal error #{0}: Could not set printer {1}", Marshal.GetLastWin32Error(), printerName))
returnValue = ClosePrinter(printerHandle) if (returnValue == 1 Assert.AreEqual(0, Marshal.GetLastWin32Error(), String.Format("Marshal error #{0}: Could not close printer {1}", Marshal.GetLastWin32Error(), printerName))
Mainly, we are interested in getting the C# code to work, and used the VB code to troubleshoot the OpenPrinter/SetPrinter issues. Any ideas on what to checkout would be greatly appreciated..
Thanks Frank
"Ying-Shen Yu[MSFT]" - 26 Apr 2004 07:17 GMT Hi frank,
You may try the following C# snippet, it could open the "Microsoft Office Document Image Writer" on my system. For the "Access Denied" issue, I'm not clear about the reason, but if the problem also occurred on VB6, I think it's probably not caused by interop. would you meet this problem if you run this problem as administrator and then open a local printer ?
Thanks.
<code> private void button1_Click(object sender, System.EventArgs e) { string printerName = "Microsoft Office Document Image Writer"; PrinterDefaults defaults = new PrinterDefaults(); defaults.DesiredAccess = PrinterAccess.PrinterAllAccess;
IntPtr printerHandle; int returnValue = OpenPrinter(printerName, out printerHandle, ref defaults); if ( 1 == returnValue) { Debug.WriteLine(printerHandle.ToInt32().ToString()); ClosePrinter(printerHandle); } else { Debug.WriteLine(Marshal.GetLastWin32Error()); } }
public enum PrinterAccess { //from winspool.h ServerAdmin = 0x01, ServerEnum = 0x02, PrinterAdmin = 0x04, PrinterUse = 0x08, JobAdmin = 0x10, JobRead = 0x20, StandardRightsRequired = 0x000f0000, // from winnt.h PrinterAllAccess = (StandardRightsRequired | PrinterAdmin | PrinterUse) }
[StructLayout(LayoutKind.Sequential)] public struct PrinterDefaults { public IntPtr pDataType;// In this scenario, these two fields are not used public IntPtr pDevMode; public PrinterAccess DesiredAccess; }
[DllImport("winspool.drv")] private static extern int OpenPrinter(string printerName,out IntPtr phPrinter, ref PrinterDefaults printerDefaults);
[DllImport("winspool.drv")] public static extern int ClosePrinter(IntPtr phPrinter); </code>
Best regards,
Ying-Shen Yu [MSFT] Microsoft Community Support Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties and confers no rights. This mail should not be replied directly, please remove the word "online" before sending mail.
Frank Jones - 26 Apr 2004 22:16 GMT Hi Ying, this code snippet works great. In general, what is the best way to translate the Win32 API's into C# declares? I see so many examples on the internet showing incorrect declares. How can I tell, for example, to use IntPtr in the ClosePrinter call instead of a general int? How do I know when it's by reference or by an out parameter? Do you have a document describing Win32 API call from C# in depth that will cover these issues
Thanks Fran ----- "Ying-Shen Yu[MSFT]" wrote: ---- Hi frank You may try the following C# snippet, it could open the "Microsoft Office Document Image Writer" on my system. For the "Access Denied" issue, I'm not clear about the reason, but if the problem also occurred on VB6, I think it's probably not caused by interop. would you meet this problem if you run this problem as administrator and then open a local printer Thanks <code private void button1_Click(object sender, System.EventArgs e string printerName = "Microsoft Office Document Image Writer" PrinterDefaults defaults = new PrinterDefaults() defaults.DesiredAccess = PrinterAccess.PrinterAllAccess IntPtr printerHandle int returnValue = OpenPrinter(printerName, out printerHandle, ref defaults) if ( 1 == returnValue Debug.WriteLine(printerHandle.ToInt32().ToString()) ClosePrinter(printerHandle) else Debug.WriteLine(Marshal.GetLastWin32Error()) public enum PrinterAcces //from winspool. ServerAdmin = 0x01 ServerEnum = 0x02 PrinterAdmin = 0x04 PrinterUse = 0x08 JobAdmin = 0x10 JobRead = 0x20 StandardRightsRequired = 0x000f0000, // from winnt. PrinterAllAccess = (StandardRightsRequired | PrinterAdmin | PrinterUse [StructLayout(LayoutKind.Sequential) public struct PrinterDefault public IntPtr pDataType;// In this scenario, these two fields are not use public IntPtr pDevMode public PrinterAccess DesiredAccess [DllImport("winspool.drv") private static extern int OpenPrinter(string printerName,out IntPtr phPrinter, ref PrinterDefaults printerDefaults) [DllImport("winspool.drv") public static extern int ClosePrinter(IntPtr phPrinter) </code Best regards, Ying-Shen Yu [MSFT Microsoft Community Suppor Get Secure! - www.microsoft.com/securit This posting is provided "AS IS" with no warranties and confers no rights This mail should not be replied directly, please remove the word "online" before sending mail
"Ying-Shen Yu[MSFT]" - 27 Apr 2004 03:09 GMT Hi Frank,
I agree with you, to define a correct P/invoke definition for real scenario is not an easy job. Many issues may affect the final P/Invoke definition, such as memory allocation, data marshalling, and the default behavior of CLR marshaler etc.
Here is an article which gives an in-depth overview on the .NET interop. "An Overview of Managed/Unmanaged Code Interoperability" http://msdn.microsoft.com/netframework/default.aspx?pull=/library/en-us/dndo tnet/html/manunmancode.asp
For more in-depth information on P/Invoke as well as COM Interop. I recommend you read the book <.NET and COM: The Complete Interoperability Guide> by Adam Nathan. http://www.amazon.com/exec/obidos/ASIN/067232170X/102-9869026-1349709
And you may reach him at his blog: http://blogs.msdn.com/adam_nathan
Thanks, wish you good luck!
Best regards,
Ying-Shen Yu [MSFT] Microsoft Community Support Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties and confers no rights. This mail should not be replied directly, please remove the word "online" before sending mail.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|