C# 从服务的环境变量路径加载dll
我们在机器上安装Matlab运行时,然后重新启动一个.NETWindows服务,该服务调用Matlab运行时中的方法。 问题是,在重新启动windows之前,我们会收到TypeInitializationException错误。 我们认为这是因为Matlab使用%Path%变量来引用它的核心DLL。 我的问题是,您认为我可以更改%Path%变量,以便Matlab在为其引擎引用核心dll时使用它吗? 或者,是否可以向.NET的运行时DLL加载机制添加一个目录,以便在不重新启动机器的情况下正确引用这些Matlab核心DLL 这是我们得到的例外C# 从服务的环境变量路径加载dll,c#,matlab,windows-services,environment-variables,C#,Matlab,Windows Services,Environment Variables,我们在机器上安装Matlab运行时,然后重新启动一个.NETWindows服务,该服务调用Matlab运行时中的方法。 问题是,在重新启动windows之前,我们会收到TypeInitializationException错误。 我们认为这是因为Matlab使用%Path%变量来引用它的核心DLL。 我的问题是,您认为我可以更改%Path%变量,以便Matlab在为其引擎引用核心dll时使用它吗? 或者,是否可以向.NET的运行时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=未从以下位置找到指定的模块:
解决方案:
当web应用程序调用CreateEnvironmentBlock函数来检索基于Microsoft Windows Server 2003或基于Microsoft Windows XP的计算机上的环境变量时,返回的path环境变量将被截断为1024字节。即使环境变量的最大大小为2048字节,也会发生此行为。此问题会阻止web应用程序获取正确的环境变量
具体来说,路径上的MATLAB编译器运行时目录可能在返回的PATH环境变量中被截断
要解决此问题,请执行以下操作之一:
1在现有PATH变量的开头添加MATLAB编译器运行时目录
2从以下Microsoft网站获取此问题的修补程序。
如果可以重写服务,可以在.NET代码中使用.GetEnvironmentVariable和SetEnvironmentVariable方法,并自己添加Matlab运行时引擎路径。如果您无法重写服务,您可以尝试/net start或,这将对服务起作用。或者你可以询问服务器故障 旧答案,因为我误解了这个问题: MATLAB组件是否正在启动,然后抛出异常?如果是这样,这些函数可能会有所帮助。可能是这样的:
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方法,然后再执行任何需要在普通文件夹之外加载程序集的操作。我以前见过这种情况。这似乎不适用于我们的情况。我们在%Path%变量上还远远没有1024个字节。我认为问题与路径变量有关,但与它被截断无关。这与他的问题无关,因为在重新启动他的计算机后,一切正常。从例外情况来看,我认为没有调用matlab代码,我想在.net方面找到解决方案,在matlab代码没有改变的情况下,我们不得不升级matlab运行时,我们遇到了同样的问题,因为路径改变了。我最终成功地使用了System.Environment.SetEnvironmentVariable。谢谢我们现在要求用户重新启动机器。也许以后我会有时间尝试提供的一些答案。我们不再需要重启机器了。我们使用System.Environment.SetEnvironmentVariable在服务启动和Matlab DLL成功加载时更改路径变量。