3

私は、Crypto Obfuscator を使用して複数の DLL を 1 つの DLL に埋め込むプロジェクトに取り組んでいます。次に、DLL が別のプロジェクトの独自のアプリ ドメインに動的に読み込まれます。埋め込まれた DLL のほとんどは正しく動作しているようです。ただし、メインの DLL クラスが継承するクラスを含む埋め込み DLL は、正しくロードされません。これを機能させる唯一の方法は、DLL をディレクトリに残すことです (これでは、DLL を埋め込む目的が無効になります)。

例えば:

MyLibrary、MyLibrary2、MyProgram、および MyInterfaces の 4 つの異なる DLL があります。

MyLibrary DLL 内の MyClass1クラスは、MyInterfaces DLL 内のインターフェイスClassInterfaceから継承します。

MyLibrary2 DLL 内の MyClass2クラスは、 MyClass1 から継承します。Crypto Obfuscator は、MyLibrary2 DLL 内に MyInterfaces と MyLibrary という DLL を埋め込むために使用されます。

MyProgram DLL 内の MyProgramClassクラスは、 MyInterfaces DLL への参照を持ち、それを使用してMyClass2のインスタンスを動的に作成します。

プログラムを実行すると、MyClass2 のインスタンスを作成しようとすると、アセンブリ MyLibrary が見つからないというメッセージが表示されます。

ファイルまたはアセンブリ 'MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' またはその依存関係の 1 つを読み込めませんでした。システムは、指定されたファイルを見つけることができません。

これを解決する方法はありますか?

MyInterfaces DLL:

namespace MyInterfaces
{
    public interface ClassInterface
    {
        string Get();
    }
}

マイライブラリ DLL:

namespace MyLibrary
{
    public class MyClass : MarshalByRefObject, ClassInterface
    {
        public string Get()
        {
            return "2.0.0.0";
        }
    }
}

MyLibrary2 DLL:

namespace MyLibrary2
{
    public class MyClass2 : MyClass, ClassInterface
    {
        public string Get()
        {
            return base.Get();
        }
    }
}

マイプログラム DLL:

namespace MyProgram
{
    public class MyProgramClass
    {
        public MyProgramClass()
        {
            try
            {
                string typeName = "MyLibrary2.MyClass2";
                string appDomainName = "MyLibrary2";

                ClassInterface c2 = CreateInstance(@"X:\Temp\MyLibrary2.dll", typeName, appDomainName);

                if (c2 == null) return;

                MessageBox.Show(c2.Get());
            }
            catch
            {
                MessageBox.Show(":(");
            }
        }

        private ClassInterface CreateInstance(string filePath, string typeName, string appDomainName)
        {
            try
            {
                AppDomainSetup appDomainSetup = new AppDomainSetup();
                FileInfo fileInfo = new FileInfo(filePath);

                if (!fileInfo.Exists) return null;

                appDomainSetup.PrivateBinPath = string.Format("{0}", fileInfo.Directory.FullName);
                appDomainSetup.PrivateBinPathProbe = "True";

                appDomainSetup.ApplicationBase = fileInfo.Directory.FullName;
                appDomainSetup.ApplicationTrust = AppDomain.CurrentDomain.ApplicationTrust;

                Evidence evidence = new Evidence(AppDomain.CurrentDomain.Evidence);
                AppDomain appDomain = AppDomain.CreateDomain(appDomainName, evidence, appDomainSetup);

                string assemblyName = Path.GetFileNameWithoutExtension(fileInfo.FullName);

                return appDomain.CreateInstanceAndUnwrap(assemblyName, typeName) as ClassInterface;
            }
            catch (Exception e)
            {                
                MessageBox.Show(e.Message);
            }

            return null;
        }
    }
}

更新 1

AssemblyResolve イベントの使用を検討しました。テストアプリケーションに実装して、機能するかどうかを確認しました。AssemblyResolve イベント内にブレークポイントを配置しましたが、ヒットすることはなく、エラーが引き続きスローされます。MyClass2をMyClass1から継承しないように設定すると、ブレークポイントがヒットし、正しく実行されます。

補足として、組み込み DLL を含む DLL で JustDecompile を使用すると、Crypto Obfuscator がこのイベントを DLL のデフォルトの名前空間に設定しているように見えます。

AssemblyResolveイベントを実装するために、次のリンクを使用していました。 第三版.aspx

MyLibrary2 DLL の変更:

namespace MyLibrary2
{
    public class MyClass2 : MyClass, ClassInterface
    {
        static MyClass2()
        {
            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;                
        }

        static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            String resourceName = string.Format("{0}.{1}.dll", "MyLibrary2", new AssemblyName(args.Name).Name);

            using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
            {
                Byte[] assemblyData = new Byte[stream.Length];

                stream.Read(assemblyData, 0, assemblyData.Length);

                return Assembly.Load(assemblyData);
            }
        }

        public string Get()
        {
            return base.Get();
        }
    }
}
4

0 に答える 0