sabato 27 gennaio 2007
Questo pomeriggio mi sono imbattutto in un problema legato alle date memorizzate in un database di SQL Server 2005. Mi sono però ricordato che il mitico Davide Mauri aveva parlato di questa tematica nel suo webcast di dicembre SQL Server Developer Best Practices - Parte 1: ho così recuperato la registrazione e, seguendo i consigli forniti, in poco tempo sono venuto a capo del problema! Grazie Davide, mi hai risparmiato un bel po' di fatica 
Con 5 giorni di anticipo rispetto alla data di rilascio prevista, lo scorso 26 gennaio è stata rilasciata la versione definitiva di Paint.NET 3.0. Queste le principali novità:
- Simple and intuitive tab-based multi-document user interface
- Now available in 8 languages: English, Chinese (Simplified), French, German, Japanese, Korean, Portuguese (Brazil), and Spanish
- Interactive Gradient Tool that makes it very easy to draw and then fine-tune placement and coloring of a gradient
- User-definable color palette (as opposed to just the color wheel)
- New effects: Clouds, Median, Unfocus, Outline, and an improved Sharpen
- More intuitive and more powerful toolbar
- Generally improved and cleaner user interface
- History files are now compressed to save disk space, reduce disk activity, and improve performance
- "Merge Down" layer command
Inutile dire che ho già provveduto a scaricarlo ed installarlo. Il download è di poco meno di 5.5 MB. L'occupazione di memoria del programma appena avviato è di circa 27 MB. Nononstante di versione in versione vengano aggiunte sempre nuove funzionalità, Paint.NET mantiene le sue caratteristiche di semplicità e immediatezza d'uso.
Mi permetto però di fare un paio di note. Innanzi tutto, Paint.NET 3.0 non supporta più Windows 2000, dunque può essere installato solo su Windows XP/2003/Vista. Non capisco il perché di questa scelta, dal momento che il software è realizzato con il .NET Framework 2.0, il cui runtime è disponibile non solo per Windows 2000, ma anche per Windows 98. L'altro appunto riguarda la stampa delle immagini, che utilizza il wizard Stampa guidata foto di Windows: da un programma di questo livello mi sarei aspettato funzionalità di stampa un po' più evolute.
Quando si deve realizzare un sistema basato su plug-in, è buona norma utilizzare un AppDomain diverso per caricare le estensioni, in modo che un plug-in mal funzionante non possa compromettere il funzionamento dell'intera applicazione. La soluzione che adotto io si basa su una classe chiamata AssemblyLoader:
1 using System;
2 using System.Reflection;
3
4 namespace System.Reflection
5 {
6 public class AssemblyLoader : MarshalByRefObject
7 {
8 public AssemblyLoader()
9 { }
10
11 public object CreateInstance(string assemblyName,
12 string interfaceName, params object[] args)
13 {
14 try
15 {
16 Assembly assembly = Assembly.LoadFrom(assemblyName);
17 foreach (Type type in assembly.GetExportedTypes())
18 {
19 Type interfaceType = type.GetInterface(interfaceName);
20 if (interfaceType != null)
21 return Activator.CreateInstance(type, args);
22 }
23 return null;
24 }
25 catch
26 {
27 return null;
28 }
29 }
30 }
31 }
Il cuore della classe è il metodo CreateInstance, che controlla i tipi esportati da un certo assembly (riga 17), quindi crea un'istanza del tipo che implementa l'interfaccia passata come argomento (righe 19-21).
Tale classe deve essere compilata in una class library. A questo punto, per caricare un plug-in in un nuovo AppDomain è sufficiente scrivere qualcosa del tipo:
AppDomain pluginAppDomain = AppDomain.CreateDomain("Plug-in AppDomain");
AssemblyLoader loader =
(AssemblyLoader)pluginAppDomain.CreateInstanceFromAndUnwrap
("AssemblyLoader.dll", typeof(AssemblyLoader).FullName);
IPlugin plugin = (IPlugin)
loader.CreateInstance(AppDomain.CurrentDomain.BaseDirectory +
@"\Plugins\TestPlugin.dll", "IPlugin");
L'oggetto loader viene caricato nell'AppDomain chiamato Plug-in AppDomain. IPlugin è l'interfaccia che deve essere implementata da ogni plug-in; ogni plug-in, inoltre, deve estendere la classe MarshalByRefObject. Il nome dell'interfaccia deve essere passato come secondo argomento alla funzione AssemblyLoader.CreateInstance. Il risultato di questo codice è l'istanziazione della classe che implementa IPlugin (e che è contenuta in TestPlugin.dll) all'interno del nuovo AppDomain. In tal modo, richiamando sull'oggetto plugin i metodi che sono definiti nell'interfaccia IPlugin, essi verranno eseguiti all'interno del Plug-in AppDomain.
Utilizzando questa strategia, se il plug-in manifesta qualche problema è sufficiente scaricare l'AppDomain che lo contiene, senza essere costretti ad interrompere l'intera applicazione.
Temevo che prima o poi sarebbe successo... Negli ultimi tempi anche il mio blog è stato preso di mira dagli spammer. Per il momento i messaggi non sono moltissimi, quindi riesco ancora ad eliminarli, ma spero che il problema non peggiori, perché mi dispiacerebbe essere costretto a disattivare i commenti, che io ritengo una delle cose più importanti di un blog.
Sono rimasto senza parole appena ho letto i prezzi delle diverse versioni di Windows Vista. Mi limito a parlare delle versioni complete. Si parte dai 299 € della versione Home Basic, per arrivare ai 599 della versione Ultimate. Andando in un grande magazzino, è possibile acquistare un PC dekstop completo di schermo LCD ad un prezzo inferiore...
La versione Business costa 499 €; per caratteristiche e funzionalità, questa è la versione "più vicina" a Windows XP Professional, che però ha un prezzo di 368 €. 131 € di differenza...
Qualche anno fa Bill Gates aveva detto che il suo sogno era vedere un PC su ogni scrivania. Secondo me far pagare così tanto il suo sistema operativo non è la strategia ideale per perseguire questo obiettivo...
Capita spesso di dover ordinare alfabeticamente una lista di stringhe. Quando si devono ordinare stringhe che contengono numeri, i metodi standard (come quello utilizzato impostando la proprietà Sorted del controllo ListBox su True) non sempre producono il risultato voluto. Tuttavia, utilizzando una apposita funzione dell'API di Windows, è possibile risolvere questo problema. Clicca qui per approfondire l'argomento.
Su CodeProject è stato pubblicato un articolo che illustra in maniera molto accurata che cos'è Windows CardSpace e in che modo può essere utilizzato nelle nuove applicazioni. Per leggerlo basta cliccare qui.
La UAC di Windows Vista influisce anche sui programmi ad esecuzione automatica. Se, infatti, si mette in esecuzione automatica un programma che richiede i privilegi di amministratore, in fase di avvio viene visualizzato il messaggio Al suo avvio Windows blocca i programmi che richiedono un'autorizzazione e l'applicazione non viene eseguita. In un caso del genere, per consentire l'esecuzione è necessario fare clic sull'icona Programmi ad esecuzione automatica bloccati che compare nella system tray, selezionare il comando Esegui programi bloccati e, infine, fare clic sull'applicazione che si desidera avviare: apparirà la solita finestra della UAC che chiede conferma prima di continuare l'operazione, dopodiché il programma sarà effetivamente avviato.
Questo comportamento è dovuto a motivi di sicurezza. Ci sono casi, tuttavia, in cui all'avvio è necessario che vengano eseguiti programmi con diritti di amministratore, come gli antivirus. Una soluzione al problema è la seguente:
- disattivare il programma ad esecuzione automatica;
- creare una nuova attività pianificata per la sua esecuzione, utilizzando lo strumento Utilità di pianificazione, in modo che venga eseguita all'accesso di qualunque utente e avendo cura che nella scheda Generale sia attivata l'opzione Esegui con i privilegi più elevati (l'account utilizzato per creare l'attività deve appartenere al gruppo Administrator).
Forse ci sono soluzioni più semplici (escludendo la disabilitazione della UAC), ma comunque questo procedimento mi sembra ragionevole.
Un professore della mia Università, docente del corso di Laboratorio di Programmazione di Sistema (in cui sostanzialmente si studia linguaggio C in ambiente Linux), ha chiesto ai suoi studenti di scrivere in C un programma che, una volta eseguito, stampa a video il proprio codice sorgente.
La soluzione dell'esercizio è un programma composto da una manciata di righe di codice:
main(char*a)
{
a="main(char*a){a=%c%s%c;printf(a,34,a,34);}";
printf(a,34,a,34);
}
Su questa pagina, inoltre, si possono trovare i programmi che stampano sé stessi scritti in diversi linguaggi, tra cui Assembler e BASIC.