アプリドメインを使用して.NetFramework4.0を使用してプラグインを分離する小さなプラグインライブラリを作成しています。したがって、各プラグインに含まれるコードは私の制御不能です。プラグインの1つで未処理の例外が発生した場合、結果は一種の混合バッグであることがわかりました。以下のとおりです。
未処理の例外がプラグインのメインスレッドでスローされると、プラグインのexecuteメソッドを呼び出すメインのプラグイン可能なアプリがそれをキャッチしてクリーンに処理できます。そこに問題はありません。でも、
プラグインがプラグインのExecuteメソッドでWinFormsベースのアプリのメッセージループを開始し、未処理の例外がWinFormアプリケーション(つまりフォーム)でスローされた場合、プラグイン可能なアプリは、VisualStudioデバッガー内から実行されている場合にのみ例外をキャッチできます。そうしないと(VSの外部で呼び出された場合)、メインのプラグイン可能なアプリがプラグインとともにクラッシュします。
未処理の例外がプラグインのExecuteメソッドによって生成された別のスレッドでスローされた場合、プラグイン可能なアプリは例外をキャッチする可能性がなく、クラッシュします。
以下のリンクで、この動作をシミュレートするための簡単なVS2010プロジェクトを作成しました。 http://www.mediafire.com/file/1af3q7tzl68cx1p/PluginExceptionTest.zip
その中で、プラガブルアプリのメインメソッドは次のようになります
namespace PluginExceptionTest
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press enter to load plugin");
Console.ReadLine();
Assembly entryAsm = Assembly.GetEntryAssembly();
string assemblyFileName = Path.Combine(Path.GetDirectoryName(entryAsm.Location), "EvilPlugin.exe");
AppDomainSetup domainSetup = new AppDomainSetup();
AppDomain domain = AppDomain.CreateDomain("PluginDomain", null, domainSetup);
PluginBase plugin = (PluginBase)domain.CreateInstanceFromAndUnwrap(assemblyFileName, "EvilPlugin.Plugin");
Console.WriteLine("Plugin Loaded.");
//SCENARIO 1: WinForms based plugin
Console.WriteLine("Press Enter to execute winforms plugin. (Remember to click on the button in the form to raise exception)");
Console.ReadLine();
try
{
plugin.ExecuteWinApp();
}
catch (Exception)
{
//The exception is caught and this gets executed only when running in visual studio debugger. Else application exits. Why?
Console.WriteLine("WinForms plugin exception caught. However same does not happen when run out of visual studio debugger. WHY?");
}
//SCENARIO 2: WinForms based plugin
Console.WriteLine("Press Enter to execute threading plugin, wait for 3 seconds and the app will exit. How to prevent app from exiting due to this?");
Console.ReadLine();
try
{
plugin.ExecuteThread();
}
catch (Exception)
{
//This never gets executed as the exception is never caught. Application exits. Why?
Console.WriteLine("WinForms plugin exception caught");
}
Console.ReadLine();
}
}
}
これはプラグインプロジェクトのコードです。上記のプラガブルアプリプロジェクトのPluginBaseクラスから継承します。
namespace EvilPlugin
{
public class Plugin:PluginBase
{
public Plugin():base()
{
}
public override void ExecuteWinApp()
{
Application.Run(new Form1());
}
public override void ExecuteThread()
{
Thread t = new Thread(new ThreadStart(RaiseEx));
t.Start();
}
private void RaiseEx()
{
Thread.Sleep(3000);
throw new Exception("Another Evil Exception in a seperate thread");
}
}
}
最後に、これはプラグインのフォームからのコードです
namespace EvilPlugin
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnException_Click(object sender, EventArgs e)
{
throw new Exception("Evil Exception");
}
}
}
上記の2つのシナリオ(1と2)が原因でメインプロセスが終了しないようにするにはどうすればよいですか?
前もって感謝します。