【问题标题】:Printing from ASP.NET to a network printer从 ASP.NET 打印到网络打印机
【发布时间】:2011-04-13 08:24:48
【问题描述】:

我需要将文档发送到网络打印机 (\myserver\myprinter)。我正在使用 System.Printing 类进行打印,当它来自 Windows 服务时,它工作正常,但来自 ASP.NET 应用程序,它只能打印到本地打印机,而不是网络打印机。我得到的错误是“打印机名称无效”这是我用来获取打印机名称的:

public string PrinterName
{
   using (LocalPrintServer server = new LocalPrintServer())
   return server.GetPrintQueue(@"\\myserver\myprinter");
}

我在这里有什么选择?这是权限问题吗?

【问题讨论】:

  • ASP.NET 在哪个用户环境下运行?你在使用模拟吗?打印机的权限是什么?
  • 它在 ASP.NET 开发服务器中运行,所以我假设它在我的 Windows 帐户下运行。我可以直接从记事本打印到该服务器打印机。

标签: c# .net asp.net printing system.printing


【解决方案1】:

可以使用 ASP.Net/C# 进行网络打印:

如果为域用户配置了网络并将打印机添加到打印服务器:

  • PrinterName 定义为 = "\\PrintServerIP_OR_Name\\PRINTERNAME" 示例:PrinterSettings.PrinterName = "\\15.1.1.1\\prn001"
  • 检查打印机访问权限集
  • 域用户或所有人
  • 如果是域用户,则可以将 C# 代码包含在可用于调用打印代码的模拟中,如下所示:
/// <summary>
    /// Does the actual impersonation.
    /// </summary>
    /// <param name="userName">The name of the user to act as.</param>
    /// <param name="domainName">The domain name of the user to act as.</param>
    /// <param name="password">The password of the user to act as.</param>
    private void ImpersonateValidUser(
        string userName, 
        string domain, 
        string password )
    {
        WindowsIdentity tempWindowsIdentity = null;
        IntPtr token = IntPtr.Zero;
        IntPtr tokenDuplicate = IntPtr.Zero;

        try
        {
            if ( RevertToSelf() )
            {
                if ( LogonUser(
                    userName, 
                    domain, 
                    password, 
                    LOGON32_LOGON_INTERACTIVE,
                    LOGON32_PROVIDER_DEFAULT, 
                    ref token ) != 0 )
                {
                    if ( DuplicateToken( token, 2, ref tokenDuplicate ) != 0 )
                    {
                        tempWindowsIdentity = new WindowsIdentity( tokenDuplicate );
                        impersonationContext = tempWindowsIdentity.Impersonate();
                    }
                    else
                    {
                        throw new Win32Exception( Marshal.GetLastWin32Error() );
                    }
                }
                else
                {
                    throw new Win32Exception( Marshal.GetLastWin32Error() );
                }
            }
            else
            {
                throw new Win32Exception( Marshal.GetLastWin32Error() );
            }
        }
        finally
        {
            if ( token!= IntPtr.Zero )
            {
                CloseHandle( token );
            }
            if ( tokenDuplicate!=IntPtr.Zero )
            {
                CloseHandle( tokenDuplicate );
            }
        }
    }

    /// <summary>
    /// Reverts the impersonation.
    /// </summary>
    private void UndoImpersonation()
    {
        if ( impersonationContext!=null )
        {
            impersonationContext.Undo();
        }   
    }

    private WindowsImpersonationContext impersonationContext = null;

首先调用模拟用户,然后调用如下所示的打印函数:

if(ImpersonateValidUser("username", "domain", "password"))
{
  PrintDetails();
  UndoImpersonation();
}

【讨论】:

    【解决方案2】:

    您可以通过模拟或提升运行 Web 应用程序的用户的权限来解决凭据问题。

    但是,我们通过将网络打印机添加为服务器上的打印机(在服务器上添加打印机对话)并将作业发送到该打印机来实现。

    我们像这样使用 Printing.PrintDocument(VB 中的代码)....

    Public Class SpecialReportPrintJob
      Inherits Printing.PrintDocument
    
    Protected Overrides Sub OnBeginPrint(ByVal ev as Printing.PrintEventArgs)
      MyBase.OnBeginPrint(ev)
    
      Me.PrinterSettings.PrinterName = "PrinterNameUsedOnServer"
    
      'setup rest of stuff....
    End Sub  
    End Class
    'And we then call it like so
    Dim printSpecialReport as new SpecialReportPrintJob()
    printSpecialReport.Print()
    

    【讨论】:

    • 那么我可以使用 \\myserver\myprinter 作为 PrinterName 吗?
    • 我们忽略了 \\myserver\。我们在服务器上命名它的另一个词就是我们如何称呼它。没有 UNC 路径或任何东西。
    • 哦,好吧..所以您的意思是您将网络打印机安装为本地打印机?
    • 它仍然是一台网络打印机,但是当我们创建打印机时,我们选择了本地打印机,但随后使用了一个新端口,即 IP 地址。 AKA - 选择本地,然后在使用打印机端口的选项上不要使用 LPT1 等,针对盒子的 IP 创建一个新端口。它对我们很有用....
    • 好的,所以我需要从我们的管理员那里获取将映射到 \\myserver\myprinter 的 IP 地址?我还需要安装驱动程序?
    【解决方案3】:

    默认情况下,ASP.NET 应用程序在具有有限权限的特殊帐户上运行。只够服务网页,仅此而已。所以你必须配置 ASPNET 用户。

    相比之下,Windows 服务通常在本地系统帐户下运行(具有高权限)

    【讨论】:

    • 谢谢...你知道我如何配置它以赋予它足够的权限吗?
    • 谢谢。我检查了它在 Windows 窗体应用程序中也不起作用。
    • @Prabhu:我不熟悉 GetPrintQueue,但我确实注意到您正在立即销毁 server。你确定这个确切的代码确实在服务中运行吗?
    • 您的 WinForms 应用程序用户是否有权使用网络打印机?我们似乎仍然不知道。
    • 我仍在尝试弄清楚如何检查。
    猜你喜欢
    • 2012-05-28
    • 2017-04-21
    • 1970-01-01
    • 2011-04-12
    • 2012-11-02
    • 2013-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多