Cosa ci serve
Per realizzare questo sistema, una volta ci si affidava a dei CGI proprietari, magari servendosi delle API. Ora, invece, tramite ASP e Windows Scripting Host è possibile farlo con poche e semplici righe di codice, senza avventurarsi troppi nei meandri di SDK e documentazione.
Windows Scripting Host di solito viene installato con Internet Information Server 4, altrimenti è scaricabile da questo link. Quindi, perché tutto funzioni, abbiamo bisogno di questi semplici cose:
In pratica pochissimi componenti, e tutti rigorosamente gratis. IIS4 dovreste averlo già installato, visto che si tratta di un componente quasi indispensabile per eseguire le pagine ASP.
Un discorso a parte merita WSH, che è una grossa rivoluzione nel suo campo. Tramite WSH è possibile accedere o cancellare chiavi nel registro di sistema, connettersi ad unità di rete, lanciare eseguibili, ma usando VBScript e JScript (o un linguaggio per cui sia disponibile un Active-X engine) direttamente da Windows, come se si trattasse di file batch! Gli oggetti WSH vengono forniti come componenti COM, per cui è possibile usarli anche in pagine ASP, che è proprio quello che fa al caso nostro.
In rete o no? Questo è il dilemma.
A questo punto abbiamo tutto quello che ci serve per cominciare. Ci potrebbero essere due situazioni in cui il nostro sistema potrebbe trovare uso. Per stampare su una stampante di rete, oppure su quella locale. Occupiamoci prima della stampa su rete.
E' questo il caso in cui WSH ci torna molto utile. Infatti, per connetterci ad una stampante di rete potremo usufruire dell'oggetto WshNetwork e dei suoi metodi AddPrinterConnection e EnumPrinterConnections. Come si intuisce dai nomi, il primo metodo si occupa della connessione vera e propria, mentre il secondo ci fornisce la lista delle stampanti connesse alla rete.
Quindi, per usare i servizi della stampante di rete, la "installeremo" sulla porta LPT1, in modo che ci sia molto più semplice di quanto non sembri stampare!
Per connetterci alla stampante di rete, dopo aver dichiarato i vari oggetti, ci serviremo del seguente codice:
>objWSHNet.AddPrinterConnection
"LPT1", strPercorsoStampante, False, strUsername, strPassword
Dopo aver aperto la connessione alla stampante, ci limiteremo a salvare su un file di nome "LPT1" i nostri dati. In questo modo, avremo un risultato del tutto simile al comando DOS echo ciao >LPT1.
Nell'esempio mostrato più sotto si capisce meglio il funzionamento e la logica su cui si basa questo sistema. Ricapitolando, ecco lo schema logico seguito dalla nostra applicazione:
<%
Option Explicit
Response.Expires=0
' Variabili che conterranno le informazioni necessarie
Dim strSottomissione, strPercorsoStampante, strTesto
Dim strUsername, strPassword
Dim ciclo, IntMaxConn
' Nomi degli oggetti utilizzati per le varie connessioni
Dim objFileSystem, objWSHNet, objStampante
' Caricamento della variabile di verifica sottomissione form
strSottomissione = Request.Form("Sottomissione")
%>
<html><head>
<title>Stampa via browser su stampante di rete</title>
</head>
<body bgcolor="white" text="black">
<h1>Stampa via browser su stampante di rete</h1>
<hr>
<%
' Verifica se è stato premuto o meno il pulsante di submit
' sul form
If strSottomissione = "" Then
%>
<form action="<%=Request.ServerVariables("SCRIPT_NAME")%>"
method="POST">
<table wdith=90% border="0">
<tr>
<td align="right">Stampante selezionata:</td>
<td><select name="PercorsoStampante">
<%
'Imposta la connessione all'oggetto WScript.Network
Set objWSHNet = CreateObject("WScript.Network")
'Conteggio delle stampanti disponibili
Set objStampante = objWSHNet.EnumPrinterConnections
IntMaxConn=objStampante.Count
if IntMaxConn>0 then
for ciclo=0 to IntMaxConn
response.write "<option>" & objStampante.Item(ciclo)
next
end if
%></select></td>
</tr>
<tr>
<td align="right">User-ID:</td>
<td><input type="text" name="username"
value="<%=strUsername%>"></td>
</tr>
<tr>
<td align="right">Password:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td align="right">Testo:</td>
<td><textarea rows="4" cols="30"
name="Testo"></textarea></td>
</tr>
<tr>
<td align="right" colspan="2"><input type="submit" value="Stampa!"
name="Sottomissione"></td>
</tr>
</table>
</form>
<%
Else
' E' stata effettuata una richiesta e verrà eseguita
strPercorsoStampante = Request.Form("PercorsoStampante")
strUsername = Request.Form("username")
strPassword = Request.Form("password")
strTesto = Request.Form("Testo")
' Creiamo gli oggetti necessari per il funzionamento dello script
Set objFileSystem = CreateObject("Scripting.FileSystemObject")
Set objWSHNet = CreateObject("WScript.Network")
' Connessione alla stampante di rete utilizzando Windows Scripting Host
objWSHNet.AddPrinterConnection "LPT1", strPercorsoStampante, False,
strUsername, strPassword
' Apriamo la stampante come se si trattasse di un puro e semplice file.
Set objStampante = objFileSystem.CreateTextFile("LPT1:", True)
' Mandiamo il testo da stampare come se si trattasse di una semplice
' scrittura su file.
objStampante.Write(strTesto)
' Chiudiamo la connessione ed in caso di errore facciamo passare
' lo script alla successiva istruzione.
On Error Resume Next
objStampante.Close
' Nel caso qualcosa non sia andato per il verso giusto, facciamolo
' sapere al nostro utente
If Err Then
Response.Write ("Errore # " & CStr(Err.Number) & " " &
Err.Description)
Err.Clear
Else
' Operazione riuscita con successo.
Response.Write("<p>E' stato stampato il seguente testo:<br>")
Response.Write("<pre>" & strTesto &
"</pre></p>")
Response.Write("<p><B>Percorso della stampante di
rete:</b><br>")
Response.Write( strPercorsoStampante & "</p>")
Response.Write("<p><b>Login ID:</b><br>")
Response.Write( strUsername & "</p>")
End If
' Rimuoviamo la connessione
objWSHNet.RemovePrinterConnection "LPT1:"
' Scarichiamo gli oggetti usati dalla memoria
Set objWSHNet = Nothing
Set objFileSystem = Nothing
Set objStampante = Nothing
End If
%>
</body></html>
Come risultato avremo la stampa sulla stampante di rete selezionata. Nell'esempio viene presentato un sistema già funzionante, che si occupa anche di mostrare le stampanti remote attualmente disponibili sulla rete a cui appartiene il server web. In questo esempio vengono anche richieste per ogni stampa una password ed un user-id, che devono poi essere quelli associati ad un utente della rete che abbia i permessi di stampa su una determinata stampante. E' bene notare che i dati viaggiano non crittografati, a meno di non usare SSL. In ogni caso è preferibile creare un solo utente con privilegi di stampa, e poi usare solo quello direttamente nel codice, magari gestendo la fase di autenticazione su SSL ma prelevando i dati da un database, il che consente di essere anche più flessibili nella gestione degli utenti stessi e del loro accesso.
E per fare prima?
Ci sono situazioni in cui non si ha a disposizione una stampante di rete o si desidera stampare su una locale. In questo caso WSH non ci serve, visto che abbiamo tutto il necessario con gli oggetti built-in di ASP.
Il funzionamento e la logica di esecuzione sono quasi identici, fatta eccezione per la parte relativa alla connessione alla stampante di rete, che questa volta non viene usata, visto che si desidera accedere ad una risorsa locale. In pratica basta aprire un file di nome LPT1 e quindi usare il metodo Write per scriverci sopra.
Conclusioni
Con pochissime righe di codice è possibile accedere a risorse che fino ad un anno fa erano "staccate" e che erano confinate, lontano dal server web. Oggi con WSH e ASP diventa possibile rendere le proprie applicazioni più potenti. E stampare su una stampante di rete via browser non è poi una cosa di poco senso, se si pensa alle moderne Intranet, soprattutto dove è necessario poi creare un output cartaceo. Sto pensando, ad esempio, a sistemi per l'evasione di ordinazioni, in cui gli addetti alle spedizioni si trovano su un piano diverso da quello in cui è localizzato il server web che raccoglie le ordinazioni. Oppure ad un internet provider che desideri ricevere le segnalazioni fatte attraverso il browser in formato cartaceo, magari per leggerle prima o per archiviarle.