Merge branch 'feature/msbuild'

This commit is contained in:
Martin Karing 2018-07-26 14:07:55 +02:00
Родитель 87a1187e9f 62bdb3ddae
Коммит 18cffad542
16 изменённых файлов: 579 добавлений и 12 удалений

Просмотреть файл

@ -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;
}
}
}
}

Просмотреть файл

@ -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;
}
}
}

Просмотреть файл

@ -0,0 +1,59 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\ConfuserEx.Common.props" Condition="Exists('..\ConfuserEx.Common.props')" />
<PropertyGroup Label="Assembly Settings">
<TargetFrameworks>net461;netstandard2.0</TargetFrameworks>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\ConfuserEx.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup Label="Nuget Package Settings">
<PackageId>Confuser.MSBuild</PackageId>
<PackageLicenseUrl>https://github.com/mkaring/ConfuserEx/blob/master/LICENSE.md</PackageLicenseUrl>
<PackageProjectUrl>https://github.com/mkaring/ConfuserEx</PackageProjectUrl>
<PackageTags>Obfuscation Confuser ConfuserEx</PackageTags>
<DevelopmentDependency>true</DevelopmentDependency>
<IncludeBuildOutput>false</IncludeBuildOutput>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<NoPackageAnalysis>true</NoPackageAnalysis>
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);IncludeConfuserDependencyFiles</TargetsForTfmSpecificContentInPackage>
</PropertyGroup>
<ItemGroup Label="Nuget Dependencies">
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="15.7.*" />
</ItemGroup>
<ItemGroup Label="Project Dependencies">
<ProjectReference Include="..\Confuser.Core\Confuser.Core.csproj" PrivateAssets="all" />
<ProjectReference Include="..\Confuser.Protections\Confuser.Protections.csproj" PrivateAssets="all" />
<ProjectReference Include="..\Confuser.Renamer\Confuser.Renamer.csproj" PrivateAssets="all" />
<ProjectReference Include="..\Confuser.Runtime\Confuser.Runtime.csproj" Condition="'$(TargetFramework)' == 'net461'" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<Content Include="build\*" PackagePath="build" />
</ItemGroup>
<ItemGroup>
<None Remove="build\Confuser.MSBuild.targets" />
</ItemGroup>
<Target Name="IncludeConfuserDependencyFiles">
<ItemGroup>
<ConfuserNetFrameworkDependencies Include="$(BaseOutputPath)\$(Configuration)\net461\*.dll" />
<ConfuserNetFrameworkDependencies Include="$(BaseOutputPath)\$(Configuration)\net461\*.pdb" />
<ConfuserNetStandardDependencies Include="$(BaseOutputPath)\$(Configuration)\netstandard2.0\*.dll" />
<ConfuserNetStandardDependencies Include="$(BaseOutputPath)\$(Configuration)\netstandard2.0\*.pdb" />
</ItemGroup>
<CreateItem Include="@(ConfuserNetFrameworkDependencies)" AdditionalMetadata="PackagePath=netframework">
<Output TaskParameter="Include" ItemName="TfmSpecificPackageFile" />
</CreateItem>
<CreateItem Include="@(ConfuserNetStandardDependencies)" AdditionalMetadata="PackagePath=netstandard">
<Output TaskParameter="Include" ItemName="TfmSpecificPackageFile" />
</CreateItem>
</Target>
<Import Project="..\ConfuserEx.Common.targets" Condition="Exists('..\ConfuserEx.Common.targets')" />
</Project>

Просмотреть файл

@ -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;
}
}
}

Просмотреть файл

@ -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);
}
}

Просмотреть файл

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8" ?>
<Project>
<Choose>
<When Condition="'$(MSBuildRuntimeType)' == 'Full'">
<PropertyGroup>
<ConfuserAssemblyPath>$(MSBuildThisFileDirectory)\..\netframework\</ConfuserAssemblyPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<ConfuserAssemblyPath>$(MSBuildThisFileDirectory)\..\netstandard\</ConfuserAssemblyPath>
</PropertyGroup>
</Otherwise>
</Choose>
<UsingTask TaskName="Confuser.MSBuild.Tasks.CreateProjectTask"
AssemblyFile="$(ConfuserAssemblyPath)Confuser.MSBuild.Tasks.dll" />
<UsingTask TaskName="Confuser.MSBuild.Tasks.ConfuseTask"
AssemblyFile="$(ConfuserAssemblyPath)Confuser.MSBuild.Tasks.dll" />
</Project>

Просмотреть файл

@ -0,0 +1,156 @@
<?xml version="1.0" encoding="utf-8" ?>
<Project>
<PropertyGroup>
<ConfuserKeyFile Condition="'$(ConfuserKeyFile)' == ''">$(AssemblyOriginatorKeyFile)</ConfuserKeyFile>
<ConfuserIntermediateOutputPath Condition="'$(ConfuserIntermediateOutputPath)' == ''">$(IntermediateOutputPath)confused\</ConfuserIntermediateOutputPath>
<ConfuserReplaceOutput Condition="'$(ConfuserReplaceOutput)' == ''">false</ConfuserReplaceOutput>
<ConfuserOutDir Condition="'$(ConfuserOutDir)' == ''">$(OutDir)confused\</ConfuserOutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(ConfuserProject)' == ''">
<ConfuserProject Condition="Exists('$(MSBuildProjectDirectory)\$(MSBuildProjectName).crproj')">$(MSBuildProjectDirectory)\$(MSBuildProjectName).crproj</ConfuserProject>
</PropertyGroup>
<PropertyGroup>
<ConfuserExDependsOn>
CreateConfuserProject;
ConfuseAssembly;
_ReplaceOutputWithConfusedAssemblies;
_ReplaceDebugOutputWithConfusedAssemblies;
CopyConfusedFilesToOutputDirectory;
</ConfuserExDependsOn>
</PropertyGroup>
<Target Name="ConfuserEx"
DependsOnTargets="$(ConfuserExDependsOn)"
BeforeTargets="PrepareForRun" />
<PropertyGroup>
<CreateConfuserProjectDependsOn>
ResolveReferences;
ComputeIntermediateSatelliteAssemblies
</CreateConfuserProjectDependsOn>
</PropertyGroup>
<Target Name="CreateConfuserProject"
Condition="$(DesignTimeBuild) != true And $(Obfuscate) == true"
DependsOnTargets="$(CreateConfuserProjectDependsOn)"
Inputs="@(IntermediateAssembly->'%(FullPath)');$(ConfuserProject);@(IntermediateSatelliteAssembliesWithTargetPath)"
Outputs="@(IntermediateAssembly->'$(IntermediateOutputPath)%(Filename).crproj')">
<Confuser.MSBuild.Tasks.CreateProjectTask
SourceProject="$(ConfuserProject)"
References="@(ReferencePath)"
AssemblyPath="@(IntermediateAssembly)"
SatelliteAssemblyPaths="@(IntermediateSatelliteAssembliesWithTargetPath)"
KeyFilePath="$(ConfuserKeyFile)"
ResultProject="@(IntermediateAssembly->'$(IntermediateOutputPath)%(Filename).crproj')"/>
</Target>
<PropertyGroup>
<ConfuseAssemblyDependsOn>
CreateConfuserProject
</ConfuseAssemblyDependsOn>
</PropertyGroup>
<Target Name="ConfuseAssembly"
Condition="Exists('@(IntermediateAssembly)') And $(DesignTimeBuild) != true And $(Obfuscate) == true"
DependsOnTargets="$(ConfuseAssemblyDependsOn)"
Inputs="@(IntermediateAssembly->'%(FullPath)');@(IntermediateAssembly->'$(IntermediateOutputPath)%(Filename).crproj')"
Outputs="@(IntermediateAssembly->'$(ConfuserIntermediateOutputPath)%(Filename)%(Extension)');@(IntermediateSatelliteAssembliesWithTargetPath->'$(ConfuserIntermediateOutputPath)%(TargetPath)')">
<Confuser.MSBuild.Tasks.ConfuseTask
Project="@(IntermediateAssembly->'$(IntermediateOutputPath)%(Filename).crproj')"
OutputAssembly="@(IntermediateAssembly->'$(ConfuserIntermediateOutputPath)%(Filename)%(Extension)')" />
</Target>
<Target Name="_ReplaceOutputWithConfusedAssemblies"
Condition="$(DesignTimeBuild) != true And $(Obfuscate) == true and '$(ConfuserReplaceOutput)' == 'true'"
DependsOnTargets="ConfuseAssembly">
<CreateItem Include="@(IntermediateAssembly->'$(ConfuserIntermediateOutputPath)%(Filename)%(Extension)')">
<Output TaskParameter="Include" ItemName="IntermediateConfusedAssembly" />
</CreateItem>
<ItemGroup>
<IntermediateAssembly Remove="@(IntermediateAssembly)" />
</ItemGroup>
<CreateItem Include="@(IntermediateConfusedAssembly)">
<Output TaskParameter="Include" ItemName="IntermediateAssembly" />
</CreateItem>
</Target>
<Target Name="_ReplaceDebugOutputWithConfusedAssemblies"
Condition="$(DesignTimeBuild) != true And $(Obfuscate) == true and '$(ConfuserReplaceOutput)' == 'true' and '@(_DebugSymbolsIntermediatePath)' != ''"
DependsOnTargets="ConfuseAssembly">
<CreateItem Include="@(IntermediateAssembly->'$(ConfuserIntermediateOutputPath)%(Filename).pdb')">
<Output TaskParameter="Include" ItemName="_ConfusedDebugSymbolsIntermediatePath" />
</CreateItem>
<ItemGroup>
<_DebugSymbolsIntermediatePath Remove="@(_DebugSymbolsIntermediatePath)" />
</ItemGroup>
<CreateItem Include="@(_ConfusedDebugSymbolsIntermediatePath)">
<Output TaskParameter="Include" ItemName="_DebugSymbolsIntermediatePath" />
</CreateItem>
</Target>
<Target Name="CopyConfusedFilesToOutputDirectory"
Condition="$(DesignTimeBuild) != true And $(Obfuscate) == true and '$(ConfuserReplaceOutput)' != 'true'">
<PropertyGroup>
<!-- By default we're not using Hard Links to copy to the output directory, and never when building in VS -->
<CreateHardLinksForCopyFilesToOutputDirectoryIfPossible Condition="'$(BuildingInsideVisualStudio)' == 'true' or '$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)' == ''">false</CreateHardLinksForCopyFilesToOutputDirectoryIfPossible>
<CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible Condition="'$(BuildingInsideVisualStudio)' == 'true' or '$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)' == ''">false</CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible>
</PropertyGroup>
<PropertyGroup>
<CopyBuildOutputToOutputDirectory Condition="'$(CopyBuildOutputToOutputDirectory)'==''">true</CopyBuildOutputToOutputDirectory>
<CopyOutputSymbolsToOutputDirectory Condition="'$(CopyOutputSymbolsToOutputDirectory)'==''">true</CopyOutputSymbolsToOutputDirectory>
</PropertyGroup>
<!-- Copy the confused build product (.dll or .exe). -->
<Copy
SourceFiles="@(IntermediateAssembly->'$(ConfuserIntermediateOutputPath)%(Filename)%(Extension)')"
DestinationFolder="$(ConfuserOutDir)"
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
Retries="$(CopyRetryCount)"
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)"
Condition="'$(CopyBuildOutputToOutputDirectory)' == 'true' and '$(SkipCopyBuildProduct)' != 'true'">
<Output TaskParameter="DestinationFiles" ItemName="ConfusedMainAssembly"/>
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
</Copy>
<!-- Copy the debug information file (.pdb), if any -->
<Copy
SourceFiles="@(IntermediateAssembly->'$(ConfuserIntermediateOutputPath)%(Filename).pdb')"
DestinationFolder="$(ConfuserOutDir)"
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
Retries="$(CopyRetryCount)"
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)"
Condition="'$(_DebugSymbolsProduced)'=='true' and '$(SkipCopyingSymbolsToOutputDirectory)' != 'true' and '$(CopyOutputSymbolsToOutputDirectory)'=='true'">
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
</Copy>
<!-- Copy the satellite assemblies (.resources.dll), if any -->
<Copy
SourceFiles="@(IntermediateSatelliteAssembliesWithTargetPath->'$(ConfuserIntermediateOutputPath)%(TargetPath)')"
DestinationFiles="@(IntermediateSatelliteAssembliesWithTargetPath->'$(ConfuserOutDir)%(TargetPath)')"
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
Retries="$(CopyRetryCount)"
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)"
Condition="'$(_DebugSymbolsProduced)'=='true' and '$(SkipCopyingSymbolsToOutputDirectory)' != 'true' and '$(CopyOutputSymbolsToOutputDirectory)'=='true'">
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
</Copy>
</Target>
</Project>

Просмотреть файл

@ -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;

Просмотреть файл

@ -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()) {

Просмотреть файл

@ -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

Просмотреть файл

@ -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<Protection>("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<object[]> CompressAndExecuteTestData() {
foreach (var compressorCompatKey in new string[] { "true", "false" })
foreach (var compressorDeriveKey in new string[] { "normal", "dynamic" })
foreach (var resourceProtectionMode in new string[] { "none", "normal", "dynamic" })
yield return new object[] { compressorCompatKey, compressorDeriveKey, resourceProtectionMode };
}
}
}

Просмотреть файл

@ -4,6 +4,9 @@ namespace CompressorWithResx {
public class Program {
internal static int Main(string[] args) {
Console.WriteLine("START");
Properties.Resources.Culture = new System.Globalization.CultureInfo("en-US");
Console.WriteLine(Properties.Resources.TestString);
Properties.Resources.Culture = new System.Globalization.CultureInfo("de-DE");
Console.WriteLine(Properties.Resources.TestString);
Console.WriteLine("END");
return 42;

Просмотреть файл

@ -61,7 +61,7 @@ namespace CompressorWithResx.Properties {
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Test ähnelt.
/// Sucht eine lokalisierte Zeichenfolge, die Test (fallback) ähnelt.
/// </summary>
internal static string TestString {
get {

Просмотреть файл

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="TestString" xml:space="preserve">
<value>Test (deutsch)</value>
</data>
</root>

Просмотреть файл

@ -118,6 +118,6 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="TestString" xml:space="preserve">
<value>Test</value>
<value>Test (fallback)</value>
</data>
</root>

Просмотреть файл

@ -24,3 +24,7 @@ build:
artifacts:
- path: Release/bin
name: ConfuserEx
type: zip
- path: Confuser.MSBuild.Tasks/bin/Release/*.nupkg
name: ConfuserEx.MSBuild