2017-04-12 102 views
0

我有通过托管在IIS中的应用程序将pdf(从流生成)传输到网络打印机的场景。我尝试过使用PrintDocument.Print(),我遇到的问题是:1.文档正在排队等待大小为0字节的打印作业队列。 2.文档正在以拥有者名称作为machine_name排队到打印作业队列。 这里是我尝试使用PdfiumViewer(以从字节组的PrintDocument)和System.Drawing.Printing.PrintDocument的代码:如何通过托管在IIS中的应用程序打印到网络打印机

public void SendPdfToPrinter(byte[] byteArray, string fileName, string printerNetworkPath) 
    { 
     using (Stream fileStream = new MemoryStream(byteArray)) //byte array for the file content 
     { 

      var printerSettings = new System.Drawing.Printing.PrinterSettings 
      { 
       PrinterName = printerNetworkPath, //this is the printer full name. i.e. \\10.10.0.12\ABC-XEROX-01 
       PrintFileName = fileName, //file name. i.e. abc.pdf 
       PrintRange = System.Drawing.Printing.PrintRange.AllPages, 
      }; 
      printerSettings.DefaultPageSettings.Margins = new System.Drawing.Printing.Margins(0, 0, 0, 0); 

      // Now print the PDF document 
      using (PdfiumViewer.PdfDocument document = PdfiumViewer.PdfDocument.Load(fileStream)) 
      { 
       using (System.Drawing.Printing.PrintDocument printDocument = document.CreatePrintDocument()) 
       { 
        printDocument.DocumentName = fileName; 
        printDocument.PrinterSettings = printerSettings; 
        printDocument.PrintController = new System.Drawing.Printing.StandardPrintController(); 
        printDocument.Print(); 
       } 
      } 

回答

0

对于这两个问题,回答是模拟用户做印刷。

在我的情况下,应用程序池在LocalSystem帐户下运行,显然这不是域用户,而打印机仅暴露给域用户。

注:应用程序池是64位,如果使用32位,你将面对另一组的挑战,这也说明如下: https://blogs.msdn.microsoft.com/winsdk/2015/05/19/printing-successfully-using-impersonation-from-a-32-bit-application-on-a-64-bit-system/

下面是做域用户冒充其所需的代码:

[PermissionSet(SecurityAction.Demand, Name = "FullTrust")] 
public class Impersonation : IDisposable 
{ 
    private readonly SafeTokenHandle _handle; 
    private readonly WindowsImpersonationContext _context; 
    bool disposed = false; 

    const int LOGON32_PROVIDER_DEFAULT = 0; 
    const int LOGON32_LOGON_INTERACTIVE = 2; 

    public Impersonation(ImpersonateUserDetails user) : this(user.Domain, user.UserName, user.Password) 
    { } 
    public Impersonation(string domain, string username, string password) 
    { 
     var ok = LogonUser(username, domain, password, 
         LOGON32_LOGON_INTERACTIVE, 0, out this._handle); 
     if (!ok) 
     { 
      var errorCode = Marshal.GetLastWin32Error(); 
      throw new ApplicationException(string.Format("Could not impersonate the elevated user. LogonUser returned error code {0}.", errorCode)); 
     } 

     this._context = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle()); 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (disposed) 
      return; 

     if (disposing) 
     { 
      this._context.Dispose(); 
      this._handle.Dispose(); 
     }   
     disposed = true; 
    } 

    ~Impersonation() 
    { 
     Dispose(false); 
    } 


    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
    private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken); 

    sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid 
    { 
     private SafeTokenHandle() 
      : base(true) { } 

     [DllImport("kernel32.dll")] 
     [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
     [SuppressUnmanagedCodeSecurity] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     private static extern bool CloseHandle(IntPtr handle); 

     protected override bool ReleaseHandle() 
     { 
      return CloseHandle(handle); 
     } 
    } 
} 

public class ImpersonateUserDetails 
{ 
    public string UserName { get; set; } 

    public string Password { get; set; } 

    public string Domain { get; set; } 
} 
+0

它被测试,所以你可以依靠这个。谢谢 –

0

另一种可能的解决方法是将您的应用程序池标识配置为有权访问/允许在网络打印机中打印的自定义/域用户。

+0

它被测试,所以你可以依靠这个。谢谢 –

相关问题