Après plusieurs sollicitations voici en fin la suite de mon article sur la création d’une Custom Activity pour FIM 2010.
Afin de rendre ce guide le plus simple possible, je vais montrer ici une activité utilisée comme exemple par Microsoft dans les guides du MSDN. L’article original est disponible à cette adresse : http://msdn.microsoft.com/en-us/library/windows/desktop/ff859524.aspx
Cette activité est créé dans la FIMCustomActivityLibrary préparée dans la première partie de ce guide : FIM Custom Activity – Guide de création (partie 1)
On va créer cette activité dans un dossier spécifique afin de séparer les différentes activités au sein d’une même librairie (ce qui permet je le rappelle de ne générer qu’une seule dll d’activité personnalisée pour le portail FIM 2010).
Commençons donc par créer un nouveau dossier dans l’explorateur de solutions, et nommons le comme l’activité à créer, RequestLoggingActivity
Ensuite d’un clic droit sur ce dossier, nous allons ajouter une nouvelle Activité, que nous nommerons avec grande subtilité RequestLoggingActivity.cs
Nous voici avec deux éléments créés dans le dossier de notre activité : le code source de l’activité (RequestLoggingActivity.cs) et le code source du designer de l’activité (RequestLoggingActivity.Designer.cs)
Ce dernier ne doit JAMAIS être modifié directement (à moins de savoir parfaitement ce que vous faites, ou bien pour un autre cas mais que nous verrons plus tard
)
Le designer sous Visual Studio et un outil avec lequel nous allons pouvoir glisser-déposer nos activités pour constituer les flux d’actions à réaliser (en gros on construit le Workflow en empilant des briques comme au bon vieux temps où l’on jouait aux legos à quatre pattes sur le tapis du salon)
La première chose à faire est d’ajouter les références de classes de Microsoft.ResourceManagement.dll à notre activité en éditant le code source (élément RequestLoggingActivity.cs), et en y ajoutant les deux lignes suivantes en début de fichier :
using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; //The following two namespaces define the FIM object model using Microsoft.ResourceManagement.WebServices.WSResourceManagement; using Microsoft.ResourceManagement.Workflow.Activities;
Note, pour éditer le code source il suffit de faire un clic droit sur l’élément RequestLoggingActivity.cs puis de choisir « Afficher le code ». Nous obtenons alors ceci, qui pour l’instant ne fait pas grand chose
Maintenant nous allons ajouter une activité FIM de type currentRequestActivity qui va nous permettre de récupérer les informations de la requête FIM qui déclenche cette Custom Activity (Auteur, ID de la ressource cible, variables de Workflow, paramètres spécifiques indiqués dans la GUI de l’activité)
Pour cela on retourne sur le Designer, puis on attrape l’activité dans la barre d’outil de gauche et effectue un auguste glissé-déposé dans le Workflow d’activité. On va ensuite générer la définition des variables associées à l’activité en faisant un clic droit sur le bloc d’activité et en choisissant « Promouvoir les propriétés pouvant être liées »
On va ensuite retourner dans le code de l’activité où l’on peut voir que les éléments relatifs à l’activité currentRequest Activity ont été créés. On va y ajouter la définition des propriétés que l’on entrera en paramètre de la GUI de cette activité, afin d’obtenir le code source suivant :
#region Current Request Properties public static DependencyProperty currentRequestActivity1_CurrentRequest1Property = DependencyProperty.Register("currentRequestActivity1_CurrentRequest1", typeof(RequestType), typeof(RequestLoggingActivity)); [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)] [BrowsableAttribute(true)] [CategoryAttribute("Divers")] public RequestType currentRequestActivity1_CurrentRequest1 { get { return ((RequestType)(base.GetValue(RequestLoggingActivity.currentRequestActivity1_CurrentRequest1Property))); } set { base.SetValue(RequestLoggingActivity.currentRequestActivity1_CurrentRequest1Property, value); } } /// <summary> /// Parameter from GUI to specify the logging activity name /// </summary> public static DependencyProperty LoggingActivityNameProperty = DependencyProperty.Register("LoggingActivityName", typeof(System.String), typeof(RequestLoggingActivity)); [Description("Please specify the Logging Activity Name")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] [Browsable(true)] public String LoggingActivityName { get { return ((String)(base.GetValue(RequestLoggingActivity.LoggingActivityNameProperty))); } set { base.SetValue(RequestLoggingActivity.LoggingActivityNameProperty, value); } } /// <summary> /// Parameter from GUI to specify the log file path /// </summary> public static DependencyProperty LogFilePathProperty = DependencyProperty.Register("LogFilePath", typeof(System.String), typeof(RequestLoggingActivity)); [Description("Please specify the Log File Path")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] [Browsable(true)] public String LogFilePath { get { return ((String)(base.GetValue(RequestLoggingActivity.LogFilePathProperty))); } set { base.SetValue(RequestLoggingActivity.LogFilePathProperty, value); } } #endregion
Ensuite nous allons ajouter une activité exécutant du code au Workflow, pour cela on reprend le Designer, puis depuis la boîte à outils dans la section Windows Workflow v3.0, on glisse une activité de type Code que l’on renomme à notre convenance (ici LogRequestToFile)
Pour générer le code de cette activité, il suffit de double cliquer sur le bloc Code. Ceci génère une fonction nommée LogRequestToFile_ExecuteCode vide, dans laquelle on va ajouter le code source suivant (ainsi qu’une fonction dépendante supplémentaire) :
/// <summary> /// Get current request parameters and log values to file. /// </summary> private void LogRequestToFile_ExecuteCode(object sender, EventArgs e) { try { // Get current request from previous activity RequestType currentRequest = this.currentRequestActivity1_CurrentRequest1; // Output the Request type and object type this.Log("Request Operation: " + currentRequest.Operation); this.Log("Target Object Type: " + currentRequest.TargetObjectType); // As UpdateRequestParameter derives from CreateRequestParameter we can simplify the code by deriving // from CreateRequestParameter only. ReadOnlyCollection<CreateRequestParameter> requestParameters = currentRequest.ParseParameters<CreateRequestParameter>(); // Loop through CreateRequestParameters and print out each attribute/value pair this.Log("Parameters for request: " + currentRequest.ObjectID); foreach (CreateRequestParameter requestParameter in requestParameters) { if (requestParameter.Value != null) this.Log(" " + requestParameter.PropertyName + ": " + requestParameter.Value.ToString()); } // In order to read the Workflow Dictionary we need to get the containing (parent) workflow SequentialWorkflow containingWorkflow = null; if (!SequentialWorkflow.TryGetContainingWorkflow(this, out containingWorkflow)) { throw new InvalidOperationException("Unable to get Containing Workflow"); } this.Log("Containing Workflow Dictionary (WorkflowData):"); // Loop through Workflow Dictionary and log each attribute/value pair foreach (KeyValuePair<string, object> item in containingWorkflow.WorkflowDictionary) { this.Log(" " + item.Key + ": " + item.Value.ToString()); } this.Log("\n\n"); } catch (Exception ex) { this.Log("Logging Activity Exception Thrown: " + ex.Message); } } /// <summary> /// Prefix the current time to the message and log the message to the log file. /// </summary> private void Log(string message) { using (StreamWriter log = new StreamWriter(this.LogFilePath)) { log.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + ": " + message); } }
Nous verrons dans la 3ème partie de ce guide comment créer le formulaire GUI du Workflow qui s’affichera dans le portail FIM 2010.
La suite de cette article ici : FIM Custom Activity – Guide de création (partie 3)