Загружайте библиотеки DLL из пути к переменной окружения из сервиса

StackOverflow https://stackoverflow.com/questions/1623935

Вопрос

Мы устанавливаем среду выполнения Matlab на компьютер, затем перезапускаем службу .net Windows, которая вызывает методы из среды выполнения Matlab.
Проблема в том, что мы получаем ошибки TypeInitializationException до тех пор, пока не перезапустим Windows.Мы думаем, что это происходит потому, что Переменные среды не изменяются в службах до перезапуска и Matlab использует переменную %Path% для ссылки на свою основную библиотеку DLL.
Мой вопрос в том, как вы думаете, могу ли я изменить переменную %Path%, чтобы Matlab использовал ее при обращении к основной библиотеке dll для своего движка?
Или возможно ли добавить каталог в механизм загрузки библиотеки DLL во время выполнения .NET, чтобы на эти библиотеки DLL Matlab core можно было правильно ссылаться без перезапуска компьютера?

Вот исключение, которое мы получаем

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" = "Указанный модуль не найден"

Это было полезно?

Решение

Если вы можете переписать сервис, вы можете использовать Система.Окружающая среда.Получите методы environmentvariable и SetEnvironmentVariable в коде .NET и добавьте путь к движку Matlab runtime engine самостоятельно.Если вы не можете переписать сервис, вы можете попробовать чистая остановка/чистый старт или installutil ( установка), которые действуют на сервисы.Или вы могли бы обратиться к ServerFault.

СТАРЫЙ ОТВЕТ потому что я неправильно понял вопрос:

Запускается ли компонент MATLAB, а затем выдает исключение?Если это так, то CTFROOT, TOOLBOXDIR и ADDPATH функции могли бы помочь.Может быть, что-то вроде:

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

Но если MATLAB вообще не запускается, это не поможет.

Другие советы

Это может помочь в вашем размышлении "Или возможно ли добавить каталог к механизму загрузки DLL во время выполнения .NET, чтобы на эти библиотеки DLL Matlab core можно было правильно ссылаться без перезапуска компьютера":

В одном приложении я использую следующий код, чтобы указать.NET, где искать сборки, когда он пытается загрузить их динамически.В моем случае мне это нужно, поскольку мое приложение загружено как расширение к другой программе, поэтому мои библиотеки dll находятся не в том же каталоге, что и exe-файл приложения.Возможно, это относится и к вам?

В моем случае моя основная библиотека dll приложения загружена правильно, потому что она зарегистрирована для COM-взаимодействия.Но мне нужно сделать следующее, чтобы библиотека MS Enterprise могла загружать свои сборки, потому что она делает это каким-то необычным динамическим способом.Следующий код сообщает .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() прежде чем делать что-либо, что потребует загрузки сборок за пределами обычных папок.

От: http://www.mathworks.com/support/solutions/en/data/1-A1A70V/index.html?product=MN&solution=1-A1A70V

Решение: Когда веб-приложение вызывает функцию CreateEnvironmentBlock для извлечения переменных среды на компьютере под управлением Microsoft Windows Server 2003 или Microsoft Windows XP, возвращаемая переменная среды path сокращается до 1024 байт.Такое поведение происходит даже при том, что максимальный размер переменной окружения составляет 2048 байт.Эта проблема не позволяет веб-приложению получить правильную переменную среды.

В частности, каталоги среды выполнения компилятора MATLAB в PATH, возможно, были усечены в возвращаемой переменной среды PATH.

Чтобы обойти проблему, выполните одно из следующих действий:

1) Добавьте каталоги среды выполнения компилятора MATLAB в начале существующей переменной PATH.

2) Получите исправление для этой проблемы на следующем веб-сайте корпорации Майкрософт.http://support.microsoft.com/kb/906469

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top