テスト モードで実行すると問題なく動作するイベントがありますが、コードをサービスとして実行すると起動しません。コードを投稿する前に、アプリケーションの構造を少し説明させてください。ここで問題が発生していると私は感じています。
ルーター サービスの制御に使用するトレイ アプリがあります。サービスが開始されると、すべての処理が行われる dll ライブラリが読み込まれます。ライブラリが開始されると、プラグインのディレクトリがスキャンされ、メイン プログラムにフックされます。
リリースとしてビルドすると、サービスが有効になり、アプリケーションをインストールする必要があります。補足として、トレイ アプリは管理者として実行されるため、サービスを制御できます。デバッグとしてビルドする場合、トレイはライブラリ dll を直接起動し、それを起動する小さなサービス アプリをスキップします。以下の図を参照してください。
いずれの場合も、このプラグインのフローは、Receiver がファイルを受信し、Sender にイベントを介して転送するように通知することです。ファイルはリモート処理のために送信され、別のレシーバーに返され、イベントを介して結果がプラグインに転送されます。プラグインはファイルを処理し、イベントでメイン プログラムに送り返す必要があります。デバッグ (サービスなし) で実行すると、まさにこれが発生します。サービスとして実行すると、結果が処理されたことをメイン プログラムに通知するプラグインを除いて、すべてのイベント処理が完全に機能します。スローされる例外はありません。イベントが正しく接続されていることをログに記録して確認しました。
イベントの接続:
// Connect delegate to plugins that will add data to the database through the Router
if (plugin is INotify)
{
((INotify)plugin).NotifyProcessingComplete += new ProcessNotification(this.OnProcessed);
LogWriter.Log("Associated " + plugin.Name + " with OnProcessed", LogFile);
}
プラグインからイベントを呼び出す:
if (NotifyProcessingComplete != null)
NotifyProcessingComplete(ExtractResults(args.ReceivedFile));
else
LogWriter.Log("NotifyProcessingComplete Delegate was null.", LogFile);
イベントハンドラ:
public void OnProcessed(ProcessArgs args)
{
LogWriter.Log("On Dicom Process was called...", LogFile);
lock (threadLock)
{
if (Settings != null)
{ ... }
}
}
ログによると、プラグインは OnProcessed に正しく接続されており、ExtractResults() メソッドにログインすると、正しく返されていることが示されます。ただし、NotifyProcessingComplete は OnProcessed メソッドを呼び出していません。
繰り返しますが、これはコードをサービスとして実行している場合にのみ発生します。管理者として実行されているトレイ、ローカル システムとして実行されているサービス、および動的にロードされているプラグインに関係があると思われます。
以下に、プラグインをロードするためのコードを含めました。
private void loadPlugins()
{
String pluginPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
// Create a domain to text for plugins
AppDomain domain = AppDomain.CreateDomain("PluginLoader");
PluginFinder finder = (PluginFinder)domain.CreateInstanceAndUnwrap(
typeof(PluginFinder).Assembly.FullName, typeof(PluginFinder).FullName);
finder.LogFile = logFile;
// Get valid plugins, and then unload the domain to clear up memory
List<String> FoundPluginTypes = finder.SearchPath(pluginPath);
AppDomain.Unload(domain);
// Load the plugins
Plugins = new List<IPlugin>();
foreach (String plugin in FoundPluginTypes)
{
Assembly assembly = Assembly.LoadFrom(plugin);
Type type = null;
foreach (Type t in assembly.GetTypes())
if (t.GetInterface("IPlugin") != null)
type = t;
try
{
IPlugin loader = (IPlugin)Activator.CreateInstance(type);
Plugins.Add(loader);
}
catch (NullReferenceException e)
{
LogWriter.Log("Could not load plugin.", e, LogFile);
}
}
}
どんな助けや提案も大歓迎です。前もって感謝します。