Skip to content
This repository has been archived by the owner on Feb 3, 2024. It is now read-only.

Commit

Permalink
make a new extractor instead of garbage one
Browse files Browse the repository at this point in the history
  • Loading branch information
zzzz465 committed Sep 11, 2020
1 parent bbeb58d commit d8b4956
Show file tree
Hide file tree
Showing 20 changed files with 659 additions and 81,138 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30002.166
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "typeinfo_extractor", "typeinfo_extractor.csproj", "{D02388B3-928D-4D2E-96C8-7EAFF5E5A3B9}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "extractor", "extractor\extractor.csproj", "{A155D393-A36B-4775-9539-DDEE9E977F1A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D02388B3-928D-4D2E-96C8-7EAFF5E5A3B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D02388B3-928D-4D2E-96C8-7EAFF5E5A3B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D02388B3-928D-4D2E-96C8-7EAFF5E5A3B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D02388B3-928D-4D2E-96C8-7EAFF5E5A3B9}.Release|Any CPU.Build.0 = Release|Any CPU
{A155D393-A36B-4775-9539-DDEE9E977F1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A155D393-A36B-4775-9539-DDEE9E977F1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A155D393-A36B-4775-9539-DDEE9E977F1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A155D393-A36B-4775-9539-DDEE9E977F1A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7637B6CF-40B4-4649-8740-98B29DB0D57B}
SolutionGuid = {3E885762-0CDB-4FD8-8EDC-9D8CEC810B08}
EndGlobalSection
EndGlobal
6 changes: 6 additions & 0 deletions extractor/extractor/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>
103 changes: 103 additions & 0 deletions extractor/extractor/AssemblyLoader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Runtime.Remoting.Lifetime;
using System.Text;
using System.Threading.Tasks;

namespace extractor
{
public static class AssemblyLoader
{
static Dictionary<AssemblyName, Assembly> cache = new Dictionary<AssemblyName, Assembly>();

static string SanitizePath(string path)
{
return path.Trim((char)7234);
}

static AssemblyLoader()
{
// AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += ResolveHandler;
AppDomain.CurrentDomain.AssemblyResolve += ResolveHandler;
}

static Assembly ResolveHandler(object sender, ResolveEventArgs e)
{
// 1) find on cache
var assemName = new AssemblyName(e.Name);
if (cache.TryGetValue(assemName, out var result))
return result;

// 2) try to find on current appdomain
// var assem = Assembly.ReflectionOnlyLoad(e.Name);
var name = e.Name.Split(',')[0].Trim();
var assem = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(assembly => assembly.GetName().Name == name);
if (assem != null)
return assem;

// 3) try to load
var assem2 = Assembly.Load(e.Name); // it is now registered to appdomain, so we don't have to store it.
return assem2;

// unused
if (assem != null)
{
cache.Add(assem.GetName(), assem);
return assem;
}
else
return null;
}

public static IEnumerable<Assembly> Load(IEnumerable<string> _paths)
{
var paths = _paths.Select(path => SanitizePath(path));
var list = new List<Assembly>();
foreach (var path in paths)
{
if (Directory.Exists(path))
{
var files = Directory.GetFiles(path, "*.dll");
foreach (var file in files)
{
try
{
list.Add(_Load(file));
}
catch (Exception ex)
{
Log.Warn(ex.ToString());
}
}
}
else if (File.Exists(path))
{
try
{
list.Add(_Load(path));
}
catch (Exception ex)
{
Log.Warn(ex.ToString());
}
}
}

return list;
}

static Assembly _Load(string path)
{
// var raw = File.ReadAllBytes(path);
var assem = Assembly.UnsafeLoadFrom(path);
// var assem = Assembly.ReflectionOnlyLoadFrom(path);
cache.Add(assem.GetName(), assem);

return assem;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using System.Threading.Tasks;

namespace Program
namespace extractor
{
public enum CompletionItemKind
{
Expand Down Expand Up @@ -39,7 +41,8 @@ public class defInfo : defNodeInfo
// public defNodeInfo[] children { get; set; }
}

public class Util {
public class Util
{
public static string GetTypeIdentifier(Type T)
{
return $"{T.Namespace}.{T.Name}";
Expand All @@ -51,17 +54,6 @@ public static string GetListTypeIdentifier(Type type)
return $"System.Collections.Generic.List<{name}>";
}
}
/*
public struct TypeIdentifier
{
public string namespaceName { get; set; }
public string className { get; set; }
public override string ToString()
{
return $"{namespaceName}.{className}";
}
}
*/

public class TypeInfo
{
Expand Down Expand Up @@ -113,7 +105,7 @@ public struct def
{
public string name;
}

public struct Enumerable
{
public string genericType, enumerableType;
Expand Down
60 changes: 60 additions & 0 deletions extractor/extractor/Log.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using log4net;
using log4net.Appender;
using log4net.Core;
using log4net.Layout;
using log4net.Repository.Hierarchy;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace extractor
{
public static class Log
{
static ILog log = LogManager.GetLogger("Extractor");
// https://stackoverflow.com/questions/16336917/can-you-configure-log4net-in-code-instead-of-using-a-config-file
public static void SetOutput(string path)
{
var hierarchy = (Hierarchy)LogManager.GetRepository();

var appender = new RollingFileAppender();
appender.Name = "FileAppender";
appender.File = path;
appender.AppendToFile = false;
appender.StaticLogFileName = true;

var layout = new PatternLayout();
layout.ConversionPattern = "%d %c [%p]: %m%n";
layout.ActivateOptions();

appender.Layout = layout;
appender.ActivateOptions();
hierarchy.Root.AddAppender(appender);

hierarchy.Root.Level = Level.Info;
hierarchy.Configured = true;
}

public static void Info(string message)
{
log.Info(message);
}

public static void Debug(string message)
{
log.Debug(message);
}

public static void Warn(string message)
{
log.Warn(message);
}

public static void Error(string message)
{
log.Error(message);
}
}
}
105 changes: 105 additions & 0 deletions extractor/extractor/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using CommandLine;
using log4net.Appender;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace extractor
{
public enum OutputMode
{
stdout = 0,
stdoutBytes = 1,
file = 2
}

public class ProgramOptions
{
[Option('v', "verbose", Required = false, HelpText = "Set output to verbose messages.")]
public bool Verbose { get; set; }

[Option("OutputMode", Required = true, HelpText = "select extraction ouptut mode, stdout or file")]
public OutputMode outputMode { get; set; }

[Option('o', "out", Required = false, HelpText = "Set output file path")]
public string outputPath { get; set; }

[Option("log", Required = false, HelpText = "Set log output path")]
public string logOutputPath { get; set; }

// [Option("--file", Required = true, Separator = ' ')]
[Value(0, Required = true, HelpText = "dll file/directory to extract data")]
public IEnumerable<string> targetFiles { get; set; }
}

class Program
{
static void Main(string[] args)
{
var commandline = Parser.Default.ParseArguments<ProgramOptions>(args);

commandline.WithParsed(option =>
{
if (option.logOutputPath != null)
{
Log.SetOutput(option.logOutputPath);
}
try
{
Log.Info("Extracting data from");
foreach (var file in option.targetFiles)
Log.Info(file);
var assemblies = AssemblyLoader.Load(option.targetFiles);
Log.Info("extracting data...");
var parseResult = Extractor.parse(assemblies);
Log.Info($"Completed extracting data, data count: {parseResult.Count}");

var result = new Dictionary<string, TypeInfo>();
foreach(var pair in parseResult)
{
var typeInfo = pair.Value;
if (result.ContainsKey(typeInfo.typeIdentifier))
continue;
result.Add(typeInfo.typeIdentifier, typeInfo);
}

var serializerSetting = new JsonSerializerSettings();
serializerSetting.Formatting = Formatting.None;
serializerSetting.NullValueHandling = NullValueHandling.Ignore;
serializerSetting.DefaultValueHandling = DefaultValueHandling.Ignore;

var serializedObject = JsonConvert.SerializeObject(result.Select(d => d.Value), serializerSetting);
Log.Info($"serialized Object string length: {serializedObject}");

switch(option.outputMode)
{
case OutputMode.stdout:
Console.WriteLine(serializedObject);
break;

case OutputMode.stdoutBytes:
var utf8bytes = UTF8Encoding.UTF8.GetBytes(serializedObject);
Log.Info($"serialized text bytes length: {utf8bytes.Length}");
Console.OpenStandardOutput().Write(utf8bytes, 0, utf8bytes.Length);
break;

case OutputMode.file:
var path = option.outputPath;
File.WriteAllText(path, serializedObject);
break;
}
Log.Info("Extraction completed!");
}
catch (Exception ex)
{
Log.Error(ex.ToString());
}

});
}
}
}
Loading

0 comments on commit d8b4956

Please sign in to comment.