diff --git a/Confuser.Core/Project/ConfuserProject.cs b/Confuser.Core/Project/ConfuserProject.cs
index d6307fa..40f220f 100644
--- a/Confuser.Core/Project/ConfuserProject.cs
+++ b/Confuser.Core/Project/ConfuserProject.cs
@@ -89,7 +89,7 @@ namespace Confuser.Core.Project {
if (IsExternal) {
XmlAttribute extAttr = xmlDoc.CreateAttribute("external");
- extAttr.Value = IsExternal.ToString();
+ extAttr.Value = IsExternal ? "true" : "false";
elem.Attributes.Append(extAttr);
}
if (SNKeyPath != null) {
@@ -610,4 +610,4 @@ namespace Confuser.Core.Project {
return ret;
}
}
-}
\ No newline at end of file
+}
diff --git a/Confuser.MSBuild.Tasks/ConfuseTask.cs b/Confuser.MSBuild.Tasks/ConfuseTask.cs
new file mode 100644
index 0000000..b59cb79
--- /dev/null
+++ b/Confuser.MSBuild.Tasks/ConfuseTask.cs
@@ -0,0 +1,33 @@
+using System.IO;
+using System.Xml;
+using Confuser.Core;
+using Confuser.Core.Project;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace Confuser.MSBuild.Tasks {
+ public sealed class ConfuseTask : Task {
+ [Required]
+ public ITaskItem Project { get; set; }
+
+ [Required, Output]
+ public ITaskItem OutputAssembly { get; set; }
+
+ public override bool Execute() {
+ var project = new ConfuserProject();
+ var xmlDoc = new XmlDocument();
+ xmlDoc.Load(Project.ItemSpec);
+ project.Load(xmlDoc);
+ project.OutputDirectory = Path.GetDirectoryName(OutputAssembly.ItemSpec);
+
+ var logger = new MSBuildLogger(Log);
+ var parameters = new ConfuserParameters {
+ Project = project,
+ Logger = logger
+ };
+
+ ConfuserEngine.Run(parameters).Wait();
+ return !logger.HasError;
+ }
+ }
+}
diff --git a/Confuser.MSBuild.Tasks/Confuser.MSBuild.Tasks.csproj b/Confuser.MSBuild.Tasks/Confuser.MSBuild.Tasks.csproj
new file mode 100644
index 0000000..bf70465
--- /dev/null
+++ b/Confuser.MSBuild.Tasks/Confuser.MSBuild.Tasks.csproj
@@ -0,0 +1,59 @@
+
+
+
+
+
+ net461;netstandard2.0
+ true
+ ..\ConfuserEx.snk
+
+
+
+ Confuser.MSBuild
+ https://github.com/mkaring/ConfuserEx/blob/master/LICENSE.md
+ https://github.com/mkaring/ConfuserEx
+ Obfuscation Confuser ConfuserEx
+ true
+ false
+ true
+ true
+ $(TargetsForTfmSpecificContentInPackage);IncludeConfuserDependencyFiles
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Confuser.MSBuild.Tasks/CreateProjectTask.cs b/Confuser.MSBuild.Tasks/CreateProjectTask.cs
new file mode 100644
index 0000000..0de560f
--- /dev/null
+++ b/Confuser.MSBuild.Tasks/CreateProjectTask.cs
@@ -0,0 +1,84 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using Confuser.Core.Project;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace Confuser.MSBuild.Tasks {
+ public sealed class CreateProjectTask : Task {
+ public ITaskItem SourceProject { get; set; }
+
+ [Required]
+ public ITaskItem[] References { get; set; }
+
+ [Required]
+ public ITaskItem AssemblyPath { get; set; }
+
+ public ITaskItem[] SatelliteAssemblyPaths { get; set; }
+
+ public ITaskItem KeyFilePath { get; set; }
+
+ [Required, Output]
+ public ITaskItem ResultProject { get; set; }
+
+ public override bool Execute() {
+ var project = new ConfuserProject();
+ if (!string.IsNullOrWhiteSpace(SourceProject?.ItemSpec)) {
+ var xmlDoc = new XmlDocument();
+ xmlDoc.Load(SourceProject.ItemSpec);
+ project.Load(xmlDoc);
+
+ // Probe Paths are not required, because all dependent assemblies are added as external modules.
+ project.ProbePaths.Clear();
+ }
+
+ project.BaseDirectory = Path.GetDirectoryName(AssemblyPath.ItemSpec);
+ var mainModule = GetOrCreateProjectModule(project, AssemblyPath.ItemSpec);
+ if (!string.IsNullOrWhiteSpace(KeyFilePath?.ItemSpec)) {
+ mainModule.SNKeyPath = KeyFilePath.ItemSpec;
+ }
+
+ if (SatelliteAssemblyPaths != null) {
+ foreach (var satelliteAssembly in SatelliteAssemblyPaths) {
+ if (!string.IsNullOrWhiteSpace(satelliteAssembly?.ItemSpec)) {
+ var satelliteModule = GetOrCreateProjectModule(project, satelliteAssembly.ItemSpec);
+ if (!string.IsNullOrWhiteSpace(KeyFilePath?.ItemSpec)) {
+ satelliteModule.SNKeyPath = KeyFilePath.ItemSpec;
+ }
+ }
+ }
+ }
+
+ foreach (var probePath in References.Select(r => Path.GetDirectoryName(r.ItemSpec)).Distinct()) {
+ project.ProbePaths.Add(probePath);
+ }
+
+ project.Save().Save(ResultProject.ItemSpec);
+
+ return true;
+ }
+
+ private static ProjectModule GetOrCreateProjectModule(ConfuserProject project, string assemblyPath, bool isExternal = false) {
+ var assemblyFileName = Path.GetFileName(assemblyPath);
+ var assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
+ foreach (var module in project) {
+ if (string.Equals(module.Path, assemblyFileName) || string.Equals(module.Path, assemblyName)) {
+ return module;
+ }
+ }
+
+ if (assemblyPath.StartsWith(project.BaseDirectory)) {
+ assemblyPath = assemblyPath.Substring(project.BaseDirectory.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
+ }
+
+ var result = new ProjectModule {
+ Path = assemblyPath,
+ IsExternal = isExternal
+ };
+ project.Add(result);
+ return result;
+ }
+ }
+}
diff --git a/Confuser.MSBuild.Tasks/MSBuildLogger.cs b/Confuser.MSBuild.Tasks/MSBuildLogger.cs
new file mode 100644
index 0000000..c0f81ed
--- /dev/null
+++ b/Confuser.MSBuild.Tasks/MSBuildLogger.cs
@@ -0,0 +1,61 @@
+using System;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using ILogger = Confuser.Core.ILogger;
+
+namespace Confuser.MSBuild.Tasks {
+ internal sealed class MSBuildLogger : ILogger {
+ private readonly TaskLoggingHelper loggingHelper;
+
+ internal bool HasError { get; private set; }
+
+ internal MSBuildLogger(TaskLoggingHelper loggingHelper) =>
+ this.loggingHelper = loggingHelper ?? throw new ArgumentNullException(nameof(loggingHelper));
+
+ void ILogger.Debug(string msg) => loggingHelper.LogMessage(MessageImportance.Low, "[DEBUG] " + msg);
+
+ void ILogger.DebugFormat(string format, params object[] args) {
+ loggingHelper.LogMessage(MessageImportance.Low, "[DEBUG] " + format, args);
+ }
+
+ void ILogger.EndProgress() {}
+
+ void ILogger.Error(string msg) {
+ loggingHelper.LogError(msg);
+ HasError = true;
+ }
+
+ void ILogger.ErrorException(string msg, Exception ex) {
+ loggingHelper.LogError(msg);
+ loggingHelper.LogErrorFromException(ex);
+ HasError = true;
+ }
+
+ void ILogger.ErrorFormat(string format, params object[] args) {
+ loggingHelper.LogError(format, args);
+ HasError = true;
+ }
+
+ void ILogger.Finish(bool successful) {
+ if (!successful) {
+ HasError = false;
+ }
+ }
+
+ void ILogger.Info(string msg) => loggingHelper.LogMessage(MessageImportance.Normal, msg);
+
+ void ILogger.InfoFormat(string format, params object[] args) =>
+ loggingHelper.LogMessage(MessageImportance.Normal, format, args);
+
+ void ILogger.Progress(int progress, int overall) { }
+
+ void ILogger.Warn(string msg) => loggingHelper.LogWarning(msg);
+
+ void ILogger.WarnException(string msg, Exception ex) {
+ loggingHelper.LogWarning(msg);
+ loggingHelper.LogWarningFromException(ex);
+ }
+
+ void ILogger.WarnFormat(string format, params object[] args) => loggingHelper.LogWarning(format, args);
+ }
+}
diff --git a/Confuser.MSBuild.Tasks/build/Confuser.MSBuild.props b/Confuser.MSBuild.Tasks/build/Confuser.MSBuild.props
new file mode 100644
index 0000000..4b4ed1c
--- /dev/null
+++ b/Confuser.MSBuild.Tasks/build/Confuser.MSBuild.props
@@ -0,0 +1,19 @@
+
+
+
+
+
+ $(MSBuildThisFileDirectory)\..\netframework\
+
+
+
+
+ $(MSBuildThisFileDirectory)\..\netstandard\
+
+
+
+
+
+
diff --git a/Confuser.MSBuild.Tasks/build/Confuser.MSBuild.targets b/Confuser.MSBuild.Tasks/build/Confuser.MSBuild.targets
new file mode 100644
index 0000000..94d378c
--- /dev/null
+++ b/Confuser.MSBuild.Tasks/build/Confuser.MSBuild.targets
@@ -0,0 +1,156 @@
+
+
+
+ $(AssemblyOriginatorKeyFile)
+ $(IntermediateOutputPath)confused\
+ false
+ $(OutDir)confused\
+
+
+
+ $(MSBuildProjectDirectory)\$(MSBuildProjectName).crproj
+
+
+
+
+ CreateConfuserProject;
+ ConfuseAssembly;
+ _ReplaceOutputWithConfusedAssemblies;
+ _ReplaceDebugOutputWithConfusedAssemblies;
+ CopyConfusedFilesToOutputDirectory;
+
+
+
+
+
+
+
+
+ ResolveReferences;
+ ComputeIntermediateSatelliteAssemblies
+
+
+
+
+
+
+
+
+
+ CreateConfuserProject
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_DebugSymbolsIntermediatePath Remove="@(_DebugSymbolsIntermediatePath)" />
+
+
+
+
+
+
+
+
+
+ false
+ false
+
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Confuser.Renamer/Analyzers/ResourceAnalyzer.cs b/Confuser.Renamer/Analyzers/ResourceAnalyzer.cs
index d911be1..fe77a73 100644
--- a/Confuser.Renamer/Analyzers/ResourceAnalyzer.cs
+++ b/Confuser.Renamer/Analyzers/ResourceAnalyzer.cs
@@ -31,7 +31,7 @@ namespace Confuser.Renamer.Analyzers {
if (!match.Success)
continue;
string typeName = match.Groups[1].Value;
- TypeDef type = mainModule.FindReflectionThrow(typeName);
+ TypeDef type = mainModule.FindReflection(typeName);
if (type == null) {
context.Logger.WarnFormat("Could not find resource type '{0}'.", typeName);
continue;
diff --git a/Confuser.Renamer/Analyzers/TypeBlobAnalyzer.cs b/Confuser.Renamer/Analyzers/TypeBlobAnalyzer.cs
index 4c28eeb..2afd098 100644
--- a/Confuser.Renamer/Analyzers/TypeBlobAnalyzer.cs
+++ b/Confuser.Renamer/Analyzers/TypeBlobAnalyzer.cs
@@ -98,6 +98,8 @@ namespace Confuser.Renamer.Analyzers {
}
void AnalyzeCAArgument(ConfuserContext context, INameService service, CAArgument arg) {
+ if (arg.Value == null) return; // null was passed to the custom attribute. We'll ignore that.
+
if (arg.Type.DefinitionAssembly.IsCorLib() && arg.Type.FullName == "System.Type") {
var typeSig = (TypeSig)arg.Value;
foreach (ITypeDefOrRef typeRef in typeSig.FindTypeRefs()) {
diff --git a/Confuser2.sln b/Confuser2.sln
index df66954..8b552fd 100644
--- a/Confuser2.sln
+++ b/Confuser2.sln
@@ -40,7 +40,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Confuser.UnitTest", "Tests\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntiTamper", "Tests\AntiTamper\AntiTamper.csproj", "{6A2BA6F7-3399-4890-9453-2D5BE8EEBBA9}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AntiTamper.Test", "Tests\AntiTamper.Test\AntiTamper.Test.csproj", "{3F5558BD-7B94-4CB0-A46C-A7252B5BCA17}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntiTamper.Test", "Tests\AntiTamper.Test\AntiTamper.Test.csproj", "{3F5558BD-7B94-4CB0-A46C-A7252B5BCA17}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Confuser.MSBuild.Tasks", "Confuser.MSBuild.Tasks\Confuser.MSBuild.Tasks.csproj", "{91B12706-DC6A-45DE-97F1-FAF0901FF6AF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -100,6 +102,10 @@ Global
{3F5558BD-7B94-4CB0-A46C-A7252B5BCA17}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3F5558BD-7B94-4CB0-A46C-A7252B5BCA17}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3F5558BD-7B94-4CB0-A46C-A7252B5BCA17}.Release|Any CPU.Build.0 = Release|Any CPU
+ {91B12706-DC6A-45DE-97F1-FAF0901FF6AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {91B12706-DC6A-45DE-97F1-FAF0901FF6AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {91B12706-DC6A-45DE-97F1-FAF0901FF6AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {91B12706-DC6A-45DE-97F1-FAF0901FF6AF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Tests/CompressorWithResx.Test/CompressTest.cs b/Tests/CompressorWithResx.Test/CompressTest.cs
index d656cfb..b5b87d3 100644
--- a/Tests/CompressorWithResx.Test/CompressTest.cs
+++ b/Tests/CompressorWithResx.Test/CompressTest.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
@@ -16,16 +17,14 @@ namespace CompressorWithResx.Test {
this.outputHelper = outputHelper ?? throw new ArgumentNullException(nameof(outputHelper));
[Theory]
- [InlineData("false", "normal")]
- [InlineData("true", "normal")]
- [InlineData("false", "dynamic")]
- [InlineData("true", "dynamic")]
+ [MemberData(nameof(CompressAndExecuteTestData))]
[Trait("Category", "Packer")]
[Trait("Packer", "compressor")]
- public async Task CompressAndExecuteTest(string compatKey, string deriverKey) {
+ public async Task CompressAndExecuteTest(string compatKey, string deriverKey, string resourceProtectionMode) {
var baseDir = Environment.CurrentDirectory;
var outputDir = Path.Combine(baseDir, "testtmp");
var inputFile = Path.Combine(baseDir, "CompressorWithResx.exe");
+ var inputSatelliteFile = Path.Combine(baseDir, "de", "CompressorWithResx.resources.dll");
var outputFile = Path.Combine(outputDir, "CompressorWithResx.exe");
FileUtilities.ClearOutput(outputFile);
var proj = new ConfuserProject {
@@ -36,7 +35,17 @@ namespace CompressorWithResx.Test {
{ "key", deriverKey }
}
};
+
+ if (resourceProtectionMode != "none") {
+ proj.Rules.Add(new Rule() {
+ new SettingItem("resources") {
+ { "mode", resourceProtectionMode }
+ }
+ });
+ }
+
proj.Add(new ProjectModule() { Path = inputFile });
+ proj.Add(new ProjectModule() { Path = inputSatelliteFile });
var parameters = new ConfuserParameters {
@@ -56,7 +65,8 @@ namespace CompressorWithResx.Test {
using (var process = Process.Start(info)) {
var stdout = process.StandardOutput;
Assert.Equal("START", await stdout.ReadLineAsync());
- Assert.Equal("Test", await stdout.ReadLineAsync());
+ Assert.Equal("Test (fallback)", await stdout.ReadLineAsync());
+ Assert.Equal("Test (deutsch)", await stdout.ReadLineAsync());
Assert.Equal("END", await stdout.ReadLineAsync());
Assert.Empty(await stdout.ReadToEndAsync());
Assert.True(process.HasExited);
@@ -65,5 +75,12 @@ namespace CompressorWithResx.Test {
FileUtilities.ClearOutput(outputFile);
}
+
+ public static IEnumerable