Tag Archive for vb.net

Creiamo un servizio Windows in VB.NET

Che cos’è un servizio Windows? Sui sistemi operativi Microsoft, un servizio Windows è un eseguibile che compie determinate funzioni e che è progettato per non richiedere intervento da parte dell’utente. Possono essere configurati per essere avviati in fase di boot e per essere eseguiti in background. In alternativa, si possono far partire manualmente, se lo si desidera. Da un punto di vista concettuale, sono analoghi ai demoni Unix.

Fatta questa premessa, rispondiamo ora alla domanda principale: come possiamo creare un nuovo Windows service in ambiente .NET? Per cominciare, creiamo in Visual Studio un nuovo progetto di tipo “Windows Service”, poi modifichiamo le proprietà del servizio dalla finestra delle proprietà: i tre booleani CanPauseAndContinue, CanShutDown, e CanStop determineranno il comportamento del servizio che stiamo sviluppando. Ovviamente la proprietà ServiceName serve ad indicare e impostare il nome. Notate inoltre che esiste anche il campo CanHandlePowerEvent, che serve a stabilire se potremo gestire i cambiamenti di stato dell’alimentazione.

il passo successivo consiste nell’aggiungere il codice di startup: tipicamente dobbiamo inserirlo nella funzione di gestione dell’evento OnStart event. Ecco un esempio elementare:

Protected Overrides Sub OnStart(ByVal args() As String)
    EventLog.WriteEntry( "Scrivi quello che vuoi.")
End Sub

Possiamo implementare il comportamento del nostro applicativo anche in relazione ad altri eventi, quali: OnContinue, OnCustomCommand, OnPause, OnShutdown, OnPowerEvent, e OnStop. Se e come farlo dipende in grandissima parte dagli obiettivi che ci siamo prefissi con la creazione del nostro progetto, ma è piuttosto evidente che di solito è necessario gestire almeno l’avvio, la pausa, la continuazione e la terminazione del servizio.

Può essere davvero importante tenere traccia delle attività della nostra applicazione tramite un log, ma per semplificare le cose ricordiamoci di impostare la proprietà AutoLog (della classe Service) a true, in modo che gli eventi basilari vengano loggati automaticamente. Se faremo ciò dovremo preoccuparci di loggare solo le operazioni o gli avvenimenti di carattere specifico.

Quando avremo finito il nostro sviluppo, dovremo anche preparare un installer (che sarà di tipo ServiceInstaller) che prenda il Windows service di nostra invenzione e lo installi nel sistema. Come si fa? Dobbiamo selezionare il progetto nel box del Solution Explorer e visualizzarne le proprietà: vedremo il link “Add Installer”, che fa al caso nostro. Seguiamo la procedura guidata, in modo da aggiungere l’oggetto installer che dovremo personalizzare.

Nel prossimo articolo di questa serie vedremo dettagliatamente come creare un service installer. ;-)

Risolviamo l’errore “DragDrop registration did not succeed” in .NET

Tempo fa mi è capitato di dover migrare alcune applicazioni dal Framework.NET 3.5 al 2.0, per esigenze di alcuni clienti. Su una in particolare è apparso l’errore “DragDrop registration did not succeed”. In effetti io avevo sviluppato qualche feature legata al drag ‘n’ drop, ma non riuscivo proprio a capire che cosa fosse fuori posto.

Ho fatto svariate ricerche, ma le informazioni su questo argomento specifico sono piuttosto scarse. Ad ogni modo, dopo alcuni sforzi ho trovato un breve ma efficace articolo di Frederick Chapleau, il quale esponeva chiaramente la risposta. Qual è? Ebbene, se abbiamo cambiato la versione del Framework di destinazione nelle opzioni di compilazione e se dovesse apparirci l’eccezione citata all’inizio, dobbiamo soltanto svuotare la cartella bin del progetto. Nel mio caso ha funzionato!

Come si può ottenere l’oggetto Assembly .NET corrente?

In ambiente .NET è possibile ricavare ed operare sui tipi, i metodi e le proprietà di qualunque assembly valido, grazie alla reflection. Probabilmente saprete già che è sufficiente importare il namespace System.Reflection per accedere a molte classi e funzionalità create a tale scopo.

Potrebbe sorgere, tuttavia, la domanda: come si può ottenere l’oggetto Assembly della propria applicazione? O meglio, dove posso trovare un riferimento all’assembly corrente, ossia quello che, a runtime, conterrà il codice che sto scrivendo? In sostanza, il codice deve recuperare informazioni su se stesso! Si può fare? La reflection consente anche questo?

La risposta è sì. Ecco il codice VB.NET di esempio:

Dim aAssembly As [Assembly] = System.Reflection.Assembly.GetExecutingAssembly
Dim sPath as String = System.Reflection.Assembly.GetExecutingAssembly.Location

La seconda riga mostra come recuperare il percorso fisico del file. Facile no? ;-)

Come richiamare più web service con la medesima classe proxy

Alcuni servers

Foto di ©G. D®oid ».

In ambiente .NET, quando vogliamo adoperare i web service solitamente aggiungiamo i web references. Una volta fatto ciò, scriviamo il codice per istanziarli e per chiamare i vari web methods. L’IDE di sviluppo genera automaticamente una classe proxy per ogni web reference aggiunto: noi usiamo sue le funzioni, che a loro volta invocheranno in modo appropriato il web service.

Tuttavia, potremmo avere n web service che implementano la stessa interfaccia e che forniscono dati differenti. Potremmo perfino non sapere a priori quanti web service avremo e dove saranno collocati! Ovviamente, in una situazione del genere non possiamo impostare dei web references a design time. Come si possono dunque invocare le funzioni di più web service (cioé quelle dell’interfaccia comune) usando una classe proxy “generica”?

Sembra qualcosa di molto complesso, ma in realtà, non è così: bastano pochi semplici passi. Sono i seguenti:

  • Aggiungi un web reference ad uno qualsiasi dei web services che implementano l’interfaccia cui abbiamo accennato all’inizio. Visual Studio creerà una classe che eredita da SoapHttpClientProtocol e la salverà in un file di nome Reference.vb;
  • Vai sul solution explorer e premi il pulsante per visualizzare tutti i files del progetto. Apri la cartella “Web References”, espandi l’elemento corrispondente al riferimento appena aggiunto (il nome di default è “localhost”);
  • A questo punto vedrai un file con estensione disco, uno con estensione wsdl ed un Reference.map. Espandi questo nodo e vedrai il file Reference.vb;
  • Crea una nuova classe, dandole il nome che desideri. Copia dentro tutto il contenuto della classe presente nel Reference.vb;
  • Sostituisci tutti i namespace in tutti gli attributi del proxy e delle sue funzioni: inserisci la stringa “http://tempuri.org/”, che è una sorta di valore di default. Ecco le parti da modificare (cercale nel testo e inserisci i valori in grassetto):

    [...]WebServiceBindingAttribute(Name:=”NomeDelNostroBinding”, [Namespace]:=“http://tempuri.org”)

    [...]

    SoapRpcMethodAttribute(“http://tempuri.org/NostroMetodo”, RequestNamespace:=“http://tempuri.org”, ResponseNamespace:=“http://tempuri.org”)

  • Testa il proxy.

Come sempre, per ulteriori spiegazioni, chiarimenti, domande e/o suggerimenti inerenti a questo breve articolo, scrivete un commento: sarà certamente letto e apprezzato! :-D

Facciamo nostri i tipi Nullable

Bagni con cartello recante la scritta

Foto di naus3a01.

Tutti gli sviluppatori devono considerare molto spesso, nelle loro implementazioni, il fatto che un certo oggetto possa non essere stato valorizzato. Per esempio, una colonna di un database potrebbe essere a NULL e noi potremmo aver bisogno di adeguare il nostro codice a tale realtà. Quando si tratta di istanze di tipi di riferimento, può essere sufficiente verificare che siano a Nothing (o a null, in C#): se lo sono, significa che non hanno nessun valore. Se invece usiamo tipi di valore, come ad esempio gli interi, il controllo appena citato non avrebbe senso: non possono essere nullable poiché dispongono di capacità sufficiente a esprimere solo i valori appropriati per tali tipi. La domanda perciò è: come si possono gestire i valori nulli su oggetti che normalmente non lo permetterebbero?

Per rappresentare elementi presenti o meno a seconda della circostanza, dobbiamo usare il tipo Nullable, introdotto nel Framework .NET 2.0. La sua peculiarità è che supporta un tipo di valore a cui può essere assegnato un riferimento nullo come tipo di riferimento. Di conseguenza, un tipo nullable può esprimere un valore oppure esprimere che non è presente alcun valore. Tutto ciò si basa sui Generics e permette perciò di definire un nullable che incapsuli una variabile di un tipo specifico. In pratica, scriveremo dichiarazioni come queste:

Dim foo as Nullable(Of Int32)
Dim dummy as Nullable(Of Double)

È più facile sviluppare seguendo tale metodo, perché si continua a garantire la cosiddetta “type safety”. Grazie alla classe Nullable è inoltre possibile ottenere il tipo sottostante, nonché eseguire operazioni di confronto e uguaglianza su coppie di nullable il cui valore sottostante non le supporta nativamente.

Boxing e unboxing

Quando si esegue il boxing di un tipo nullable, il CLR esegue automaticamente il boxing del valore sottostante, non dell’oggetto Nullable stesso. Se pertanto la proprietà HasValue è impostata su true, il contenuto della proprietà Value viene sottoposto a boxing. Se invece è a false verrà sottoposto a boxing il valore nullo (ossia Nothing in VB.NET, appunto).