private bool DeserializeJsonConfig(string jsonConfig, out MergerSettings settings)
        {
            settings = null;
            bool success = true;

            if (string.IsNullOrWhiteSpace(jsonConfig))
            {
                Log.LogError("Unable to deserialize configuration. Configuration string is null or empty.");
                return(false);
            }

            try
            {
                Log.LogMessage("Deserializing configuration.");
                settings = MergerSettings.FromJson(jsonConfig);
                Log.LogMessage("Configuration file deserialized successfully.");
            }
            catch (Exception ex)
            {
                Log.LogError("Error deserializing configuration.");
                Log.LogErrorFromException(ex);
                success = false;
            }

            return(success);
        }
        private void LogConfigFile(MergerSettings settings)
        {
            string outputPath = Path.Combine(Path.GetDirectoryName(settings.General.OutputFile), Path.GetFileNameWithoutExtension(settings.General.OutputFile) + ".merge.json");
            string outputDir  = Path.GetDirectoryName(outputPath);

            if (!Directory.Exists(outputDir))
            {
                Directory.CreateDirectory(outputDir);
            }

            Log.LogMessage("Saving current configuration to: {0}", outputPath);
            File.WriteAllText(outputPath, settings.ToJson(), Encoding.UTF8);
        }
Example #3
0
        private void DeleteCopiesAndCopyTargetPath(MergerSettings settings)
        {
            // Delete input assemblies and copy the merged outputfile to the TargetPath

            Log.LogMessage(MessageImportance.Normal, "Deleting Merged Assembl{0}",
                           (settings.General.InputAssemblies.Count != 1) ? "ies" : "y");

            foreach (string file in settings.General.InputAssemblies)
            {
                try
                {
                    // Input can reference dependency project, make sure the assembly is removed from the TargetDir
                    DeleteFileAndPDB(Path.Combine(this.TargetDir, Path.GetFileName(file)));
                }
                catch (Exception ex)
                {
                    Log.LogErrorFromException(ex);
                }
            }

            // Copy the output-file to the target-dir
            Log.LogMessage(MessageImportance.Normal, "Overwriting OutputTarget");
            try
            {
                // Remove and copy Target
                DeleteFileAndPDB(this.TargetPath);

                if (File.Exists(settings.General.OutputFile))
                {
                    File.Copy(settings.General.OutputFile, this.TargetPath);
                }

                // Also copy debug-information
                string outputFilePDB = Path.ChangeExtension(settings.General.OutputFile, "pdb");
                if (File.Exists(outputFilePDB))
                {
                    File.Copy(outputFilePDB, Path.ChangeExtension(this.TargetPath, "pdb"));
                }
            }
            catch (Exception ex)
            {
                Log.LogErrorFromException(ex);
            }
        }
        private bool MergeAssemblies(string mergerPath, MergerSettings settings)
        {
            bool     success     = true;
            Assembly ilmerge     = LoadILMerge(mergerPath);
            Type     ilmergeType = ilmerge.GetType("ILMerging.ILMerge", true, true);

            if (ilmergeType == null)
            {
                throw new InvalidOperationException("Cannot find 'ILMerging.ILMerge' in executable.");
            }

            Log.LogMessage("Instantianting ILMerge.");
            dynamic merger = Activator.CreateInstance(ilmergeType);

            Log.LogMessage("Setting up ILMerge.");

            merger.AllowMultipleAssemblyLevelAttributes = settings.Advanced.AllowMultipleAssemblyLevelAttributes;
            merger.AllowWildCards   = settings.Advanced.AllowWildCards;
            merger.AllowZeroPeKind  = settings.Advanced.AllowZeroPeKind;
            merger.AttributeFile    = settings.Advanced.AttributeFile;
            merger.Closed           = settings.Advanced.Closed;
            merger.CopyAttributes   = settings.Advanced.CopyAttributes;
            merger.DebugInfo        = settings.Advanced.DebugInfo;
            merger.DelaySign        = settings.Advanced.DelaySign;
            merger.FileAlignment    = settings.Advanced.FileAlignment > 0 ? settings.Advanced.FileAlignment : 512;
            merger.KeyFile          = settings.General.KeyFile;
            merger.Log              = settings.Advanced.Log;
            merger.LogFile          = settings.Advanced.LogFile;
            merger.OutputFile       = settings.General.OutputFile;
            merger.PublicKeyTokens  = settings.Advanced.PublicKeyTokens;
            merger.UnionMerge       = settings.Advanced.UnionMerge;
            merger.XmlDocumentation = settings.Advanced.XmlDocumentation;

            if (!string.IsNullOrWhiteSpace(settings.Advanced.ExcludeFile))
            {
                merger.ExcludeFile = settings.Advanced.ExcludeFile;
            }

            merger.Internalize = settings.Advanced.Internalize;

            if (settings.Advanced.TargetKind.HasValue())
            {
                merger.TargetKind = (dynamic)Enum.Parse(merger.TargetKind.GetType(), settings.Advanced.TargetKind);
            }

            if (settings.Advanced.Version.HasValue())
            {
                merger.Version = new Version(settings.Advanced.Version);
            }

            if (settings.Advanced.AllowDuplicateType.HasValue())
            {
                if (settings.Advanced.AllowDuplicateType == "*")
                {
                    merger.AllowDuplicateType(null);
                }
                else
                {
                    foreach (string typeName in settings.Advanced.AllowDuplicateType.Split(','))
                    {
                        merger.AllowDuplicateType(typeName);
                    }
                }
            }

            string[] tp = settings.General.TargetPlatform.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);

            merger.SetTargetPlatform(tp[0].Trim(), @tp[1].Trim());
            merger.SetInputAssemblies(settings.General.InputAssemblies.ToArray());
            merger.SetSearchDirectories(settings.Advanced.SearchDirectories.ToArray());

            try
            {
                string outputDir = Path.GetDirectoryName(settings.General.OutputFile);
                if (!Directory.Exists(outputDir))
                {
                    Log.LogWarning($"Output directory not found. An attempt to create the directory will be made: {outputDir}");
                    Directory.CreateDirectory(outputDir);
                    Log.LogMessage("Output directory created.");
                }

                Log.LogMessage(
                    MessageImportance.Normal,
                    "Merging {0} assembl{1} to '{2}'.",
                    settings.General.InputAssemblies.Count.ToString(),
                    (settings.General.InputAssemblies.Count != 1) ? "ies" : "y",
                    settings.General.OutputFile);

                merger.Merge();

                if (merger.StrongNameLost)
                {
                    Log.LogMessage(MessageImportance.High, "StrongNameLost = true");
                }
            }
            catch (Exception exception)
            {
                Log.LogErrorFromException(exception);
                success = false;
            }
            finally
            {
                merger  = null;
                ilmerge = null;
            }

            return(success);
        }
        private void SetDefaults(MergerSettings settings)
        {
            if (settings == null)
            {
                throw new ArgumentNullException(nameof(settings));
            }

            if (settings.General == null)
            {
                settings.General = new GeneralSettings();
            }

            if (!settings.General.KeyFile.HasValue() && this.KeyFile.HasValue())
            {
                settings.General.KeyFile = ToAbsolutePath(KeyFile);
                Log.LogMessage("Applying default value for KeyFile.");
            }

            if (!settings.General.OutputFile.HasValue())
            {
                settings.General.OutputFile = Path.Combine(this.TargetDir, "ILMerge", this.TargetFileName);
                Log.LogMessage("Applying default value for OutputFile.");
            }

            if (!settings.General.TargetPlatform.HasValue())
            {
                settings.General.TargetPlatform = FrameworkInfo.ToILmergeTargetPlatform(this.TargetFrameworkVersion, this.TargetArchitecture);
                Log.LogMessage($"Applying default value for TargetPlatform: {settings.General.TargetPlatform}");
            }

            if (settings.General.InputAssemblies == null || settings.General.InputAssemblies.Count == 0)
            {
                Log.LogMessage("No input assembles were found in configuration.");

                settings.General.InputAssemblies = new List <string>();

                Log.LogMessage($"Adding target assembly: {this.TargetPath}");
                settings.General.InputAssemblies.Add(this.TargetPath);

                foreach (var item in this.InputAssemblies)
                {
                    Log.LogMessage($"Adding assembly: {item.ItemSpec}");
                    settings.General.InputAssemblies.Add(item.ItemSpec);
                }
            }
            else
            {
                foreach (var item in settings.General.InputAssemblies)
                {
                    Log.LogMessage($"Config input assembly: {item}");
                }

                Log.LogMessage($"Adding target assembly at position [0]: {this.TargetPath}");
                settings.General.InputAssemblies.Insert(0, this.TargetPath);
            }

            if (settings.Advanced == null)
            {
                settings.Advanced = new AdvancedSettings();
            }

            if (settings.Advanced.SearchDirectories == null)
            {
                settings.Advanced.SearchDirectories = new List <string>();
            }

            if (!settings.Advanced.SearchDirectories.Contains(this.TargetDir))
            {
                settings.Advanced.SearchDirectories.Add(this.TargetDir);
            }

            if (this.AdditionalLocations != null && this.AdditionalLocations.Any())
            {
                foreach (var dir in this.AdditionalLocations)
                {
                    if (!settings.Advanced.SearchDirectories.Contains(dir))
                    {
                        settings.Advanced.SearchDirectories.Add(dir);
                    }
                }
            }
        }
        public override bool Execute()
        {
            LogInputVariables();

            string jsonConfig;
            string exePath;

            var settings = new MergerSettings();

            // try to read configuration if file exists
            if (!ReadConfigFile(out jsonConfig))
            {
                return(false);
            }

            // replace tokens if applicable
            if (!string.IsNullOrWhiteSpace(jsonConfig))
            {
                jsonConfig = ReplaceTokens(jsonConfig);
            }

            // if json config exists, try to deserialize into settings object
            if (!string.IsNullOrWhiteSpace(jsonConfig) && !DeserializeJsonConfig(jsonConfig, out settings))
            {
                return(false);
            }

            if (settings == null)
            {
                // create instance if seetings still null which indicates a custom json config was not used
                settings = new MergerSettings();
            }

            // apply defaults
            SetDefaults(settings);

            if (settings.General.AlternativeILMergePath.HasValue())
            {
                if (!File.Exists(settings.General.AlternativeILMergePath))
                {
                    Log.LogError($"An alternative path for ILMerge.exe was provided but the file was not found: {settings.General.AlternativeILMergePath}");
                    return(false);
                }
                else
                {
                    exePath = settings.General.AlternativeILMergePath;
                    Log.LogMessage("Using alternative ILMerge path: {0}", settings.General.AlternativeILMergePath);
                }
            }
            else
            {
                exePath = this.GetILMergePath();
            }

            if (!exePath.HasValue())
            {
                Log.LogError("ILMerge.exe was no located. Make sure you have the ILMerge nuget package installed. "
                             + "If you defined a custom packages folder in your Nuget.Config it is possible we are having a hard time figuring it out. "
                             + "In this case please use attribute 'AlternativeILMergePath' in the configuration file to indicate the full path for ILMerge.exe.");
                return(false);
            }

            // log configuration file used by this task.
            LogConfigFile(settings);

            if (!MergeAssemblies(exePath, settings))
            {
                return(false);
            }


            return(true);
        }