从服务中加载来自环境变量路径的dll

时间:2009-10-26 09:46:47

标签: c# matlab windows-services environment-variables

我们在机器上安装Matlab Runtime,然后我们重新启动一个调用Matlab运行时方法的.net窗口服务。
问题是我们收到TypeInitializationException错误,直到我们重新启动Windows。 我们认为这是因为Environment Variables are not changed on services until restart和Matlab使用%Path%变量来引用它的核心DLL。 我的问题是,你认为我可以改变%Path%变量,以便Matlab在引用它的引擎的核心dll时会使用它吗? 或者是否可以将目录添加到.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”=“未找到指定的模块”

3 个答案:

答案 0 :(得分:1)

如果您可以重写该服务,则可以在.NET代码中使用System.Environment。GetEnvironmentVariable和SetEnvironmentVariable方法,并自行添加Matlab运行时引擎路径。如果您无法重写该服务,可以尝试net stop / net start或installutil,它们会对服务进行操作。或者您可能会询问ServerFault。

OLD ANSWER 因为我误解了这个问题:

MATLAB组件是否启动然后抛出异常?如果是这样,CTFROOT, TOOLBOXDIR, and ADDPATH函数可能有所帮助。也许是这样的:

if isdeployed
    addpath(ctfroot);
    addpath(toolboxdir('signal'));
    %more addpath(toolboxdir('toolboxname')) statements
end

但是如果MATLAB没有开始,那将无济于事。

答案 1 :(得分:0)

这可能有助于您的思路“或者是否可以将目录添加到.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()

答案 2 :(得分:-1)

来自: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编译器运行时目录可能已在返回的PATH环境变量中被截断。

要解决此问题,请执行以下操作之一:

1)在现有PATH变量的开头添加MATLAB Compiler Runtime目录。

2)从以下Microsoft网站获取此问题的修补程序。 http://support.microsoft.com/kb/906469