2017-04-12 78 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

它被測試,所以你可以依靠這個。謝謝 –

相關問題