private void addAssemblyConfigToList(IncludedAssemblyConfig includedAssemblyConfig) { if (GetAssemblyConfigByID(includedAssemblyConfig.ID) != null) { throw new InvalidOperationException(ERROR_ID_ALREADY_EXISTS); } this.assemblyConfigs.Add(includedAssemblyConfig); }
public OutputConfig(OutputAppType outputAppType, OutputMachine outputMachine, string outputPath, string assemblyName, string outputWin32IconPath, IncludedAssemblyConfig mainAssembly, ApartmentState outputApartmentState, bool grabResources, string compilerOptions, CompilerVersionRequired compilerVersionRequired, string appConfigFileId, bool useShadowCopying) { // this.appType = outputAppType; this.machine = outputMachine; this.path = outputPath; this.assemblyName = assemblyName; this.win32IconPath = outputWin32IconPath; this.mainAssembly = mainAssembly; this.apartmentState = outputApartmentState; this.grabResources = grabResources; this.compilerOptions = compilerOptions; this.compilerVersionRequired = compilerVersionRequired; this.appConfigFileId = appConfigFileId; this.useShadowCopying = useShadowCopying; }
public BuildConfiguration(XmlDocument document, BuildConfigurationVariables variables) { ArgumentChecker.NotNull(document, "document"); // this.variables = variables; // XmlSchema schema; Assembly executingAssembly = Assembly.GetExecutingAssembly(); Stream schemaStream = executingAssembly.GetManifestResourceStream(executingAssembly.GetName().Name + ".config-file.xsd"); if (schemaStream == null) { schemaStream = executingAssembly.GetManifestResourceStream("config-file.xsd"); if (schemaStream == null) { throw new InvalidOperationException("Cannot load XSD schema for XML configuration."); } } using (schemaStream) { schema = XmlSchema.Read(schemaStream, schemaValidationEventHandler); } // document.Schemas.Add(schema); document.Validate(documentValidationEventHandler); // XmlNamespaceManager namespaceManager = new XmlNamespaceManager(document.NameTable); namespaceManager.AddNamespace("def", targetNamespace = schema.TargetNamespace); // Parsing compression options XmlNode compressionOptionsSetNode = document.SelectSingleNode("def:configuration/def:compression-options-set", namespaceManager); if (compressionOptionsSetNode == null) { throw new InvalidOperationException("Unable to find any compression option."); } // XmlNodeList compressionOptionNodes = compressionOptionsSetNode.SelectNodes("def:compression-option", namespaceManager); // ReSharper disable PossibleNullReferenceException foreach (XmlNode compressionOptionNode in compressionOptionNodes) { // ReSharper restore PossibleNullReferenceException string id = compressionOptionNode.Attributes["id"].Value; XmlNode levelNode = compressionOptionNode.SelectSingleNode("def:level", namespaceManager); if (levelNode == null) { throw new InvalidOperationException("Cannot determine the level of compression."); } CompressionLevel compressionLevel = (CompressionLevel)Enum.Parse(typeof(CompressionLevel), levelNode.Attributes["value"].Value, true); CompressionConfig compressionConfig = new CompressionConfig(id, compressionLevel); addCompressionConfigToList(compressionConfig); } // Parsing included assemblies options XmlNode assembliesNode = document.SelectSingleNode("def:configuration/def:assemblies", namespaceManager); if (assembliesNode != null) { if (assembliesNode.Attributes["default-compression-ref"] != null) { this.defaultCompressionConfigRefForAssemblies = assembliesNode.Attributes["default-compression-ref"].Value; } if (assembliesNode.Attributes["default-include-method"] != null) { this.defaultIncludeMethodKindForAssemblies = (IncludeMethodKind)Enum.Parse(typeof(IncludeMethodKind), assembliesNode.Attributes["default-include-method"].Value, true); } if (assembliesNode.Attributes["default-generate-partial-aliases"] != null) { this.defaultGeneratePartialAliasesForAssemblies = bool.Parse(assembliesNode.Attributes["default-generate-partial-aliases"].Value); } if (assembliesNode.Attributes["default-lazy-load"] != null) { this.defaultLazyLoadForAssemblies = bool.Parse(assembliesNode.Attributes["default-lazy-load"].Value); } } // XmlNodeList assemblyNodes = document.SelectNodes("def:configuration/def:assemblies/def:assembly", namespaceManager); // ReSharper disable PossibleNullReferenceException foreach (XmlNode assemblyNode in assemblyNodes) { // ReSharper restore PossibleNullReferenceException string idAttributeValue = assemblyNode.Attributes["id"].Value; string pathAttributeValue = assemblyNode.Attributes["path"].Value; string compressionRefAttributeValue; if (assemblyNode.Attributes["compression-ref"] != null) { compressionRefAttributeValue = assemblyNode.Attributes["compression-ref"].Value; } else { compressionRefAttributeValue = this.defaultCompressionConfigRefForAssemblies; } // string copyCompressedToAttributeValue = String.Empty; if (assemblyNode.Attributes["copy-compressed-to"] != null) { copyCompressedToAttributeValue = assemblyNode.Attributes["copy-compressed-to"].Value; } CompressionConfig compressionConfigByRef = GetCompressionConfigByID(compressionRefAttributeValue); if (compressionConfigByRef == null) { throw new InvalidOperationException("Requested compression option was not found."); } // IncludeMethod includeMethod = (assemblyNode.Attributes["include-method"] != null) ? IncludeMethod.Parse(assemblyNode) : new IncludeMethod(this.defaultIncludeMethodKindForAssemblies); // Specially for assembly attributes bool lazyLoadAttributeValue = defaultLazyLoadForAssemblies; if (assemblyNode.Attributes["lazy-load"] != null) { lazyLoadAttributeValue = bool.Parse(assemblyNode.Attributes["lazy-load"].Value); } // bool generatePartialAliasesAttributeValue = defaultGeneratePartialAliasesForAssemblies; XmlAttribute generatePartialAliasesAttribute = assemblyNode.Attributes["generate-partial-aliases"]; if (generatePartialAliasesAttribute != null) { generatePartialAliasesAttributeValue = bool.Parse(generatePartialAliasesAttribute.Value); } // List <string> aliases = new List <string>(); XmlNodeList aliasNodes = assemblyNode.SelectNodes("def:aliases/def:alias", namespaceManager); // ReSharper disable PossibleNullReferenceException foreach (XmlNode aliasNode in aliasNodes) { // ReSharper restore PossibleNullReferenceException XmlAttribute aliasValueAttribute = aliasNode.Attributes["value"]; if (aliasValueAttribute == null) { throw new InvalidOperationException("Required attribute 'value' has been skipped in alias definition."); } aliases.Add(aliasValueAttribute.Value); } // addAssemblyConfigToList(new IncludedAssemblyConfig(idAttributeValue, includeMethod, pathAttributeValue, compressionConfigByRef, copyCompressedToAttributeValue, lazyLoadAttributeValue, aliases, generatePartialAliasesAttributeValue)); } // Parsing included files options XmlNode filesNode = document.SelectSingleNode("def:configuration/def:files", namespaceManager); if (filesNode != null) { if (filesNode.Attributes["default-compression-ref"] != null) { this.defaultCompressionConfigRefForFiles = filesNode.Attributes["default-compression-ref"].Value; } if (filesNode.Attributes["default-include-method"] != null) { this.defaultIncludeMethodKindForFiles = (IncludeMethodKind)Enum.Parse(typeof(IncludeMethodKind), filesNode.Attributes["default-include-method"].Value, true); } if (filesNode.Attributes["default-overwrite-on-extracting"] != null) { this.defaultOverwritingOptionsForFiles = (OverwritingOptions)Enum.Parse(typeof(OverwritingOptions), filesNode.Attributes["default-overwrite-on-extracting"].Value, true); } } // XmlNodeList fileNodes = document.SelectNodes("def:configuration/def:files/def:file", namespaceManager); // ReSharper disable PossibleNullReferenceException foreach (XmlNode fileNode in fileNodes) { // ReSharper restore PossibleNullReferenceException string idAttributeValue = fileNode.Attributes["id"].Value; string pathAttributeValue = fileNode.Attributes["path"].Value; string compressionRefAttributeValue; if (fileNode.Attributes["compression-ref"] != null) { compressionRefAttributeValue = fileNode.Attributes["compression-ref"].Value; } else { compressionRefAttributeValue = this.defaultCompressionConfigRefForFiles; } // string copyCompressedToAttributeValue = String.Empty; if (fileNode.Attributes["copy-compressed-to"] != null) { copyCompressedToAttributeValue = fileNode.Attributes["copy-compressed-to"].Value; } CompressionConfig compressionConfigByRef = GetCompressionConfigByID(compressionRefAttributeValue); if (compressionConfigByRef == null) { throw new InvalidOperationException("Requested compression option was not found."); } // IncludeMethod includeMethod; if (fileNode.Attributes["include-method"] != null) { includeMethod = IncludeMethod.Parse(fileNode); } else { includeMethod = new IncludeMethod(this.defaultIncludeMethodKindForFiles); } // Speciallied for file attributes string extractToPathAttributeValue = String.Empty; XmlAttribute extractToPathAttribute = fileNode.Attributes["extract-to-path"]; if (extractToPathAttribute != null) { extractToPathAttributeValue = extractToPathAttribute.Value; } // OverwritingOptions overwritingOptionsAttributeValue = defaultOverwritingOptionsForFiles; XmlAttribute overwritingOptionsAttribute = fileNode.Attributes["overwrite-on-extracting"]; if (overwritingOptionsAttribute != null) { overwritingOptionsAttributeValue = (OverwritingOptions)Enum.Parse(typeof(OverwritingOptions), overwritingOptionsAttribute.Value, true); } // addFileConfigToList(new IncludedFileConfig(idAttributeValue, includeMethod, pathAttributeValue, compressionConfigByRef, copyCompressedToAttributeValue, extractToPathAttributeValue, overwritingOptionsAttributeValue)); } // Parsing output configuration ApartmentState outputApartmentState; string outputPath; string assemblyName = null; OutputAppType outputAppType; OutputMachine outputMachine; IncludedAssemblyConfig mainAssembly; bool outputGrabResources = false; string outputWin32IconPath = null; string compilerOptions = null; CompilerVersionRequired compilerVersionRequired = CompilerVersionRequired.v2_0; string appConfigFileId = null; bool useShadowCopying = false; // XmlNode outputNode = document.SelectSingleNode("def:configuration/def:output", namespaceManager); if (outputNode == null) { throw new InvalidOperationException("Unable to find an output exe configuration."); } // outputApartmentState = (ApartmentState)Enum.Parse(typeof(ApartmentState), outputNode.Attributes["apartment"].Value, true); outputPath = outputNode.Attributes["path"].Value; if (outputNode.Attributes["assembly-name"] != null) { assemblyName = outputNode.Attributes["assembly-name"].Value; } outputAppType = (OutputAppType)Enum.Parse(typeof(OutputAppType), outputNode.Attributes["apptype"].Value, true); outputMachine = (OutputMachine)Enum.Parse(typeof(OutputMachine), outputNode.Attributes["machine"].Value, true); if (outputNode.Attributes["grab-resources"] != null) { outputGrabResources = bool.Parse(outputNode.Attributes["grab-resources"].Value); } // XmlNode compilerOptionsNode = outputNode.SelectSingleNode("def:compiler-options/def:options", namespaceManager); if (compilerOptionsNode != null) { compilerOptions = compilerOptionsNode.InnerText; } XmlNode compilerVersionRequiredNode = outputNode.SelectSingleNode("def:compiler-options", namespaceManager); if (null != compilerVersionRequiredNode) { XmlAttribute compilerVerRequiredAttr = compilerVersionRequiredNode.Attributes["version-required"]; if (null != compilerVerRequiredAttr) { string compilerVerRaw = compilerVerRequiredAttr.Value; switch (compilerVerRaw) { case "v2.0": { compilerVersionRequired = CompilerVersionRequired.v2_0; break; } case "v3.0": { compilerVersionRequired = CompilerVersionRequired.v3_0; break; } case "v3.5": { compilerVersionRequired = CompilerVersionRequired.v3_5; break; } case "v4.0": { compilerVersionRequired = CompilerVersionRequired.v4_0; break; } } } } // mainAssembly = GetAssemblyConfigByID(outputNode.Attributes["main-assembly-ref"].Value); if (mainAssembly == null) { throw new InvalidOperationException("Main assembly specified with incorrect ID."); } // XmlAttribute outputWin32IconAttribute = outputNode.Attributes["win32icon"]; if (outputWin32IconAttribute != null) { outputWin32IconPath = outputWin32IconAttribute.Value; } // XmlNode appConfigNode = outputNode.SelectSingleNode("def:includes/def:files/def:app-config", namespaceManager); if (null != appConfigNode) { XmlAttribute appConfigFileIdAttribute = appConfigNode.Attributes["ref"]; if (null == appConfigFileIdAttribute) { throw new InvalidOperationException("Required attribute ref not specidied for app-config."); } appConfigFileId = appConfigFileIdAttribute.Value; XmlAttribute useShahowCopyingAttribute = appConfigNode.Attributes["use-shadow-copying"]; if (null != useShahowCopyingAttribute) { useShadowCopying = bool.Parse(useShahowCopyingAttribute.Value); } } this.outputConfig = new OutputConfig(outputAppType, outputMachine, outputPath, assemblyName, outputWin32IconPath, mainAssembly, outputApartmentState, outputGrabResources, compilerOptions, compilerVersionRequired, appConfigFileId, useShadowCopying); // XmlNodeList includesAssemblyNodes = outputNode.SelectNodes("def:includes/def:assemblies/def:assembly", namespaceManager); // ReSharper disable PossibleNullReferenceException foreach (XmlNode assemblyNode in includesAssemblyNodes) { // ReSharper restore PossibleNullReferenceException IncludedAssemblyConfig assemblyConfigByRef = GetAssemblyConfigByID(assemblyNode.Attributes["ref"].Value); if (assemblyConfigByRef == null) { throw new InvalidOperationException(String.Format("Cannot find assembly to include by ID='{0}'.", assemblyNode.Attributes["ref"].Value)); } outputConfig.IncludedObjects.Add(assemblyConfigByRef); } // XmlNodeList includesFileNodes = outputNode.SelectNodes("def:includes/def:files/def:file", namespaceManager); // ReSharper disable PossibleNullReferenceException foreach (XmlNode includesFileNode in includesFileNodes) { // ReSharper restore PossibleNullReferenceException string id = includesFileNode.Attributes["ref"].Value; // Avoid duplicating the app.config file. if (null == appConfigFileId || appConfigFileId != id) { IncludedFileConfig fileConfigByRef = GetFileConfigByID(id); if (fileConfigByRef == null) { throw new InvalidOperationException(String.Format("Cannot find file to include by ID='{0}'.", includesFileNode.Attributes["ref"])); } outputConfig.IncludedObjects.Add(fileConfigByRef); } } // if (null != appConfigFileId) { outputConfig.IncludedObjects.Add(GetFileConfigByID(appConfigFileId)); } }
/// <summary> /// Reflects included assemblies using Mono.Cecil. /// Grabs: assembly aliases, standard assembly definition attributes if need, resources of main assembly if need. /// </summary> private static void reflectAssembliesAliasesAndGrabResourcesAndAssemblyInfo(BuildConfiguration configuration, string tempDirectoryName, List<string> resourcesReflectedPaths) { // foreach (IncludedObjectConfigBase configBase in configuration.OutputConfig.GetAllIncludedObjects()) { if (configBase is IncludedAssemblyConfig) { string configuredAssemblyPath = configurePathByConfigurationVariables(configBase.Path, configuration); // if (logger.IsTraceEnabled) { logger.Trace(String.Format("Reading {0} assembly.", configuredAssemblyPath)); } ModuleDefinition moduleDefinition = ModuleDefinition.ReadModule(configuredAssemblyPath); if ((configBase == configuration.OutputConfig.MainAssembly) && configuration.OutputConfig.GrabResources) { Collection<Resource> resources = moduleDefinition.Resources; // foreach (Resource resource in resources) { if (resource.ResourceType != ResourceType.Embedded) { logger.Info(string.Format("Found resource {0}, resource type is not embedded, skip them.", resource.Name)); continue; } EmbeddedResource embeddedResource = (EmbeddedResource) resource; // Change name of resources started with assembly name string string assemblyName = moduleDefinition.Assembly.Name.Name; string modifiedResourceName; if (resource.Name.StartsWith(assemblyName)) { modifiedResourceName = getOutputAssemblyName(configuration.OutputConfig) + resource.Name.Substring(assemblyName.Length); } else { modifiedResourceName = resource.Name; } // string resourceFilePath = Path.Combine(tempDirectoryName, modifiedResourceName); // if (File.Exists(resourceFilePath)) { throw new InvalidOperationException(String.Format("File for resource with name {0} already exists. May be resources naming conflict ?", resource.Name)); } // using (FileStream fileStream = File.Create(resourceFilePath)) { using (Stream stream = embeddedResource.GetResourceStream()) { if (stream == null) { throw new InvalidOperationException("Cannot read one of manifest resource stream from assembly."); } const int bufferSize = 32 * 1024; byte[] buffer = new byte[bufferSize]; int totalBytesReaded = 0; while (stream.CanRead && (totalBytesReaded < stream.Length)) { int readedBytes = stream.Read(buffer, 0, bufferSize); fileStream.Write(buffer, 0, readedBytes); totalBytesReaded += readedBytes; } } } // resourcesReflectedPaths.Add(resourceFilePath); } } // string fullName = moduleDefinition.Assembly.FullName; if (fullName == null) { throw new InvalidOperationException("Cannot resolve full name of assembly."); } IncludedAssemblyConfig assemblyConfig = ((IncludedAssemblyConfig)configBase); // if (addStringToTheListIfNotAlready(assemblyConfig.Aliases, fullName)) { if (logger.IsTraceEnabled) { logger.Trace(String.Format("Added full name to aliases : '{0}'.", fullName)); } } // if (assemblyConfig.GeneratePartialAliases) { string[] fullNameParts = fullName.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); // string partiallyName = fullNameParts[0]; for (int i = 1; i < fullNameParts.Length; i++) { if (addStringToTheListIfNotAlready(assemblyConfig.Aliases, partiallyName)) { if (logger.IsTraceEnabled) { logger.Trace(String.Format("Added partially name to aliases : '{0}'.", partiallyName)); } } partiallyName = partiallyName + "," + fullNameParts[i]; } } } } }
private static int Main(string[] args) { AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainOnAssemblyResolve; // try { const string nboxForkedPrefix = "__NBox_Forked_"; if (!AppDomain.CurrentDomain.FriendlyName.StartsWith(nboxForkedPrefix)) { string appConfigFileId = configuration.OutputConfig.AppConfigFileID; string configFilePath = null; // Initial extracting files foreach (IncludedObjectConfigBase configBase in configuration.OutputConfig.IncludedObjects) { if (configBase is IncludedFileConfig) { IncludedFileConfig fileConfig = configBase as IncludedFileConfig; if (fileConfig.ID != appConfigFileId) { string configuredExtractingPath = configurePath(fileConfig.ExtractToPath); // long decodedDataLength = 0; byte[] bytes = null; // bool extracting = true; if (fileConfig.OverwriteOnExtract == OverwritingOptions.CheckExist) { extracting = !File.Exists(configuredExtractingPath); } else if (fileConfig.OverwriteOnExtract == OverwritingOptions.CheckSize) { bytes = loadRawData(fileConfig, out decodedDataLength); extracting = !File.Exists(configuredExtractingPath) || new FileInfo(configuredExtractingPath).Length != bytes.Length; } else if (fileConfig.OverwriteOnExtract == OverwritingOptions.Never) { extracting = false; } // if (extracting) { if (bytes == null) { bytes = loadRawData(fileConfig, out decodedDataLength); } // using (FileStream stream = File.Create(configuredExtractingPath)) { stream.Write(bytes, 0, unchecked ((int)decodedDataLength)); } } } else { // It is the App.config file if (configuration.OutputConfig.UseShadowCopying) { string hashedCurrentExeLocation = getMd5Hash(Assembly.GetEntryAssembly().Location); string tempDir = Path.GetTempPath(); configFilePath = Path.Combine(tempDir, hashedCurrentExeLocation + ".config"); } else { string entryAssemblyLocation = Assembly.GetEntryAssembly().Location; configFilePath = Path.Combine(Path.GetDirectoryName(entryAssemblyLocation), Path.GetFileName(entryAssemblyLocation) + ".config"); } if (!File.Exists(configFilePath)) { long decodedDataLength; byte[] bytes; bytes = loadRawData(fileConfig, out decodedDataLength); using (FileStream stream = File.Create(configFilePath)) { stream.Write(bytes, 0, unchecked ((int)decodedDataLength)); } } } } } if (null != appConfigFileId) { AppDomainSetup setupInfo = new AppDomainSetup(); string entryAssemblyPath = Assembly.GetEntryAssembly().Location; setupInfo.ApplicationBase = Path.GetDirectoryName(entryAssemblyPath); setupInfo.ConfigurationFile = configFilePath; AppDomain forkedDomain = AppDomain.CreateDomain(nboxForkedPrefix + Guid.NewGuid(), null, setupInfo); forkedDomain.ExecuteAssembly(Assembly.GetEntryAssembly().Location); AppDomain.Unload(forkedDomain); return(0); } } // Initial loading assemblies with lazy-load = false attribute foreach (IncludedObjectConfigBase configBase in configuration.OutputConfig.IncludedObjects) { if (configBase is IncludedAssemblyConfig) { IncludedAssemblyConfig assemblyConfig = configBase as IncludedAssemblyConfig; if (!assemblyConfig.LazyLoad) { loadAssembly(assemblyConfig); } } } // Starting application Assembly assembly = loadAssembly(configuration.OutputConfig.MainAssembly); if (assembly == null) { throw new InvalidOperationException("Cannot load main module."); } MethodInfo entryPoint = assembly.EntryPoint; if (entryPoint != null) { ParameterInfo[] parameters = entryPoint.GetParameters(); // int length = parameters.Length; parametersArr = new object[length]; if (parametersArr.Length > 0) { parametersArr[0] = args; } // Starting thread with selected ThreadApartment Thread threadWithApartment = new Thread(start); threadWithApartment.IsBackground = false; threadWithApartment.SetApartmentState(configuration.OutputConfig.ApartmentState); threadWithApartment.Start(entryPoint); threadWithApartment.Join(); } } catch (Exception exc) { File.AppendAllText("rolling-fatal.log", exc.ToString()); throw; } // return((returnedValue != null) && (returnedValue is int) ? (int)returnedValue : (0)); }