C# 如何避免我们的程序因为动态加载的DLL有缺陷而崩溃
我有一个别人写的dll,它有很多缺陷。假设此DLL中只定义了一个类。我需要导入这个DLL并创建这个类的实例。 DLL代码可能如下所示:C# 如何避免我们的程序因为动态加载的DLL有缺陷而崩溃,c#,dll,appdomain,C#,Dll,Appdomain,我有一个别人写的dll,它有很多缺陷。假设此DLL中只定义了一个类。我需要导入这个DLL并创建这个类的实例。 DLL代码可能如下所示: [Serializable()] public class makeExceptionClass { public bool isStringNormalized(string aString) { // A null check should be performed
[Serializable()]
public class makeExceptionClass
{
public bool isStringNormalized(string aString)
{
// A null check should be performed
return aString.IsNormalized();
}
}
class Program
{
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
static void Main(string[] args)
{
string typeOfLoading = args[0];
string crash = args[1];
// Load the DLL
if (typeOfLoading.Equals("direct") == true)
{
Console.WriteLine("Loading directly a DLL");
Assembly anAssembly = Assembly.Load("unloadableDLL"); // Directly load the DLL
unloadableDLL.makeExceptionClass anObject = (unloadableDLL.makeExceptionClass)anAssembly.CreateInstance("unloadableDLL.makeExceptionClass");
if (crash.Equals("crash") == true)
{
bool test = anObject.isStringNormalized(null);
}
else
{
bool test = anObject.isStringNormalized("test");
}
}
else if (typeOfLoading.Equals("indirect") == true)
{
Console.WriteLine("Loading indirectly a DLL");
AppDomain anAppDomain = AppDomain.CreateDomain("RemoteLoaderDomain"); // Assume it does not fail;
Type t = typeof(unloadableDLL.makeExceptionClass);
unloadableDLL.makeExceptionClass anObject = (unloadableDLL.makeExceptionClass)anAppDomain.CreateInstanceAndUnwrap("unloadableDLL", t.FullName);
if (crash.Equals("crash") == true)
{
bool test = anObject.isStringNormalized(null);
}
else
{
bool test = anObject.isStringNormalized("test");
}
Console.WriteLine("Unloading the domain");
AppDomain.Unload(anAppDomain);
}
else
{
// don't care
}
// terminate
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
}
我写了一个小程序来检查我的程序是否仍然可以运行,即使dll崩溃。该计划只是一个概念证明。它有两个参数,第一个用于直接从程序集加载DLL,第二个用于引发崩溃。
程序代码如下所示:
[Serializable()]
public class makeExceptionClass
{
public bool isStringNormalized(string aString)
{
// A null check should be performed
return aString.IsNormalized();
}
}
class Program
{
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
static void Main(string[] args)
{
string typeOfLoading = args[0];
string crash = args[1];
// Load the DLL
if (typeOfLoading.Equals("direct") == true)
{
Console.WriteLine("Loading directly a DLL");
Assembly anAssembly = Assembly.Load("unloadableDLL"); // Directly load the DLL
unloadableDLL.makeExceptionClass anObject = (unloadableDLL.makeExceptionClass)anAssembly.CreateInstance("unloadableDLL.makeExceptionClass");
if (crash.Equals("crash") == true)
{
bool test = anObject.isStringNormalized(null);
}
else
{
bool test = anObject.isStringNormalized("test");
}
}
else if (typeOfLoading.Equals("indirect") == true)
{
Console.WriteLine("Loading indirectly a DLL");
AppDomain anAppDomain = AppDomain.CreateDomain("RemoteLoaderDomain"); // Assume it does not fail;
Type t = typeof(unloadableDLL.makeExceptionClass);
unloadableDLL.makeExceptionClass anObject = (unloadableDLL.makeExceptionClass)anAppDomain.CreateInstanceAndUnwrap("unloadableDLL", t.FullName);
if (crash.Equals("crash") == true)
{
bool test = anObject.isStringNormalized(null);
}
else
{
bool test = anObject.isStringNormalized("test");
}
Console.WriteLine("Unloading the domain");
AppDomain.Unload(anAppDomain);
}
else
{
// don't care
}
// terminate
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
}
问题是,无论dll是直接加载还是加载到AppDomain中,我的程序都会崩溃。
我对C是全新的(我今天早上开始),但是我有C++背景。
在你的电话中添加尝试/捕捉:
try
{
if (crash.Equals("crash") == true)
{
bool test = anObject.isStringNormalized(null);
}
else
{
bool test = anObject.isStringNormalized("test");
}
} catch (Exception ex) {
Console.WriteLine("exception in dll call: "+ex);
}
在通话中添加try/catch:
try
{
if (crash.Equals("crash") == true)
{
bool test = anObject.isStringNormalized(null);
}
else
{
bool test = anObject.isStringNormalized("test");
}
} catch (Exception ex) {
Console.WriteLine("exception in dll call: "+ex);
}
你说的“撞车”是什么意思?一个例外?你可以考虑查看MEF和/或MAF;这两种框架都允许您将潜在的恶意或有缺陷的第三方代码加载到应用程序中,并通过已建立的接口与之通信。更一般地说:您正在尝试一项本质上很难的任务,即使是有经验的C#程序员也会觉得很棘手。这不是我会选择作为某人C#编码的第一天,甚至不是他们的第1000天。祝你好运是的,我并没有真正选择它,我的老板好心地让我去做:我想知道同样的事情,但有点不同。如果模块/DLL本身执行了某些操作,并且得到了未捕获的异常,则整个父应用程序/容器将崩溃。因此,让我们假设一个DLL启动一个TcpListener,客户端连接到它。然后,客户端发送的东西发生了一些问题,然后容器应用程序崩溃。我想知道如何处理这些情况,使容器应用程序不会崩溃。您所说的“崩溃”是什么意思?一个例外?你可以考虑查看MEF和/或MAF;这两种框架都允许您将潜在的恶意或有缺陷的第三方代码加载到应用程序中,并通过已建立的接口与之通信。更一般地说:您正在尝试一项本质上很难的任务,即使是有经验的C#程序员也会觉得很棘手。这不是我会选择作为某人C#编码的第一天,甚至不是他们的第1000天。祝你好运是的,我并没有真正选择它,我的老板好心地让我去做:我想知道同样的事情,但有点不同。如果模块/DLL本身执行了某些操作,并且得到了未捕获的异常,则整个父应用程序/容器将崩溃。因此,让我们假设一个DLL启动一个TcpListener,客户端连接到它。然后,客户端发送的东西发生了一些问题,然后容器应用程序崩溃。我想知道如何处理这些情况,使容器应用程序不会崩溃。您好。那么appDomain的用途是什么呢?我猜NullRef异常不是崩溃。你得到了那个异常,应该处理它。崩溃将被视为非托管代码中发生的非法事件,如访问冲突或段错误。您的逻辑将阻止DLL中的代码引发异常。嗨。我必须澄清问题:团队需要测试产品通过以太网的通信。团队使用NI TestStand编写测试。
TestStand使用我编写的DLL,但我无法控制TestStand代码。在我的DLL中,我有一个类B的成员。这个类型B的成员来自一个DLL(我们称之为DLLB),我无法控制它,因为我不负责它。
测试台崩溃,因为如果DLLB中出现异常。TestStand没有try-catch异常处理,它认为它通过我的B成员使用DLLB。这就是为什么我需要将DLL B与我的DLL隔离,并维护对另一个域中实例化的B的引用。发生的崩溃是访问冲突。DLL B使用LibCurlNet。在一些测试中,我认为两个连接是在两个单独的线程中打开的。可以设置一个连接。然后,当尝试处理第二个连接时,出现访问冲突。Hi。那么appDomain的用途是什么呢?我猜NullRef异常不是崩溃。你得到了那个异常,应该处理它。崩溃将被视为非托管代码中发生的非法事件,如访问冲突或段错误。您的逻辑将阻止DLL中的代码引发异常。嗨。我必须澄清问题:团队需要测试产品通过以太网的通信。团队使用NI TestStand编写测试。
TestStand使用我编写的DLL,但我无法控制TestStand代码。在我的DLL中,我有一个类B的成员。这个类型B的成员来自一个DLL(我们称之为DLLB),我无法控制它,因为我不负责它。
测试台崩溃,因为如果DLLB中出现异常。TestStand没有try-catch异常处理,它认为它通过我的B成员使用DLLB。这就是为什么我需要将DLL B与我的DLL隔离,并维护对另一个域中实例化的B的引用。发生的崩溃是访问冲突。DLL B使用LibCurlNet。在一些测试中,我认为两个连接是在两个单独的线程中打开的。可以设置一个连接。然后,当尝试处理第二个连接时,出现访问冲突。