Tuesday, July 29, 2008

Compiler Workflow

. Tuesday, July 29, 2008
0 commenti

E' possibile compilare il flusso di lavoro scritto in C# / Visual Basic o tag XAML tramite il metodo Compile della classe WorkflowCompiler.
Ma vediamo un semplice esempio.
Supponiamo che il nostro flusso sia composto dai seguenti file:

  • Workflow1.cs
  • Workflow1.designer.cs

il codice per eseguire il compile è così fatto:

   1: //Path della directory in cui si trovano i files cs da compilare
   2: string pathFolder = @"path";
   3: string[] filesCompilation = { System.IO.Path.Combine( pathFolder, "Workflow1.cs"),
   4:         System.IO.Path.Combine( pathFolder, "Workflow1.designer.cs")};
   5:  
   6: WorkflowCompiler wfc = new WorkflowCompiler();
   7: WorkflowCompilerParameters paramters = new WorkflowCompilerParameters();
   8: paramters.OutputAssembly = System.IO.Path.Combine(pathFolder, "Workflow1.dll");
   9:  
  10: WorkflowCompilerResults results = wfc.Compile(paramters, filesCompilation);
  11:  
  12: if (results.Errors.Count == 0)
  13: {
  14:   //OK
  15: }
  16: else
  17: {
  18:   foreach (WorkflowCompilerError error in results.Errors)
  19:   {
  20:     string err = error.ErrorText;
  21:   }
  22: }

La classe WorkflowCompilerParameter ci permette di passare una serie di parametri alla classe WorkflowCompiler necessari alla fase di compilazione.
In questo preciso esempio per impostare il nome dell'assembly di output valorizzo la propertyOutputAssembly.
Se invece dobbiamo referenziare una serie di assembly, la classe ci fornisce la collection ReferencedAssemblies:


   1: paramters.ReferencedAssemblies.Add("MyAssembly.dll");


Oppure se abbiamo la necessità di includere dei file di risorse:


   1: paramters.EmbeddedResources.Add( System.IO.Path.Combine( pathFolder, "Workflow1.rules"));

 

Per concludere è possibile compilare, anche, attraverso linea di comando tramite:
Start -> Tutti i Programmi -> Microsoft Visual Studio 2008 -> Visual Studio Tools -> Visual Studio 2008 Command Prompt
e lanciare wfc.exe
Se si vuole conoscere le varie opzioni basta lanciare wfc /?

Read More »»

Saturday, July 26, 2008

Cambiare opinione su Vista?

. Saturday, July 26, 2008
0 commenti

Semplice, basta dire che il suo vero nome è Mojave.
Adesso sono curioso di vedere il video (29 Luglio) di questo strepitoso esperimento:
Mojave Experiment
Fonte: A Ovest di Paperino

Read More »»

Microsoft Scalable Fabric

.
0 commenti

Scalable Microsoft Scalable Fabric è un task management system per desktop Windows, che genera una sorta di tumbnail gallery delle finestre non attive.
Tramite un menù è possibile personalizzare il tutto: indicare la zona di ridimensionamento delle finestre, la massima/minima dimensione.
Man mano che trasciniamo la finestra fuori zona avvicinandoci così ai bordi dello schermo, questa diventerà sempre più piccola.
Inoltre si ricorda dell'ultima posizione delle finestre quando queste vengono ridotte.
Necessita del Framework .NET 1.1.

Read More »»

Monday, July 21, 2008

Creare un albero genealogico

. Monday, July 21, 2008
1 commenti

Per chi vuole divertirsi nel creare il proprio albero genealogico, esistono diversi servizi web che offrono la possibilità non solo di disegnarlo ma anche di condividere online, con parenti ed amici, il proprio lavoro.

Genoom

Genoom
Ancestry ancestry
Geni Geni
Famillion Famillion

Read More »»

Saturday, July 19, 2008

ToDoList

. Saturday, July 19, 2008
0 commenti

todolistToDoList, segnalatomi da un mio collega, è un task list manager utile a gestire le note di lavori. Presenta moltissime funzionalità: ordinamenti, filtri, export, possibilità di task gerarchici, ecc.
Il tutto viene memorizzato in file XML.
Presenta un'interfaccia molto semplice e anche dal punto di vista grafico devo dire che c'è stato un'ottimo lavoro.
Se a tutto questo ci aggiungiamo che è freeware, non possiamo esimerci dal provarlo.

Read More »»

Monday, July 14, 2008

Esecuzione di un workflow usando XOML

. Monday, July 14, 2008
0 commenti

E' possibile eseguire un workflow passando al metodo CreateWorkflow un tipo di flusso:

   1: WorkflowInstance instance = runtime.CreateWorkflow(typeof(Workflow1));
oppure facendo uso di tag basati su XAML.
Prima di spiegare il come, faccio un piccolo passo indietro per dire che Workflow Foundation ci permette di creare un flusso di lavoro essenzialmente in tre modi:
-solo codice, ne scaturisce che deve essere necessariamente compilato;
-separazione del codice, quindi code-behind più markup del flusso, simile a ciò che avviene quando si programma in Asp.Net,
-niente codice, quindi solo markup. In quest'ultimo caso si può anche non compilare.
Il markup viene definito in un file con estensione .xoml.
Giusto per dare un'idea di ciò che si può fare, possiamo per esempio, eseguire questo semplicissimo file XOML:
   1: <SequentialWorkflowActivity x:Class="SeqWF.Workflow3" x:Name="Workflow3" 
   2: xmlns:ns0="clr-namespace:ActivityLibrary;Assembly=ActivityLibrary, Version=1.0.0.0, 
Culture=neutral, PublicKeyToken=null"
   3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
   5:     <ns0:MyActivity x:Name="MyActivity" />
   6: </SequentialWorkflowActivity>

Il contenuto del file è abbastanza parlante, si tratta di un flusso sequenziale con un custom activity MyActivity dell'assembly ActivityLibrary.
Questo activity non fa altro che scrivere nella finestra di Output di Visual Studio un semplice messaggio:
   1: public partial class MyActivity : System.Workflow.ComponentModel.Activity
   2: {
   3:   public MyActivity()
   4:   {
   5:     InitializeComponent();
   6:   }
   7:  
   8:   protected override ActivityExecutionStatus Execute(ActivityExecutionContext    executionContext)
   9:   {
  10:     System.Diagnostics.Debug.WriteLine("Esecuzione metodo");
  11:     return ActivityExecutionStatus.Closed;
  12:   }
  13: }
Non ci rimane che creare il workflow usando il file xoml appena visto:
   1: try
   2: {
   3:   //Folder contenente la dll dell'assembly ActivityLibrary e il file XOML
   4:   string path = "path dll Activity e file XOML";
   5:   WorkflowRuntime runtime = new WorkflowRuntime();
   6:   
   7:   ManualWorkflowSchedulerService scheduler = new ManualWorkflowSchedulerService();
   8:   runtime.AddService(scheduler);
   9:  
  10:   TypeProvider typeProvider = new TypeProvider(runtime);
  11:   System.Reflection.Assembly ass = System.Reflection.Assembly.LoadFrom(
  12:     System.IO.Path.Combine(path, "ActivityLibrary.dll"));
  13:   typeProvider.AddAssembly(ass);
  14:   runtime.AddService(typeProvider);
  15:  
  16:   runtime.StartRuntime();
  17:  
  18:   System.IO.StreamReader sr = new System.IO.StreamReader(
  19:     System.IO.Path.Combine(path, "Workflow3.xoml"));
  20:   System.Xml.XmlReader xml = System.Xml.XmlReader.Create(sr);
  21:   WorkflowInstance instance = runtime.CreateWorkflow(xml);
  22:  
  23:   instance.Start();
  24:   scheduler.RunWorkflow(instance.InstanceId);
  25: }
  26: catch (System.Workflow.ComponentModel.Compiler.WorkflowValidationFailedException exc)
  27: {
  28:   foreach (ValidationError err in exc.Errors)
  29:   {
  30:     string error = err.ErrorText;
  31:   }
  32: }

Il servizio TypeProvider si occupa di mantenere i riferimenti all'assembly del custom activity.
Per l'uso di un file xoml viene usato l'overload del metodo CreateWorkflow in cui invece di un tipo viene passato un oggetto XmlReader.
Con tale file Workflow3.xoml verrà lanciata la seguente eccezione:


x:Class cannot be used when the markup is executed directly without creating a new activity type

questo perchè l'attributo x:Class può essere presente solo quando il flusso viene compilato, ma in questo caso, di workflow con solo tag XAML deve essere eliminato.
Volendo è possibile ignorare errori di convalida, quando viene invocato il metodo CreateWorkflow, settando a false la property ValidateOnCreate:
   1: WorkflowRuntimeSection section = new WorkflowRuntimeSection();
   2: section.ValidateOnCreate = false;
   4: WorkflowRuntime runtime = new WorkflowRuntime( section);

Ovviamente così facendo sarà l'host a garantire la corretta configurazione del flusso di lavoro.

Read More »»

Thursday, July 10, 2008

Pictomio

. Thursday, July 10, 2008
0 commenti

pictomio Pictomio è un software freeware utile a catalogare/visualizzare foto e video, ma anche creare presentazioni animate, il tutto in un modo estremamente d'effetto:




Read More »»

Microsoft Source Analysis

.
0 commenti

Questo tool, usato fino a qualche mese fa solo internamente a Microsoft, è stato ora rilasciato pubblicamente.
Lo scopo di Source Analysis è quello di controllare lo stile del codice usato, nel rispetto di tutta una serie di best practice ( più di 200).
Si integra direttamente in Visual Studio, e per diversi aspetti è simile al famoso utility FxCop, ma a differenza di quest'ultimo analizza il codice sorgente e non il codice compilato.
Per il download cliccare qui, mentre per ulteriori dettagli qui.

Read More »»

Sunday, July 6, 2008

Back State

. Sunday, July 6, 2008
0 commenti

Un workflow sequenziale come suggerisce la parola stessa scorre linearmente eseguendo uno dopo l'altro gli activity che costituiscono il flusso.
In questi giorni però mi son ritrovato a sviluppare un sistema che permettesse al cliente per cui sto lavorando, di effettuare un ritorno indietro in un workflow sequenziale composto da activity long running.
Detto con un esempio, se il workflow sequenziale è composto dai seguenti tre activity A, B e C, e il flusso si trova "persistito nell'activity B", allora deve essere possibile ritornare in A.
Nel caso di una macchina a stati la cosa sarebbe stata di semplice implementazione, poichè il flusso è costituito da un'insieme di stati collegati fra loro da una serie di eventi che determinano il passaggio da uno stato ad un altro.
Inoltre tramite il metodo SetState è possibile effettuare una transazione indicando il nome dello stato di destinazione:

   1: StateMachineWorkflowInstance ins = new StateMachineWorkflowInstance(runtime, instance.InstanceId);
   2: ins.SetState("TargetState");

Purtroppo nel mio caso la strada di "trasformazione" dell'attuale flusso sequenziale in una macchina a stati non è di facile attuazione, anche se molto probabilmente si tratta della soluzione migliore.

Quindi ho pensato di preservare man mano che si effettua il passaggio tra gli activity, lo stato del workflow in una tabella history, recuperando dalla tabella InstaceState; il blob, serializzato in BinaryFormatter e compresso tramite Gzip, contenuto nel campo State.
BackWorkflow1La tabella "base" presenta l'identificativo del flusso, lo stato ed infine un campo identity che indica l'ordine di inserimento.
A questo punto possiamo espandere il codice del custom activity visto nel post precedente, aggiungendo la logica del salvataggio dello stato del workflow:

   1: protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
   2: {
   3:   WorkflowQueuingService queueService = executionContext.GetService<WorkflowQueuingService>();
   4:   WorkflowQueue wfQueue = queueService.CreateWorkflowQueue(this.Name, true);
   5:   wfQueue.QueueItemAvailable += new EventHandler<QueueEventArgs>(nextActivity);
   6:   return ActivityExecutionStatus.Executing;
   7: }
   8:  
   9: void nextActivity(object sender, QueueEventArgs e)
  10: {
  11:   ActivityExecutionContext context = (ActivityExecutionContext)sender;
  12:   WorkflowQueuingService queueService = context.GetService<WorkflowQueuingService>();
  13:   queueService.DeleteWorkflowQueue(e.QueueName);
  14:   /*
  15:   * Recupero lo stato del workflow dalla tabella InstanceState
  16:   */
  17:             
  18:   /*
  19:   * Insert dello stato del workflow nella tabella history
  20:   */
  21:   context.CloseActivity();
  22: }

Da tale processo escludo i custom activity incapsulati in un branch ParallelActivity.
Per indicare quali activity devono partecipare al processo utilizzo un DependencyProperty:

   1: public static DependencyProperty ActivePersistenceProperty = 
      DependencyProperty.Register("ActivePersistence", typeof(Boolean), typeof(WorkflowClasse));
   2:  
   3: [DescriptionAttribute("ActivePersistence")]
   4: [CategoryAttribute("ActivePersistence Category")]
   5: [BrowsableAttribute(true)]
   6: [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
   7: public Boolean ActivePersistence
   8: {
   9:     get
  10:     {
  11:         return ((Boolean)(base.GetValue(Workflow1.ActivePersistenceProperty)));
  12:     }
  13:     set
  14:     {
  15:         base.SetValue(Workflow1.ActivePersistenceProperty, value);
  16:     }
  17: }

Per completare il giro è necessario verificare nel metodo nextActivity, se la property ActivePersistence è settata con il valore true.  
E'  facile immaginare come, per effettuare un ritorno in uno "stato" precedente basta effettuare l'update del campo State della tabella InstanceState; dalla tabella History.
Ovviamente sono molto curioso di sapere se esiste una soluzione più elegante da poter adottare in questo preciso contesto, in caso contrario spero che questo post possa essere d'aiuto, o quantomeno di ispirazione a qualcun altro.

Read More »»

Saturday, July 5, 2008

Alternativa ad Illustrator

. Saturday, July 5, 2008
1 commenti

CreativeDocs Creative Docs .NET è un software per il disegno vettoriale simile ai stra-famosi Illustrator e Corel Draw con la grossa differenza che è completamente free.
E' costituito da una serie di tool per manipolare testo, eseguire operazioni di merge sulle forme, lavorare con le curve di Bezier, possibilità di salvare direttamente in formato pdf ecc.
E' scritto in .Net e come tale richiede come requisito l'installazione del .NET Framework 2.0.
Può essere installato tranquillamente su sistemi Windows: 2000, XP, Server 2003 o Vista.

Read More »»

Tuesday, July 1, 2008

Microsoft Math per Word 2007

. Tuesday, July 1, 2008
0 commenti

Un add-in per Microsoft Office Word 2007 che permette di risolvere equazioni, creare grafici 2D e 3D, svolgere vari calcoli numerici, semplificare espressioni algebriche ecc.

Read More »»