Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Interop / April 2004

Tip: Looking for answers? Try searching our database.

SetPrinter Call

Thread view: 
Enable EMail Alerts  Start New Thread
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.

Rate this thread:







Free Magazines

Get 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 ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.