public static void RegisterPluginsAndWorkflows <TPlugin>(string projectName) { var xrmFrameworkConfigSection = ConfigHelper.GetSection(); var projectConfig = xrmFrameworkConfigSection.Projects.OfType <ProjectElement>() .FirstOrDefault(p => p.Name == projectName); if (projectConfig == null) { var defaultColor = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"No reference to the project {projectName} has been found in the xrmFramework.config file."); Console.ForegroundColor = defaultColor; return; } var pluginSolutionUniqueName = projectConfig.TargetSolution; var connectionString = ConfigurationManager.ConnectionStrings[xrmFrameworkConfigSection.SelectedConnection].ConnectionString; Console.WriteLine($"You are about to deploy on {connectionString} organization. If ok press any key."); Console.ReadKey(); Console.WriteLine("Connecting to CRM..."); var service = new CrmServiceClient(connectionString); service.OrganizationServiceProxy?.EnableProxyTypes(); InitMetadata(service, pluginSolutionUniqueName); var pluginAssembly = typeof(TPlugin).Assembly; var pluginType = pluginAssembly.GetType("XrmFramework.Plugin"); var customApiType = pluginAssembly.GetType("XrmFramework.CustomApi"); var workflowType = pluginAssembly.GetType("XrmFramework.Workflow.CustomWorkflowActivity"); var pluginList = new List <Plugin>(); var pluginTypes = pluginAssembly.GetTypes().Where(t => pluginType.IsAssignableFrom(t) && !customApiType.IsAssignableFrom(t) && t.IsPublic && !t.IsAbstract).ToList(); var workflowTypes = pluginAssembly.GetTypes().Where(t => workflowType.IsAssignableFrom(t) && !t.IsAbstract && t.IsPublic).ToList(); var customApiTypes = pluginAssembly.GetTypes().Where(t => customApiType.IsAssignableFrom(t) && t.IsPublic && !t.IsAbstract).ToList(); foreach (var type in pluginTypes) { dynamic pluginTemp; if (type.GetConstructor(new[] { typeof(string), typeof(string) }) != null) { pluginTemp = Activator.CreateInstance(type, new object[] { null, null }); } else { pluginTemp = Activator.CreateInstance(type, new object[] { }); } var plugin = Plugin.FromXrmFrameworkPlugin(pluginTemp, false); pluginList.Add(plugin); } foreach (var type in workflowTypes) { dynamic pluginTemp = Activator.CreateInstance(type, new object[] { }); var plugin = Plugin.FromXrmFrameworkPlugin(pluginTemp, true); pluginList.Add(plugin); } var customApis = new List <CustomApi>(); foreach (var type in customApiTypes) { dynamic customApiTemp; if (type.GetConstructor(new[] { typeof(string), typeof(string) }) != null) { customApiTemp = Activator.CreateInstance(type, new object[] { null, null }); } else { customApiTemp = Activator.CreateInstance(type, new object[] { }); } var customApi = CustomApi.FromXrmFrameworkCustomApi(customApiTemp, _publisher.CustomizationPrefix); customApis.Add(customApi); } var assembly = GetAssemblyByName(service, pluginAssembly.GetName().Name); var profilerAssembly = GetProfilerAssembly(service); var registeredPluginTypes = new List <PluginType>(); var registeredCustomApis = new List <CustomApi>(); var registeredCustomApiRequestParameters = new List <CustomApiRequestParameter>(); var registeredCustomApiResponseProperties = new List <CustomApiResponseProperty>(); var profiledSteps = new List <SdkMessageProcessingStep>(); ICollection <SdkMessageProcessingStep> registeredSteps = Enumerable.Empty <SdkMessageProcessingStep>().ToList(); var assemblyPath = pluginAssembly.Location; if (assembly == null) { Console.WriteLine("Registering assembly"); assembly = GetAssemblyToRegister(pluginAssembly, assemblyPath); assembly.Id = service.Create(assembly); } else { Console.WriteLine("Updating plugin assembly"); var updatedAssembly = new Entity("pluginassembly") { Id = assembly.Id, ["content"] = Convert.ToBase64String(File.ReadAllBytes(assemblyPath)) }; registeredPluginTypes = GetRegisteredPluginTypes(service, assembly.Id).ToList(); registeredCustomApis = GetRegisteredCustomApis(service).ToList(); registeredCustomApiRequestParameters = GetRegisteredCustomApiRequestParameters(service).ToList(); registeredCustomApiResponseProperties = GetRegisteredCustomApiResponseProperties(service).ToList(); registeredSteps = GetRegisteredSteps(service, assembly.Id); if (profilerAssembly != null) { profiledSteps = GetRegisteredSteps(service, profilerAssembly.Id).ToList(); } foreach (var registeredType in registeredPluginTypes) { if (pluginList.All(p => p.FullName != registeredType.Name) && pluginList.Where(p => p.IsWorkflow).All(c => c.FullName != registeredType.TypeName) && customApis.All(c => c.FullName != registeredType.TypeName)) { var registeredStepsForPluginType = registeredSteps.Where(s => s.EventHandler.Id == registeredType.Id).ToList(); foreach (var step in registeredStepsForPluginType) { service.Delete(SdkMessageProcessingStep.EntityLogicalName, step.Id); registeredSteps.Remove(step); } foreach (var customApi in registeredCustomApis.Where(c => c.PluginTypeId?.Id == registeredType.Id)) { service.Delete(customApi.LogicalName, customApi.Id); } service.Delete(PluginType.EntityLogicalName, registeredType.Id); } } service.Update(updatedAssembly); } AddSolutionComponentToSolution(service, pluginSolutionUniqueName, assembly.ToEntityReference()); var registeredImages = GetRegisteredImages(service, assembly.Id); Console.WriteLine(); Console.WriteLine(@"Registering Plugins"); foreach (var plugin in pluginList.Where(p => !p.IsWorkflow)) { Console.WriteLine($@" - {plugin.FullName}"); var registeredPluginType = registeredPluginTypes.FirstOrDefault(p => p.Name == plugin.FullName); if (registeredPluginType == null) { registeredPluginType = GetPluginTypeToRegister(assembly.Id, plugin.FullName); registeredPluginType.Id = service.Create(registeredPluginType); } var registeredStepsForPluginType = registeredSteps.Where(s => s.EventHandler.Id == registeredPluginType.Id).ToList(); var comparer = new SdkMessageStepComparer(); foreach (var convertedStep in plugin.Steps) { var stepToRegister = GetStepToRegister(registeredPluginType.Id, convertedStep); var registeredStep = registeredStepsForPluginType.FirstOrDefault(s => comparer.Equals(s, stepToRegister)); if (registeredStep == null) { stepToRegister.Id = service.Create(stepToRegister); } else { registeredSteps.Remove(registeredStep); stepToRegister.Id = registeredStep.Id; if (comparer.NeedsUpdate(stepToRegister, registeredStep)) { var profiledStep = profiledSteps.FirstOrDefault(p => p.Name.StartsWith(registeredStep.Name)); if (profiledStep != null) { service.Delete(profiledStep.LogicalName, profiledStep.Id); service.Execute(new SetStateRequest { EntityMoniker = registeredStep.ToEntityReference(), State = new OptionSetValue((int)SdkMessageProcessingStepState.Enabled), Status = new OptionSetValue(-1) }); } service.Update(stepToRegister); } } AddSolutionComponentToSolution(service, pluginSolutionUniqueName, stepToRegister.ToEntityReference()); if (convertedStep.Message != Messages.Associate.ToString() && convertedStep.Message != Messages.Lose.ToString() && convertedStep.Message != Messages.Win.ToString()) { var registeredPostImage = registeredImages.FirstOrDefault(i => i.Name == "PostImage" && i.SdkMessageProcessingStepId.Id == stepToRegister.Id); if (convertedStep.PostImageUsed && convertedStep.Message != Messages.Delete.ToString()) { if (registeredPostImage == null) { registeredPostImage = GetImageToRegister(service, stepToRegister.Id, convertedStep, false); registeredPostImage.Id = service.Create(registeredPostImage); } else if (registeredPostImage.Attributes1 != convertedStep.JoinedPostImageAttributes) { registeredPostImage.Attributes1 = convertedStep.JoinedPostImageAttributes; service.Update(registeredPostImage); } } else if (registeredPostImage != null) { service.Delete(registeredPostImage.LogicalName, registeredPostImage.Id); } var registeredPreImage = registeredImages.FirstOrDefault(i => i.Name == "PreImage" && i.SdkMessageProcessingStepId.Id == stepToRegister.Id); if (convertedStep.PreImageUsed) { if (registeredPreImage == null) { registeredPreImage = GetImageToRegister(service, stepToRegister.Id, convertedStep, true); registeredPreImage.Id = service.Create(registeredPreImage); } else if (registeredPreImage.Attributes1 != convertedStep.JoinedPreImageAttributes) { registeredPreImage.Attributes1 = convertedStep.JoinedPreImageAttributes; service.Update(registeredPreImage); } } else if (registeredPreImage != null) { service.Delete(registeredPreImage.LogicalName, registeredPreImage.Id); } } } } Console.WriteLine(); Console.WriteLine(@"Registering Custom Workflow activities"); foreach (var customWf in pluginList.Where(p => p.IsWorkflow)) { var registeredPluginType = registeredPluginTypes.FirstOrDefault(p => p.TypeName == customWf.FullName); Console.WriteLine($@" - {customWf.FullName}"); if (registeredPluginType == null) { registeredPluginType = GetCustomWorkflowTypeToRegister(assembly.Id, customWf.FullName, customWf.DisplayName); registeredPluginType.Id = service.Create(registeredPluginType); } if (registeredPluginType.Name != customWf.DisplayName) { registeredPluginType.Name = customWf.DisplayName; service.Update(registeredPluginType); } } Console.WriteLine(); Console.WriteLine(@"Registering Custom Apis"); foreach (var customApi in customApis) { Console.WriteLine($@" - {customApi.FullName}"); var registeredPluginType = registeredPluginTypes.FirstOrDefault(p => p.Name == customApi.FullName); if (registeredPluginType == null) { registeredPluginType = GetPluginTypeToRegister(assembly.Id, customApi.FullName); registeredPluginType.Id = service.Create(registeredPluginType); } customApi.PluginTypeId = new EntityReference(PluginType.EntityLogicalName, registeredPluginType.Id); var existingCustomApi = registeredCustomApis.FirstOrDefault(c => c.UniqueName == customApi.UniqueName); if (existingCustomApi == null) { existingCustomApi = customApi; existingCustomApi.Id = service.Create(customApi); } else { customApi.Id = existingCustomApi.Id; service.Update(customApi); } foreach (var customApiRequestParameter in customApi.InArguments) { var existingRequestParameter = registeredCustomApiRequestParameters.FirstOrDefault(p => p.UniqueName == customApiRequestParameter.UniqueName && p.CustomApiId.Id == existingCustomApi.Id); customApiRequestParameter.CustomApiId = new EntityReference(CustomApi.EntityLogicalName, existingCustomApi.Id); if (existingRequestParameter == null) { service.Create(customApiRequestParameter); } else { customApiRequestParameter.Id = existingRequestParameter.Id; service.Update(customApiRequestParameter); } } foreach (var customApiResponseProperty in customApi.OutArguments) { var existingResponseProperty = registeredCustomApiResponseProperties.FirstOrDefault(p => p.UniqueName == customApiResponseProperty.UniqueName && p.CustomApiId.Id == existingCustomApi.Id); customApiResponseProperty.CustomApiId = new EntityReference(CustomApi.EntityLogicalName, existingCustomApi.Id); if (existingResponseProperty == null) { service.Create(customApiResponseProperty); } else { customApiResponseProperty.Id = existingResponseProperty.Id; service.Update(customApiResponseProperty); } } } Console.WriteLine(); foreach (var step in registeredSteps) { service.Delete(SdkMessageProcessingStep.EntityLogicalName, step.Id); } }