private async Task CheckingPluginSteps(ConnectionData connectionData, CommonConfiguration commonConfig)
        {
            if (connectionData == null)
            {
                this._iWriteToOutput.WriteToOutput(connectionData, Properties.OutputStrings.NoCurrentCRMConnection);
                return;
            }

            StringBuilder content = new StringBuilder();

            content.AppendLine(this._iWriteToOutput.WriteToOutput(connectionData, Properties.OutputStrings.ConnectingToCRM));

            content.AppendLine(this._iWriteToOutput.WriteToOutput(connectionData, connectionData.GetConnectionDescription()));

            // Подключаемся к CRM.
            var service = await QuickConnection.ConnectAsync(connectionData);

            if (service == null)
            {
                this._iWriteToOutput.WriteToOutput(connectionData, Properties.OutputStrings.ConnectionFailedFormat1, connectionData.Name);
                return;
            }

            content.AppendLine(this._iWriteToOutput.WriteToOutput(connectionData, Properties.OutputStrings.CurrentServiceEndpointFormat1, service.CurrentServiceEndpoint));

            var repository = new PluginSearchRepository(service);

            var search = await repository.FindAllAsync(null, string.Empty, string.Empty, string.Empty);

            var querySteps = search.SdkMessageProcessingStep
                            .OrderBy(ent => ent.EventHandler?.Name ?? "Unknown")
                            .ThenBy(ent => ent.PrimaryObjectTypeCodeName)
                            .ThenBy(ent => ent.SdkMessageId?.Name ?? "Unknown", new MessageComparer())
                            .ThenBy(ent => ent.Stage.Value)
                            .ThenBy(ent => ent.Mode.Value)
                            .ThenBy(ent => ent.Rank)
                            .ThenBy(ent => ent.Name)
                            ;

            var pluginTypesWithConflicts = querySteps.GroupBy(step => new
            {
                EventHandlerId = step.EventHandler.Id,
                Stage = step.Stage.Value,

                EntityName = step.PrimaryObjectTypeCodeName,
                Message = step.SdkMessageId?.Name ?? "Unknown",

                EventHandlerName = step.EventHandler?.Name ?? "Unknown",
                step.Configuration,
            }).Where(gr => gr.Count() > 1);

            int pluginTypeNumber = 1;

            bool hasInfo = false;

            foreach (var gr in pluginTypesWithConflicts)
            {
                hasInfo = true;

                if (content.Length > 0)
                {
                    content.AppendLine().AppendLine();
                }

                content.AppendFormat("{0}. {1}", pluginTypeNumber, gr.Key.EventHandlerName).AppendLine();

                content.AppendFormat("Entity '{0}',   Message '{1}',   Stage '{2}'"
                    , gr.Key.EntityName
                    , gr.Key.Message
                    , SdkMessageProcessingStepRepository.GetStageName(gr.Key.Stage, null)
                    ).AppendLine();

                if (!string.IsNullOrEmpty(gr.Key.Configuration))
                {
                    content.AppendFormat("Configuration: {0}", gr.Key.Configuration).AppendLine();
                }

                foreach (var step in gr)
                {
                    content.AppendFormat("Stage '{0}',   Rank {1},   Statuscode {2}"
                        , SdkMessageProcessingStepRepository.GetStageName(step.Stage.Value, step.Mode.Value)
                        , step.Rank.ToString()
                        , step.FormattedValues[SdkMessageProcessingStep.Schema.Attributes.statuscode]
                        ).AppendLine();

                    var queryImage = from image in search.SdkMessageProcessingStepImage
                                     where image.SdkMessageProcessingStepId != null
                                     where image.SdkMessageProcessingStepId.Id == step.Id
                                     orderby image.ImageType.Value, image.CreatedOn, image.Name
                                     select image;

                    int numberImage = 1;

                    foreach (var image in queryImage)
                    {
                        string imageDescription = GetImageDescription(numberImage.ToString(), image);

                        var coll = imageDescription.Split(new string[] { "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);

                        foreach (var item in coll)
                        {
                            content.AppendLine(tabSpacer + tabSpacer + item);
                        }

                        numberImage++;
                    }
                }

                pluginTypeNumber++;
            }

            if (!hasInfo)
            {
                content.AppendLine(this._iWriteToOutput.WriteToOutput(connectionData, "No duplicates were found."));
            }

            string fileName = string.Format("{0}.Checking Plugin Steps Duplicates at {1}.txt", connectionData.Name, DateTime.Now.ToString("yyyy.MM.dd HH-mm-ss"));

            if (string.IsNullOrEmpty(commonConfig.FolderForExport))
            {
                _iWriteToOutput.WriteToOutput(null, Properties.OutputStrings.FolderForExportIsEmpty);
                commonConfig.FolderForExport = FileOperations.GetDefaultFolderForExportFilePath();
            }
            else if (!Directory.Exists(commonConfig.FolderForExport))
            {
                _iWriteToOutput.WriteToOutput(null, Properties.OutputStrings.FolderForExportDoesNotExistsFormat1, commonConfig.FolderForExport);
                commonConfig.FolderForExport = FileOperations.GetDefaultFolderForExportFilePath();
            }

            string filePath = Path.Combine(commonConfig.FolderForExport, FileOperations.RemoveWrongSymbols(fileName));

            File.WriteAllText(filePath, content.ToString(), new UTF8Encoding(false));

            this._iWriteToOutput.WriteToOutput(connectionData, "Created file with Checking Plugin Steps Duplicates: {0}", filePath);

            this._iWriteToOutput.PerformAction(service.ConnectionData, filePath);
        }
        private async Task CheckingPluginStepsRequiredComponents(ConnectionData connectionData, CommonConfiguration commonConfig)
        {
            if (connectionData == null)
            {
                this._iWriteToOutput.WriteToOutput(connectionData, Properties.OutputStrings.NoCurrentCRMConnection);
                return;
            }

            StringBuilder content = new StringBuilder();

            content.AppendLine(this._iWriteToOutput.WriteToOutput(connectionData, Properties.OutputStrings.ConnectingToCRM));

            content.AppendLine(this._iWriteToOutput.WriteToOutput(connectionData, connectionData.GetConnectionDescription()));

            // Подключаемся к CRM.
            var service = await QuickConnection.ConnectAsync(connectionData);

            if (service == null)
            {
                this._iWriteToOutput.WriteToOutput(connectionData, Properties.OutputStrings.ConnectionFailedFormat1, connectionData.Name);
                return;
            }

            content.AppendLine(this._iWriteToOutput.WriteToOutput(connectionData, Properties.OutputStrings.CurrentServiceEndpointFormat1, service.CurrentServiceEndpoint));

            var repository = new PluginSearchRepository(service);

            var search = await repository.FindAllAsync(new List<PluginStage>(), string.Empty, string.Empty, string.Empty);

            var querySteps = search.SdkMessageProcessingStep
                            .OrderBy(ent => ent.EventHandler.Name)
                            .ThenBy(ent => ent.PrimaryObjectTypeCodeName)
                            .ThenBy(ent => ent.SdkMessageId.Name, new MessageComparer())
                            .ThenBy(ent => ent.Stage.Value)
                            .ThenBy(ent => ent.Mode.Value)
                            .ThenBy(ent => ent.Rank)
                            .ThenBy(ent => ent.Name)
                            ;

            EntityMetadataRepository repositoryMetadata = new EntityMetadataRepository(service);

            DependencyRepository dependencyRepository = new DependencyRepository(service);

            var listMetaData = await repositoryMetadata.GetEntitiesWithAttributesAsync();

            var dictEntity = new Dictionary<Guid, EntityMetadata>();
            var dictAttribute = new Dictionary<Guid, AttributeMetadata>();

            bool hasInfo = false;

            foreach (var metaEntity in listMetaData)
            {
                dictEntity.Add(metaEntity.MetadataId.Value, metaEntity);

                foreach (var metaAttribute in metaEntity.Attributes)
                {
                    dictAttribute.Add(metaAttribute.MetadataId.Value, metaAttribute);
                }
            }

            foreach (var step in querySteps)
            {
                var listRequired = await dependencyRepository.GetRequiredComponentsAsync((int)ComponentType.SdkMessageProcessingStep, step.Id);

                var stepEntities = GetSetEntites(step);
                var stepAttributes = GetSetStepAttributes(step);

                var componentsEntities = GetSetComponentsEntites(listRequired, dictEntity);
                var componentsAttributes = GetSetComponentsAttributes(listRequired, dictAttribute);

                bool entitiesIsSame = stepEntities.SequenceEqual(componentsEntities);
                bool attributesIsSame = stepAttributes.SequenceEqual(componentsAttributes);

                if (!entitiesIsSame || !attributesIsSame)
                {
                    if (content.Length > 0)
                    {
                        content.AppendLine().AppendLine().AppendLine();
                    }

                    content.AppendFormat("{0}   Primary {1}   Secondary {2}   Message {3}   Stage {4}   Rank {5}   Status {6}   FilteringAttributes {7}",
                        step.EventHandler?.Name ?? "Unknown"
                        , step.PrimaryObjectTypeCodeName
                        , step.SecondaryObjectTypeCodeName
                        , step.SdkMessageId?.Name ?? "Unknown"
                        , SdkMessageProcessingStepRepository.GetStageName(step.Stage.Value, step.Mode.Value)
                        , step.Rank.ToString()
                        , step.FormattedValues[SdkMessageProcessingStep.Schema.Attributes.statuscode]
                        , step.FilteringAttributesStringsSorted
                    ).AppendLine();

                    if (!entitiesIsSame)
                    {
                        hasInfo = true;

                        content.AppendLine("Conflict in entites.");

                        content.Append("Entities in plugin step description");

                        if (stepEntities.Count > 0)
                        {
                            content.AppendLine(":");

                            foreach (var item in stepEntities)
                            {
                                content.AppendFormat("    {0}", item).AppendLine();
                            }
                        }
                        else
                        {
                            content.AppendLine(" are empty.");
                        }


                        content.Append("Entities in required components");

                        if (componentsEntities.Count > 0)
                        {
                            content.AppendLine(":");

                            foreach (var item in componentsEntities)
                            {
                                content.AppendFormat("    {0}", item).AppendLine();
                            }
                        }
                        else
                        {
                            content.AppendLine(" are empty.");
                        }
                    }

                    if (!attributesIsSame)
                    {
                        hasInfo = true;

                        content.AppendLine("Conflict in attributes.");

                        content.Append("Attributes in plugin step description");

                        if (componentsEntities.Count > 0)
                        {
                            content.AppendLine(":");

                            foreach (var item in stepAttributes)
                            {
                                content.AppendFormat("    {0}", item).AppendLine();
                            }
                        }
                        else
                        {
                            content.AppendLine(" are empty.");
                        }

                        content.Append("Attributes in required components");

                        if (componentsAttributes.Count > 0)
                        {
                            content.AppendLine(":");

                            foreach (var item in componentsAttributes)
                            {
                                content.AppendFormat("    {0}", item).AppendLine();
                            }
                        }
                        else
                        {
                            content.AppendLine(" are empty.");
                        }
                    }
                }
            }

            if (!hasInfo)
            {
                content.AppendLine(this._iWriteToOutput.WriteToOutput(connectionData, "No conflicts were found."));
            }

            string fileName = string.Format("{0}.Checking Plugin Steps Required Components at {1}.txt", connectionData.Name, DateTime.Now.ToString("yyyy.MM.dd HH-mm-ss"));

            if (string.IsNullOrEmpty(commonConfig.FolderForExport))
            {
                _iWriteToOutput.WriteToOutput(null, Properties.OutputStrings.FolderForExportIsEmpty);
                commonConfig.FolderForExport = FileOperations.GetDefaultFolderForExportFilePath();
            }
            else if (!Directory.Exists(commonConfig.FolderForExport))
            {
                _iWriteToOutput.WriteToOutput(null, Properties.OutputStrings.FolderForExportDoesNotExistsFormat1, commonConfig.FolderForExport);
                commonConfig.FolderForExport = FileOperations.GetDefaultFolderForExportFilePath();
            }

            string filePath = Path.Combine(commonConfig.FolderForExport, FileOperations.RemoveWrongSymbols(fileName));

            File.WriteAllText(filePath, content.ToString(), new UTF8Encoding(false));

            this._iWriteToOutput.WriteToOutput(connectionData, "Created file with Checking Plugin Steps Required Components: {0}", filePath);

            this._iWriteToOutput.PerformAction(service.ConnectionData, filePath);
        }
        private async Task CheckingPluginImages(ConnectionData connectionData, CommonConfiguration commonConfig)
        {
            if (connectionData == null)
            {
                this._iWriteToOutput.WriteToOutput(connectionData, Properties.OutputStrings.NoCurrentCRMConnection);
                return;
            }

            StringBuilder content = new StringBuilder();

            content.AppendLine(this._iWriteToOutput.WriteToOutput(connectionData, Properties.OutputStrings.ConnectingToCRM));

            content.AppendLine(this._iWriteToOutput.WriteToOutput(connectionData, connectionData.GetConnectionDescription()));

            // Подключаемся к CRM.
            var service = await QuickConnection.ConnectAsync(connectionData);

            if (service == null)
            {
                this._iWriteToOutput.WriteToOutput(connectionData, Properties.OutputStrings.ConnectionFailedFormat1, connectionData.Name);
                return;
            }

            content.AppendLine(this._iWriteToOutput.WriteToOutput(connectionData, Properties.OutputStrings.CurrentServiceEndpointFormat1, service.CurrentServiceEndpoint));

            var repository = new PluginSearchRepository(service);

            var search = await repository.FindAllAsync(null, string.Empty, string.Empty, string.Empty);

            var querySteps = search.SdkMessageProcessingStep
                            .OrderBy(ent => ent.EventHandler?.Name ?? "Unknown")
                            .ThenBy(ent => ent.PrimaryObjectTypeCodeName)
                            .ThenBy(ent => ent.SdkMessageId?.Name ?? "Unknown", new MessageComparer())
                            .ThenBy(ent => ent.Stage.Value)
                            .ThenBy(ent => ent.Mode.Value)
                            .ThenBy(ent => ent.Rank)
                            .ThenBy(ent => ent.Name)
                            ;

            int stepNumber = 1;

            bool hasInfo = false;

            foreach (var step in querySteps)
            {
                var queryImage = from image in search.SdkMessageProcessingStepImage
                                 where image.SdkMessageProcessingStepId != null
                                 where image.SdkMessageProcessingStepId.Id == step.Id
                                 orderby image.ImageType.Value, image.CreatedOn, image.Name
                                 select image;

                var preImages = queryImage.Where(im => im.ImageType.Value == 0 || im.ImageType.Value == 2);
                var postImages = queryImage.Where(im => im.ImageType.Value == 1 || im.ImageType.Value == 2);

                var preImagesByEntityAlias = preImages.GroupBy(im => im.EntityAlias).Where(gr => gr.Count() > 1);
                var preImagesByName = preImages.GroupBy(im => im.EntityAlias).Where(gr => gr.Count() > 1);

                var postImagesByEntityAlias = postImages.GroupBy(im => im.EntityAlias).Where(gr => gr.Count() > 1);
                var postImagesByName = postImages.GroupBy(im => im.EntityAlias).Where(gr => gr.Count() > 1);

                var hasDuplicatesPreImagesByEntityAlias = preImagesByEntityAlias.Count() > 0;
                var hasDuplicatesPreImagesByName = preImagesByName.Count() > 0;

                var hasDuplicatesPostImagesByEntityAlias = postImagesByEntityAlias.Count() > 0;
                var hasDuplicatesPostImagesByName = postImagesByName.Count() > 0;

                if (hasDuplicatesPreImagesByEntityAlias
                    || hasDuplicatesPreImagesByName
                    || hasDuplicatesPostImagesByEntityAlias
                    || hasDuplicatesPostImagesByName
                    )
                {
                    if (content.Length > 0)
                    {
                        content.AppendLine().AppendLine();
                    }

                    hasInfo = true;

                    content.AppendFormat("{0}. {1}", stepNumber, step.EventHandler?.Name ?? "Unknown").AppendLine();

                    content.AppendFormat("Entity '{0}',   Message '{1}',   Stage '{2}',   Rank {3},   Statuscode {4}"
                        , step.PrimaryObjectTypeCodeName
                        , step.SdkMessageId?.Name ?? "Unknown"
                        , SdkMessageProcessingStepRepository.GetStageName(step.Stage.Value, step.Mode.Value)
                        , step.Rank.ToString()
                        , step.FormattedValues[SdkMessageProcessingStep.Schema.Attributes.statuscode]
                        ).AppendLine();

                    DescribeImages(content, stepNumber, hasDuplicatesPreImagesByEntityAlias, preImagesByEntityAlias, "Pre images duplicates by EntityAlias:");

                    DescribeImages(content, stepNumber, hasDuplicatesPreImagesByName, preImagesByName, "Pre images duplicates by Name:");

                    DescribeImages(content, stepNumber, hasDuplicatesPostImagesByEntityAlias, postImagesByEntityAlias, "Post images duplicates by EntityAlias:");

                    DescribeImages(content, stepNumber, hasDuplicatesPostImagesByName, postImagesByName, "Post images duplicates by Name:");

                    stepNumber++;
                }
            }

            if (!hasInfo)
            {
                content.AppendLine(this._iWriteToOutput.WriteToOutput(connectionData, "No duplicates were found."));
            }

            string fileName = string.Format("{0}.Checking Plugin Images Duplicates at {1}.txt", connectionData.Name, DateTime.Now.ToString("yyyy.MM.dd HH-mm-ss"));

            if (string.IsNullOrEmpty(commonConfig.FolderForExport))
            {
                _iWriteToOutput.WriteToOutput(null, Properties.OutputStrings.FolderForExportIsEmpty);
                commonConfig.FolderForExport = FileOperations.GetDefaultFolderForExportFilePath();
            }
            else if (!Directory.Exists(commonConfig.FolderForExport))
            {
                _iWriteToOutput.WriteToOutput(null, Properties.OutputStrings.FolderForExportDoesNotExistsFormat1, commonConfig.FolderForExport);
                commonConfig.FolderForExport = FileOperations.GetDefaultFolderForExportFilePath();
            }

            string filePath = Path.Combine(commonConfig.FolderForExport, FileOperations.RemoveWrongSymbols(fileName));

            File.WriteAllText(filePath, content.ToString(), new UTF8Encoding(false));

            this._iWriteToOutput.WriteToOutput(connectionData, "Created file with Checking Plugin Images Duplicates: {0}", filePath);

            this._iWriteToOutput.PerformAction(service.ConnectionData, filePath);
        }