diff --git a/README.md b/README.md index 70d4f1b..94c30c5 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ If you are making use of the [NuGet package](https://www.nuget.org/packages/Brut ```xml + Command=""..\packages\Brutal.Dev.StrongNameSigner.1.4.8\tools\StrongNameSigner.Console.exe" -in "..\packages"" /> ``` @@ -46,7 +46,7 @@ To add multiple directories to process at the same time (similar to how the UI c ```xml + Command=""..\packages\Brutal.Dev.StrongNameSigner.1.4.8\tools\StrongNameSigner.Console.exe" -in "..\packages\elmah.corelibrary.1.2.2|..\packages\Elmah.MVC.2.1.1"" /> ``` @@ -59,6 +59,28 @@ Another alternative is to simply call the `StrongNameSigner.Console.exe` with re `"C:\Program Files\BrutalDev\.NET Assembly Strong-Name Signer\StrongNameSigner.Console.exe" -in "..\packages"` +Dealing With Dependencies +------------------------- + +To avoid a complicated explanation on how this works, just include ALL assemblies that reference each other whether they are signed or not. As of version 1.4.8, all included file paths are probed for references so they can be fixed without having to copy them into the signed assembly directory. + +When dependant assemblies cannot be found and references weren't fixed correctly, the following type of error will occur during a build. + +``` +The type 'XYZ' is defined in an assembly that is not referenced. You must add a reference to assembly 'SomeAssembly, Version=1.2.34.5, Culture=neutral, PublicKeyToken=null'. +``` + +For example, ServiceStack's PostgreSQL NuGet package is not signed but other dependant assemblies are. Furthermore, these dependant assembly versions don't match what is referenced in `ServiceStack.OrmLite.PostgreSQL`. To correct the reference versions as well as ensuring the correct signed assemblies are referenced, simply include all the files that need to be processed in a single command to the strong-name signer. + +```xml + + + +``` + +Even though `ServiceStack.OrmLite.PostgreSQL.dll` references the unsigned `ServiceStack.Text` v4.0.39 and the unsigned `ServiceStack.OrmLite.Signed` v4.0.40, using the command above will force it to use the included signed versions as references as well as correcting the reference versions to match. + API Usage --------- Reference **Brutal.Dev.StrongNameSigner.dll** in your project or include it in a PowerShell script. diff --git a/src/Brutal.Dev.StrongNameSigner.Console/Program.cs b/src/Brutal.Dev.StrongNameSigner.Console/Program.cs index 44b5239..de2480c 100644 --- a/src/Brutal.Dev.StrongNameSigner.Console/Program.cs +++ b/src/Brutal.Dev.StrongNameSigner.Console/Program.cs @@ -147,7 +147,7 @@ private static Stats SignAssemblies(Options options) // Go through all the references excluding the file we are working on. foreach (var referencePath in referencesToFix.Where(r => !r.Equals(filePath))) { - if (FixSingleAssemblyReference(filePath, referencePath, options.KeyFile, options.Password)) + if (FixSingleAssemblyReference(filePath, referencePath, options.KeyFile, options.Password, filesToSign.Select(f => Path.GetDirectoryName(f)).Distinct().ToArray())) { referenceFixes++; } @@ -157,7 +157,7 @@ private static Stats SignAssemblies(Options options) // Remove all InternalsVisibleTo attributes without public keys from the processed assemblies. Signed assemblies cannot have unsigned friend assemblies. foreach (var filePath in signedAssemblyPaths) { - if (RemoveInvalidFriendAssemblyReferences(filePath, options.KeyFile, options.Password)) + if (RemoveInvalidFriendAssemblyReferences(filePath, options.KeyFile, options.Password, filesToSign.Select(f => Path.GetDirectoryName(f)).Distinct().ToArray())) { referenceFixes++; } @@ -203,7 +203,7 @@ private static AssemblyInfo SignSingleAssembly(string assemblyPath, string keyPa return null; } - private static bool FixSingleAssemblyReference(string assemblyPath, string referencePath, string keyFile, string keyFilePassword) + private static bool FixSingleAssemblyReference(string assemblyPath, string referencePath, string keyFile, string keyFilePassword, params string[] probingPaths) { try { @@ -211,7 +211,7 @@ private static bool FixSingleAssemblyReference(string assemblyPath, string refer PrintMessage(string.Format("Fixing references to '{1}' in '{0}'...", assemblyPath, referencePath), LogLevel.Verbose); var info = SigningHelper.GetAssemblyInfo(assemblyPath); - if (SigningHelper.FixAssemblyReference(assemblyPath, referencePath, keyFile, keyFilePassword)) + if (SigningHelper.FixAssemblyReference(assemblyPath, referencePath, keyFile, keyFilePassword, probingPaths)) { PrintMessageColor(string.Format("References to '{1}' in '{0}' were fixed successfully.", assemblyPath, referencePath), LogLevel.Changes, ConsoleColor.Green); @@ -234,7 +234,7 @@ private static bool FixSingleAssemblyReference(string assemblyPath, string refer return false; } - private static bool RemoveInvalidFriendAssemblyReferences(string assemblyPath, string keyFile, string keyFilePassword) + private static bool RemoveInvalidFriendAssemblyReferences(string assemblyPath, string keyFile, string keyFilePassword, params string[] probingPaths) { try { @@ -242,7 +242,7 @@ private static bool RemoveInvalidFriendAssemblyReferences(string assemblyPath, s PrintMessage(string.Format("Removing invalid friend references from '{0}'...", assemblyPath), LogLevel.Verbose); var info = SigningHelper.GetAssemblyInfo(assemblyPath); - if (SigningHelper.RemoveInvalidFriendAssemblies(assemblyPath, keyFile, keyFilePassword)) + if (SigningHelper.RemoveInvalidFriendAssemblies(assemblyPath, keyFile, keyFilePassword, probingPaths)) { PrintMessageColor(string.Format("Invalid friend assemblies removed successfully from '{0}'.", assemblyPath), LogLevel.Changes, ConsoleColor.Green); diff --git a/src/Brutal.Dev.StrongNameSigner.UI/MainForm.cs b/src/Brutal.Dev.StrongNameSigner.UI/MainForm.cs index b41cdee..96cbebb 100644 --- a/src/Brutal.Dev.StrongNameSigner.UI/MainForm.cs +++ b/src/Brutal.Dev.StrongNameSigner.UI/MainForm.cs @@ -418,7 +418,7 @@ private void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e) } log.AppendFormat("Fixing references to {1} in {0}...", filePath, reference).AppendLine(); - if (SigningHelper.FixAssemblyReference(filePath, reference, keyFile, password)) + if (SigningHelper.FixAssemblyReference(filePath, reference, keyFile, password, assemblyPaths.Select(f => Path.GetDirectoryName(f)).Distinct().ToArray())) { log.Append("Reference was found and fixed.").AppendLine(); referenceFixes++; @@ -442,7 +442,7 @@ private void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e) } log.AppendFormat("Removing invalid friend references from '{0}'...", filePath).AppendLine(); - if (SigningHelper.RemoveInvalidFriendAssemblies(filePath, keyFile, password)) + if (SigningHelper.RemoveInvalidFriendAssemblies(filePath, keyFile, password, assemblyPaths.Select(f => Path.GetDirectoryName(f)).Distinct().ToArray())) { log.Append("Invalid friend assemblies removed.").AppendLine(); referenceFixes++; diff --git a/src/Brutal.Dev.StrongNameSigner/SigningHelper.cs b/src/Brutal.Dev.StrongNameSigner/SigningHelper.cs index 55abfa4..67313f2 100644 --- a/src/Brutal.Dev.StrongNameSigner/SigningHelper.cs +++ b/src/Brutal.Dev.StrongNameSigner/SigningHelper.cs @@ -77,19 +77,16 @@ public static AssemblyInfo SignAssembly(string assemblyPath, string keyPath, str /// The path to the strong-name key file you want to use (.snk or .pfx). /// The directory path where the strong-name signed assembly will be copied to. /// The password for the provided strong-name key file. - /// The assembly information of the new strong-name signed assembly. - /// - /// assemblyPath parameter was not provided. - /// - /// - /// Could not find provided assembly file. + /// Additional paths to probe for references. + /// + /// The assembly information of the new strong-name signed assembly. + /// + /// assemblyPath parameter was not provided. + /// Could not find provided assembly file. /// or - /// Could not find provided strong-name key file file. - /// - /// - /// The file is not a .NET managed assembly. - /// - public static AssemblyInfo SignAssembly(string assemblyPath, string keyPath, string outputPath, string keyFilePassword) + /// Could not find provided strong-name key file file. + /// The file is not a .NET managed assembly. + public static AssemblyInfo SignAssembly(string assemblyPath, string keyPath, string outputPath, string keyFilePassword, params string[] probingPaths) { // Verify assembly path was passed in. if (string.IsNullOrWhiteSpace(assemblyPath)) @@ -138,7 +135,7 @@ public static AssemblyInfo SignAssembly(string assemblyPath, string keyPath, str try { - AssemblyDefinition.ReadAssembly(assemblyPath, GetReadParameters(assemblyPath)) + AssemblyDefinition.ReadAssembly(assemblyPath, GetReadParameters(assemblyPath, probingPaths)) .Write(outputFile, new WriterParameters() { StrongNameKeyPair = GetStrongNameKeyPair(keyPath, keyFilePassword) }); } catch (Exception) @@ -159,14 +156,13 @@ public static AssemblyInfo SignAssembly(string assemblyPath, string keyPath, str /// Gets .NET assembly information. /// /// The path to an assembly you want to get information from. - /// The assembly information. - /// - /// assemblyPath parameter was not provided. - /// - /// - /// Could not find provided assembly file. - /// - public static AssemblyInfo GetAssemblyInfo(string assemblyPath) + /// Additional paths to probe for references. + /// + /// The assembly information. + /// + /// assemblyPath parameter was not provided. + /// Could not find provided assembly file. + public static AssemblyInfo GetAssemblyInfo(string assemblyPath, params string[] probingPaths) { // Verify assembly path was passed in. if (string.IsNullOrWhiteSpace(assemblyPath)) @@ -180,7 +176,7 @@ public static AssemblyInfo GetAssemblyInfo(string assemblyPath) throw new FileNotFoundException("Could not find provided assembly file.", assemblyPath); } - var a = AssemblyDefinition.ReadAssembly(assemblyPath, GetReadParameters(assemblyPath)); + var a = AssemblyDefinition.ReadAssembly(assemblyPath, GetReadParameters(assemblyPath, probingPaths)); return new AssemblyInfo() { @@ -218,22 +214,21 @@ public static bool FixAssemblyReference(string assemblyPath, string referenceAss /// /// Fixes an assembly reference. /// - /// The path to the assembly you want to fix a reference for. + /// The path to the assembly you want to fix a reference for. /// The path to the reference assembly path you want to fix in the first assembly. /// The path to the strong-name key file you want to use (.snk or .pfx). /// The password for the provided strong-name key file. - /// true if an assembly reference was found and fixed, false if no reference was found. - /// - /// assemblyPath was not provided. + /// Additional paths to probe for references. + /// + /// true if an assembly reference was found and fixed, false if no reference was found. + /// + /// assemblyPath was not provided. /// or - /// referenceAssemblyPath was not provided. - /// - /// - /// Could not find provided assembly file. + /// referenceAssemblyPath was not provided. + /// Could not find provided assembly file. /// or - /// Could not find provided reference assembly file. - /// - public static bool FixAssemblyReference(string assemblyPath, string referenceAssemblyPath, string keyPath, string keyFilePassword) + /// Could not find provided reference assembly file. + public static bool FixAssemblyReference(string assemblyPath, string referenceAssemblyPath, string keyPath, string keyFilePassword, params string[] probingPaths) { // Verify assembly path was passed in. if (string.IsNullOrWhiteSpace(assemblyPath)) @@ -258,8 +253,8 @@ public static bool FixAssemblyReference(string assemblyPath, string referenceAss } bool fixApplied = false; - var a = AssemblyDefinition.ReadAssembly(assemblyPath, GetReadParameters(assemblyPath)); - var b = AssemblyDefinition.ReadAssembly(referenceAssemblyPath, GetReadParameters(referenceAssemblyPath)); + var a = AssemblyDefinition.ReadAssembly(assemblyPath, GetReadParameters(assemblyPath, probingPaths)); + var b = AssemblyDefinition.ReadAssembly(referenceAssemblyPath, GetReadParameters(referenceAssemblyPath, probingPaths)); var assemblyReference = a.MainModule.AssemblyReferences.FirstOrDefault(r => r.Name == b.Name.Name); @@ -324,14 +319,13 @@ public static bool RemoveInvalidFriendAssemblies(string assemblyPath) /// The path to the assembly you want to remove friend references from. /// The path to the strong-name key file you want to use (.snk or .pfx). /// The password for the provided strong-name key file. - /// true if any invalid friend references were found and fixed, false if no invalid friend references was found. - /// - /// assemblyPath was not provided. - /// - /// - /// Could not find provided assembly file. - /// - public static bool RemoveInvalidFriendAssemblies(string assemblyPath, string keyPath, string keyFilePassword) + /// Additional paths to probe for references. + /// + /// true if any invalid friend references were found and fixed, false if no invalid friend references was found. + /// + /// assemblyPath was not provided. + /// Could not find provided assembly file. + public static bool RemoveInvalidFriendAssemblies(string assemblyPath, string keyPath, string keyFilePassword, params string[] probingPaths) { // Verify assembly path was passed in. if (string.IsNullOrWhiteSpace(assemblyPath)) @@ -346,7 +340,7 @@ public static bool RemoveInvalidFriendAssemblies(string assemblyPath, string key } bool fixApplied = false; - var a = AssemblyDefinition.ReadAssembly(assemblyPath, GetReadParameters(assemblyPath)); + var a = AssemblyDefinition.ReadAssembly(assemblyPath, GetReadParameters(assemblyPath, probingPaths)); var ivtAttributes = a.CustomAttributes.Where(attr => attr.AttributeType.FullName == typeof(InternalsVisibleToAttribute).FullName).ToList(); @@ -375,7 +369,7 @@ public static bool RemoveInvalidFriendAssemblies(string assemblyPath, string key return fixApplied; } - private static ReaderParameters GetReadParameters(string assemblyPath) + private static ReaderParameters GetReadParameters(string assemblyPath, string[] probingPaths) { var resolver = new DefaultAssemblyResolver(); @@ -384,6 +378,17 @@ private static ReaderParameters GetReadParameters(string assemblyPath) resolver.AddSearchDirectory(Path.GetDirectoryName(assemblyPath)); } + if (probingPaths != null) + { + foreach (var searchDir in probingPaths) + { + if (Directory.Exists(searchDir)) + { + resolver.AddSearchDirectory(searchDir); + } + } + } + return new ReaderParameters() { AssemblyResolver = resolver }; }