为什么我的 C# AppDomain 前一秒还正常,下一秒就抛出异常?

发布于 2024-09-06 11:04:23 字数 1825 浏览 6 评论 0原文

我有一个 AppDomain,用于将模块加载到沙箱中:

class PluginLoader
{
    public static AppDomain PluginSandbox;

    static PluginLoader()
    {
        AppDomainSetup ads = new AppDomainSetup();
        ads.ApplicationName = "Plugin Modules";
        PermissionSet trustedLoadFromRemoteSourceGrantSet = 
                     new PermissionSet(PermissionState.Unrestricted);
        PluginSandbox = 
                     AppDomain.CreateDomain("Plugin App Domain", 
                     null, ads, trustedLoadFromRemoteSourceGrantSet);
     }

然后,我将提取我需要的 DLL 并创建一个对象实例:

     public IPlugin FindPlugin(string pluginName)
     {
          ObjectHandle handle = 
                   PluginSandbox.CreateInstance(pluginName, 
                       "Plugins." + pluginName);
                IPlugin ip = (IPlugin)handle.Unwrap();
                return ip;
     }

我运行了几次,没有出现任何问题。在沙盒中获取各种对象的实例,没有任何问题。

稍后在代码中,在另一种方法中,我需要找到程序集来获取嵌入式资源(在数据文件中编译,带有 ManifestResource)。所以我打电话:

     Assembly [] ar = PluginSandbox.GetAssemblies();

然后错误被抛出:

A first chance exception of type 'System.IO.FileNotFoundException' 
occurred in PluginRunner.dll.

Additional information: Could not load file or assembly '10wl4qso,
Version=1.0.3826.25439, culture info=neutral, PublicKeyToken=null'
or one of its dependencies.  The system cannot find the file specified.

我并不感到惊讶。 “10wl4qso”不是程序集、dll 或类似名称的名称。事实上,每次运行似乎都是伪随机的。另外,GetAssemblies 的额外乐趣甚至没有记录为抛出此异常。

现在,我可以在获得初始对象后立即调用 GetAssemblies,一切都很顺利。但几秒钟后,我用另一种方法得到了这个。由于处于远程状态,PluginSandbox 在调试器中根本没有任何有用的信息。

我在 AppDomain 上捕获 UnhandledException 和 DomainUnload,但两者都没有被触发。

为什么我的 AppDomain 突然不知道它的程序集? 这些垃圾数据从哪里来? 我该怎么做才能防止这两种情况发生?

I have an AppDomain that I'm using to load modules into a sandbox with:

class PluginLoader
{
    public static AppDomain PluginSandbox;

    static PluginLoader()
    {
        AppDomainSetup ads = new AppDomainSetup();
        ads.ApplicationName = "Plugin Modules";
        PermissionSet trustedLoadFromRemoteSourceGrantSet = 
                     new PermissionSet(PermissionState.Unrestricted);
        PluginSandbox = 
                     AppDomain.CreateDomain("Plugin App Domain", 
                     null, ads, trustedLoadFromRemoteSourceGrantSet);
     }

And then later on, I'll pull in the DLL I need and create an object instance:

     public IPlugin FindPlugin(string pluginName)
     {
          ObjectHandle handle = 
                   PluginSandbox.CreateInstance(pluginName, 
                       "Plugins." + pluginName);
                IPlugin ip = (IPlugin)handle.Unwrap();
                return ip;
     }

I run through this a couple of times with no problems. Getting instances of various objects out in the Sandbox, with no problems.

A bit later in the code, in another method, I need to find the assembly to get an embedded resource (a compiled in data file, with ManifestResource). So I call:

     Assembly [] ar = PluginSandbox.GetAssemblies();

And the error gets thrown:

A first chance exception of type 'System.IO.FileNotFoundException' 
occurred in PluginRunner.dll.

Additional information: Could not load file or assembly '10wl4qso,
Version=1.0.3826.25439, culture info=neutral, PublicKeyToken=null'
or one of its dependencies.  The system cannot find the file specified.

I'm not surprised. '10wl4qso' isn't the name of the assembly, the dll, or anything like it. In fact it seems pseudo-random for each run. Plus the added fun of GetAssemblies isn't even documented to throw this exception.

Now I can call GetAssemblies right after I get the initial object just fine, and everything is peachy. But a couple of seconds later, in a different method I get this. Being remoted, PluginSandbox has no useful information at all in the debugger.

I'm catching UnhandledException and DomainUnload on the AppDomain and neither is being triggered.

Why does my AppDomain suddenly not know about its assemblies?
Where's that garbage data coming from?
What can I do to prevent either/both of these from happening?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

惜醉颜 2024-09-13 11:04:23

您看到的这个奇怪的命名程序集可能是由 XmlSerializer 生成的。 XML序列化器将输出动态程序集,以便能够快速序列化和反序列化特定类型。检查代码中是否使用了 XmlSerializer,将其注释掉,然后查看问题是否再次出现。

This weird named assembly you're seeing is probably generated by XmlSerializer. The XML serializer will output a dynamic assembly to be able to quickly serialize and deserialize a specific type quickly. Check your code for uses of XmlSerializer, comment them out and see if the problem occurs again.

月竹挽风 2024-09-13 11:04:23

不知道对你有没有帮助...
尝试覆盖 IPlugin 上的 InitializeLifeTimeService。您的 IPlugin 实现应该首先继承自 MarshalByRefObject。

public class PluginSample : MarshalByRefObject, IPlugin
{

   public overrides object InitializeLifetimeService()
   {
       return null; //Return null to infinite object remote life.
   }
  //...implementation

}

看看这篇文章:
跨 AppDomain 引发事件时出现 RemotingException

I don't know if it helps you...
Try to override InitializeLifeTimeService on IPlugin. Your IPlugin implementation should inherits from MarshalByRefObject first.

public class PluginSample : MarshalByRefObject, IPlugin
{

   public overrides object InitializeLifetimeService()
   {
       return null; //Return null to infinite object remote life.
   }
  //...implementation

}

Take a look at this article:
RemotingException when raising events across AppDomains

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文