678 messaggi dal 12 maggio 2001
www.idioteca.it
Ciao a tutti,
ho la necessità di lanciare la stampa diretta di alcuni file pdf presenti in una cartella del server attraverso un'applicazione web asp.net.
L'applicazione gira con autenticazione windows e dovrà inviare i file ad una stampante predefinita (di rete o locale è indifferente, in pratica sarà una stampante gestibile dall'utente che utilizzerà l'applicazione). Ho capito che di default l'utente asp.net non può farlo da solo e quindi ho provato a forzare un utente (locale? di dominio?) ma ogni volta mi viene restituito uno di questi errori:
- Login non valido. (forzando utente, password e dominio al processo)
- The specified executable is not a valid application for this OS platform. (senza impersonate user)
- No application is associated with the specified file for this operation (con impersonate user, utente locale del server o utente di dominio)

Se invece non assegno nessun utente al processo, sembra funzionare tutto, ma in stampa non esce niente.

Il codice utilizzato è il seguente:
Dim myProcess As New System.Diagnostics.Process()
myProcess.StartInfo.FileName = "C:\Testing.pdf"
myProcess.StartInfo.Verb = "Printto"
myProcess.StartInfo.CreateNoWindow = True
myProcess.Start()
myProcess.WaitForExit(2000) 

Con alcune varianti per l'uso diretto di username e password sul processo:
myProcess.StartInfo.UserName = strUsername
myProcess.StartInfo.Domain = strDomainName
myProcess.StartInfo.Password = secret
myProcess.StartInfo.LoadUserProfile = True
myProcess.StartInfo.UseShellExecute = False

o con l'uso di una classe che mi consente di lanciare il processo come utente XXXX.
Non vorrei eseguire l'intera applicazione come utente windows per quanto non sia un'applicazione accessibile a molti.

Ovviamente, se eseguo l'applicazione in locale e con il mio utente, mi posso divertire e mandare file a tutte le stampanti presenti in rete.

Avete qualche dritta?
grazie in anticipo, ma mi rendo conto di dove possa essere il problema, ma non ho la lucidità necessaria per trovare una soluzione :-P
ciao

P.s.
dimenticavo:
Server: Windows Server 2008 e IIS 7.5 (se non sbaglio)
Modificato da giangi_77 il 04 luglio 2011 11.11 -
24 messaggi dal 19 ottobre 2010
puo' essere un problema di permessi
l'utente che fa girare l'applicazione e' Administrator?

puoi provare ad utilizzare Impersonate()

using (new Impersonation())
{


//..... Esegui il metodo che fa la stampa


}








classe impersonation

public class Impersonation : IDisposable
{
private const int LOGON32_LOGON_INTERACTIVE = 2;
private const int LOGON32_PROVIDER_DEFAULT = 0;
private const int IMPERSONATION_LEVEL = 2;

private string _userName;
private string _domain;
private string _password;
private WindowsImpersonationContext _impersonationContext;
private bool _disposed;

[DllImport("advapi32.dll")]
private static extern int LogonUserA(string lpszUserName,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool RevertToSelf();

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);

/// <summary>
/// Impersona l'utente passato come parametro.
/// </summary>
/// <param name="userName">Nome dell'utente.</param>
/// <param name="domain">Dominio.</param>
/// <param name="password">Password.</param>
public Impersonation(string userName, string domain, string password)
{
_disposed = false;

_userName = userName;
_domain = domain;
_password = password;

Impersonate();
}

/// <summary>
/// Impersona l'utente passato come parametro.
/// </summary>
public Impersonation()
{
_disposed = false;

_userName = ConfigurationManager.AppSettings["impersonation_username"];
_domain = ConfigurationManager.AppSettings["impersonation_domain"];
_password = ConfigurationManager.AppSettings["impersonation_password"];

Impersonate(9);
}

private void Impersonate()
{
WindowsIdentity tempWindowsIdentity = null;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;

if (RevertToSelf())
{
if (LogonUserA(_userName, _domain, _password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if (DuplicateToken(token, IMPERSONATION_LEVEL, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
_impersonationContext = tempWindowsIdentity.Impersonate();
if (_impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return;
}
}
}
}

if (token != IntPtr.Zero)
{
CloseHandle(token);
}
if (tokenDuplicate != IntPtr.Zero)
{
CloseHandle(tokenDuplicate);
}

throw new InvalidOperationException("Impossibile eseguire l'impersonation con le credenziali fornite.");
}

/// <summary>
/// Fa l'impersonation usando il LogonType - NEW_CREDENTIALS
/// </summary>
private void Impersonate(int dwLogonType)
{
WindowsIdentity tempWindowsIdentity = null;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;

if (RevertToSelf())
{
if (LogonUserA(_userName, _domain, _password, dwLogonType, LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if (DuplicateToken(token, IMPERSONATION_LEVEL, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
_impersonationContext = tempWindowsIdentity.Impersonate();
if (_impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return;
}
}
}
}

if (token != IntPtr.Zero)
CloseHandle(token);

if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);

throw new InvalidOperationException("Impossibile eseguire l'impersonation con le credenziali fornite.");
}

/// <summary>
/// Rilascia la risorsa.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>
/// Azione senza parametri.
/// </summary>
public delegate void Action();

/// <summary>
/// Esegue un metodo fuori dal contesto dell'impersonation.
/// </summary>
/// <param name="action">Azione da eseguire.</param>
public void ExecuteWithoutImpersonation(Action action)
{
if (_disposed) throw new ObjectDisposedException("Impersonation");

Undo();
action();
Impersonate();
}

private void Undo()
{
if (_impersonationContext != null)
{
_impersonationContext.Undo();
}
_impersonationContext = null;
}

/// <summary>
/// Rilascia la risorsa.
/// </summary>
/// <param name="disposing">Valorizzato a true nel caso il metodo venga chiamato dal metodo pubblico Dispose.</param>
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;

if (disposing)
{
Undo();
}
_disposed = true;
}
}
678 messaggi dal 12 maggio 2001
www.idioteca.it
Ho provato anche in questo modo, ma il messaggio d'errore restituito è il seguente:
The specified executable is not a valid application for this OS platform
Ho fatto un po di pulizia, è al momento sono in questa situazione:
Using New Impersonation
            Try

                ' Get the path that stores user documents.
                Dim myDocumentsPath As String = txtPathFile.Text ' "C:\inetpub\cedolinitest\test"

                myProcess.StartInfo.FileName = myDocumentsPath '+ "C:\temp\testStampa.pdf" o "C:\temp\testStampa.txt" --> ho provato anche con una cartella interna alla mia applicazione
                myProcess.StartInfo.Verb = strProcessVerb
                myProcess.StartInfo.Arguments = strStampante ' Stampante Maurizio: "\\VEDANO1\edp-laser"

                myProcess.StartInfo.LoadUserProfile = True
                myProcess.StartInfo.UseShellExecute = bShellExecute
                strMsgPagina += "<br /><br />Stampante utilizzata: " & myProcess.StartInfo.Arguments.ToString & "<br /><br />"
                myProcess.StartInfo.CreateNoWindow = True
                myProcess.Start()
                strMsgPagina += "<br />- Start"
                strMsgPagina += "<br />- aspetto"
                While Not myProcess.HasExited
                    strMsgPagina += "<br />- aspetto"
                    If Not Response.IsClientConnected Then
                        myProcess.Kill()
                        strMsgPagina += "<br />- kill"
                        Exit While
                    End If
                End While

                'myProcess.WaitForExit(20000)
                strMsgPagina += "<br />- fine attesa"

            Catch ex As System.ComponentModel.Win32Exception
                If ex.NativeErrorCode = ERROR_FILE_NOT_FOUND Then
                    'Console.WriteLine((ex.Message + ". Check the path."))
                    strMsgPagina += "<br />ERROR_FILE_NOT_FOUND - ex.Message:<br />" & ex.Message & ". Check the path."
                ElseIf ex.NativeErrorCode = ERROR_ACCESS_DENIED Then
                    ' Note that if your word processor might generate exceptions
                    ' such as this, which are handled first.
                    'Console.WriteLine((ex.Message + ". You do not have permission to print this file."))
                    strMsgPagina += "<br />ERROR_ACCESS_DENIED - ex.Message:<br />" & ex.Message & ". You do not have permission to print this file."

                Else
                    strMsgPagina += "<br />ELSE - ex.Message:<br />" & ex.Message
                End If
            Catch ex2 As Exception
                strMsgPagina += "<br />ex2.Message:<br />" & ex2.Message ' & ". Generic errors."
            End Try
        End Using
678 messaggi dal 12 maggio 2001
www.idioteca.it
Aggiornamento situazione:
Verificando lo spooler della stampante, il file arriva, ma scompare immediatamente (anche con stampante in pausa) e nel registro eventi non compare nulla.
Qualche idea in proposito?
ciao
678 messaggi dal 12 maggio 2001
www.idioteca.it
problema risolto!
Come al solito il problema è sempre più stupido di quanto sembri...
in IIS l'application pool era impostato su ApplicationPoolIdentity invece che Networkservice.
Ora funziona tutto... vabbe'... dovrò installare un reader per consentire la stampa dei pdf, ma questo non è certo un problema per un'applicazione intranet.
ciao

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.