private Guid _CreateAssembly(byte[] assemblyData, bool sandbox)
        {
            UpdateStatus("Creating assembly ... ", 1);

            var assemblyInfo = AssemblyHelper.GetAssemblyInfo(typeof(IPlugin).FullName);

            var assembly = new PluginAssembly
            {
                Name          = DteHelper.GetProjectName(),
                IsolationMode = (sandbox
                                                                        ? PluginAssembly.Enums.IsolationMode.Sandbox
                                                                        : PluginAssembly.Enums.IsolationMode.None).ToOptionSetValue(),
                Content    = Convert.ToBase64String(assemblyData),
                SourceType = PluginAssembly.Enums.SourceType.Database.ToOptionSetValue(),
                Culture    = assemblyInfo.CultureInfo.LCID == CultureInfo.InvariantCulture.LCID
                                                                 ? "neutral"
                                                                 : assemblyInfo.CultureInfo.Name
            };

            Context.AddObject(assembly);
            UpdateStatus("Saving new assembly to CRM ...");
            Context.SaveChanges();
            Id = assembly.Id;

            AddNewTypes(GetExistingTypeNames());

            //UpdateStatus("Saving new types to CRM ...");
            //Context.SaveChanges();

            UpdateStatus("Finished creating assembly. ID => " + Id, -1);

            OnRegActionTaken(RegistrationEvent.Create);

            return(Id);
        }
        private void AddNewTypes(ICollection <string> existingTypeNames)
        {
            UpdateStatus("Adding new types ... ", 1);

            var pluginClasses = AssemblyHelper.GetClasses <IPlugin>();
            var wfClasses     = AssemblyHelper.GetClasses <CodeActivity>();

            pluginClasses.Where(pluginType => !existingTypeNames.Contains(pluginType)).ToList()
            .ForEach(pluginType =>
            {
                var className = pluginType.Split('.')[pluginType.Split('.').Length - 1];

                UpdateStatus($"Adding plugin '{className}' ... ", 1);

                var newType = new PluginType
                {
                    PluginTypeId     = Guid.NewGuid(),
                    Name             = pluginType,
                    TypeName         = pluginType,
                    FriendlyName     = className,
                    PluginAssemblyId =
                        new EntityReference(PluginAssembly.EntityLogicalName, Id)
                };

                Service.Create(newType);
                //Context.AddObject(newType);

                UpdateStatus($"Finished adding plugin '{className}'.", -1);
            });

            // create new types
            wfClasses.Where(pluginType => !existingTypeNames.Contains(pluginType)).ToList()
            .ForEach(pluginType =>
            {
                var className = pluginType.Split('.')[pluginType.Split('.').Length - 1];

                UpdateStatus($"Adding custom step '{className}' ... ", 1);

                var newType = new PluginType
                {
                    PluginTypeId     = Guid.NewGuid(),
                    Name             = pluginType,
                    TypeName         = pluginType,
                    FriendlyName     = className,
                    PluginAssemblyId =
                        new EntityReference(PluginAssembly.EntityLogicalName, Id),
                    WorkflowActivityGroupName
                        = string.Format(CultureInfo.InvariantCulture, "{0} ({1})",
                                        DteHelper.GetProjectName(), AssemblyHelper.GetAssemblyVersion())
                };

                Service.Create(newType);
                //Context.AddObject(newType);

                UpdateStatus($"Finished adding custom step '{className}'.", -1);
            });

            UpdateStatus("Finished adding new types.", -1);
        }
        private void RefreshTypes(List <string> existingTypeNames)
        {
            var wfClasses = AssemblyHelper.GetClasses <CodeActivity>();

            if (wfClasses.Any())
            {
                UpdateStatus("Refreshing custom steps ... ", 1);

                // create new types
                wfClasses.Where(existingTypeNames.Contains).ToList()
                .ForEach(pluginType =>
                {
                    var className = pluginType.Split('.')[pluginType.Split('.').Length - 1];

                    UpdateStatus($"Refreshing '{className}' ... ", 1);

                    var typeId = (from typeQ in Context.PluginTypeSet
                                  where typeQ.TypeName == pluginType
                                  select typeQ.PluginTypeId).First();

                    if (typeId == null)
                    {
                        throw new Exception("Failed to get plugin type ID.");
                    }

                    //var updatedType = Context.PluginTypeSet.FirstOrDefault(entity => entity.PluginTypeId == typeId)
                    //				   ?? new PluginType();

                    var updatedType = new PluginType
                    {
                        PluginTypeId              = typeId,
                        Name                      = pluginType,
                        TypeName                  = pluginType,
                        FriendlyName              = className,
                        PluginAssemblyId          = new EntityReference(PluginAssembly.EntityLogicalName, Id),
                        WorkflowActivityGroupName = string.Format(CultureInfo.InvariantCulture, "{0} ({1})",
                                                                  DteHelper.GetProjectName(), AssemblyHelper.GetAssemblyVersion())
                    };

                    //if (updatedType.Id == Guid.Empty)
                    //{
                    // updatedType.Id = typeId.Value;
                    //}


                    //Context.ConfirmAttached(updatedType);
                    //Context.UpdateObject(updatedType);
                    UpdateStatus($"Refreshing type '{updatedType.Id}' ... ");
                    Service.Update(updatedType);

                    UpdateStatus($"Finished refreshing '{className}'.", -1);
                });

                UpdateStatus("Finished refreshing custom steps.", -1);
            }
        }
        /// <summary>
        ///     This function is the callback used to execute a command when the a menu item is clicked.
        ///     See the Initialize method to see how the menu item is associated to this function using
        ///     the OleMenuCommandService service and the MenuCommand class.
        /// </summary>
        private async Task RegisterModifyPluginCallbackAsync(object sender, EventArgs args)
        {
            try
            {
                var session = Math.Abs(DateTime.Now.ToString(CultureInfo.CurrentCulture).GetHashCode());
                Status.Update($">>>>> Starting new session: {session} <<<<<");

                var selected = DteHelper.GetSelectedProjects().ToArray();

                if (!selected.Any())
                {
                    throw new UserException("Please select a project first.");
                }

                foreach (var project in selected)
                {
                    Status.Update($">>> Processing project: {DteHelper.GetProjectName(project)} <<<");

                    DteHelper.SetCurrentProject(project);
                    AssemblyHelper.BuildProject();

                    await RegisterModifyPluginAsync();

                    Status.Update($"^^^ Finished processing project: {DteHelper.GetProjectName(project)} ^^^");
                }

                Status.Update($"^^^^^ Finished session: {session} ^^^^^");
            }
            catch (UserException e)
            {
                VsShellUtilities.ShowMessageBox(ServiceProvider.GlobalProvider, e.Message, "Error", OLEMSGICON.OLEMSGICON_WARNING,
                                                OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
            }
            catch (Exception e)
            {
                var error1 = "[ERROR] " + e.Message
                             + (e.InnerException != null ? "\n" + "[ERROR] " + e.InnerException.Message : "");
                Status.Update(error1);
                Status.Update(e.StackTrace);
                Status.Update("Unable to register assembly, see error above.");
                var error2 = e.Message + "\n" + e.StackTrace;
                MessageBox.Show(error2, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                Status.Update(">>>>> DONE! <<<<<");
            }
        }
        private async Task UpdatePluginAsync()
        {
            var settingsArray = Configuration.LoadSettings();
            var settings      = settingsArray.GetSelectedSettings();

            // if no connection info, then it's a new run
            if (settings.ConnectionString.IsEmpty())
            {
                await RegisterModifyPluginAsync();
            }
            else
            {
                var connectionManager    = new ConnectionManager(settings.ConnectionString);
                var registrationFeedback = new RegistrationFeedback();
                var registrationLogger   = new DefaultPluginRegLogger(m => Status.Update(m));

                var assemblyPath = AssemblyHelper.GetAssemblyPath();
                var assemblyName = AssemblyHelper.GetAssemblyName();

                var registration = new AssemblyRegistration(settings, assemblyPath, connectionManager, registrationFeedback);

                registration.RegLogEntryAdded +=
                    (o, args) =>
                {
                    lock (registration.LoggingLock)
                    {
                        Status.Update(args.Message);
                    }
                };

                // if the assembly is registered, update
                if (CrmAssemblyHelpers.IsAssemblyRegistered(assemblyName, connectionManager, registrationLogger))
                {
                    registration.UpdateAssembly(null);
                    Status.Update($"Ran update on: {Regex.Replace(settings.ConnectionString, @"Password\s*?=.*?(?:;{0,1}$|;)", "Password=********;").Replace("\r\n", " ")}.");
                    Status.Update($"For project: {DteHelper.GetProjectName(DteHelper.CurrentProject)}.");
                }
                else
                {
                    // else open dialogue
                    await RegisterModifyPluginAsync();
                }
            }
        }
Exemple #6
0
        private void UpdatePlugin(Project project)
        {
            DteHelper.SetCurrentProject(project);

            var settingsArray = Configuration.LoadConfigs();
            var settings      = settingsArray.GetSelectedSettings();

            // if an ID does not exist and no connection info, then it's a new run
            if (settings.Id == Guid.Empty &&
                (string.IsNullOrEmpty(settings.ServerName) || string.IsNullOrEmpty(settings.Username)))
            {
                CopySettings();
                RegisterModifyPlugin(project);
            }
            else
            {
                using (var service = ConnectionHelper.GetConnection(settings.GetOrganizationCrmConnectionString()))
                {
                    var context      = new XrmServiceContext(service);
                    var registration = new AssemblyRegistration(context, service);

                    registration.PropertyChanged +=
                        (o, args) =>
                    {
                        try
                        {
                            switch (args.PropertyName)
                            {
                            case "LogMessage":
                                lock (registration.LoggingLock)
                                {
                                    Status.Update(registration.LogMessage);
                                }
                                break;
                            }
                        }
                        catch
                        {
                            // ignored
                        }
                    };

                    // if the assembly is registered, get ID and update
                    if (CrmAssemblyHelper.IsAssemblyRegistered(context))
                    {
                        var id = settings.Id == Guid.Empty
                                                        ? CrmAssemblyHelper.GetAssemblyId(context)
                                                        : settings.Id;
                        registration.UpdateAssembly(id, null);
                        Status.Update($"Ran update on: {settings.ServerName} - {settings.CrmOrg} - {settings.Username}.");
                        Status.Update($"For project: {DteHelper.GetProjectName(project)}.");
                    }
                    else
                    {
                        // else, reset and open dialogue
                        // reset ID
                        settings.Id = Guid.Empty;
                        Configuration.SaveConfigs(settingsArray);

                        RegisterModifyPlugin(project);
                    }
                }
            }
        }