private void btnRegister_Click(object sender, EventArgs e)
        {
            const string ERROR_CAPTION = "Registration Error";
            string       ERROR_MESSAGE;

            if (m_currentAssembly == null)
            {
                ERROR_MESSAGE = "There was an error while registering the selected plugins. Please check the Registration Log for more information.";
            }
            else
            {
                ERROR_MESSAGE = "There was an error while updating the selected plugins. Please check the Registration Log for more information.";
            }

            #region Extract Plugin Registration Information
            m_progRegistration.Complete(true); //Just in case it has incorrect information

            //Determine the source type. If we are talking about an assembly on disk, verify that it exists
            if (GetAssemblySourceType() == CrmAssemblySourceType.Disk)
            {
                if (string.IsNullOrEmpty(txtServerFileName.Text.Trim()))
                {
                    MessageBox.Show("If the Registration Location is Disk, the \"File Name on Server\" must be specified",
                                    "Missing Information", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    m_progRegistration.Complete(false);
                    return;
                }
            }

            //Create a list of currently selected plugins
            bool assemblyCanBeIsolated = true;
            Dictionary <string, CrmPlugin> checkedPluginList = new Dictionary <string, CrmPlugin>();
            foreach (ICrmTreeNode node in trvPlugins.CheckedNodes)
            {
                if (node.NodeType == CrmTreeNodeType.Plugin || node.NodeType == CrmTreeNodeType.WorkflowActivity)
                {
                    CrmPlugin plugin = (CrmPlugin)node;
                    if (CrmPluginIsolatable.No == plugin.Isolatable)
                    {
                        assemblyCanBeIsolated = false;
                    }

                    checkedPluginList.Add(plugin.TypeName, plugin);
                }
            }

            //Check if there are any plugins selected
            if (checkedPluginList.Count == 0)
            {
                MessageBox.Show("No plugins have been selected from the list. Please select at least one and try again.",
                                "No Plugins Selected", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            //Verify that a valid isolation mode has been selected
            if (radIsolationSandbox.Checked && !assemblyCanBeIsolated)
            {
                MessageBox.Show("Since some of the plug-ins cannot be isolated, the assembly cannot be marked as Isolated.",
                                "Isolation", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            //Reload the assembly
            string            assemblyPath = AssemblyPathControl.FileName;
            CrmPluginAssembly assembly;
            if (string.IsNullOrEmpty(assemblyPath))
            {
                //Clone the existing assembly
                assembly = (CrmPluginAssembly)m_currentAssembly.Clone(false);
            }
            else
            {
                assembly = RegistrationHelper.RetrievePluginsFromAssembly(assemblyPath);

                //Retrieve the source type and determine if the
                assembly.SourceType = GetAssemblySourceType();
                if (CrmAssemblySourceType.Disk != assembly.SourceType)
                {
                    assembly.ServerFileName = null;
                }
                else
                {
                    assembly.ServerFileName = txtServerFileName.Text;
                }
            }

            // Ensure the checked items were all found in the assembly
            var registerPluginList = new List <CrmPlugin>();
            var pluginList         = new List <CrmPlugin>();
            var removedPluginList  = new List <CrmPlugin>();
            var missingPluginList  = new List <CrmPlugin>();

            try
            {
                Parallel.ForEach(assembly.Plugins.Values, (currentPlugin) => {
                    var foundPlugin    = m_registeredPluginList.Where(x => x.TypeName.ToLowerInvariant() == currentPlugin.TypeName.ToLowerInvariant()).FirstOrDefault();
                    var alreadyExisted = (m_registeredPluginList != null && foundPlugin != null);

                    if (alreadyExisted)
                    {
                        currentPlugin.AssemblyId = m_currentAssembly.AssemblyId;
                        currentPlugin.PluginId   = foundPlugin.PluginId;
                    }

                    if (checkedPluginList.ContainsKey(currentPlugin.TypeName))
                    {
                        registerPluginList.Add(currentPlugin);

                        if (currentPlugin.PluginType == CrmPluginType.Plugin)
                        {
                            pluginList.Add(currentPlugin);
                        }
                    }
                    else if (alreadyExisted)
                    {
                        removedPluginList.Add(currentPlugin);
                    }
                });

                if (m_registeredPluginList != null)
                {
                    Parallel.ForEach(m_registeredPluginList, (currentRecord) => {
                        if (!assembly.Plugins.Values.ToList().Any(x => x.TypeName.ToLowerInvariant() == currentRecord.TypeName.ToLowerInvariant()))
                        {
                            missingPluginList.Add(currentRecord);
                        }
                    });
                }
            }
            catch (Exception ex)
            {
                ErrorMessageForm.ShowErrorMessageBox(this, "Unable to load the specified Plugin Assembly", "Plugins", ex);
                return;
            }

            //Update the assembly with the information specified by the user
            assembly.IsolationMode = GetIsolationMode();

            if (missingPluginList.Count != 0)
            {
                var list = missingPluginList.Select(x => x.TypeName).Aggregate((name01, name02) => name01 + "\n" + name02);

                MessageBox.Show($"Following plugin are missing in the assembly:\n\n{list}\n\nRegistration cannot continue!",
                                "Plugins are missing", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            //An assembly with plugins must be strongly signed
            if (pluginList.Count != 0)
            {
                if (string.IsNullOrEmpty(assembly.PublicKeyToken))
                {
                    MessageBox.Show("Assemblies containing Plugins must be strongly signed. Sign the Assembly using a KeyFile.",
                                    "Strong Names Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
            }

            //Check if there are any plugins selected that were in the assembly.
            if (registerPluginList.Count == 0)
            {
                MessageBox.Show("No plugins have been selected from the list. Please select at least one and try again.",
                                "No Plugins Selected", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            else
            {
                assembly.ClearPlugins();
            }

            //If we are doing an Update, do some special processing
            if (m_currentAssembly != null)
            {
                assembly.AssemblyId = m_currentAssembly.AssemblyId;
            }
            #endregion

            #region Register Plugin
            m_progRegistration.Initialize(registerPluginList.Count + removedPluginList.Count, "Preparing Registration");

            int  registeredAssemblies = 0;
            int  ignoredAssemblies    = 0;
            int  updatedAssemblies    = 0;
            bool createAssembly;

            //Check whether the plugin exists. If it exists, should we use the existing one?
            var retrieveDateList = new List <ICrmEntity>();
            try
            {
                Guid pluginAssemblyId = Guid.Empty;
                if (m_currentAssembly != null)
                {
                    if (chkUpdateAssembly.Checked)
                    {
                        string originalGroupName = RegistrationHelper.GenerateDefaultGroupName(m_currentAssembly.Name, new Version(m_currentAssembly.Version));
                        string newGroupName      = RegistrationHelper.GenerateDefaultGroupName(assembly.Name, new Version(assembly.Version));

                        var updateGroupNameList = new List <PluginType>();
                        foreach (var plugin in m_currentAssembly.Plugins)
                        {
                            if (plugin.PluginType == CrmPluginType.WorkflowActivity && string.Equals(plugin.WorkflowActivityGroupName, originalGroupName))
                            {
                                updateGroupNameList.Add(new PluginType()
                                {
                                    Id = plugin.PluginId,
                                    WorkflowActivityGroupName = newGroupName
                                });
                            }
                        }

                        //Do the actual update to the assembly
                        RegistrationHelper.UpdateAssembly(m_org, assemblyPath, assembly, updateGroupNameList.ToArray());

                        m_currentAssembly.Name               = assembly.Name;
                        m_currentAssembly.Culture            = assembly.Culture;
                        m_currentAssembly.CustomizationLevel = assembly.CustomizationLevel;
                        m_currentAssembly.PublicKeyToken     = assembly.PublicKeyToken;
                        m_currentAssembly.ServerFileName     = assembly.ServerFileName;
                        m_currentAssembly.SourceType         = assembly.SourceType;
                        m_currentAssembly.Version            = assembly.Version;
                        m_currentAssembly.IsolationMode      = assembly.IsolationMode;

                        retrieveDateList.Add(m_currentAssembly);

                        foreach (var type in updateGroupNameList)
                        {
                            var plugin = m_currentAssembly.Plugins[type.Id];

                            plugin.WorkflowActivityGroupName = type.WorkflowActivityGroupName;
                            retrieveDateList.Add(plugin);
                        }

                        updatedAssemblies++;
                    }
                    else if (!chkUpdateAssembly.Visible && assembly.IsolationMode != m_currentAssembly.IsolationMode)
                    {
                        var updateAssembly = new PluginAssembly()
                        {
                            Id            = assembly.AssemblyId,
                            IsolationMode = new OptionSetValue((int)assembly.IsolationMode)
                        };

                        m_org.OrganizationService.Update(updateAssembly);

                        m_currentAssembly.ServerFileName = assembly.ServerFileName;
                        m_currentAssembly.SourceType     = assembly.SourceType;
                        m_currentAssembly.IsolationMode  = assembly.IsolationMode;

                        retrieveDateList.Add(m_currentAssembly);

                        updatedAssemblies++;
                    }

                    assembly = m_currentAssembly;

                    createAssembly = false;
                    m_progRegistration.Increment();

                    m_orgControl.RefreshAssembly(m_currentAssembly, false);
                }
                else
                {
                    createAssembly = true;
                    m_progRegistration.Increment();
                }
            }
            catch (Exception ex)
            {
                m_progRegistration.Increment("ERROR: Occurred while checking whether the assembly exists");

                ErrorMessageForm.ShowErrorMessageBox(this, ERROR_MESSAGE, ERROR_CAPTION, ex);

                m_progRegistration.Complete(false);
                return;
            }

            //Register the assembly (if needed)
            if (createAssembly)
            {
                try
                {
                    assembly.AssemblyId   = RegistrationHelper.RegisterAssembly(m_org, assemblyPath, assembly);
                    assembly.Organization = m_org;

                    retrieveDateList.Add(assembly);
                }
                catch (Exception ex)
                {
                    m_progRegistration.Increment("ERROR: Error occurred while registering the assembly");

                    ErrorMessageForm.ShowErrorMessageBox(this, ERROR_MESSAGE, ERROR_CAPTION, ex);

                    m_progRegistration.Complete(false);
                    return;
                }

                registeredAssemblies++;
                m_progRegistration.Increment("SUCCESS: Plugin Assembly was registered");
            }
            else if (m_currentAssembly == null)
            {
                ignoredAssemblies++;
                m_progRegistration.Increment("INFORMATION: Assembly was not registered");
            }
            else
            {
                if (chkUpdateAssembly.Checked)
                {
                    m_progRegistration.Increment("SUCCESS: Assembly was updated");
                }
                else
                {
                    m_progRegistration.Increment("INFORMATION: Assembly was not updated");
                }
            }

            //Check to see if the assembly needs to be added to the list
            if (!m_org.Assemblies.ContainsKey(assembly.AssemblyId))
            {
                m_org.AddAssembly(assembly);

                //Update the Main Form
                try
                {
                    m_orgControl.AddAssembly(assembly);
                    m_progRegistration.Increment();
                }
                catch (Exception ex)
                {
                    m_progRegistration.Increment("ERROR: Error occurred while updating the Main form for the assembly");

                    ErrorMessageForm.ShowErrorMessageBox(this, ERROR_MESSAGE, ERROR_CAPTION, ex);

                    m_progRegistration.Complete(false);
                    return;
                }
            }
            else
            {
                m_progRegistration.Increment();
            }

            // Register the Plugin
            bool createPlugin;
            int  registeredPlugins = 0;
            int  ignoredPlugins    = 0;
            int  errorsPlugins     = 0;

            foreach (var currentPlugin in registerPluginList)
            {
                currentPlugin.AssemblyId = assembly.AssemblyId;

                //Check if the plugin exists
                bool pluginUpdate = m_registeredPluginList != null && m_registeredPluginList.Any(x => x.TypeName.ToLowerInvariant() == currentPlugin.TypeName.ToLowerInvariant());
                try
                {
                    Guid pluginTypeId = Guid.Empty;

                    if (pluginUpdate || (!createAssembly && RegistrationHelper.PluginExists(m_org, currentPlugin.TypeName, assembly.AssemblyId, out pluginTypeId)))
                    {
                        if (pluginUpdate)
                        {
                            createPlugin = false;
                        }
                        else
                        {
                            m_progRegistration.AppendText(string.Format("INFORMATION: Plugin Type Name is already being used by PluginType {0}.", pluginTypeId));

                            switch (MessageBox.Show(string.Format("The specified name \"{0}\" is already registered. Skip the registration of this plugin?\n\nPlease note the plugins may not be the same.", currentPlugin.TypeName),
                                                    "Plugin Already Exists", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question))
                            {
                            case DialogResult.Yes:
                                createPlugin = false;

                                currentPlugin.PluginId     = pluginTypeId;
                                currentPlugin.Organization = assembly.Organization;
                                break;

                            case DialogResult.No:
                                createPlugin = true;
                                break;

                            case DialogResult.Cancel:
                                m_progRegistration.AppendText("ABORTED: Plugin Registration has been aborted by the user.");
                                m_progRegistration.Complete(false);
                                return;

                            default:
                                throw new NotImplementedException();
                            }
                        }

                        m_progRegistration.Increment();
                    }
                    else
                    {
                        createPlugin = true;
                        m_progRegistration.Increment();
                    }
                }
                catch (Exception ex)
                {
                    m_progRegistration.Increment(string.Format("ERROR: Occurred while checking if {0} is already registered.",
                                                               currentPlugin.TypeName));

                    ErrorMessageForm.ShowErrorMessageBox(this, ERROR_MESSAGE, ERROR_CAPTION, ex);

                    m_progRegistration.Complete(false);
                    return;
                }

                //Create the plugin (if necessary)
                if (createPlugin)
                {
                    try
                    {
                        Guid pluginId = currentPlugin.PluginId;
                        currentPlugin.PluginId     = RegistrationHelper.RegisterPlugin(m_org, currentPlugin);
                        currentPlugin.Organization = m_org;

                        if (pluginId != currentPlugin.PluginId && assembly.Plugins.ContainsKey(pluginId))
                        {
                            assembly.RemovePlugin(pluginId);
                        }

                        retrieveDateList.Add(currentPlugin);

                        m_progRegistration.Increment(string.Format("SUCCESS: Plugin {0} was registered.",
                                                                   currentPlugin.TypeName));

                        registeredPlugins++;
                    }
                    catch (Exception ex)
                    {
                        m_progRegistration.Increment(2, string.Format("ERROR: Occurred while registering {0}.",
                                                                      currentPlugin.TypeName));

                        ErrorMessageForm.ShowErrorMessageBox(this, ERROR_MESSAGE, ERROR_CAPTION, ex);

                        errorsPlugins++;
                        continue;
                    }
                }
                else
                {
                    if (!pluginUpdate)
                    {
                        ignoredPlugins++;
                    }

                    m_progRegistration.Increment();
                }

                //Check if the plugin needs to be added to the list
                if (!assembly.Plugins.ContainsKey(currentPlugin.PluginId))
                {
                    assembly.AddPlugin(currentPlugin);

                    //Update the main form
                    try
                    {
                        m_orgControl.AddPlugin(currentPlugin);
                        m_progRegistration.Increment();
                    }
                    catch (Exception ex)
                    {
                        m_progRegistration.Increment(string.Format("ERROR: Occurred while updating the Main form for {0}.",
                                                                   currentPlugin.TypeName));

                        ErrorMessageForm.ShowErrorMessageBox(this, ERROR_MESSAGE, ERROR_CAPTION, ex);

                        m_progRegistration.Complete(false);
                        return;
                    }
                }
                else
                {
                    m_progRegistration.Increment();
                }
            }

            // Unregister plugins that were unchecked
            int updatedPlugins = 0;
            foreach (var currectPlugin in removedPluginList)
            {
                //Check if the plugin exists
                try
                {
                    RegistrationHelper.Unregister(m_org, currectPlugin);
                    m_progRegistration.Increment(3, string.Format("SUCCESS: Plugin {0} was unregistered.", currectPlugin.TypeName));
                    m_orgControl.RemovePlugin(currectPlugin.PluginId);

                    updatedPlugins++;
                }
                catch (Exception ex)
                {
                    m_progRegistration.Increment(3, string.Format("ERROR: Occurred while unregistering {0}.", currectPlugin.TypeName));

                    ErrorMessageForm.ShowErrorMessageBox(this, ERROR_MESSAGE, ERROR_CAPTION, ex);

                    errorsPlugins++;
                }
            }

            //Update the entities whose Created On / Modified On dates changed
            try
            {
                OrganizationHelper.UpdateDates(m_org, retrieveDateList);
                m_progRegistration.Increment("SUCCESS: Created On / Modified On dates updated");
            }
            catch (Exception ex)
            {
                m_progRegistration.Increment("ERROR: Unable to update Created On / Modified On dates");

                ErrorMessageForm.ShowErrorMessageBox(this, "Unable to update Created On / Modified On dates", "Update Error", ex);
            }
            #endregion

            m_progRegistration.AppendText("SUCCESS: Selected Plugins have been registered");
            m_progRegistration.Complete(false);

            MessageBox.Show(string.Format("The selected Plugins have been registered.\n{0} Assembly Registered\n{1} Assembly Ignored\n{2} Assembly Updated\n{3} Plugin(s) Registered\n{4} Plugin(s) Ignored\n{5} Plugin(s) Encountered Errors\n{6} Plugin(s) Removed",
                                          registeredAssemblies, ignoredAssemblies, updatedAssemblies, registeredPlugins, ignoredPlugins, errorsPlugins, updatedPlugins),
                            "Registered Plugins", MessageBoxButtons.OK, MessageBoxIcon.Information);

            if (errorsPlugins == 0)
            {
                Close();
            }
        }
Ejemplo n.º 2
0
        public CrmPluginAssembly RetrievePluginsFromAssembly(string path)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }
            else if (!File.Exists(path))
            {
                throw new ArgumentException("Path does not point to an existing file");
            }

            //Load the assembly
            var assembly         = LoadAssembly(path);
            var assemblyName     = assembly.GetName();
            var defaultGroupName = RegistrationHelper.GenerateDefaultGroupName(assemblyName.Name, assemblyName.Version);

            //Retrieve the assembly properties
            var pluginAssembly = RetrieveAssemblyProperties(assembly, path);

            //Loop through each type and process it
            var errorList = new List <string>();

            foreach (var t in assembly.GetExportedTypes())
            {
                //Plugins and Workflow Activities must be non-abstract classes
                if (t.IsAbstract || !t.IsClass)
                {
                    continue;
                }

                // Plugins must implement the IPlugin interface
                string              errorMessage = null;
                CrmPluginType       type;
                CrmPluginIsolatable isolatable;

                //Retrieve the two interface types
                Type xrmPlugin = t.GetInterface(typeof(IPlugin).FullName);
                var  v4Plugin  = t.GetInterface("Microsoft.Crm.Sdk.IPlugin");

                var workflowGroupName = defaultGroupName;
                var pluginName        = t.FullName;

                Version sdkVersion = null;
                if (null != xrmPlugin)
                {
                    type       = CrmPluginType.Plugin;
                    isolatable = CrmPluginIsolatable.Yes;
                    sdkVersion = xrmPlugin.Assembly.GetName().Version;
                }
                else if (null != v4Plugin)
                {
                    type       = CrmPluginType.Plugin;
                    isolatable = CrmPluginIsolatable.No;
                }
                else if (t.IsSubclassOf(typeof(CodeActivity)) || t.IsSubclassOf(typeof(Activity)))
                {
                    type       = CrmPluginType.WorkflowActivity;
                    isolatable = CrmPluginIsolatable.Yes;
                }
                else
                {
                    continue;
                }

                if (errorMessage != null)
                {
                    errorList.Add(errorMessage);
                }
                else
                {
                    var plugin = new CrmPlugin(null)
                    {
                        TypeName     = t.FullName,
                        Name         = pluginName,
                        PluginType   = type,
                        PluginId     = Guid.NewGuid(),
                        AssemblyId   = pluginAssembly.AssemblyId,
                        AssemblyName = pluginAssembly.Name,
                        Isolatable   = isolatable
                    };

                    if (type == CrmPluginType.WorkflowActivity && !string.IsNullOrWhiteSpace(workflowGroupName))
                    {
                        plugin.WorkflowActivityGroupName = workflowGroupName;
                    }

                    pluginAssembly.AddPlugin(plugin);
                }
            }

            return(pluginAssembly);
        }