Печать с ASP.NET на сетевой принтер

Мне нужно отправить документы на сетевой принтер (\ myserver\myprinter). Я использую классы System.Printing для печати, и он отлично работает, когда он работает с Windows Service, но из приложения ASP.NET, он способен печатать только на локальные принтеры, а не на сетевые принтеры. Ошибка, которую я получаю, это "Имя принтера недействительно". Это то, что я использую, чтобы получить имя принтера:

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

Каковы мои варианты здесь? Это проблема с разрешениями?

Ответ 1

Есть проблемы с учетными данными, которые вы можете решить путем олицетворения или повышения прав пользователя, в котором работает веб-приложение.

Однако мы сделали это, добавив сетевой принтер в качестве принтера на сервере (добавьте диалог принтера на сервер) и выполнив задание, отправленное на этот принтер.

Мы использовали Print.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()

Ответ 2

По умолчанию приложение ASP.NET работает на специальной учетной записи с ограниченными правами. Достаточно просто, чтобы обслуживать веб-страницы, не более того. Поэтому вам нужно будет настроить пользователя ASPNET.

В отличие от этого службы Windows обычно запускаются под учетной записью локальной системы (с высокими привилегиями)

Ответ 3

Сетевая печать из ASP.Net/C# может быть выполнена с помощью:

Если сеть настроена для пользователей домена и принтер добавлен на сервер печати:

  • Имя принтера, которое должно быть определено как = "\\ PrintServerIP_OR_Name\\PRINTERNAME" Пример: PrinterSettings.PrinterName = "\\ 15.1.1.1\\prn001"
  • Проверьте настройки разрешений на доступ к принтеру
  • Которые либо являются пользователями домена, либо всем
  • Если пользователи домена, то код С# может быть заключен в олицетворение, которое может использоваться для вызова кода печати, который выглядит следующим образом:
/// <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();
}