Merge branch 'guiwpf'
Conflicts: Confuser.Core/ConfuserEngine.cs Confuser.Core/Marker.cs Confuser.Renamer/AnalyzePhase.cs
|
@ -28,7 +28,6 @@ obj/
|
|||
_ReSharper*/
|
||||
[Tt]est[Rr]esult*
|
||||
|
||||
/docs
|
||||
!packages/*/build/
|
||||
packages/
|
||||
/Confuser.Test
|
||||
|
|
|
@ -128,9 +128,9 @@ namespace Confuser.CLI {
|
|||
WriteLineWithColor(ConsoleColor.Red, "Exception: " + ex);
|
||||
}
|
||||
|
||||
public void Progress(int overall, int progress) {
|
||||
WriteLineWithColor(ConsoleColor.Gray, string.Format("{0}/{1}", progress, overall));
|
||||
}
|
||||
public void Progress(int progress, int overall) { }
|
||||
|
||||
public void EndProgress() { }
|
||||
|
||||
public void Finish(bool successful) {
|
||||
DateTime now = DateTime.Now;
|
||||
|
|
|
@ -67,20 +67,21 @@ namespace Confuser.Core {
|
|||
context.PackerInitiated = parameters.PackerInitiated;
|
||||
context.token = token;
|
||||
|
||||
|
||||
var asmResolver = new AssemblyResolver();
|
||||
asmResolver.EnableTypeDefCache = true;
|
||||
asmResolver.DefaultModuleContext = new ModuleContext(asmResolver);
|
||||
context.Resolver = asmResolver;
|
||||
context.BaseDirectory = Path.Combine(Environment.CurrentDirectory, parameters.Project.BaseDirectory + "\\");
|
||||
context.OutputDirectory = Path.Combine(parameters.Project.BaseDirectory, parameters.Project.OutputDirectory + "\\");
|
||||
foreach (string probePath in parameters.Project.ProbePaths)
|
||||
asmResolver.PostSearchPaths.Add(Path.Combine(context.BaseDirectory, probePath));
|
||||
|
||||
PrintInfo(context);
|
||||
|
||||
bool ok = false;
|
||||
try {
|
||||
var asmResolver = new AssemblyResolver();
|
||||
asmResolver.EnableTypeDefCache = true;
|
||||
asmResolver.DefaultModuleContext = new ModuleContext(asmResolver);
|
||||
context.Resolver = asmResolver;
|
||||
context.BaseDirectory = Path.Combine(Environment.CurrentDirectory, parameters.Project.BaseDirectory + "\\");
|
||||
context.OutputDirectory = Path.Combine(parameters.Project.BaseDirectory, parameters.Project.OutputDirectory + "\\");
|
||||
foreach (string probePath in parameters.Project.ProbePaths)
|
||||
asmResolver.PostSearchPaths.Add(Path.Combine(context.BaseDirectory, probePath));
|
||||
|
||||
context.CheckCancellation();
|
||||
|
||||
Marker marker = parameters.GetMarker();
|
||||
|
||||
// 2. Discover plugins
|
||||
|
@ -93,13 +94,14 @@ namespace Confuser.Core {
|
|||
|
||||
context.Logger.InfoFormat("Discovered {0} protections, {1} packers.", prots.Count, packers.Count);
|
||||
|
||||
context.CheckCancellation();
|
||||
|
||||
// 3. Resolve dependency
|
||||
context.Logger.Debug("Resolving component dependency...");
|
||||
try {
|
||||
var resolver = new DependencyResolver(prots);
|
||||
prots = resolver.SortDependency();
|
||||
}
|
||||
catch (CircularDependencyException ex) {
|
||||
} catch (CircularDependencyException ex) {
|
||||
context.Logger.ErrorException("", ex);
|
||||
throw new ConfuserException(ex);
|
||||
}
|
||||
|
@ -110,6 +112,8 @@ namespace Confuser.Core {
|
|||
foreach (Packer packer in packers)
|
||||
components.Add(packer);
|
||||
|
||||
context.CheckCancellation();
|
||||
|
||||
// 4. Load modules
|
||||
context.Logger.Info("Loading input modules...");
|
||||
marker.Initalize(prots, packers);
|
||||
|
@ -122,19 +126,22 @@ namespace Confuser.Core {
|
|||
asmResolver.AddToCache(module);
|
||||
context.Packer = markings.Packer;
|
||||
|
||||
context.CheckCancellation();
|
||||
|
||||
// 5. Initialize components
|
||||
context.Logger.Info("Initializing...");
|
||||
foreach (ConfuserComponent comp in components) {
|
||||
try {
|
||||
comp.Initialize(context);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
} catch (Exception ex) {
|
||||
context.Logger.ErrorException("Error occured during initialization of '" + comp.Name + "'.", ex);
|
||||
throw new ConfuserException(ex);
|
||||
}
|
||||
context.CheckCancellation();
|
||||
}
|
||||
|
||||
context.CheckCancellation();
|
||||
|
||||
// 6. Build pipeline
|
||||
context.Logger.Debug("Building pipeline...");
|
||||
var pipeline = new ProtectionPipeline();
|
||||
|
@ -142,35 +149,28 @@ namespace Confuser.Core {
|
|||
foreach (ConfuserComponent comp in components) {
|
||||
comp.PopulatePipeline(pipeline);
|
||||
}
|
||||
|
||||
context.CheckCancellation();
|
||||
|
||||
//7. Run pipeline
|
||||
RunPipeline(pipeline, context);
|
||||
|
||||
ok = true;
|
||||
}
|
||||
catch (AssemblyResolveException ex) {
|
||||
} catch (AssemblyResolveException ex) {
|
||||
context.Logger.ErrorException("Failed to resolve a assembly, check if all dependencies are of correct version.", ex);
|
||||
}
|
||||
catch (TypeResolveException ex) {
|
||||
} catch (TypeResolveException ex) {
|
||||
context.Logger.ErrorException("Failed to resolve a type, check if all dependencies are of correct version.", ex);
|
||||
}
|
||||
catch (MemberRefResolveException ex) {
|
||||
} catch (MemberRefResolveException ex) {
|
||||
context.Logger.ErrorException("Failed to resolve a member, check if all dependencies are of correct version.", ex);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
context.Logger.ErrorException("An IO error occured, check if all input/output locations are read/writable.", ex);
|
||||
}
|
||||
catch (OperationCanceledException) {
|
||||
} catch (OperationCanceledException) {
|
||||
context.Logger.Error("Operation is canceled.");
|
||||
}
|
||||
catch (ConfuserException) {
|
||||
} catch (ConfuserException) {
|
||||
// Exception is already handled/logged, so just ignore and report failure
|
||||
}
|
||||
catch (Exception ex) {
|
||||
} catch (Exception ex) {
|
||||
context.Logger.ErrorException("Unknown error occured.", ex);
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
context.Logger.Finish(ok);
|
||||
}
|
||||
}
|
||||
|
@ -234,8 +234,7 @@ namespace Confuser.Core {
|
|||
.SelectMany(module => module.GetAssemblyRefs().Select(asmRef => Tuple.Create(asmRef, module)))) {
|
||||
try {
|
||||
AssemblyDef assembly = context.Resolver.ResolveThrow(dependency.Item1, dependency.Item2);
|
||||
}
|
||||
catch (AssemblyResolveException ex) {
|
||||
} catch (AssemblyResolveException ex) {
|
||||
context.Logger.ErrorException("Failed to resolve dependency of '" + dependency.Item2.Name + "'.", ex);
|
||||
throw new ConfuserException(ex);
|
||||
}
|
||||
|
@ -300,6 +299,7 @@ namespace Confuser.Core {
|
|||
context.Logger.InfoFormat("Processing module '{0}'...", context.CurrentModule.Name);
|
||||
|
||||
context.CurrentModuleWriterListener = new ModuleWriterListener();
|
||||
context.CurrentModuleWriterListener.OnWriterEvent += (sender, e) => context.CheckCancellation();
|
||||
context.CurrentModuleWriterOptions = new ModuleWriterOptions(context.CurrentModule, context.CurrentModuleWriterListener);
|
||||
var snKey = context.Annotations.Get<StrongNameKey>(context.CurrentModule, Marker.SNKey);
|
||||
context.CurrentModuleWriterOptions.InitializeStrongNameSigning(context.CurrentModule, snKey);
|
||||
|
@ -388,8 +388,7 @@ namespace Confuser.Core {
|
|||
private static void PrintInfo(ConfuserContext context) {
|
||||
if (context.PackerInitiated) {
|
||||
context.Logger.Info("Protecting packer stub...");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
context.Logger.InfoFormat("{0} {1}", Version, Copyright);
|
||||
|
||||
Type mono = Type.GetType("Mono.Runtime");
|
||||
|
|
|
@ -74,9 +74,26 @@ namespace Confuser.Core {
|
|||
/// <summary>
|
||||
/// Logs the progress of protection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method is intended to be used with <see cref="EndProgress" />.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// for (int i = 0; i < defs.Length; i++) {
|
||||
/// logger.Progress(i + 1, defs.Length);
|
||||
/// }
|
||||
/// logger.EndProgress();
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// <param name="overall">The total work amount .</param>
|
||||
/// <param name="progress">The amount of work done.</param>
|
||||
void Progress(int overall, int progress);
|
||||
void Progress(int progress, int overall);
|
||||
|
||||
/// <summary>
|
||||
/// End the progress of protection.
|
||||
/// </summary>
|
||||
/// <seealso cref="Progress" />
|
||||
void EndProgress();
|
||||
|
||||
/// <summary>
|
||||
/// Logs the finish of protection.
|
||||
|
|
|
@ -110,6 +110,8 @@ namespace Confuser.Core {
|
|||
context.Logger.InfoFormat("Loading '{0}'...", module.Path);
|
||||
|
||||
ModuleDefMD modDef = module.Resolve(proj.BaseDirectory, context.Resolver.DefaultModuleContext);
|
||||
context.CheckCancellation();
|
||||
|
||||
if (proj.Debug)
|
||||
modDef.LoadPdb();
|
||||
|
||||
|
@ -118,8 +120,10 @@ namespace Confuser.Core {
|
|||
context.Annotations.Set(modDef, SNKey, LoadSNKey(context, module.SNKeyPath == null ? null : Path.Combine(proj.BaseDirectory, module.SNKeyPath), module.SNKeyPassword));
|
||||
context.Annotations.Set(modDef, RulesKey, rules);
|
||||
|
||||
foreach (IDnlibDef def in modDef.FindDefinitions())
|
||||
foreach (IDnlibDef def in modDef.FindDefinitions()) {
|
||||
ApplyRules(context, def, rules);
|
||||
context.CheckCancellation();
|
||||
}
|
||||
|
||||
// Packer parameters are stored in modules
|
||||
if (packerParams != null)
|
||||
|
|
|
@ -49,6 +49,9 @@ namespace Confuser.Core {
|
|||
/// <inheritdoc />
|
||||
public void Progress(int overall, int progress) { }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void EndProgress() { }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Finish(bool successful) { }
|
||||
|
||||
|
|
|
@ -124,8 +124,12 @@ namespace Confuser.Core {
|
|||
baseLogger.ErrorException(msg, ex);
|
||||
}
|
||||
|
||||
public void Progress(int overall, int progress) {
|
||||
baseLogger.Progress(overall, progress);
|
||||
public void Progress(int progress, int overall) {
|
||||
baseLogger.Progress(progress, overall);
|
||||
}
|
||||
|
||||
public void EndProgress() {
|
||||
baseLogger.EndProgress();
|
||||
}
|
||||
|
||||
public void Finish(bool successful) {
|
||||
|
|
|
@ -32,7 +32,12 @@ namespace Confuser.Core {
|
|||
GetPluginsInternal(context, protections, packers, components);
|
||||
}
|
||||
|
||||
private static bool HasAccessibleDefConstructor(Type type) {
|
||||
/// <summary>
|
||||
/// Determines whether the specified type has an accessible default constructor.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns><c>true</c> if the specified type has an accessible default constructor; otherwise, <c>false</c>.</returns>
|
||||
public static bool HasAccessibleDefConstructor(Type type) {
|
||||
ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes);
|
||||
if (ctor == null) return false;
|
||||
return ctor.IsPublic;
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
<xs:sequence>
|
||||
<xs:element name="rule" type="rule" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element name="packer" type="objSettings" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="module" type="module" minOccurs="1" maxOccurs="unbounded" />
|
||||
<xs:element name="module" type="module" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element name="probePath" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element name="plugin" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
|
|
|
@ -23,6 +23,12 @@
|
|||
/// <value>The protection targets.</value>
|
||||
public abstract ProtectionTargets Targets { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the phase.
|
||||
/// </summary>
|
||||
/// <value>The name of phase.</value>
|
||||
public abstract string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this phase process all targets, not just the targets that requires the component.
|
||||
/// </summary>
|
||||
|
|
|
@ -120,12 +120,15 @@ namespace Confuser.Core {
|
|||
/// <param name="context">The working context.</param>
|
||||
internal void ExecuteStage(PipelineStage stage, Action<ConfuserContext> func, Func<IList<IDnlibDef>> targets, ConfuserContext context) {
|
||||
foreach (ProtectionPhase pre in preStage[stage]) {
|
||||
pre.Execute(context, new ProtectionParameters(pre.Parent, Filter(context, targets(), pre)));
|
||||
context.CheckCancellation();
|
||||
context.Logger.DebugFormat("Executing '{0}' phase...", pre.Name);
|
||||
pre.Execute(context, new ProtectionParameters(pre.Parent, Filter(context, targets(), pre)));
|
||||
}
|
||||
context.CheckCancellation();
|
||||
func(context);
|
||||
context.CheckCancellation();
|
||||
foreach (ProtectionPhase post in postStage[stage]) {
|
||||
context.Logger.DebugFormat("Executing '{0}' phase...", post.Name);
|
||||
post.Execute(context, new ProtectionParameters(post.Parent, Filter(context, targets(), post)));
|
||||
context.CheckCancellation();
|
||||
}
|
||||
|
|
|
@ -24,42 +24,41 @@ namespace Confuser.Core.Services {
|
|||
/// <inheritdoc />
|
||||
public MethodDef GetRuntimeDecompressor(ModuleDef module, Action<IDnlibDef> init) {
|
||||
Tuple<MethodDef, List<IDnlibDef>> decompressor = context.Annotations.GetOrCreate(module, Decompressor, m => {
|
||||
var rt = context.Registry.GetService<IRuntimeService>();
|
||||
var rt = context.Registry.GetService<IRuntimeService>();
|
||||
|
||||
List<IDnlibDef> members = InjectHelper.Inject(rt.GetRuntimeType("Confuser.Runtime.Lzma"), module.GlobalType, module).ToList();
|
||||
MethodDef decomp = null;
|
||||
foreach (IDnlibDef member in members) {
|
||||
if (member is MethodDef) {
|
||||
var method = (MethodDef)member;
|
||||
if (method.Access == MethodAttributes.Public)
|
||||
method.Access = MethodAttributes.Assembly;
|
||||
if (!method.IsConstructor)
|
||||
method.IsSpecialName = false;
|
||||
List<IDnlibDef> members = InjectHelper.Inject(rt.GetRuntimeType("Confuser.Runtime.Lzma"), module.GlobalType, module).ToList();
|
||||
MethodDef decomp = null;
|
||||
foreach (IDnlibDef member in members) {
|
||||
if (member is MethodDef) {
|
||||
var method = (MethodDef)member;
|
||||
if (method.Access == MethodAttributes.Public)
|
||||
method.Access = MethodAttributes.Assembly;
|
||||
if (!method.IsConstructor)
|
||||
method.IsSpecialName = false;
|
||||
|
||||
if (method.Name == "Decompress")
|
||||
decomp = method;
|
||||
}
|
||||
else if (member is FieldDef) {
|
||||
var field = (FieldDef)member;
|
||||
if (field.Access == FieldAttributes.Public)
|
||||
field.Access = FieldAttributes.Assembly;
|
||||
if (field.IsLiteral) {
|
||||
field.DeclaringType.Fields.Remove(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
members.RemoveWhere(def => def is FieldDef && ((FieldDef)def).IsLiteral);
|
||||
if (method.Name == "Decompress")
|
||||
decomp = method;
|
||||
} else if (member is FieldDef) {
|
||||
var field = (FieldDef)member;
|
||||
if (field.Access == FieldAttributes.Public)
|
||||
field.Access = FieldAttributes.Assembly;
|
||||
if (field.IsLiteral) {
|
||||
field.DeclaringType.Fields.Remove(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
members.RemoveWhere(def => def is FieldDef && ((FieldDef)def).IsLiteral);
|
||||
|
||||
Debug.Assert(decomp != null);
|
||||
return Tuple.Create(decomp, members);
|
||||
});
|
||||
Debug.Assert(decomp != null);
|
||||
return Tuple.Create(decomp, members);
|
||||
});
|
||||
foreach (IDnlibDef member in decompressor.Item2)
|
||||
init(member);
|
||||
return decompressor.Item1;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte[] Compress(byte[] data) {
|
||||
public byte[] Compress(byte[] data, Action<double> progressFunc = null) {
|
||||
CoderPropID[] propIDs = {
|
||||
CoderPropID.DictionarySize,
|
||||
CoderPropID.PosStateBits,
|
||||
|
@ -89,9 +88,29 @@ namespace Confuser.Core.Services {
|
|||
fileSize = data.Length;
|
||||
for (int i = 0; i < 8; i++)
|
||||
x.WriteByte((Byte)(fileSize >> (8 * i)));
|
||||
encoder.Code(new MemoryStream(data), x, -1, -1, null);
|
||||
|
||||
ICodeProgress progress = null;
|
||||
if (progressFunc != null)
|
||||
progress = new CompressionLogger(progressFunc, data.Length);
|
||||
encoder.Code(new MemoryStream(data), x, -1, -1, progress);
|
||||
|
||||
return x.ToArray();
|
||||
}
|
||||
|
||||
private class CompressionLogger : ICodeProgress {
|
||||
private readonly Action<double> progressFunc;
|
||||
private readonly int size;
|
||||
|
||||
public CompressionLogger(Action<double> progressFunc, int size) {
|
||||
this.progressFunc = progressFunc;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public void SetProgress(long inSize, long outSize) {
|
||||
double precentage = (double)inSize / size;
|
||||
progressFunc(precentage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -110,7 +129,8 @@ namespace Confuser.Core.Services {
|
|||
/// Compresses the specified data.
|
||||
/// </summary>
|
||||
/// <param name="data">The buffer storing the data.</param>
|
||||
/// <param name="progressFunc">The function that receive the progress of compression.</param>
|
||||
/// <returns>The compressed data.</returns>
|
||||
byte[] Compress(byte[] data);
|
||||
byte[] Compress(byte[] data, Action<double> progressFunc = null);
|
||||
}
|
||||
}
|
|
@ -68,7 +68,7 @@ namespace Confuser.Core {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// OBtains the relative path from the specified base path.
|
||||
/// Obtains the relative path from the specified base path.
|
||||
/// </summary>
|
||||
/// <param name="filespec">The file path.</param>
|
||||
/// <param name="folder">The base path.</param>
|
||||
|
@ -181,5 +181,23 @@ namespace Confuser.Core {
|
|||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="IEnumerable{T}" /> that log the progress of iterating the specified list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of list element</typeparam>
|
||||
/// <param name="enumerable">The list.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <returns>A wrapper of the list.</returns>
|
||||
public static IEnumerable<T> WithProgress<T>(this IEnumerable<T> enumerable, ILogger logger) {
|
||||
var list = new List<T>(enumerable);
|
||||
int i;
|
||||
for (i = 0; i < list.Count; i++) {
|
||||
logger.Progress(i, list.Count);
|
||||
yield return list[i];
|
||||
}
|
||||
logger.Progress(i, list.Count);
|
||||
logger.EndProgress();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -49,6 +49,10 @@ namespace Confuser.Protections {
|
|||
get { return ProtectionTargets.Modules; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Anti-debug injection"; }
|
||||
}
|
||||
|
||||
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
|
||||
var rt = context.Registry.GetService<IRuntimeService>();
|
||||
var marker = context.Registry.GetService<IMarkerService>();
|
||||
|
|
|
@ -49,6 +49,10 @@ namespace Confuser.Protections {
|
|||
get { return ProtectionTargets.Modules; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Anti-dump injection"; }
|
||||
}
|
||||
|
||||
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
|
||||
TypeDef rtType = context.Registry.GetService<IRuntimeService>().GetRuntimeType("Confuser.Runtime.AntiDump");
|
||||
|
||||
|
|
|
@ -43,6 +43,10 @@ namespace Confuser.Protections {
|
|||
get { return ProtectionTargets.Modules; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Anti-ILDasm marking"; }
|
||||
}
|
||||
|
||||
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
|
||||
foreach (ModuleDef module in parameters.Targets.OfType<ModuleDef>()) {
|
||||
TypeRef attrRef = module.CorLibTypes.GetTypeRef("System.Runtime.CompilerServices", "SuppressIldasmAttribute");
|
||||
|
|
|
@ -53,6 +53,10 @@ namespace Confuser.Protections {
|
|||
get { return ProtectionTargets.Methods; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Anti-tamper helpers injection"; }
|
||||
}
|
||||
|
||||
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
|
||||
if (!parameters.Targets.Any())
|
||||
return;
|
||||
|
@ -82,6 +86,10 @@ namespace Confuser.Protections {
|
|||
get { return ProtectionTargets.Methods; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Anti-tamper metadata preparation"; }
|
||||
}
|
||||
|
||||
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
|
||||
if (!parameters.Targets.Any())
|
||||
return;
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace Confuser.Protections.AntiTamper {
|
|||
private uint c;
|
||||
private MethodDef cctor;
|
||||
private MethodDef cctorRepl;
|
||||
private ConfuserContext context;
|
||||
private IKeyDeriver deriver;
|
||||
private byte[] fieldLayout;
|
||||
|
||||
|
@ -37,6 +38,7 @@ namespace Confuser.Protections.AntiTamper {
|
|||
private uint z;
|
||||
|
||||
public void HandleInject(AntiTamperProtection parent, ConfuserContext context, ProtectionParameters parameters) {
|
||||
this.context = context;
|
||||
random = context.Registry.GetService<IRandomService>().GetRandomGenerator(parent.FullId);
|
||||
z = random.NextUInt32();
|
||||
x = random.NextUInt32();
|
||||
|
@ -77,8 +79,7 @@ namespace Confuser.Protections.AntiTamper {
|
|||
Instruction instr = instrs[i];
|
||||
if (instr.OpCode == OpCodes.Ldtoken) {
|
||||
instr.Operand = context.CurrentModule.GlobalType;
|
||||
}
|
||||
else if (instr.OpCode == OpCodes.Call) {
|
||||
} else if (instr.OpCode == OpCodes.Call) {
|
||||
var method = (IMethod)instr.Operand;
|
||||
if (method.DeclaringType.Name == "Mutation" &&
|
||||
method.Name == "Crypt") {
|
||||
|
@ -144,9 +145,10 @@ namespace Confuser.Protections.AntiTamper {
|
|||
private void OnWriterEvent(object sender, ModuleWriterListenerEventArgs e) {
|
||||
var writer = (ModuleWriter)sender;
|
||||
if (e.WriterEvent == ModuleWriterEvent.MDBeginWriteMethodBodies) {
|
||||
context.Logger.Debug("Extracting method bodies...");
|
||||
CreateSection(writer);
|
||||
}
|
||||
else if (e.WriterEvent == ModuleWriterEvent.BeginStrongNameSign) {
|
||||
} else if (e.WriterEvent == ModuleWriterEvent.BeginStrongNameSign) {
|
||||
context.Logger.Debug("Encrypting method section...");
|
||||
EncryptSection(writer);
|
||||
}
|
||||
}
|
||||
|
@ -202,7 +204,7 @@ namespace Confuser.Protections.AntiTamper {
|
|||
cctor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
|
||||
|
||||
// save methods
|
||||
foreach (MethodDef method in methods) {
|
||||
foreach (MethodDef method in methods.WithProgress(context.Logger)) {
|
||||
if (!method.HasBody)
|
||||
continue;
|
||||
|
||||
|
@ -216,6 +218,7 @@ namespace Confuser.Protections.AntiTamper {
|
|||
|
||||
method.Body = NopBody;
|
||||
writer.MetaData.TablesHeap.MethodTable[token.Rid].ImplFlags |= (ushort)MethodImplAttributes.NoInlining;
|
||||
context.CheckCancellation();
|
||||
}
|
||||
bodyIndex.PopulateSection(newSection);
|
||||
|
||||
|
@ -242,8 +245,7 @@ namespace Confuser.Protections.AntiTamper {
|
|||
if (nameHash == name1 * name2) {
|
||||
encSize = reader.ReadUInt32();
|
||||
encLoc = reader.ReadUInt32();
|
||||
}
|
||||
else if (nameHash != 0) {
|
||||
} else if (nameHash != 0) {
|
||||
uint sectSize = reader.ReadUInt32();
|
||||
uint sectLoc = reader.ReadUInt32();
|
||||
Hash(stream, reader, sectLoc, sectSize);
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace Confuser.Protections {
|
|||
protected override void Pack(ConfuserContext context, ProtectionParameters parameters) {
|
||||
var ctx = context.Annotations.Get<CompressorContext>(context, ContextKey);
|
||||
if (ctx == null) {
|
||||
context.Logger.Error("No main module specified!");
|
||||
context.Logger.Error("No executable module!");
|
||||
throw new ConfuserException(null);
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,7 @@ namespace Confuser.Protections {
|
|||
stubModule.Write(ms, new ModuleWriterOptions(stubModule, new KeyInjector(ctx)) {
|
||||
StrongNameKey = snKey
|
||||
});
|
||||
context.CheckCancellation();
|
||||
base.ProtectStub(context, context.OutputPaths[ctx.ModuleIndex], ms.ToArray(), snKey, new StubProtection(ctx));
|
||||
}
|
||||
}
|
||||
|
@ -105,6 +106,7 @@ namespace Confuser.Protections {
|
|||
key[i] |= 1;
|
||||
compCtx.KeySig = key;
|
||||
|
||||
int moduleIndex = 0;
|
||||
foreach (var entry in modules) {
|
||||
byte[] name = Encoding.UTF8.GetBytes(entry.Key);
|
||||
for (int i = 0; i < name.Length; i++)
|
||||
|
@ -113,11 +115,17 @@ namespace Confuser.Protections {
|
|||
uint state = 0x6fff61;
|
||||
foreach (byte chr in name)
|
||||
state = state * 0x5e3f1f + chr;
|
||||
byte[] encrypted = compCtx.Encrypt(comp, entry.Value, state);
|
||||
byte[] encrypted = compCtx.Encrypt(comp, entry.Value, state, progress => {
|
||||
progress = (progress + moduleIndex) / modules.Count;
|
||||
context.Logger.Progress((int)(progress * 10000), 10000);
|
||||
});
|
||||
context.CheckCancellation();
|
||||
|
||||
var resource = new EmbeddedResource(Convert.ToBase64String(name), encrypted, ManifestResourceAttributes.Private);
|
||||
stubModule.Resources.Add(resource);
|
||||
moduleIndex++;
|
||||
}
|
||||
context.Logger.EndProgress();
|
||||
}
|
||||
|
||||
private void InjectData(ModuleDef stubModule, MethodDef method, byte[] data) {
|
||||
|
@ -137,14 +145,14 @@ namespace Confuser.Protections {
|
|||
stubModule.GlobalType.Fields.Add(dataField);
|
||||
|
||||
MutationHelper.ReplacePlaceholder(method, arg => {
|
||||
var repl = new List<Instruction>();
|
||||
repl.AddRange(arg);
|
||||
repl.Add(Instruction.Create(OpCodes.Dup));
|
||||
repl.Add(Instruction.Create(OpCodes.Ldtoken, dataField));
|
||||
repl.Add(Instruction.Create(OpCodes.Call, stubModule.Import(
|
||||
typeof (RuntimeHelpers).GetMethod("InitializeArray"))));
|
||||
return repl.ToArray();
|
||||
});
|
||||
var repl = new List<Instruction>();
|
||||
repl.AddRange(arg);
|
||||
repl.Add(Instruction.Create(OpCodes.Dup));
|
||||
repl.Add(Instruction.Create(OpCodes.Ldtoken, dataField));
|
||||
repl.Add(Instruction.Create(OpCodes.Call, stubModule.Import(
|
||||
typeof (RuntimeHelpers).GetMethod("InitializeArray"))));
|
||||
return repl.ToArray();
|
||||
});
|
||||
}
|
||||
|
||||
private void InjectStub(ConfuserContext context, CompressorContext compCtx, ProtectionParameters parameters, ModuleDef stubModule) {
|
||||
|
@ -165,13 +173,20 @@ namespace Confuser.Protections {
|
|||
}
|
||||
compCtx.Deriver.Init(context, random);
|
||||
|
||||
context.Logger.Debug("Encrypting modules...");
|
||||
|
||||
// Main
|
||||
MethodDef entryPoint = defs.OfType<MethodDef>().Single(method => method.Name == "Main");
|
||||
stubModule.EntryPoint = entryPoint;
|
||||
|
||||
uint seed = random.NextUInt32();
|
||||
compCtx.OriginModule = context.OutputModules[compCtx.ModuleIndex];
|
||||
byte[] encryptedModule = compCtx.Encrypt(comp, compCtx.OriginModule, seed);
|
||||
|
||||
byte[] encryptedModule = compCtx.Encrypt(comp, compCtx.OriginModule, seed,
|
||||
progress => context.Logger.Progress((int)(progress * 10000), 10000));
|
||||
context.Logger.EndProgress();
|
||||
context.CheckCancellation();
|
||||
|
||||
compCtx.EncryptedModule = encryptedModule;
|
||||
|
||||
MutationHelper.InjectKeys(entryPoint,
|
||||
|
@ -196,9 +211,8 @@ namespace Confuser.Protections {
|
|||
instrs.RemoveAt(i - 1);
|
||||
instrs.RemoveAt(i - 2);
|
||||
instrs.InsertRange(i - 2, compCtx.Deriver.EmitDerivation(decrypter, context, (Local)ldDst.Operand, (Local)ldSrc.Operand));
|
||||
}
|
||||
else if (method.DeclaringType.Name == "Lzma" &&
|
||||
method.Name == "Decompress") {
|
||||
} else if (method.DeclaringType.Name == "Lzma" &&
|
||||
method.Name == "Decompress") {
|
||||
MethodDef decomp = comp.GetRuntimeDecompressor(stubModule, member => { });
|
||||
instr.Operand = decomp;
|
||||
}
|
||||
|
@ -228,8 +242,7 @@ namespace Confuser.Protections {
|
|||
uint sigToken = 0x11000000 | sigRid;
|
||||
ctx.KeyToken = sigToken;
|
||||
MutationHelper.InjectKey(writer.Module.EntryPoint, 2, (int)sigToken);
|
||||
}
|
||||
else if (evt == ModuleWriterEvent.MDBeginAddResources) {
|
||||
} else if (evt == ModuleWriterEvent.MDBeginAddResources) {
|
||||
// Compute hash
|
||||
byte[] hash = SHA1.Create().ComputeHash(ctx.OriginModule);
|
||||
uint hashBlob = writer.MetaData.BlobHeap.Add(hash);
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Confuser.Protections.Compress {
|
|||
public string ModuleName;
|
||||
public byte[] OriginModule;
|
||||
|
||||
public byte[] Encrypt(ICompressionService compress, byte[] data, uint seed) {
|
||||
public byte[] Encrypt(ICompressionService compress, byte[] data, uint seed, Action<double> progressFunc) {
|
||||
data = (byte[])data.Clone();
|
||||
var dst = new uint[0x10];
|
||||
var src = new uint[0x10];
|
||||
|
@ -37,7 +37,7 @@ namespace Confuser.Protections.Compress {
|
|||
if ((i & 0xff) == 0)
|
||||
state = (state * state) % 0x8a5cb7;
|
||||
}
|
||||
data = compress.Compress(data);
|
||||
data = compress.Compress(data, progressFunc);
|
||||
Array.Resize(ref data, (data.Length + 3) & ~3);
|
||||
|
||||
var encryptedData = new byte[data.Length];
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Confuser.Core;
|
||||
|
@ -14,15 +15,26 @@ namespace Confuser.Protections.Compress {
|
|||
get { return ProtectionTargets.Modules; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Packer info extraction"; }
|
||||
}
|
||||
|
||||
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
|
||||
if (context.Packer == null)
|
||||
return;
|
||||
|
||||
if (context.Annotations.Get<CompressorContext>(context, Compressor.ContextKey) != null)
|
||||
return;
|
||||
bool isExe = context.CurrentModule.Kind == ModuleKind.Windows ||
|
||||
context.CurrentModule.Kind == ModuleKind.Console;
|
||||
|
||||
var mainModule = parameters.GetParameter<string>(context, null, "main");
|
||||
if (context.CurrentModule.Name == mainModule) {
|
||||
if (context.Annotations.Get<CompressorContext>(context, Compressor.ContextKey) != null) {
|
||||
if (isExe) {
|
||||
context.Logger.Error("Too many executable modules!");
|
||||
throw new ConfuserException(null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (isExe) {
|
||||
var ctx = new CompressorContext {
|
||||
ModuleIndex = context.CurrentModuleIndex,
|
||||
Assembly = context.CurrentModule.Assembly
|
||||
|
|
|
@ -49,6 +49,10 @@ namespace Confuser.Protections.Compress {
|
|||
get { return ProtectionTargets.Modules; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Packer info encoding"; }
|
||||
}
|
||||
|
||||
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
|
||||
context.CurrentModuleWriterListener.OnWriterEvent += (sender, e) => {
|
||||
if (e.WriterEvent == ModuleWriterEvent.MDBeginCreateTables) {
|
||||
|
|
|
@ -20,6 +20,10 @@ namespace Confuser.Protections.Constants {
|
|||
get { return ProtectionTargets.Methods; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Constants encoding"; }
|
||||
}
|
||||
|
||||
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
|
||||
var moduleCtx = context.Annotations.Get<CEContext>(context.CurrentModule, ConstantProtection.ContextKey);
|
||||
if (!parameters.Targets.Any() || moduleCtx == null)
|
||||
|
@ -33,11 +37,12 @@ namespace Confuser.Protections.Constants {
|
|||
|
||||
// encode
|
||||
moduleCtx.EncodedBuffer = new List<uint>();
|
||||
foreach (var entry in ldInit) // Ensure the array length haven't been encoded yet
|
||||
foreach (var entry in ldInit.WithProgress(context.Logger)) // Ensure the array length haven't been encoded yet
|
||||
{
|
||||
EncodeInitializer(moduleCtx, entry.Key, entry.Value);
|
||||
context.CheckCancellation();
|
||||
}
|
||||
foreach (var entry in ldc) {
|
||||
foreach (var entry in ldc.WithProgress(context.Logger)) {
|
||||
if (entry.Key is string) {
|
||||
EncodeString(moduleCtx, (string)entry.Key, entry.Value);
|
||||
}
|
||||
|
@ -59,6 +64,7 @@ namespace Confuser.Protections.Constants {
|
|||
}
|
||||
else
|
||||
throw new UnreachableException();
|
||||
context.CheckCancellation();
|
||||
}
|
||||
|
||||
// compress
|
||||
|
@ -72,6 +78,7 @@ namespace Confuser.Protections.Constants {
|
|||
}
|
||||
Debug.Assert(buffIndex == encodedBuff.Length);
|
||||
encodedBuff = context.Registry.GetService<ICompressionService>().Compress(encodedBuff);
|
||||
context.CheckCancellation();
|
||||
|
||||
uint compressedLen = (uint)(encodedBuff.Length + 3) / 4;
|
||||
compressedLen = (compressedLen + 0xfu) & ~0xfu;
|
||||
|
@ -214,7 +221,7 @@ namespace Confuser.Protections.Constants {
|
|||
ConfuserContext context, ProtectionParameters parameters, CEContext moduleCtx,
|
||||
Dictionary<object, List<Tuple<MethodDef, Instruction>>> ldc,
|
||||
Dictionary<byte[], List<Tuple<MethodDef, Instruction>>> ldInit) {
|
||||
foreach (MethodDef method in parameters.Targets.OfType<MethodDef>()) {
|
||||
foreach (MethodDef method in parameters.Targets.OfType<MethodDef>().WithProgress(context.Logger)) {
|
||||
if (!method.HasBody)
|
||||
continue;
|
||||
|
||||
|
@ -319,6 +326,8 @@ namespace Confuser.Protections.Constants {
|
|||
if (eligible)
|
||||
ldc.AddListEntry(instr.Operand, Tuple.Create(method, instr));
|
||||
}
|
||||
|
||||
context.CheckCancellation();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,10 @@ namespace Confuser.Protections.Constants {
|
|||
get { return ProtectionTargets.Methods; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Constant encryption helpers injection"; }
|
||||
}
|
||||
|
||||
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
|
||||
if (parameters.Targets.Any()) {
|
||||
var compression = context.Registry.GetService<ICompressionService>();
|
||||
|
|
|
@ -20,6 +20,10 @@ namespace Confuser.Protections.ControlFlow {
|
|||
get { return ProtectionTargets.Methods; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Control flow mangling"; }
|
||||
}
|
||||
|
||||
private static CFContext ParseParameters(MethodDef method, ConfuserContext context, ProtectionParameters parameters, RandomGenerator random, bool disableOpti) {
|
||||
var ret = new CFContext();
|
||||
ret.Type = parameters.GetParameter(context, method, "type", CFType.Switch);
|
||||
|
@ -67,9 +71,10 @@ namespace Confuser.Protections.ControlFlow {
|
|||
bool disabledOpti = DisabledOptimization(context.CurrentModule);
|
||||
RandomGenerator random = context.Registry.GetService<IRandomService>().GetRandomGenerator(ControlFlowProtection._FullId);
|
||||
|
||||
foreach (MethodDef method in parameters.Targets.OfType<MethodDef>())
|
||||
foreach (MethodDef method in parameters.Targets.OfType<MethodDef>().WithProgress(context.Logger))
|
||||
if (method.HasBody && method.Body.Instructions.Count > 0) {
|
||||
ProcessMethod(method.Body, ParseParameters(method, context, parameters, random, disabledOpti));
|
||||
context.CheckCancellation();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,10 @@ namespace Confuser.Protections {
|
|||
get { return ProtectionTargets.Modules; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Invalid metadata addition"; }
|
||||
}
|
||||
|
||||
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
|
||||
if (parameters.Targets.Contains(context.CurrentModule)) {
|
||||
random = context.Registry.GetService<IRandomService>().GetRandomGenerator(_FullId);
|
||||
|
|
|
@ -16,6 +16,10 @@ namespace Confuser.Protections.ReferenceProxy {
|
|||
get { return ProtectionTargets.Methods; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Encoding reference proxies"; }
|
||||
}
|
||||
|
||||
private static RPContext ParseParameters(MethodDef method, ConfuserContext context, ProtectionParameters parameters, RPStore store) {
|
||||
var ret = new RPContext();
|
||||
ret.Mode = parameters.GetParameter(context, method, "mode", Mode.Mild);
|
||||
|
@ -96,9 +100,10 @@ namespace Confuser.Protections.ReferenceProxy {
|
|||
|
||||
var store = new RPStore { random = random };
|
||||
|
||||
foreach (MethodDef method in parameters.Targets.OfType<MethodDef>())
|
||||
foreach (MethodDef method in parameters.Targets.OfType<MethodDef>().WithProgress(context.Logger))
|
||||
if (method.HasBody && method.Body.Instructions.Count > 0) {
|
||||
ProcessMethod(ParseParameters(method, context, parameters, store));
|
||||
context.CheckCancellation();
|
||||
}
|
||||
|
||||
RPContext ctx = ParseParameters(context.CurrentModule, context, parameters, store);
|
||||
|
|
|
@ -19,6 +19,10 @@ namespace Confuser.Protections.Resources {
|
|||
get { return ProtectionTargets.Methods; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Resource encryption helpers injection"; }
|
||||
}
|
||||
|
||||
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
|
||||
if (parameters.Targets.Any()) {
|
||||
var compression = context.Registry.GetService<ICompressionService>();
|
||||
|
|
|
@ -26,6 +26,9 @@ namespace Confuser.Protections.Resources {
|
|||
private void OnWriterEvent(object sender, ModuleWriterListenerEventArgs e) {
|
||||
var writer = (ModuleWriter)sender;
|
||||
if (e.WriterEvent == ModuleWriterEvent.MDBeginAddResources) {
|
||||
ctx.Context.CheckCancellation();
|
||||
ctx.Context.Logger.Debug("Encrypting resources...");
|
||||
|
||||
List<EmbeddedResource> resources = ctx.Module.Resources.OfType<EmbeddedResource>().ToList();
|
||||
ctx.Module.Resources.RemoveWhere(res => res is EmbeddedResource);
|
||||
|
||||
|
@ -51,7 +54,11 @@ namespace Confuser.Protections.Resources {
|
|||
}
|
||||
|
||||
// compress
|
||||
moduleBuff = ctx.Context.Registry.GetService<ICompressionService>().Compress(moduleBuff);
|
||||
moduleBuff = ctx.Context.Registry.GetService<ICompressionService>().Compress(
|
||||
moduleBuff,
|
||||
progress => ctx.Context.Logger.Progress((int)(progress * 10000), 10000));
|
||||
ctx.Context.Logger.EndProgress();
|
||||
ctx.Context.CheckCancellation();
|
||||
|
||||
uint compressedLen = (uint)(moduleBuff.Length + 3) / 4;
|
||||
compressedLen = (compressedLen + 0xfu) & ~0xfu;
|
||||
|
@ -91,8 +98,7 @@ namespace Confuser.Protections.Resources {
|
|||
MutationHelper.InjectKeys(ctx.InitMethod,
|
||||
new[] { 0, 1 },
|
||||
new[] { (int)(size / 4), (int)(keySeed) });
|
||||
}
|
||||
else if (e.WriterEvent == ModuleWriterEvent.EndCalculateRvasAndFileOffsets) {
|
||||
} else if (e.WriterEvent == ModuleWriterEvent.EndCalculateRvasAndFileOffsets) {
|
||||
TablesHeap tblHeap = writer.MetaData.TablesHeap;
|
||||
tblHeap.FieldRVATable[writer.MetaData.GetFieldRVARid(ctx.DataField)].RVA = (uint)encryptedResource.RVA;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,10 @@ namespace Confuser.Renamer {
|
|||
get { return ProtectionTargets.AllDefinitions; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Name analysis"; }
|
||||
}
|
||||
|
||||
private void ParseParameters(IDnlibDef def, ConfuserContext context, NameService service, ProtectionParameters parameters) {
|
||||
var mode = parameters.GetParameter<RenameMode?>(context, def, "mode", null);
|
||||
if (mode != null)
|
||||
|
@ -24,7 +28,7 @@ namespace Confuser.Renamer {
|
|||
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
|
||||
var service = (NameService)context.Registry.GetService<INameService>();
|
||||
context.Logger.Debug("Building VTables & identifier list...");
|
||||
foreach (IDnlibDef def in parameters.Targets) {
|
||||
foreach (IDnlibDef def in parameters.Targets.WithProgress(context.Logger)) {
|
||||
ParseParameters(def, context, service, parameters);
|
||||
|
||||
if (def is ModuleDef) {
|
||||
|
@ -39,12 +43,14 @@ namespace Confuser.Renamer {
|
|||
service.GetVTables().GetVTable((TypeDef)def);
|
||||
service.SetOriginalNamespace(def, ((TypeDef)def).Namespace);
|
||||
}
|
||||
context.CheckCancellation();
|
||||
}
|
||||
|
||||
context.Logger.Debug("Analyzing...");
|
||||
IList<IRenamer> renamers = service.Renamers;
|
||||
foreach (IDnlibDef def in parameters.Targets) {
|
||||
foreach (IDnlibDef def in parameters.Targets.WithProgress(context.Logger)) {
|
||||
Analyze(service, context, parameters, def, true);
|
||||
context.CheckCancellation();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,12 +14,17 @@ namespace Confuser.Renamer {
|
|||
get { return ProtectionTargets.AllDefinitions; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Post-renaming"; }
|
||||
}
|
||||
|
||||
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
|
||||
var service = (NameService)context.Registry.GetService<INameService>();
|
||||
|
||||
foreach (IRenamer renamer in service.Renamers) {
|
||||
foreach (IDnlibDef def in parameters.Targets)
|
||||
renamer.PostRename(context, service, def);
|
||||
context.CheckCancellation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,10 @@ namespace Confuser.Renamer {
|
|||
get { return ProtectionTargets.AllDefinitions; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Renaming"; }
|
||||
}
|
||||
|
||||
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
|
||||
var service = (NameService)context.Registry.GetService<INameService>();
|
||||
|
||||
|
@ -19,9 +23,10 @@ namespace Confuser.Renamer {
|
|||
foreach (IRenamer renamer in service.Renamers) {
|
||||
foreach (IDnlibDef def in parameters.Targets)
|
||||
renamer.PreRename(context, service, def);
|
||||
context.CheckCancellation();
|
||||
}
|
||||
|
||||
foreach (IDnlibDef def in parameters.Targets) {
|
||||
foreach (IDnlibDef def in parameters.Targets.WithProgress(context.Logger)) {
|
||||
if (def is MethodDef)
|
||||
if (parameters.GetParameter(context, def, "renameArgs", true)) {
|
||||
foreach (ParamDef param in ((MethodDef)def).ParamDefs)
|
||||
|
@ -62,6 +67,7 @@ namespace Confuser.Renamer {
|
|||
throw new ConfuserException(null);
|
||||
}
|
||||
}
|
||||
context.CheckCancellation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Confuser.Runtime", "Confuse
|
|||
{BEB67A6E-4C54-4DE5-8C6B-2C12F44A7B92} = {BEB67A6E-4C54-4DE5-8C6B-2C12F44A7B92}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConfuserEx", "ConfuserEx\ConfuserEx.csproj", "{B5205EBA-EC32-4C53-86A0-FAEEE7393EC0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -58,6 +60,10 @@ Global
|
|||
{A45C184F-F98F-4258-A928-BFF437034791}.Debug|Any CPU.Build.0 = Release|Any CPU
|
||||
{A45C184F-F98F-4258-A928-BFF437034791}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A45C184F-F98F-4258-A928-BFF437034791}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B5205EBA-EC32-4C53-86A0-FAEEE7393EC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B5205EBA-EC32-4C53-86A0-FAEEE7393EC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B5205EBA-EC32-4C53-86A0-FAEEE7393EC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B5205EBA-EC32-4C53-86A0-FAEEE7393EC0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<Application x:Class="ConfuserEx.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="Skin.xaml" />
|
||||
<ResourceDictionary Source="Views.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<BitmapImage x:Key="New" UriSource="Resources/New.png" />
|
||||
<BitmapImage x:Key="Open" UriSource="Resources/Open.png" />
|
||||
<BitmapImage x:Key="Save" UriSource="Resources/Save.png" />
|
||||
<BitmapImage x:Key="Tools" UriSource="Resources/Tools.png" />
|
||||
<BitmapImage x:Key="Decode" UriSource="Resources/Decode.png" />
|
||||
<BitmapImage x:Key="Error" UriSource="Resources/Error.png" />
|
||||
<FontFamily x:Key="FontAwesome">Resources/#FontAwesome</FontFamily>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
|
@ -0,0 +1,6 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
|
||||
namespace ConfuserEx {
|
||||
public partial class App : Application { }
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace ConfuserEx {
|
||||
public class BrushToColorConverter : IValueConverter {
|
||||
public static readonly BrushToColorConverter Instance = new BrushToColorConverter();
|
||||
private BrushToColorConverter() { }
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
var brush = value as SolidColorBrush;
|
||||
if (brush != null)
|
||||
return brush.Color;
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<UserControl x:Class="ConfuserEx.CompComboBox"
|
||||
x:Name="Root"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:core="clr-namespace:Confuser.Core;assembly=Confuser.Core">
|
||||
<ComboBox ItemsSource="{Binding Components, ElementName=Root}"
|
||||
SelectedItem="{Binding SelectedComponent, ElementName=Root}"
|
||||
DisplayMemberPath="Id" FontFamily="Consolas"
|
||||
ScrollViewer.CanContentScroll="False">
|
||||
<ComboBox.ItemContainerStyle>
|
||||
<Style TargetType="{x:Type ComboBoxItem}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ComboBoxItem}">
|
||||
<Border Width="350" BorderBrush="{StaticResource Foreground}"
|
||||
Background="{TemplateBinding Background}" BorderThickness="1" Margin="5">
|
||||
<Grid Background="Transparent">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<Label Grid.Row="0" Content="{Binding Name}" HorizontalAlignment="Left" />
|
||||
<Label Grid.Row="0" Content="{Binding Id}" HorizontalAlignment="Right" />
|
||||
<Label Grid.Row="1">
|
||||
<TextBlock Text="{Binding Description}" TextTrimming="WordEllipsis"
|
||||
FontSize="10" Foreground="Gray" />
|
||||
</Label>
|
||||
</Grid>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="{StaticResource HighlightBackground}" />
|
||||
<Setter Property="Foreground" Value="{StaticResource SelectedForeground}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ComboBox.ItemContainerStyle>
|
||||
</ComboBox>
|
||||
</UserControl>
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Confuser.Core;
|
||||
|
||||
namespace ConfuserEx {
|
||||
public partial class CompComboBox : UserControl {
|
||||
public static readonly DependencyProperty ComponentsProperty = DependencyProperty.Register("Components", typeof (IEnumerable<ConfuserComponent>), typeof (CompComboBox), new UIPropertyMetadata(null));
|
||||
public static readonly DependencyProperty SelectedComponentProperty = DependencyProperty.Register("SelectedComponent", typeof (ConfuserComponent), typeof (CompComboBox), new UIPropertyMetadata(null));
|
||||
public static readonly DependencyProperty ArgumentsProperty = DependencyProperty.Register("Arguments", typeof (Dictionary<string, string>), typeof (CompComboBox), new UIPropertyMetadata(null));
|
||||
|
||||
public CompComboBox() {
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public IEnumerable<ConfuserComponent> Components {
|
||||
get { return (IEnumerable<ConfuserComponent>)GetValue(ComponentsProperty); }
|
||||
set { SetValue(ComponentsProperty, value); }
|
||||
}
|
||||
|
||||
public ConfuserComponent SelectedComponent {
|
||||
get { return (ConfuserComponent)GetValue(SelectedComponentProperty); }
|
||||
set { SetValue(SelectedComponentProperty, value); }
|
||||
}
|
||||
|
||||
public Dictionary<string, string> Arguments {
|
||||
get { return (Dictionary<string, string>)GetValue(ArgumentsProperty); }
|
||||
set { SetValue(ArgumentsProperty, value); }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using Confuser.Core;
|
||||
|
||||
namespace ConfuserEx {
|
||||
internal class ComponentConverter : Freezable, IValueConverter {
|
||||
public static readonly DependencyProperty ComponentsProperty = DependencyProperty.Register("Components", typeof (IList<ConfuserComponent>), typeof (ComponentConverter), new UIPropertyMetadata(null));
|
||||
|
||||
public IList<ConfuserComponent> Components {
|
||||
get { return (IList<ConfuserComponent>)GetValue(ComponentsProperty); }
|
||||
set { SetValue(ComponentsProperty, value); }
|
||||
}
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
Debug.Assert(value is string || value == null);
|
||||
Debug.Assert(targetType == typeof (ConfuserComponent));
|
||||
Debug.Assert(Components != null);
|
||||
|
||||
if (value == null) return null;
|
||||
return Components.Single(comp => comp.Id == (string)value);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
Debug.Assert(value is ConfuserComponent || value == null);
|
||||
Debug.Assert(targetType == typeof (string));
|
||||
|
||||
if (value == null) return null;
|
||||
return ((ConfuserComponent)value).Id;
|
||||
}
|
||||
|
||||
protected override Freezable CreateInstanceCore() {
|
||||
return new ComponentConverter();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Confuser.Core;
|
||||
|
||||
namespace ConfuserEx {
|
||||
internal class ComponentDiscovery {
|
||||
private static void CrossDomainLoadComponents() {
|
||||
var ctx = (CrossDomainContext)AppDomain.CurrentDomain.GetData("ctx");
|
||||
Assembly assembly = Assembly.LoadFile(ctx.PluginPath);
|
||||
foreach (Type i in assembly.GetTypes()) {
|
||||
if (i.IsAbstract || !PluginDiscovery.HasAccessibleDefConstructor(i))
|
||||
continue;
|
||||
|
||||
if (typeof (Protection).IsAssignableFrom(i)) {
|
||||
var prot = (Protection)Activator.CreateInstance(i);
|
||||
ctx.AddProtection(Info.FromComponent(prot, ctx.PluginPath));
|
||||
} else if (typeof (Packer).IsAssignableFrom(i)) {
|
||||
var packer = (Packer)Activator.CreateInstance(i);
|
||||
ctx.AddPacker(Info.FromComponent(packer, ctx.PluginPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void LoadComponents(IList<ConfuserComponent> protections, IList<ConfuserComponent> packers, string pluginPath) {
|
||||
var ctx = new CrossDomainContext(protections, packers, pluginPath);
|
||||
AppDomain appDomain = AppDomain.CreateDomain("");
|
||||
appDomain.SetData("ctx", ctx);
|
||||
appDomain.DoCallBack(CrossDomainLoadComponents);
|
||||
AppDomain.Unload(appDomain);
|
||||
}
|
||||
|
||||
public static void RemoveComponents(IList<ConfuserComponent> protections, IList<ConfuserComponent> packers, string pluginPath) {
|
||||
protections.RemoveWhere(comp => comp is InfoComponent && ((InfoComponent)comp).info.path == pluginPath);
|
||||
packers.RemoveWhere(comp => comp is InfoComponent && ((InfoComponent)comp).info.path == pluginPath);
|
||||
}
|
||||
|
||||
private class CrossDomainContext : MarshalByRefObject {
|
||||
private readonly IList<ConfuserComponent> packers;
|
||||
private readonly string pluginPath;
|
||||
private readonly IList<ConfuserComponent> protections;
|
||||
|
||||
public CrossDomainContext(IList<ConfuserComponent> protections, IList<ConfuserComponent> packers, string pluginPath) {
|
||||
this.protections = protections;
|
||||
this.packers = packers;
|
||||
this.pluginPath = pluginPath;
|
||||
}
|
||||
|
||||
public string PluginPath {
|
||||
get { return pluginPath; }
|
||||
}
|
||||
|
||||
public void AddProtection(Info info) {
|
||||
protections.Add(new InfoComponent(info));
|
||||
}
|
||||
|
||||
public void AddPacker(Info info) {
|
||||
packers.Add(new InfoComponent(info));
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private class Info {
|
||||
public string desc;
|
||||
public string fullId;
|
||||
public string id;
|
||||
public string name;
|
||||
public string path;
|
||||
|
||||
public static Info FromComponent(ConfuserComponent component, string pluginPath) {
|
||||
var ret = new Info();
|
||||
ret.name = component.Name;
|
||||
ret.desc = component.Description;
|
||||
ret.id = component.Id;
|
||||
ret.fullId = component.FullId;
|
||||
ret.path = pluginPath;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
private class InfoComponent : ConfuserComponent {
|
||||
public readonly Info info;
|
||||
|
||||
public InfoComponent(Info info) {
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return info.name; }
|
||||
}
|
||||
|
||||
public override string Description {
|
||||
get { return info.desc; }
|
||||
}
|
||||
|
||||
public override string Id {
|
||||
get { return info.id; }
|
||||
}
|
||||
|
||||
public override string FullId {
|
||||
get { return info.fullId; }
|
||||
}
|
||||
|
||||
protected override void Initialize(ConfuserContext context) {
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
protected override void PopulatePipeline(ProtectionPipeline pipeline) {
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,247 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{B5205EBA-EC32-4C53-86A0-FAEEE7393EC0}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>ConfuserEx</RootNamespace>
|
||||
<AssemblyName>ConfuserEx</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Utf8Output>true</Utf8Output>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\Debug\bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
|
||||
<OutputPath>..\Release\bin\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>ConfuserEx.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AssemblyOriginatorKeyFile>..\ConfuserEx.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="GalaSoft.MvvmLight.Extras.WPF4">
|
||||
<HintPath>..\packages\MvvmLightLibs.4.3.31.1\lib\net40\GalaSoft.MvvmLight.Extras.WPF4.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GalaSoft.MvvmLight.WPF4">
|
||||
<HintPath>..\packages\MvvmLightLibs.4.3.31.1\lib\net40\GalaSoft.MvvmLight.WPF4.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Practices.ServiceLocation">
|
||||
<HintPath>..\packages\CommonServiceLocator.1.2\lib\portable-windows8+net40+sl5+windowsphone8\Microsoft.Practices.ServiceLocation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Ookii.Dialogs.Wpf">
|
||||
<HintPath>..\deps\Ookii.Dialogs.Wpf.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Threading, Version=1.0.2856.102, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\TaskParallelLibrary.1.0.2856.0\lib\Net35\System.Threading.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Windows.Interactivity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MvvmLightLibs.4.3.31.1\lib\net40\System.Windows.Interactivity.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xaml" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="..\GlobalAssemblyInfo.cs">
|
||||
<Link>Properties\GlobalAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="BrushToColorConverter.cs" />
|
||||
<Compile Include="CompComboBox.xaml.cs">
|
||||
<DependentUpon>CompComboBox.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ComponentConverter.cs" />
|
||||
<Compile Include="ComponentDiscovery.cs" />
|
||||
<Compile Include="EnumValuesExtension.cs" />
|
||||
<Compile Include="FileDragDrop.cs" />
|
||||
<Compile Include="InvertBoolConverter.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Skin.cs" />
|
||||
<Compile Include="ViewModel\Project\ProjectRuleVM.cs" />
|
||||
<Compile Include="ViewModel\Project\ProjectSettingVM.cs" />
|
||||
<Compile Include="ViewModel\StringItem.cs" />
|
||||
<Compile Include="ViewModel\UI\AppVM.cs" />
|
||||
<Compile Include="ViewModel\IViewModel.cs" />
|
||||
<Compile Include="ViewModel\Project\ProjectModuleVM.cs" />
|
||||
<Compile Include="ViewModel\UI\ProjectTabVM.cs" />
|
||||
<Compile Include="ViewModel\Project\ProjectVM.cs" />
|
||||
<Compile Include="ViewModel\UI\ProtectTabVM.cs" />
|
||||
<Compile Include="ViewModel\UI\SettingsTabVM.cs" />
|
||||
<Compile Include="ViewModel\UI\TabViewModel.cs" />
|
||||
<Compile Include="ViewModel\Utils.cs" />
|
||||
<Compile Include="ViewModel\ViewModelBase.cs" />
|
||||
<Compile Include="Views\ProjectModuleView.xaml.cs">
|
||||
<DependentUpon>ProjectModuleView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\ProjectRuleView.xaml.cs">
|
||||
<DependentUpon>ProjectRuleView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\ProjectTabAdvancedView.xaml.cs">
|
||||
<DependentUpon>ProjectTabAdvancedView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Page Include="CompComboBox.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Page Include="Skin.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Views.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Views\ProtectTabView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Views\ProjectRuleView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsTabView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Views\ProjectModuleView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\ProjectTabAdvancedView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\ProjectTabView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AppDesigner Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="ConfuserEx.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\ConfuserEx.snk">
|
||||
<Link>Properties\ConfuserEx.snk</Link>
|
||||
</None>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="Resources\CREDITS" />
|
||||
<Resource Include="Resources\FontAwesome.otf" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Confuser.Core\Confuser.Core.csproj">
|
||||
<Project>{BEB67A6E-4C54-4DE5-8C6B-2C12F44A7B92}</Project>
|
||||
<Name>Confuser.Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Confuser.DynCipher\Confuser.DynCipher.csproj">
|
||||
<Project>{E832E9B8-2158-4FC0-89A1-56C6ECC10F6B}</Project>
|
||||
<Name>Confuser.DynCipher</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Confuser.Protections\Confuser.Protections.csproj">
|
||||
<Project>{3EAB01B5-9B49-48D8-BFA1-5493B26CCB71}</Project>
|
||||
<Name>Confuser.Protections</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Confuser.Renamer\Confuser.Renamer.csproj">
|
||||
<Project>{862DA0DA-52E1-47CD-B9C2-46B106031B28}</Project>
|
||||
<Name>Confuser.Renamer</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Confuser.Runtime\Confuser.Runtime.csproj">
|
||||
<Project>{A45C184F-F98F-4258-A928-BFF437034791}</Project>
|
||||
<Name>Confuser.Runtime</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\dnlib\src\dnlib.csproj">
|
||||
<Project>{FDFC1237-143F-4919-8318-4926901F4639}</Project>
|
||||
<Name>dnlib</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Decode.png" />
|
||||
<Resource Include="Resources\New.png" />
|
||||
<Resource Include="Resources\Open.png" />
|
||||
<Resource Include="Resources\Save.png" />
|
||||
<Resource Include="Resources\Tools.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Error.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
|
||||
</Target>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
|
||||
<Target Name="solveAliasProblem" >
|
||||
<ConvertToAbsolutePath Paths="..\packages\TaskParallelLibrary.1.0.2856.0\lib\Net35\System.Threading.dll">
|
||||
<Output TaskParameter="AbsolutePaths" PropertyName="FullPathOriginal" />
|
||||
</ConvertToAbsolutePath>
|
||||
<ItemGroup>
|
||||
<ReferencePath Remove="$(FullPathOriginal)"/>
|
||||
<ReferencePath Include="$(FullPathOriginal)">
|
||||
<Aliases>PTL</Aliases>
|
||||
</ReferencePath>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
<PropertyGroup>
|
||||
<CoreCompileDependsOn>solveAliasProblem;$(PrepareResourcesDependsOn)</CoreCompileDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
После Ширина: | Высота: | Размер: 37 KiB |
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Windows.Markup;
|
||||
|
||||
namespace ConfuserEx {
|
||||
public class EnumValuesExtension : MarkupExtension {
|
||||
private readonly Type enumType;
|
||||
|
||||
public EnumValuesExtension(Type enumType) {
|
||||
this.enumType = enumType;
|
||||
}
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider) {
|
||||
return Enum.GetValues(enumType);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using ConfuserEx.ViewModel;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
|
||||
namespace ConfuserEx {
|
||||
public class FileDragDrop {
|
||||
public static readonly DependencyProperty CommandProperty =
|
||||
DependencyProperty.RegisterAttached("Command", typeof (ICommand), typeof (FileDragDrop), new UIPropertyMetadata(null, OnCommandChanged));
|
||||
|
||||
public static ICommand FileCmd = new DragDropCommand(
|
||||
data => {
|
||||
Debug.Assert(data.Item2.GetDataPresent(DataFormats.FileDrop));
|
||||
if (data.Item1 is TextBox) {
|
||||
string file = ((string[])data.Item2.GetData(DataFormats.FileDrop))[0];
|
||||
Debug.Assert(File.Exists(file));
|
||||
((TextBox)data.Item1).Text = file;
|
||||
} else if (data.Item1 is ListBox) {
|
||||
var files = (string[])data.Item2.GetData(DataFormats.FileDrop);
|
||||
Debug.Assert(files.All(file => File.Exists(file)));
|
||||
var list = (IList<StringItem>)((ListBox)data.Item1).ItemsSource;
|
||||
foreach (string file in files)
|
||||
list.Add(new StringItem(file));
|
||||
} else
|
||||
throw new NotSupportedException();
|
||||
}, data => {
|
||||
if (!data.Item2.GetDataPresent(DataFormats.FileDrop))
|
||||
return false;
|
||||
return ((string[])data.Item2.GetData(DataFormats.FileDrop)).All(file => File.Exists(file));
|
||||
});
|
||||
|
||||
|
||||
public static ICommand DirectoryCmd = new DragDropCommand(
|
||||
data => {
|
||||
Debug.Assert(data.Item2.GetDataPresent(DataFormats.FileDrop));
|
||||
if (data.Item1 is TextBox) {
|
||||
string dir = ((string[])data.Item2.GetData(DataFormats.FileDrop))[0];
|
||||
Debug.Assert(Directory.Exists(dir));
|
||||
((TextBox)data.Item1).Text = dir;
|
||||
} else if (data.Item1 is ListBox) {
|
||||
var dirs = (string[])data.Item2.GetData(DataFormats.FileDrop);
|
||||
Debug.Assert(dirs.All(dir => Directory.Exists(dir)));
|
||||
var list = (IList<StringItem>)((ListBox)data.Item1).ItemsSource;
|
||||
foreach (string dir in dirs)
|
||||
list.Add(new StringItem(dir));
|
||||
} else
|
||||
throw new NotSupportedException();
|
||||
}, data => {
|
||||
if (!data.Item2.GetDataPresent(DataFormats.FileDrop))
|
||||
return false;
|
||||
return ((string[])data.Item2.GetData(DataFormats.FileDrop)).All(dir => Directory.Exists(dir));
|
||||
});
|
||||
|
||||
public static ICommand GetCommand(DependencyObject obj) {
|
||||
return (ICommand)obj.GetValue(CommandProperty);
|
||||
}
|
||||
|
||||
public static void SetCommand(DependencyObject obj, ICommand value) {
|
||||
obj.SetValue(CommandProperty, value);
|
||||
}
|
||||
|
||||
private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
|
||||
var elem = (UIElement)d;
|
||||
if (e.NewValue != null) {
|
||||
elem.AllowDrop = true;
|
||||
elem.PreviewDragOver += OnDragOver;
|
||||
elem.PreviewDrop += OnDrop;
|
||||
} else {
|
||||
elem.AllowDrop = false;
|
||||
elem.PreviewDragOver -= OnDragOver;
|
||||
elem.PreviewDrop -= OnDrop;
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnDragOver(object sender, DragEventArgs e) {
|
||||
ICommand cmd = GetCommand((DependencyObject)sender);
|
||||
e.Effects = DragDropEffects.None;
|
||||
if (cmd is DragDropCommand) {
|
||||
if (cmd.CanExecute(Tuple.Create((UIElement)sender, e.Data)))
|
||||
e.Effects = DragDropEffects.Link;
|
||||
} else {
|
||||
if (cmd.CanExecute(e.Data))
|
||||
e.Effects = DragDropEffects.Link;
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private static void OnDrop(object sender, DragEventArgs e) {
|
||||
ICommand cmd = GetCommand((DependencyObject)sender);
|
||||
if (cmd is DragDropCommand) {
|
||||
if (cmd.CanExecute(Tuple.Create((UIElement)sender, e.Data)))
|
||||
cmd.Execute(Tuple.Create((UIElement)sender, e.Data));
|
||||
} else {
|
||||
if (cmd.CanExecute(e.Data))
|
||||
cmd.Execute(e.Data);
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
|
||||
private class DragDropCommand : RelayCommand<Tuple<UIElement, IDataObject>> {
|
||||
public DragDropCommand(Action<Tuple<UIElement, IDataObject>> execute, Func<Tuple<UIElement, IDataObject>, bool> canExecute)
|
||||
: base(execute, canExecute) { }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ConfuserEx {
|
||||
internal class InvertBoolConverter : IValueConverter {
|
||||
public static readonly InvertBoolConverter Instance = new InvertBoolConverter();
|
||||
private InvertBoolConverter() { }
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
Debug.Assert(value is bool);
|
||||
Debug.Assert(targetType == typeof (bool));
|
||||
return !(bool)value;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<Window x:Class="ConfuserEx.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:ConfuserEx"
|
||||
Title="{Binding Title}" Width="800" Height="600" Style="{StaticResource DarkWindow}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<ToolBar Grid.Row="0" Grid.ColumnSpan="2" ToolBarTray.IsLocked="True" ToolBar.OverflowMode="Never"
|
||||
KeyboardNavigation.TabNavigation="Continue">
|
||||
<Button Command="{Binding NewProject}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image Source="{StaticResource New}" Margin="0,0,4,0" />
|
||||
<TextBlock Text="New project" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button Command="{Binding OpenProject}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image Source="{StaticResource Open}" Margin="0,0,4,0" />
|
||||
<TextBlock Text="Open project" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button Command="{Binding SaveProject}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image Source="{StaticResource Save}" Margin="0,0,4,0" />
|
||||
<TextBlock Text="Save project" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button ContextMenuService.IsEnabled="False" Click="OpenMenu">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image Source="{StaticResource Tools}" Margin="0,0,4,0" />
|
||||
<TextBlock Text="Tools" VerticalAlignment="Center" />
|
||||
<Path Data="M 0.5 4 L 6.5 4 L 3.5 9 Z" Fill="{StaticResource Foreground}" Margin="4,0,0,0"
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
<Button.ContextMenu>
|
||||
<ContextMenu
|
||||
DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
|
||||
<MenuItem Header="Stack Trace Decoder" Command="{Binding Decode}">
|
||||
<MenuItem.Icon>
|
||||
<Image Source="{StaticResource Decode}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</Button.ContextMenu>
|
||||
</Button>
|
||||
</ToolBar>
|
||||
<TabControl Grid.Row="1" Grid.ColumnSpan="2" Margin="10" ItemsSource="{Binding Tabs}" Padding="5"
|
||||
SelectedIndex="0" local:Skin.TabsDisabled="{Binding NavigationDisabled}">
|
||||
<TabControl.ItemContainerStyle>
|
||||
<Style TargetType="{x:Type TabItem}" BasedOn="{StaticResource {x:Type TabItem}}">
|
||||
<Setter Property="Width" Value="80" />
|
||||
<Setter Property="Header" Value="{Binding Header}" />
|
||||
</Style>
|
||||
</TabControl.ItemContainerStyle>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</Window>
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using Confuser.Core.Project;
|
||||
using ConfuserEx.ViewModel;
|
||||
|
||||
namespace ConfuserEx {
|
||||
public partial class MainWindow : Window {
|
||||
public MainWindow() {
|
||||
InitializeComponent();
|
||||
|
||||
var app = new AppVM();
|
||||
app.Project = new ProjectVM(new ConfuserProject());
|
||||
app.FileName = "Unnamed.crproj";
|
||||
|
||||
app.Tabs.Add(new ProjectTabVM(app));
|
||||
app.Tabs.Add(new SettingsTabVM(app));
|
||||
app.Tabs.Add(new ProtectTabVM(app));
|
||||
|
||||
DataContext = app;
|
||||
}
|
||||
|
||||
private void OpenMenu(object sender, RoutedEventArgs e) {
|
||||
var btn = (Button)sender;
|
||||
ContextMenu menu = btn.ContextMenu;
|
||||
menu.PlacementTarget = btn;
|
||||
menu.Placement = PlacementMode.MousePoint;
|
||||
menu.IsOpen = true;
|
||||
}
|
||||
|
||||
protected override void OnClosing(CancelEventArgs e) {
|
||||
base.OnClosing(e);
|
||||
e.Cancel = !((AppVM)DataContext).OnWindowClosing();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyTitle("ConfuserEx")]
|
||||
[assembly: AssemblyDescription("ConfuserEx GUI")]
|
|
@ -0,0 +1 @@
|
|||
Icons adapted from http://flaticons.net
|
После Ширина: | Высота: | Размер: 1.1 KiB |
После Ширина: | Высота: | Размер: 536 B |
После Ширина: | Высота: | Размер: 1.1 KiB |
После Ширина: | Высота: | Размер: 1.1 KiB |
После Ширина: | Высота: | Размер: 1.1 KiB |
После Ширина: | Высота: | Размер: 1.1 KiB |
|
@ -0,0 +1,51 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
|
||||
namespace ConfuserEx {
|
||||
public class Skin {
|
||||
public static readonly DependencyProperty EmptyPromptProperty =
|
||||
DependencyProperty.RegisterAttached("EmptyPrompt", typeof (string), typeof (Skin), new UIPropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty TabsDisabledProperty =
|
||||
DependencyProperty.RegisterAttached("TabsDisabled", typeof (bool), typeof (Skin), new UIPropertyMetadata(false));
|
||||
|
||||
public static readonly DependencyProperty RTBDocumentProperty =
|
||||
DependencyProperty.RegisterAttached("RTBDocument", typeof (FlowDocument), typeof (Skin), new FrameworkPropertyMetadata(null, OnRTBDocumentChanged));
|
||||
|
||||
public static string GetEmptyPrompt(DependencyObject obj) {
|
||||
return (string)obj.GetValue(EmptyPromptProperty);
|
||||
}
|
||||
|
||||
public static void SetEmptyPrompt(DependencyObject obj, string value) {
|
||||
obj.SetValue(EmptyPromptProperty, value);
|
||||
}
|
||||
|
||||
public static bool GetTabsDisabled(DependencyObject obj) {
|
||||
return (bool)obj.GetValue(TabsDisabledProperty);
|
||||
}
|
||||
|
||||
public static void SetTabsDisabled(DependencyObject obj, bool value) {
|
||||
obj.SetValue(TabsDisabledProperty, value);
|
||||
}
|
||||
|
||||
public static void OnRTBDocumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs dpe) {
|
||||
var rtb = (RichTextBox)d;
|
||||
if (dpe.NewValue != null) {
|
||||
rtb.Document = (FlowDocument)dpe.NewValue;
|
||||
rtb.TextChanged += (sender, e) => rtb.ScrollToEnd();
|
||||
}
|
||||
else
|
||||
rtb.Document = new FlowDocument();
|
||||
}
|
||||
|
||||
public static FlowDocument GetRTBDocument(DependencyObject obj) {
|
||||
return (FlowDocument)obj.GetValue(RTBDocumentProperty);
|
||||
}
|
||||
|
||||
public static void SetRTBDocument(DependencyObject obj, FlowDocument value) {
|
||||
obj.SetValue(RTBDocumentProperty, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
using System;
|
||||
|
||||
namespace ConfuserEx.ViewModel {
|
||||
public interface IViewModel<TModel> {
|
||||
TModel Model { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using Confuser.Core.Project;
|
||||
|
||||
namespace ConfuserEx.ViewModel {
|
||||
public class ProjectModuleVM : ViewModelBase, IViewModel<ProjectModule>, IRuleContainer {
|
||||
private readonly ProjectModule module;
|
||||
private readonly ProjectVM parent;
|
||||
private string asmName = "Unknown";
|
||||
private string simpleName;
|
||||
|
||||
public ProjectModuleVM(ProjectVM parent, ProjectModule module) {
|
||||
this.parent = parent;
|
||||
this.module = module;
|
||||
|
||||
ObservableCollection<ProjectRuleVM> rules = Utils.Wrap(module.Rules, rule => new ProjectRuleVM(parent, rule));
|
||||
rules.CollectionChanged += (sender, e) => parent.IsModified = true;
|
||||
Rules = rules;
|
||||
|
||||
SimpleName = System.IO.Path.GetFileName(module.Path);
|
||||
LoadAssemblyName();
|
||||
}
|
||||
|
||||
public ProjectModule Module {
|
||||
get { return module; }
|
||||
}
|
||||
|
||||
public string Path {
|
||||
get { return module.Path; }
|
||||
set {
|
||||
if (SetProperty(module.Path != value, val => module.Path = val, value, "Path")) {
|
||||
parent.IsModified = true;
|
||||
SimpleName = System.IO.Path.GetFileName(module.Path);
|
||||
LoadAssemblyName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string SimpleName {
|
||||
get { return simpleName; }
|
||||
private set { SetProperty(ref simpleName, value, "SimpleName"); }
|
||||
}
|
||||
|
||||
public string AssemblyName {
|
||||
get { return asmName; }
|
||||
private set { SetProperty(ref asmName, value, "AssemblyName"); }
|
||||
}
|
||||
|
||||
public string SNKeyPath {
|
||||
get { return module.SNKeyPath; }
|
||||
set {
|
||||
if (SetProperty(module.SNKeyPath != value, val => module.SNKeyPath = val, value, "SNKeyPath"))
|
||||
parent.IsModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
public string SNKeyPassword {
|
||||
get { return module.SNKeyPassword; }
|
||||
set {
|
||||
if (SetProperty(module.SNKeyPassword != value, val => module.SNKeyPassword = val, value, "SNKeyPassword"))
|
||||
parent.IsModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
public IList<ProjectRuleVM> Rules { get; private set; }
|
||||
|
||||
ProjectModule IViewModel<ProjectModule>.Model {
|
||||
get { return module; }
|
||||
}
|
||||
|
||||
private void LoadAssemblyName() {
|
||||
AssemblyName = "Loading...";
|
||||
ThreadPool.QueueUserWorkItem(_ => {
|
||||
try {
|
||||
string path = System.IO.Path.Combine(parent.BaseDirectory, Path);
|
||||
AssemblyName name = System.Reflection.AssemblyName.GetAssemblyName(path);
|
||||
AssemblyName = name.FullName;
|
||||
} catch {
|
||||
AssemblyName = "Unknown";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using Confuser.Core;
|
||||
using Confuser.Core.Project;
|
||||
using Confuser.Core.Project.Patterns;
|
||||
|
||||
namespace ConfuserEx.ViewModel {
|
||||
internal interface IRuleContainer {
|
||||
IList<ProjectRuleVM> Rules { get; }
|
||||
}
|
||||
|
||||
public class ProjectRuleVM : ViewModelBase, IViewModel<Rule> {
|
||||
private readonly ProjectVM parent;
|
||||
private readonly Rule rule;
|
||||
private string error;
|
||||
private PatternExpression exp;
|
||||
|
||||
public ProjectRuleVM(ProjectVM parent, Rule rule) {
|
||||
this.parent = parent;
|
||||
this.rule = rule;
|
||||
|
||||
ObservableCollection<ProjectSettingVM<Protection>> protections = Utils.Wrap(rule, setting => new ProjectSettingVM<Protection>(parent, setting));
|
||||
protections.CollectionChanged += (sender, e) => parent.IsModified = true;
|
||||
Protections = protections;
|
||||
|
||||
ParseExpression();
|
||||
}
|
||||
|
||||
public ProjectVM Project {
|
||||
get { return parent; }
|
||||
}
|
||||
|
||||
public string Pattern {
|
||||
get { return rule.Pattern; }
|
||||
set {
|
||||
if (SetProperty(rule.Pattern != value, val => rule.Pattern = val, value, "Pattern")) {
|
||||
parent.IsModified = true;
|
||||
ParseExpression();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PatternExpression Expression {
|
||||
get { return exp; }
|
||||
set { SetProperty(ref exp, value, "Expression"); }
|
||||
}
|
||||
|
||||
public string ExpressionError {
|
||||
get { return error; }
|
||||
set { SetProperty(ref error, value, "ExpressionError"); }
|
||||
}
|
||||
|
||||
public ProtectionPreset Preset {
|
||||
get { return rule.Preset; }
|
||||
set {
|
||||
if (SetProperty(rule.Preset != value, val => rule.Preset = val, value, "Preset"))
|
||||
parent.IsModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Inherit {
|
||||
get { return rule.Inherit; }
|
||||
set {
|
||||
if (SetProperty(rule.Inherit != value, val => rule.Inherit = val, value, "Inherit"))
|
||||
parent.IsModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
public IList<ProjectSettingVM<Protection>> Protections { get; private set; }
|
||||
|
||||
Rule IViewModel<Rule>.Model {
|
||||
get { return rule; }
|
||||
}
|
||||
|
||||
private void ParseExpression() {
|
||||
PatternExpression expression;
|
||||
try {
|
||||
expression = new PatternParser().Parse(Pattern);
|
||||
ExpressionError = null;
|
||||
} catch (Exception e) {
|
||||
ExpressionError = e.Message;
|
||||
expression = null;
|
||||
}
|
||||
Expression = expression;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using Confuser.Core.Project;
|
||||
|
||||
namespace ConfuserEx.ViewModel {
|
||||
public class ProjectSettingVM<T> : ViewModelBase, IViewModel<SettingItem<T>> {
|
||||
private readonly ProjectVM parent;
|
||||
private readonly SettingItem<T> setting;
|
||||
|
||||
public ProjectSettingVM(ProjectVM parent, SettingItem<T> setting) {
|
||||
this.parent = parent;
|
||||
this.setting = setting;
|
||||
}
|
||||
|
||||
public string Id {
|
||||
get { return setting.Id; }
|
||||
set {
|
||||
if (SetProperty(setting.Id != value, val => setting.Id = val, value, "Id"))
|
||||
parent.IsModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
public SettingItemAction Action {
|
||||
get { return setting.Action; }
|
||||
set {
|
||||
if (SetProperty(setting.Action != value, val => setting.Action = val, value, "Action"))
|
||||
parent.IsModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
SettingItem<T> IViewModel<SettingItem<T>>.Model {
|
||||
get { return setting; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using Confuser.Core;
|
||||
using Confuser.Core.Project;
|
||||
|
||||
namespace ConfuserEx.ViewModel {
|
||||
public class ProjectVM : ViewModelBase, IViewModel<ConfuserProject>, IRuleContainer {
|
||||
private readonly ConfuserProject proj;
|
||||
private bool modified;
|
||||
private ProjectSettingVM<Packer> packer;
|
||||
|
||||
public ProjectVM(ConfuserProject proj) {
|
||||
this.proj = proj;
|
||||
|
||||
ObservableCollection<ProjectModuleVM> modules = Utils.Wrap(proj, module => new ProjectModuleVM(this, module));
|
||||
modules.CollectionChanged += (sender, e) => IsModified = true;
|
||||
Modules = modules;
|
||||
|
||||
ObservableCollection<StringItem> plugins = Utils.Wrap(proj.PluginPaths, path => new StringItem(path));
|
||||
plugins.CollectionChanged += (sender, e) => IsModified = true;
|
||||
Plugins = plugins;
|
||||
|
||||
ObservableCollection<StringItem> probePaths = Utils.Wrap(proj.ProbePaths, path => new StringItem(path));
|
||||
probePaths.CollectionChanged += (sender, e) => IsModified = true;
|
||||
ProbePaths = probePaths;
|
||||
|
||||
ObservableCollection<ProjectRuleVM> rules = Utils.Wrap(proj.Rules, rule => new ProjectRuleVM(this, rule));
|
||||
rules.CollectionChanged += (sender, e) => IsModified = true;
|
||||
Rules = rules;
|
||||
|
||||
Protections = new ObservableCollection<ConfuserComponent>();
|
||||
Packers = new ObservableCollection<ConfuserComponent>();
|
||||
ComponentDiscovery.LoadComponents(Protections, Packers, Assembly.Load("Confuser.Protections").Location);
|
||||
ComponentDiscovery.LoadComponents(Protections, Packers, Assembly.Load("Confuser.Renamer").Location);
|
||||
}
|
||||
|
||||
public ConfuserProject Project {
|
||||
get { return proj; }
|
||||
}
|
||||
|
||||
public bool IsModified {
|
||||
get { return modified; }
|
||||
set { SetProperty(ref modified, value, "IsModified"); }
|
||||
}
|
||||
|
||||
public string Seed {
|
||||
get { return proj.Seed; }
|
||||
set { SetProperty(proj.Seed != value, val => proj.Seed = val, value, "Seed"); }
|
||||
}
|
||||
|
||||
public bool Debug {
|
||||
get { return proj.Debug; }
|
||||
set { SetProperty(proj.Debug != value, val => proj.Debug = val, value, "Debug"); }
|
||||
}
|
||||
|
||||
public string BaseDirectory {
|
||||
get { return proj.BaseDirectory; }
|
||||
set { SetProperty(proj.BaseDirectory != value, val => proj.BaseDirectory = val, value, "BaseDirectory"); }
|
||||
}
|
||||
|
||||
public string OutputDirectory {
|
||||
get { return proj.OutputDirectory; }
|
||||
set { SetProperty(proj.OutputDirectory != value, val => proj.OutputDirectory = val, value, "OutputDirectory"); }
|
||||
}
|
||||
|
||||
public ProjectSettingVM<Packer> Packer {
|
||||
get {
|
||||
if (proj.Packer == null)
|
||||
packer = null;
|
||||
else
|
||||
packer = new ProjectSettingVM<Packer>(this, proj.Packer);
|
||||
return packer;
|
||||
}
|
||||
set {
|
||||
var vm = (IViewModel<SettingItem<Packer>>)value;
|
||||
bool changed = (vm == null && proj.Packer != null) || (vm != null && proj.Packer != vm.Model);
|
||||
SetProperty(changed, val => proj.Packer = val == null ? null : val.Model, vm, "Packer");
|
||||
}
|
||||
}
|
||||
|
||||
public IList<ProjectModuleVM> Modules { get; private set; }
|
||||
public IList<StringItem> Plugins { get; private set; }
|
||||
public IList<StringItem> ProbePaths { get; private set; }
|
||||
|
||||
public ObservableCollection<ConfuserComponent> Protections { get; private set; }
|
||||
public ObservableCollection<ConfuserComponent> Packers { get; private set; }
|
||||
public IList<ProjectRuleVM> Rules { get; private set; }
|
||||
|
||||
ConfuserProject IViewModel<ConfuserProject>.Model {
|
||||
get { return proj; }
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(string property) {
|
||||
base.OnPropertyChanged(property);
|
||||
if (property != "IsModified")
|
||||
IsModified = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
|
||||
namespace ConfuserEx.ViewModel {
|
||||
public class StringItem : IViewModel<string> {
|
||||
public StringItem(string item) {
|
||||
Item = item;
|
||||
}
|
||||
|
||||
public string Item { get; private set; }
|
||||
|
||||
string IViewModel<string>.Model {
|
||||
get { return Item; }
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return Item;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Xml;
|
||||
using Confuser.Core;
|
||||
using Confuser.Core.Project;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
|
||||
namespace ConfuserEx.ViewModel {
|
||||
public class AppVM : ViewModelBase {
|
||||
private readonly IList<TabViewModel> tabs = new ObservableCollection<TabViewModel>();
|
||||
private string fileName;
|
||||
private bool navDisabled;
|
||||
|
||||
private ProjectVM proj;
|
||||
|
||||
public bool NavigationDisabled {
|
||||
get { return navDisabled; }
|
||||
set { SetProperty(ref navDisabled, value, "NavigationDisabled"); }
|
||||
}
|
||||
|
||||
public ProjectVM Project {
|
||||
get { return proj; }
|
||||
set {
|
||||
if (proj != null)
|
||||
proj.PropertyChanged -= OnProjectPropertyChanged;
|
||||
|
||||
SetProperty(ref proj, value, "Project");
|
||||
|
||||
if (proj != null)
|
||||
proj.PropertyChanged += OnProjectPropertyChanged;
|
||||
}
|
||||
}
|
||||
|
||||
public string FileName {
|
||||
get { return fileName; }
|
||||
set {
|
||||
SetProperty(ref fileName, value, "Project");
|
||||
OnPropertyChanged("Title");
|
||||
}
|
||||
}
|
||||
|
||||
public string Title {
|
||||
get {
|
||||
return string.Format("{0}{1} - {2}",
|
||||
Path.GetFileName(fileName),
|
||||
(proj.IsModified ? "*" : ""),
|
||||
ConfuserEngine.Version);
|
||||
}
|
||||
}
|
||||
|
||||
public IList<TabViewModel> Tabs {
|
||||
get { return tabs; }
|
||||
}
|
||||
|
||||
public ICommand NewProject {
|
||||
get { return new RelayCommand(NewProj, () => !NavigationDisabled); }
|
||||
}
|
||||
|
||||
public ICommand OpenProject {
|
||||
get { return new RelayCommand(OpenProj, () => !NavigationDisabled); }
|
||||
}
|
||||
|
||||
public ICommand SaveProject {
|
||||
get { return new RelayCommand(() => SaveProj(), () => !NavigationDisabled); }
|
||||
}
|
||||
|
||||
public ICommand Decode {
|
||||
get { return new RelayCommand(() => { MessageBox.Show("Not yet implemented!", "ConfuserEx", MessageBoxButton.OK, MessageBoxImage.Information); }, () => !NavigationDisabled); }
|
||||
}
|
||||
|
||||
public bool OnWindowClosing() {
|
||||
return PromptSave();
|
||||
}
|
||||
|
||||
private bool SaveProj() {
|
||||
if (File.Exists(FileName)) {
|
||||
var sfd = new VistaSaveFileDialog();
|
||||
sfd.FileName = FileName;
|
||||
sfd.Filter = "ConfuserEx Projects (*.crproj)|*.crproj|All Files (*.*)|*.*";
|
||||
if (!(sfd.ShowDialog(Application.Current.MainWindow) ?? false) || sfd.FileName == null)
|
||||
return false;
|
||||
FileName = sfd.FileName;
|
||||
}
|
||||
ConfuserProject proj = ((IViewModel<ConfuserProject>)Project).Model;
|
||||
proj.Save().Save(FileName);
|
||||
Project.IsModified = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool PromptSave() {
|
||||
if (!Project.IsModified)
|
||||
return true;
|
||||
switch (MessageBox.Show("The current project has unsaved changes. Do you want to save them?", "ConfuserEx", MessageBoxButton.YesNoCancel, MessageBoxImage.Question)) {
|
||||
case MessageBoxResult.Yes:
|
||||
return SaveProj();
|
||||
case MessageBoxResult.No:
|
||||
return true;
|
||||
case MessageBoxResult.Cancel:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void NewProj() {
|
||||
if (!PromptSave())
|
||||
return;
|
||||
|
||||
Project = new ProjectVM(new ConfuserProject());
|
||||
FileName = "Unnamed.crproj";
|
||||
}
|
||||
|
||||
private void OpenProj() {
|
||||
if (!PromptSave())
|
||||
return;
|
||||
|
||||
var ofd = new VistaOpenFileDialog();
|
||||
ofd.Filter = "ConfuserEx Projects (*.crproj)|*.crproj|All Files (*.*)|*.*";
|
||||
if ((ofd.ShowDialog(Application.Current.MainWindow) ?? false) && ofd.FileName != null) {
|
||||
string fileName = ofd.FileName;
|
||||
try {
|
||||
var xmlDoc = new XmlDocument();
|
||||
xmlDoc.Load(fileName);
|
||||
var proj = new ConfuserProject();
|
||||
proj.Load(xmlDoc);
|
||||
Project = new ProjectVM(proj);
|
||||
FileName = fileName;
|
||||
} catch {
|
||||
MessageBox.Show("Invalid project!", "ConfuserEx", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnProjectPropertyChanged(object sender, PropertyChangedEventArgs e) {
|
||||
if (e.PropertyName == "IsModified" && proj.IsModified)
|
||||
OnPropertyChanged("Title");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using Confuser.Core.Project;
|
||||
using ConfuserEx.Views;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
|
||||
namespace ConfuserEx.ViewModel {
|
||||
public class ProjectTabVM : TabViewModel {
|
||||
private int selIndex = -1;
|
||||
|
||||
public ProjectTabVM(AppVM app)
|
||||
: base(app, "Project") { }
|
||||
|
||||
public ICommand DragDrop {
|
||||
get {
|
||||
return new RelayCommand<IDataObject>(data => {
|
||||
foreach (string file in (string[])data.GetData(DataFormats.FileDrop))
|
||||
AddModule(file);
|
||||
}, data => {
|
||||
if (!data.GetDataPresent(DataFormats.FileDrop))
|
||||
return false;
|
||||
var files = (string[])data.GetData(DataFormats.FileDrop);
|
||||
bool ret = files.All(file => File.Exists(file));
|
||||
return ret;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public int SelectedIndex {
|
||||
get { return selIndex; }
|
||||
set { SetProperty(ref selIndex, value, "SelectedIndex"); }
|
||||
}
|
||||
|
||||
public ICommand ChooseBaseDir {
|
||||
get {
|
||||
return new RelayCommand(() => {
|
||||
var fbd = new VistaFolderBrowserDialog();
|
||||
fbd.SelectedPath = App.Project.BaseDirectory;
|
||||
if (fbd.ShowDialog() ?? false) {
|
||||
App.Project.BaseDirectory = fbd.SelectedPath;
|
||||
App.Project.OutputDirectory = Path.Combine(App.Project.BaseDirectory, "Confused");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand ChooseOutputDir {
|
||||
get {
|
||||
return new RelayCommand(() => {
|
||||
var fbd = new VistaFolderBrowserDialog();
|
||||
fbd.SelectedPath = App.Project.OutputDirectory;
|
||||
if (fbd.ShowDialog() ?? false) {
|
||||
App.Project.OutputDirectory = fbd.SelectedPath;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand Add {
|
||||
get {
|
||||
return new RelayCommand(() => {
|
||||
var ofd = new VistaOpenFileDialog();
|
||||
ofd.Filter = ".NET assemblies (*.exe, *.dll)|*.exe;*.dll|All Files (*.*)|*.*";
|
||||
if (ofd.ShowDialog() ?? false) {
|
||||
AddModule(ofd.FileName);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand Remove {
|
||||
get {
|
||||
return new RelayCommand(() => {
|
||||
int selIndex = SelectedIndex;
|
||||
Debug.Assert(selIndex != -1);
|
||||
ProjectModuleVM module = App.Project.Modules[selIndex];
|
||||
string msg = string.Format("Are you sure to remove module '{0}'?\r\nAll settings specific to it would be lost!", module.Path);
|
||||
if (MessageBox.Show(msg, "ConfuserEx", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) {
|
||||
App.Project.Modules.RemoveAt(selIndex);
|
||||
SelectedIndex = selIndex >= App.Project.Modules.Count ? App.Project.Modules.Count - 1 : selIndex;
|
||||
}
|
||||
}, () => SelectedIndex != -1);
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand Edit {
|
||||
get {
|
||||
return new RelayCommand(() => {
|
||||
Debug.Assert(SelectedIndex != -1);
|
||||
var dialog = new ProjectModuleView(App.Project.Modules[SelectedIndex]);
|
||||
dialog.Owner = Application.Current.MainWindow;
|
||||
dialog.ShowDialog();
|
||||
}, () => SelectedIndex != -1);
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand Advanced {
|
||||
get {
|
||||
return new RelayCommand(() => {
|
||||
var dialog = new ProjectTabAdvancedView(App.Project);
|
||||
dialog.Owner = Application.Current.MainWindow;
|
||||
dialog.ShowDialog();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void AddModule(string file) {
|
||||
if (!File.Exists(file)) {
|
||||
MessageBox.Show(string.Format("File '{0}' does not exists!", file), "ConfuserEx", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrEmpty(App.Project.BaseDirectory)) {
|
||||
string directory = Path.GetDirectoryName(file);
|
||||
App.Project.BaseDirectory = directory;
|
||||
App.Project.OutputDirectory = Path.Combine(directory, "Confused");
|
||||
}
|
||||
var module = new ProjectModuleVM(App.Project, new ProjectModule());
|
||||
try {
|
||||
module.Path = Confuser.Core.Utils.GetRelativePath(file, App.Project.BaseDirectory);
|
||||
} catch {
|
||||
module.Path = file;
|
||||
}
|
||||
App.Project.Modules.Add(module);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
extern alias PTL;
|
||||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using Confuser.Core;
|
||||
using Confuser.Core.Project;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using PTL::System.Threading;
|
||||
|
||||
// http://connect.microsoft.com/VisualStudio/feedback/details/615953/
|
||||
|
||||
namespace ConfuserEx.ViewModel {
|
||||
internal class ProtectTabVM : TabViewModel, ILogger {
|
||||
private readonly Paragraph documentContent;
|
||||
private double? progress = 0;
|
||||
private bool? result;
|
||||
|
||||
public ProtectTabVM(AppVM app)
|
||||
: base(app, "Protect!") {
|
||||
documentContent = new Paragraph();
|
||||
LogDocument = new FlowDocument();
|
||||
LogDocument.Blocks.Add(documentContent);
|
||||
}
|
||||
|
||||
public ICommand ProtectCmd {
|
||||
get { return new RelayCommand(DoProtect, () => !App.NavigationDisabled); }
|
||||
}
|
||||
|
||||
public ICommand CancelCmd {
|
||||
get { return new RelayCommand(DoCancel, () => App.NavigationDisabled); }
|
||||
}
|
||||
|
||||
public double? Progress {
|
||||
get { return progress; }
|
||||
set { SetProperty(ref progress, value, "Progress"); }
|
||||
}
|
||||
|
||||
public FlowDocument LogDocument { get; private set; }
|
||||
|
||||
public bool? Result {
|
||||
get { return result; }
|
||||
set { SetProperty(ref result, value, "Result"); }
|
||||
}
|
||||
|
||||
CancellationTokenSource cancelSrc;
|
||||
private void DoProtect() {
|
||||
var parameters = new ConfuserParameters();
|
||||
parameters.Project = ((IViewModel<ConfuserProject>)App.Project).Model;
|
||||
parameters.Logger = this;
|
||||
|
||||
documentContent.Inlines.Clear();
|
||||
cancelSrc = new CancellationTokenSource();
|
||||
Result = null;
|
||||
Progress = null;
|
||||
begin = DateTime.Now;
|
||||
App.NavigationDisabled = true;
|
||||
|
||||
ConfuserEngine.Run(parameters, cancelSrc.Token)
|
||||
.ContinueWith(_ =>
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() => {
|
||||
Progress = 0;
|
||||
App.NavigationDisabled = false;
|
||||
CommandManager.InvalidateRequerySuggested();
|
||||
})));
|
||||
}
|
||||
|
||||
private void DoCancel() {
|
||||
cancelSrc.Cancel();
|
||||
}
|
||||
|
||||
private void AppendLine(string format, Brush foreground, params object[] args) {
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() => {
|
||||
documentContent.Inlines.Add(new Run(string.Format(format, args)) { Foreground = foreground });
|
||||
documentContent.Inlines.Add(new LineBreak());
|
||||
}));
|
||||
}
|
||||
|
||||
#region Logger Impl
|
||||
|
||||
private DateTime begin;
|
||||
|
||||
void ILogger.Debug(string msg) {
|
||||
AppendLine("[DEBUG] {0}", Brushes.Gray, msg);
|
||||
}
|
||||
|
||||
void ILogger.DebugFormat(string format, params object[] args) {
|
||||
AppendLine("[DEBUG] {0}", Brushes.Gray, string.Format(format, args));
|
||||
}
|
||||
|
||||
void ILogger.Info(string msg) {
|
||||
AppendLine(" [INFO] {0}", Brushes.White, msg);
|
||||
}
|
||||
|
||||
void ILogger.InfoFormat(string format, params object[] args) {
|
||||
AppendLine(" [INFO] {0}", Brushes.White, string.Format(format, args));
|
||||
}
|
||||
|
||||
void ILogger.Warn(string msg) {
|
||||
AppendLine(" [WARN] {0}", Brushes.Yellow, msg);
|
||||
}
|
||||
|
||||
void ILogger.WarnFormat(string format, params object[] args) {
|
||||
AppendLine(" [WARN] {0}", Brushes.Yellow, string.Format(format, args));
|
||||
}
|
||||
|
||||
void ILogger.WarnException(string msg, Exception ex) {
|
||||
AppendLine(" [WARN] {0}", Brushes.Yellow, msg);
|
||||
AppendLine("Exception: {0}", Brushes.Yellow, ex);
|
||||
}
|
||||
|
||||
void ILogger.Error(string msg) {
|
||||
AppendLine("[ERROR] {0}", Brushes.Red, msg);
|
||||
}
|
||||
|
||||
void ILogger.ErrorFormat(string format, params object[] args) {
|
||||
AppendLine("[ERROR] {0}", Brushes.Red, string.Format(format, args));
|
||||
}
|
||||
|
||||
void ILogger.ErrorException(string msg, Exception ex) {
|
||||
AppendLine("[ERROR] {0}", Brushes.Red, msg);
|
||||
AppendLine("Exception: {0}", Brushes.Red, ex);
|
||||
}
|
||||
|
||||
void ILogger.Progress(int progress, int overall) {
|
||||
Progress = (double)progress / overall;
|
||||
}
|
||||
|
||||
void ILogger.EndProgress() {
|
||||
Progress = null;
|
||||
}
|
||||
|
||||
void ILogger.Finish(bool successful) {
|
||||
DateTime now = DateTime.Now;
|
||||
string timeString = string.Format(
|
||||
"at {0}, {1}:{2:d2} elapsed.",
|
||||
now.ToShortTimeString(),
|
||||
(int)now.Subtract(begin).TotalMinutes,
|
||||
now.Subtract(begin).Seconds);
|
||||
if (successful)
|
||||
AppendLine("Finished {0}", Brushes.Lime, timeString);
|
||||
else
|
||||
AppendLine("Failed {0}", Brushes.Red, timeString);
|
||||
Result = successful;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
using Confuser.Core;
|
||||
using Confuser.Core.Project;
|
||||
using ConfuserEx.Views;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
|
||||
namespace ConfuserEx.ViewModel {
|
||||
internal class SettingsTabVM : TabViewModel {
|
||||
private bool hasPacker;
|
||||
private IRuleContainer selectedList;
|
||||
private int selectedRuleIndex;
|
||||
|
||||
public SettingsTabVM(AppVM app)
|
||||
: base(app, "Settings") {
|
||||
app.PropertyChanged += (sender, e) => {
|
||||
if (e.PropertyName == "Project")
|
||||
InitProject();
|
||||
};
|
||||
InitProject();
|
||||
}
|
||||
|
||||
public bool HasPacker {
|
||||
get { return hasPacker; }
|
||||
set { SetProperty(ref hasPacker, value, "HasPacker"); }
|
||||
}
|
||||
|
||||
public IList ModulesView { get; private set; }
|
||||
|
||||
public IRuleContainer SelectedList {
|
||||
get { return selectedList; }
|
||||
set {
|
||||
if (SetProperty(ref selectedList, value, "SelectedList"))
|
||||
SelectedRuleIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public int SelectedRuleIndex {
|
||||
get { return selectedRuleIndex; }
|
||||
set { SetProperty(ref selectedRuleIndex, value, "SelectedRuleIndex"); }
|
||||
}
|
||||
|
||||
public ICommand Add {
|
||||
get {
|
||||
return new RelayCommand(() => {
|
||||
Debug.Assert(SelectedList != null);
|
||||
|
||||
var rule = new ProjectRuleVM(App.Project, new Rule());
|
||||
rule.Pattern = "true";
|
||||
SelectedList.Rules.Add(rule);
|
||||
SelectedRuleIndex = SelectedList.Rules.Count - 1;
|
||||
}, () => SelectedList != null);
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand Remove {
|
||||
get {
|
||||
return new RelayCommand(() => {
|
||||
int selIndex = SelectedRuleIndex;
|
||||
Debug.Assert(SelectedList != null);
|
||||
Debug.Assert(selIndex != -1);
|
||||
|
||||
ProjectRuleVM rule = SelectedList.Rules[selIndex];
|
||||
SelectedList.Rules.RemoveAt(selIndex);
|
||||
SelectedRuleIndex = selIndex >= SelectedList.Rules.Count ? SelectedList.Rules.Count - 1 : selIndex;
|
||||
}, () => SelectedRuleIndex != -1 && SelectedList != null);
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand Edit {
|
||||
get {
|
||||
return new RelayCommand(() => {
|
||||
Debug.Assert(SelectedRuleIndex != -1);
|
||||
var dialog = new ProjectRuleView(App.Project, SelectedList.Rules[SelectedRuleIndex]);
|
||||
dialog.Owner = Application.Current.MainWindow;
|
||||
dialog.ShowDialog();
|
||||
dialog.Cleanup();
|
||||
}, () => SelectedRuleIndex != -1 && SelectedList != null);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitProject() {
|
||||
ModulesView = new CompositeCollection {
|
||||
App.Project,
|
||||
new CollectionContainer { Collection = App.Project.Modules }
|
||||
};
|
||||
OnPropertyChanged("ModulesView");
|
||||
HasPacker = App.Project.Packer != null;
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(string property) {
|
||||
if (property == "HasPacker") {
|
||||
if (hasPacker)
|
||||
App.Project.Packer = new ProjectSettingVM<Packer>(App.Project, new SettingItem<Packer> { Id = App.Project.Packers[0].Id });
|
||||
else
|
||||
App.Project.Packer = null;
|
||||
}
|
||||
base.OnPropertyChanged(property);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
|
||||
namespace ConfuserEx.ViewModel {
|
||||
public abstract class TabViewModel : ViewModelBase {
|
||||
protected TabViewModel(AppVM app, string header) {
|
||||
App = app;
|
||||
Header = header;
|
||||
}
|
||||
|
||||
public AppVM App { get; private set; }
|
||||
public string Header { get; private set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
|
||||
namespace ConfuserEx.ViewModel {
|
||||
public static class Utils {
|
||||
public static ObservableCollection<T> Wrap<T>(IList<T> list) {
|
||||
var ret = new ObservableCollection<T>(list);
|
||||
|
||||
ret.CollectionChanged += (sender, e) => {
|
||||
var collection = (ObservableCollection<T>)sender;
|
||||
switch (e.Action) {
|
||||
case NotifyCollectionChangedAction.Reset:
|
||||
list.Clear();
|
||||
foreach (T item in collection)
|
||||
list.Add(item);
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
for (int i = 0; i < e.NewItems.Count; i++)
|
||||
list.Insert(e.NewStartingIndex + i, (T)e.NewItems[i]);
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
for (int i = 0; i < e.OldItems.Count; i++)
|
||||
list.RemoveAt(e.OldStartingIndex);
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Move:
|
||||
list.RemoveAt(e.OldStartingIndex);
|
||||
list.Insert(e.NewStartingIndex, (T)e.NewItems[0]);
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Replace:
|
||||
list[e.NewStartingIndex] = (T)e.NewItems[0];
|
||||
break;
|
||||
}
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static ObservableCollection<TViewModel> Wrap<TModel, TViewModel>(IList<TModel> list, Func<TModel, TViewModel> transform) where TViewModel : IViewModel<TModel> {
|
||||
var ret = new ObservableCollection<TViewModel>(list.Select(item => transform(item)));
|
||||
|
||||
ret.CollectionChanged += (sender, e) => {
|
||||
var collection = (ObservableCollection<TViewModel>)sender;
|
||||
switch (e.Action) {
|
||||
case NotifyCollectionChangedAction.Reset:
|
||||
list.Clear();
|
||||
foreach (TViewModel item in collection)
|
||||
list.Add(item.Model);
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
for (int i = 0; i < e.NewItems.Count; i++)
|
||||
list.Insert(e.NewStartingIndex + i, ((TViewModel)e.NewItems[i]).Model);
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
for (int i = 0; i < e.OldItems.Count; i++)
|
||||
list.RemoveAt(e.OldStartingIndex);
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Move:
|
||||
list.RemoveAt(e.OldStartingIndex);
|
||||
list.Insert(e.NewStartingIndex, ((TViewModel)e.NewItems[0]).Model);
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Replace:
|
||||
list[e.NewStartingIndex] = ((TViewModel)e.NewItems[0]).Model;
|
||||
break;
|
||||
}
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ConfuserEx.ViewModel {
|
||||
public class ViewModelBase : INotifyPropertyChanged {
|
||||
// http://stackoverflow.com/a/1316417/462805
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
protected virtual void OnPropertyChanged(string property) {
|
||||
if (PropertyChanged != null)
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(property));
|
||||
}
|
||||
|
||||
protected bool SetProperty<T>(ref T field, T value, string property) {
|
||||
if (!EqualityComparer<T>.Default.Equals(field, value)) {
|
||||
field = value;
|
||||
OnPropertyChanged(property);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected bool SetProperty<T>(bool changed, Action<T> setter, T value, string property) {
|
||||
if (changed) {
|
||||
setter(value);
|
||||
OnPropertyChanged(property);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="Views\ProjectTabView.xaml" />
|
||||
<ResourceDictionary Source="Views\SettingsTabView.xaml" />
|
||||
<ResourceDictionary Source="Views\ProtectTabView.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
|
@ -0,0 +1,46 @@
|
|||
<Window x:Class="ConfuserEx.Views.ProjectModuleView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:ConfuserEx"
|
||||
Title="{Binding Path, StringFormat=Edit module \'{0}\'...}" Style="{StaticResource DarkWindow}"
|
||||
SizeToContent="WidthAndHeight" ShowInTaskbar="False" ResizeMode="NoResize">
|
||||
<Grid Margin="5">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="36px" />
|
||||
<RowDefinition Height="36px" />
|
||||
<RowDefinition Height="36px" />
|
||||
<RowDefinition Height="36px" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="150px" />
|
||||
<ColumnDefinition Width="250px" />
|
||||
<ColumnDefinition Width="35px" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="Assembly Path : " Grid.Row="0" Grid.Column="0" HorizontalContentAlignment="Right"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Margin="5" VerticalContentAlignment="Center"
|
||||
Text="{Binding Path, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
local:FileDragDrop.Command="{x:Static local:FileDragDrop.FileCmd}" />
|
||||
|
||||
<Label Content="SN Key Path : " Grid.Row="1" Grid.Column="0" HorizontalContentAlignment="Right"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox x:Name="PathBox" Grid.Row="1" Grid.Column="1" Margin="5" VerticalContentAlignment="Center"
|
||||
TextChanged="PathBox_TextChanged"
|
||||
Text="{Binding SNKeyPath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
local:FileDragDrop.Command="{x:Static local:FileDragDrop.FileCmd}" />
|
||||
<Button Grid.Row="1" Grid.Column="2" Margin="5" VerticalAlignment="Center" Height="26" Click="ChooseSNKey">
|
||||
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="" Height="10px"
|
||||
TextOptions.TextRenderingMode="GrayScale" />
|
||||
</Button>
|
||||
|
||||
<Label Content="SN Key Password : " Grid.Row="2" Grid.Column="0" HorizontalContentAlignment="Right"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox x:Name="PwdBox" Grid.Row="2" Grid.Column="1" Margin="5" Grid.ColumnSpan="2"
|
||||
VerticalContentAlignment="Center"
|
||||
Text="{Binding SNKeyPassword, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
|
||||
<Button Grid.Row="3" Grid.ColumnSpan="3" HorizontalAlignment="Right" Content="Done"
|
||||
Width="70" Margin="5" Click="Done" />
|
||||
</Grid>
|
||||
</Window>
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using ConfuserEx.ViewModel;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
|
||||
namespace ConfuserEx.Views {
|
||||
public partial class ProjectModuleView : Window {
|
||||
private readonly ProjectModuleVM module;
|
||||
|
||||
public ProjectModuleView(ProjectModuleVM module) {
|
||||
InitializeComponent();
|
||||
this.module = module;
|
||||
DataContext = module;
|
||||
PwdBox.IsEnabled = !string.IsNullOrEmpty(PathBox.Text);
|
||||
}
|
||||
|
||||
private void Done(object sender, RoutedEventArgs e) {
|
||||
DialogResult = true;
|
||||
}
|
||||
|
||||
private void PathBox_TextChanged(object sender, TextChangedEventArgs e) {
|
||||
PwdBox.IsEnabled = !string.IsNullOrEmpty(PathBox.Text);
|
||||
}
|
||||
|
||||
private void ChooseSNKey(object sender, RoutedEventArgs e) {
|
||||
var ofd = new VistaOpenFileDialog();
|
||||
ofd.Filter = "Supported Key Files (*.snk, *.pfx)|*.snk;*.pfx|All Files (*.*)|*.*";
|
||||
if (ofd.ShowDialog() ?? false) {
|
||||
module.SNKeyPath = ofd.FileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<Window x:Class="ConfuserEx.Views.ProjectRuleView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:ConfuserEx"
|
||||
xmlns:core="clr-namespace:Confuser.Core;assembly=Confuser.Core"
|
||||
xmlns:proj="clr-namespace:Confuser.Core.Project;assembly=Confuser.Core"
|
||||
Title="Edit rule..." Height="600" Width="400" x:Name="View"
|
||||
Style="{StaticResource DarkWindow}" ShowInTaskbar="False" ResizeMode="NoResize">
|
||||
<Grid Margin="5">
|
||||
<Grid.Resources>
|
||||
<local:ComponentConverter x:Key="ProtConverter"
|
||||
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
|
||||
PresentationOptions:Freeze="True"
|
||||
Components="{Binding Project.Protections}" />
|
||||
</Grid.Resources>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="36px" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="25px" />
|
||||
<RowDefinition Height="36px" />
|
||||
<RowDefinition Height="36px" />
|
||||
<RowDefinition Height="25px" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="40px" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label Grid.Row="0" Grid.ColumnSpan="2" Content="Pattern:" VerticalAlignment="Center"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBox x:Name="pattern" Grid.Row="1" Grid.ColumnSpan="2"
|
||||
Text="{Binding Pattern, UpdateSourceTrigger=PropertyChanged}" FontFamily="Consolas" Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<Image x:Name="errorImg" Grid.Row="1" Grid.ColumnSpan="2" Source="{StaticResource Error}"
|
||||
Width="16px" Height="16px" ToolTip="{Binding ExpressionError}" Margin="0,0,10,0"
|
||||
Visibility="Hidden" HorizontalAlignment="Right" />
|
||||
|
||||
<DockPanel Grid.Row="2" Grid.ColumnSpan="2" LastChildFill="False">
|
||||
<Label DockPanel.Dock="Left" Content="Preset : " VerticalAlignment="Center" />
|
||||
<ComboBox DockPanel.Dock="Left" SelectedItem="{Binding Preset, UpdateSourceTrigger=PropertyChanged}"
|
||||
Margin="5" Width="100" VerticalAlignment="Center"
|
||||
ItemsSource="{local:EnumValues {x:Type core:ProtectionPreset}}" />
|
||||
<CheckBox DockPanel.Dock="Right" Content="Inherit protections"
|
||||
IsChecked="{Binding Inherit}" Margin="5" VerticalAlignment="Center" />
|
||||
</DockPanel>
|
||||
|
||||
<Label Grid.Row="3" Content="Protections:" VerticalAlignment="Center"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<ListBox x:Name="prots" Grid.Row="4" Margin="5"
|
||||
ItemsSource="{Binding Protections}" Grid.IsSharedSizeScope="True">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition SharedSizeGroup="Action" />
|
||||
<ColumnDefinition Width="10px" />
|
||||
<ColumnDefinition SharedSizeGroup="Protection" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ComboBox Grid.Column="0" Width="80" SelectedItem="{Binding Action}" IsEnabled="True"
|
||||
ItemsSource="{local:EnumValues {x:Type proj:SettingItemAction}}" />
|
||||
<local:CompComboBox Grid.Column="2" Width="150"
|
||||
Components="{Binding Project.Protections, ElementName=View}"
|
||||
SelectedComponent="{Binding Id, Converter={StaticResource ProtConverter}, Mode=TwoWay}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<DockPanel Grid.Row="4" Grid.Column="1" LastChildFill="False">
|
||||
<Button Height="26" Margin="5" DockPanel.Dock="Top" x:Name="AddBtn">
|
||||
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="" Height="12px"
|
||||
TextOptions.TextRenderingMode="GrayScale" />
|
||||
</Button>
|
||||
<Button Height="26" Margin="5" DockPanel.Dock="Top" x:Name="RemoveBtn">
|
||||
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="" Height="12px"
|
||||
TextOptions.TextRenderingMode="GrayScale" />
|
||||
</Button>
|
||||
</DockPanel>
|
||||
|
||||
<Button Grid.Row="5" Grid.ColumnSpan="2" HorizontalAlignment="Right"
|
||||
Margin="5" Width="70" Content="Done" Click="Done" />
|
||||
</Grid>
|
||||
</Window>
|
|
@ -0,0 +1,70 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using Confuser.Core;
|
||||
using Confuser.Core.Project;
|
||||
using ConfuserEx.ViewModel;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
|
||||
namespace ConfuserEx.Views {
|
||||
public partial class ProjectRuleView : Window {
|
||||
private readonly ProjectVM proj;
|
||||
private readonly ProjectRuleVM rule;
|
||||
|
||||
public ProjectRuleView(ProjectVM proj, ProjectRuleVM rule) {
|
||||
InitializeComponent();
|
||||
this.rule = rule;
|
||||
this.proj = proj;
|
||||
DataContext = rule;
|
||||
|
||||
rule.PropertyChanged += OnPropertyChanged;
|
||||
CheckValidity();
|
||||
}
|
||||
|
||||
public ProjectVM Project {
|
||||
get { return proj; }
|
||||
}
|
||||
|
||||
public override void OnApplyTemplate() {
|
||||
base.OnApplyTemplate();
|
||||
|
||||
AddBtn.Command = new RelayCommand(() => {
|
||||
var prot = new ProjectSettingVM<Protection>(proj, new SettingItem<Protection>());
|
||||
prot.Id = proj.Protections[0].Id;
|
||||
rule.Protections.Add(prot);
|
||||
});
|
||||
RemoveBtn.Command = new RelayCommand(() => {
|
||||
int selIndex = prots.SelectedIndex;
|
||||
Debug.Assert(selIndex != -1);
|
||||
|
||||
rule.Protections.RemoveAt(prots.SelectedIndex);
|
||||
prots.SelectedIndex = selIndex >= rule.Protections.Count ? rule.Protections.Count - 1 : selIndex;
|
||||
}, () => prots.SelectedIndex != -1);
|
||||
}
|
||||
|
||||
public void Cleanup() {
|
||||
rule.PropertyChanged -= OnPropertyChanged;
|
||||
}
|
||||
|
||||
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) {
|
||||
if (e.PropertyName == "Expression")
|
||||
CheckValidity();
|
||||
}
|
||||
|
||||
private void CheckValidity() {
|
||||
if (rule.Expression == null) {
|
||||
pattern.BorderBrush = Brushes.Red;
|
||||
errorImg.Visibility = Visibility.Visible;
|
||||
} else {
|
||||
pattern.ClearValue(BorderBrushProperty);
|
||||
errorImg.Visibility = Visibility.Hidden;
|
||||
}
|
||||
}
|
||||
|
||||
private void Done(object sender, RoutedEventArgs e) {
|
||||
DialogResult = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<Window x:Class="ConfuserEx.Views.ProjectTabAdvancedView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:ConfuserEx"
|
||||
Title="Advanced Settings..." Height="400" Width="600"
|
||||
Style="{StaticResource DarkWindow}" ShowInTaskbar="False" ResizeMode="NoResize">
|
||||
<Grid Margin="5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="36px" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="36px" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="36px" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="0" Content="Probe Paths :" Margin="5" VerticalAlignment="Center" />
|
||||
<ListBox Grid.Row="1" Grid.Column="0" Margin="5" x:Name="ProbePaths" ItemsSource="{Binding ProbePaths}"
|
||||
local:FileDragDrop.Command="{x:Static local:FileDragDrop.DirectoryCmd}"
|
||||
ScrollViewer.CanContentScroll="False" />
|
||||
<StackPanel Grid.Row="1" Grid.Column="1">
|
||||
<Button Height="26" Margin="5" DockPanel.Dock="Top" x:Name="AddProbe">
|
||||
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="" Height="12px"
|
||||
TextOptions.TextRenderingMode="GrayScale" />
|
||||
</Button>
|
||||
<Button Height="26" Margin="5" DockPanel.Dock="Top" x:Name="RemoveProbe">
|
||||
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="" Height="12px"
|
||||
TextOptions.TextRenderingMode="GrayScale" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="2" Content="Plugins :" Margin="5" VerticalAlignment="Center" />
|
||||
<ListBox Grid.Row="1" Grid.Column="2" Margin="5" x:Name="PluginPaths" ItemsSource="{Binding Plugins}"
|
||||
local:FileDragDrop.Command="{x:Static local:FileDragDrop.FileCmd}"
|
||||
ScrollViewer.CanContentScroll="False" />
|
||||
<StackPanel Grid.Row="1" Grid.Column="3">
|
||||
<Button Height="26" Margin="5" DockPanel.Dock="Top" x:Name="AddPlugin">
|
||||
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="" Height="12px"
|
||||
TextOptions.TextRenderingMode="GrayScale" />
|
||||
</Button>
|
||||
<Button Height="26" Margin="5" DockPanel.Dock="Top" x:Name="RemovePlugin">
|
||||
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="" Height="12px"
|
||||
TextOptions.TextRenderingMode="GrayScale" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using ConfuserEx.ViewModel;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
|
||||
namespace ConfuserEx.Views {
|
||||
public partial class ProjectTabAdvancedView : Window {
|
||||
private readonly ProjectVM project;
|
||||
|
||||
public ProjectTabAdvancedView(ProjectVM project) {
|
||||
InitializeComponent();
|
||||
this.project = project;
|
||||
DataContext = project;
|
||||
}
|
||||
|
||||
public override void OnApplyTemplate() {
|
||||
base.OnApplyTemplate();
|
||||
|
||||
AddPlugin.Command = new RelayCommand(() => {
|
||||
var ofd = new VistaOpenFileDialog();
|
||||
ofd.Filter = ".NET assemblies (*.exe, *.dll)|*.exe;*.dll|All Files (*.*)|*.*";
|
||||
ofd.Multiselect = true;
|
||||
if (ofd.ShowDialog() ?? false) {
|
||||
foreach (string plugin in ofd.FileNames) {
|
||||
try {
|
||||
ComponentDiscovery.LoadComponents(project.Protections, project.Packers, plugin);
|
||||
project.Plugins.Add(new StringItem(plugin));
|
||||
} catch {
|
||||
MessageBox.Show("Failed to load plugin '" + plugin + "'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
RemovePlugin.Command = new RelayCommand(() => {
|
||||
int selIndex = PluginPaths.SelectedIndex;
|
||||
Debug.Assert(selIndex != -1);
|
||||
|
||||
string plugin = project.Plugins[selIndex].Item;
|
||||
ComponentDiscovery.RemoveComponents(project.Protections, project.Packers, plugin);
|
||||
project.Plugins.RemoveAt(selIndex);
|
||||
|
||||
PluginPaths.SelectedIndex = selIndex >= project.Plugins.Count ? project.Plugins.Count - 1 : selIndex;
|
||||
}, () => PluginPaths.SelectedIndex != -1);
|
||||
|
||||
|
||||
AddProbe.Command = new RelayCommand(() => {
|
||||
var fbd = new VistaFolderBrowserDialog();
|
||||
if (fbd.ShowDialog() ?? false)
|
||||
project.ProbePaths.Add(new StringItem(fbd.SelectedPath));
|
||||
});
|
||||
|
||||
RemoveProbe.Command = new RelayCommand(() => {
|
||||
int selIndex = ProbePaths.SelectedIndex;
|
||||
Debug.Assert(selIndex != -1);
|
||||
project.ProbePaths.RemoveAt(selIndex);
|
||||
ProbePaths.SelectedIndex = selIndex >= project.ProbePaths.Count ? project.ProbePaths.Count - 1 : selIndex;
|
||||
}, () => ProbePaths.SelectedIndex != -1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:ConfuserEx"
|
||||
xmlns:vm="clr-namespace:ConfuserEx.ViewModel">
|
||||
<DataTemplate DataType="{x:Type vm:ProjectTabVM}">
|
||||
<Grid Background="Transparent">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="36px" />
|
||||
<RowDefinition Height="36px" />
|
||||
<RowDefinition Height="36px" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="150px" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="36px" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Content="Base Directory : " Grid.Row="0" Grid.Column="0" HorizontalContentAlignment="Right"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Margin="5" VerticalContentAlignment="Center"
|
||||
Text="{Binding App.Project.BaseDirectory, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
local:FileDragDrop.Command="{x:Static local:FileDragDrop.DirectoryCmd}" />
|
||||
<Button Grid.Row="0" Grid.Column="2" Margin="5" VerticalAlignment="Center" Height="26"
|
||||
Command="{Binding ChooseBaseDir}">
|
||||
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="" Height="10px"
|
||||
TextOptions.TextRenderingMode="GrayScale" />
|
||||
</Button>
|
||||
|
||||
<Label Content="Output Directory : " Grid.Row="1" Grid.Column="0" HorizontalContentAlignment="Right"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Grid.Row="1" Grid.Column="1" Margin="5" VerticalContentAlignment="Center"
|
||||
Text="{Binding App.Project.OutputDirectory, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
local:FileDragDrop.Command="{x:Static local:FileDragDrop.DirectoryCmd}" />
|
||||
<Button Grid.Row="1" Grid.Column="2" Margin="5" VerticalAlignment="Center" Height="26"
|
||||
Command="{Binding ChooseOutputDir}">
|
||||
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="" Height="10px"
|
||||
TextOptions.TextRenderingMode="GrayScale" />
|
||||
</Button>
|
||||
|
||||
<Grid Grid.Row="2" Grid.ColumnSpan="3">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="150px" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Content="Seed : " Grid.Column="0" HorizontalContentAlignment="Right"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Grid.Column="1" Margin="5" VerticalContentAlignment="Center"
|
||||
Text="{Binding App.Project.Seed, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
local:Skin.EmptyPrompt="Leave blank for random seed" />
|
||||
<CheckBox Grid.Column="2" Content="Generate Debug Symbols" VerticalAlignment="Center" Margin="5"
|
||||
IsChecked="{Binding App.Project.Debug, Mode=TwoWay}" />
|
||||
</Grid>
|
||||
|
||||
<ListBox Grid.Row="3" Grid.ColumnSpan="2" Margin="5" local:Skin.EmptyPrompt="Drag input modules here"
|
||||
ItemsSource="{Binding App.Project.Modules}" HorizontalContentAlignment="Stretch"
|
||||
SelectedIndex="{Binding SelectedIndex}" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
Grid.IsSharedSizeScope="True" local:FileDragDrop.Command="{Binding DragDrop}"
|
||||
ScrollViewer.CanContentScroll="False">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type vm:ProjectModuleVM}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Text="{Binding AssemblyName}"
|
||||
TextAlignment="Left" Margin="0,0,5,0" TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding Path}"
|
||||
TextAlignment="Right" Margin="5,0,0,0" TextTrimming="CharacterEllipsis" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<DockPanel Grid.Row="3" Grid.Column="2" LastChildFill="False">
|
||||
<Button Height="26" Margin="5" DockPanel.Dock="Top" Command="{Binding Add}">
|
||||
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="" Height="12px"
|
||||
TextOptions.TextRenderingMode="GrayScale" />
|
||||
</Button>
|
||||
<Button Height="26" Margin="5" DockPanel.Dock="Top" Command="{Binding Remove}">
|
||||
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="" Height="12px"
|
||||
TextOptions.TextRenderingMode="GrayScale" />
|
||||
</Button>
|
||||
<Button Height="26" Margin="5" DockPanel.Dock="Top" Command="{Binding Edit}">
|
||||
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="" Height="12px"
|
||||
TextOptions.TextRenderingMode="GrayScale" />
|
||||
</Button>
|
||||
<Button Height="26" Margin="5" DockPanel.Dock="Bottom" Command="{Binding Advanced}">
|
||||
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="" Height="12px"
|
||||
TextOptions.TextRenderingMode="GrayScale" />
|
||||
</Button>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ResourceDictionary>
|
|
@ -0,0 +1,37 @@
|
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:ConfuserEx"
|
||||
xmlns:vm="clr-namespace:ConfuserEx.ViewModel">
|
||||
<DataTemplate DataType="{x:Type vm:ProtectTabVM}">
|
||||
<Grid Background="Transparent">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="40px" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="100px" />
|
||||
<ColumnDefinition Width="100px" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<ProgressBar x:Name="progress" Grid.Row="0" Grid.Column="0" Margin="5"
|
||||
Value="{Binding Progress}" Minimum="0" Maximum="1" />
|
||||
<Button Grid.Row="0" Grid.Column="1" Margin="5" Content="Protect!" Command="{Binding ProtectCmd}" />
|
||||
<Button Grid.Row="0" Grid.Column="2" Margin="5" Content="Cancel" Command="{Binding CancelCmd}" />
|
||||
<RichTextBox x:Name="log" Grid.Row="1" Grid.ColumnSpan="3" Margin="5" FontFamily="Consolas"
|
||||
IsReadOnly="True" IsReadOnlyCaretVisible="True" local:Skin.RTBDocument="{Binding LogDocument}"
|
||||
VerticalScrollBarVisibility="Visible" />
|
||||
</Grid>
|
||||
<DataTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding Progress}" Value="{x:Null}">
|
||||
<Setter TargetName="progress" Property="IsIndeterminate" Value="True" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Result}" Value="True">
|
||||
<Setter TargetName="log" Property="BorderBrush" Value="#40ff40" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Result}" Value="False">
|
||||
<Setter TargetName="log" Property="BorderBrush" Value="#ff4040" />
|
||||
</DataTrigger>
|
||||
</DataTemplate.Triggers>
|
||||
</DataTemplate>
|
||||
</ResourceDictionary>
|
|
@ -0,0 +1,83 @@
|
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:ConfuserEx"
|
||||
xmlns:vm="clr-namespace:ConfuserEx.ViewModel">
|
||||
<DataTemplate DataType="{x:Type vm:SettingsTabVM}">
|
||||
<Grid Background="Transparent">
|
||||
<Grid.Resources>
|
||||
<local:ComponentConverter x:Key="PackerConverter" x:Shared="False"
|
||||
Components="{Binding App.Project.Packers}" />
|
||||
</Grid.Resources>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="40px" />
|
||||
<RowDefinition Height="40px" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="200px" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="36px" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel Grid.Row="0" Grid.ColumnSpan="3" Orientation="Horizontal" Margin="5">
|
||||
<CheckBox Content="Packer : " VerticalAlignment="Center" HorizontalAlignment="Right"
|
||||
Margin="5,0,0,0" IsChecked="{Binding HasPacker}" />
|
||||
<local:CompComboBox Width="300" Components="{Binding App.Project.Packers}" Margin="5,0,0,0"
|
||||
IsEnabled="{Binding HasPacker}" HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
SelectedComponent="{Binding App.Project.Packer.Id, Converter={StaticResource PackerConverter}, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="Modules : " VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left" Margin="5,0,0,0" />
|
||||
<Label Grid.Row="1" Grid.Column="1" Content="Rules : " VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left" Margin="5,0,0,0" />
|
||||
|
||||
<ListBox Grid.Row="2" Grid.Column="0" Margin="5" ItemsSource="{Binding ModulesView}"
|
||||
SelectedItem="{Binding SelectedList, Mode=OneWayToSource}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock>
|
||||
<TextBlock.Text>
|
||||
<PriorityBinding>
|
||||
<Binding Path="SimpleName" />
|
||||
<Binding Source="<Global settings>" />
|
||||
</PriorityBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<ListBox Grid.Row="2" Grid.Column="1" Margin="5" FontFamily="Consolas"
|
||||
ItemsSource="{Binding SelectedList.Rules}"
|
||||
SelectedIndex="{Binding SelectedRuleIndex, Mode=TwoWay}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock x:Name="txt" Text="{Binding Pattern}" />
|
||||
<DataTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding Expression}" Value="{x:Null}">
|
||||
<Setter TargetName="txt" Property="Foreground" Value="Red" />
|
||||
</DataTrigger>
|
||||
</DataTemplate.Triggers>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<DockPanel Grid.Row="2" Grid.Column="2" LastChildFill="False">
|
||||
<Button Height="26" Margin="5" DockPanel.Dock="Top" Command="{Binding Add}">
|
||||
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="" Height="12px"
|
||||
TextOptions.TextRenderingMode="GrayScale" />
|
||||
</Button>
|
||||
<Button Height="26" Margin="5" DockPanel.Dock="Top" Command="{Binding Remove}">
|
||||
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="" Height="12px"
|
||||
TextOptions.TextRenderingMode="GrayScale" />
|
||||
</Button>
|
||||
<Button Height="26" Margin="5" DockPanel.Dock="Top" Command="{Binding Edit}">
|
||||
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="" Height="12px"
|
||||
TextOptions.TextRenderingMode="GrayScale" />
|
||||
</Button>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ResourceDictionary>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Practices.ServiceLocation" publicKeyToken="31BF3856AD364E35"
|
||||
culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.2.0.0" newVersion="1.2.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<packages>
|
||||
<package id="CommonServiceLocator" version="1.2" targetFramework="net40" />
|
||||
<package id="MvvmLightLibs" version="4.3.31.1" targetFramework="net40" />
|
||||
<package id="TaskParallelLibrary" version="1.0.2856.0" targetFramework="net40" />
|
||||
</packages>
|
|
@ -24,7 +24,7 @@ Usage
|
|||
`Confuser.CLI <path to project file>`
|
||||
|
||||
The project file is a ConfuserEx Project (*.crproj).
|
||||
The format of project file can be found in ProjectFormat.md
|
||||
The format of project file can be found in docs\ProjectFormat.md
|
||||
|
||||
Bug Report
|
||||
----------
|
||||
|
|