サービスから環境変数パスからDLLをロード
-
06-07-2019 - |
質問
Matlabランタイムをマシンにインストールしてから、Matlabランタイムからメソッドを呼び出す.net Windowsサービスを再起動します。
問題は、Windowsを再起動するまでTypeInitializationExceptionエラーを受け取ることです。
これは、環境変数が再起動するまでサービスで変更されないため、Matlabが%Pathを使用するためだと考えられます。コアDLLを参照する%変数。
私の質問は、エンジンのコアDLLを参照するときにMatlabが使用するように%Path%変数を変更できると思いますか?
または、.NETのランタイムDLLロードメカニズムにディレクトリを追加して、それらのMatlabコアdllがマシンを再起動せずに正しく参照されるようにすることは可能ですか?
ここに例外があります
System.TypeInitializationException: The type initializer for 'MatlabCalculation.Calculation' threw an exception. ---> System.TypeInitializationException: The type initializer for 'MathWorks.MATLAB.NET.Utility.MWMCR' threw an exception. ---> System.DllNotFoundException: Unable to load DLL 'mclmcrrt710.dll': Kan opgegeven module niet vinden. (Exception from HRESULT: 0x8007007E)
at MathWorks.MATLAB.NET.Utility.MWMCR.mclmcrInitialize()
at MathWorks.MATLAB.NET.Utility.MWMCR..cctor()
--- End of inner exception stack trace ---
at MatlabCalculation.Calculation..cctor()
--- End of inner exception stack trace ---
at MatlabCalculation.Calculation.Finalize()
” Kan opgegeven module niet vinden" ="指定されたモジュールが見つかりません"
解決
サービスを書き換えられる場合は、システムを使用できます。 Environment .GetEnvironmentVariableおよびSetEnvironmentVariableメソッドを.NETコード内に追加し、Matlabランタイムエンジンパスを自分で追加します。サービスを書き換えられない場合は、 net stop / netを試してください。 startまたは installutil 。これらはサービスに作用します。または、ServerFaultで確認することもできます。
古い回答:質問を誤解したためです:
MATLABコンポーネントは起動してから例外をスローしますか?その場合、 CTFROOT、TOOLBOXDIR、およびADDPATH 関数が役立つ場合があります。たぶん次のようなものです:
if isdeployed
addpath(ctfroot);
addpath(toolboxdir('signal'));
%more addpath(toolboxdir('toolboxname')) statements
end
ただし、MATLABがまったく起動しない場合、これは役に立ちません。
他のヒント
これはあなたの考え方に沿って役立つかもしれません"または.NETのランタイムDLLロードメカニズムにディレクトリを追加して、マシンを再起動せずにそれらのMatlabコアdllが正しく参照されるようにすることは可能ですか?
あるアプリでは、次のコードを使用して、アセンブリを動的にロードしようとしたときに.NETにアセンブリの検索場所を伝えます。私の場合、アプリは別のプログラムの拡張機能としてロードされるため、これが必要です。したがって、dllはアプリケーションexeと同じディレクトリにありません。おそらくこれはあなたにも当てはまりますか?
私の場合、メインアプリケーションdllはCOM相互運用機能に登録されているため、正しくロードされます。しかし、MS Enterprise Libraryがそのアセンブリをロードするためには、ファンキーでダイナミックな方法でそれを行う方法があるため、以下を行う必要があります。次のコードは、ロードするアセンブリを検索するときに、現在実行中のアセンブリのディレクトリを検索するように.NETに指示します。 .NETで検索したい任意のディレクトリで同じことができます。環境変数に基づいたもの。
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.IO;
namespace CommonClasses
{
/// <summary>
/// Helper class to ensure the Common Language Runtime can dynamically load our referenced dlls.
/// Because our components are called from COM via iexplore.exe the executing directory is likely to be something like
/// c:\program files\internet explorer\, which obviously doesn't contain our assemblies. This only seems to be a problem
/// with the Enterprise Library so far, because it dynamically loads the assemblies it needs.
/// This class helps by directing the CLR to use the directory of this assembly when it can't find the assembly
/// normally. The directory of this assembly is likely to be something like c:\program files\my program\
/// and will contain all the dlls you could ask for.
/// </summary>
public static class AssemblyResolveAssistant
{
/// <summary>
/// Records whether the AssemblyResolve event has been wired.
/// </summary>
private static bool _isWired = false;
/// <summary>
/// Add the handler to enable assemblies to be loaded from this assembly's directory, if it hasn't
/// already been added.
/// </summary>
public static void AddAssemblyResolveHandler()
{
if (!_isWired)
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
_isWired = true;
}
}
/// <summary>
/// Event handler that's called when the CLR tries to load an assembly and fails.
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
/// <returns></returns>
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
Assembly result = null;
// Get the directory where we think the assembly can be loaded from.
string dirName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
AssemblyName assemblyName = new AssemblyName(args.Name);
assemblyName.CodeBase = dirName;
try
{
//Load the assembly from the specified path.
result = Assembly.Load(assemblyName);
}
catch (Exception) { }
//Return the loaded assembly, or null if assembly resolution failed.
return result;
}
}
}
次に、通常のフォルダーの外にアセンブリをロードする必要があることを行う前に、メソッド AssemblyResolveAssistant.AddAssemblyResolveHandler()
を呼び出します。
from: http://www.mathworks.com/support/solutions/en/data/1-A1A70V/index.html?product=MN&solution=1-A1A70V
解決策: WebアプリケーションがCreateEnvironmentBlock関数を呼び出して、Microsoft Windows Server 2003ベースまたはMicrosoft Windows XPベースのコンピューターで環境変数を取得すると、返されるパス環境変数は1,024バイトに切り捨てられます。この動作は、環境変数の最大サイズが2,048バイトであっても発生します。この問題により、Webアプリケーションは正しい環境変数を取得できません。
特に、PATH上のMATLAB Compiler Runtimeディレクトリは、返されたPATH環境変数で切り捨てられている場合があります。
問題を回避するには、次のいずれかを実行します。
1)既存のPATH変数の先頭にMATLAB Compiler Runtimeディレクトリを追加します。
2)次のマイクロソフトWebサイトからこの問題のパッチを入手します。 http://support.microsoft.com/kb/906469