Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.64/11: Рейтинг темы: голосов - 11, средняя оценка - 4.64
288 / 251 / 107
Регистрация: 26.10.2012
Сообщений: 796

Dll-ка работает только один раз при каждом запуске программы

30.08.2018, 15:08. Показов 2210. Ответов 12

Студворк — интернет-сервис помощи студентам
Здравствуйте.

Есть файл .dll-ки, написанный на другом языке с несколькими известными импортированными методами.
C#
1
2
3
4
5
6
7
8
9
10
11
12
[DllImport(@"DLL\OdeWrapDll.dll")]
static extern bool DoInit([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] ar,
                                  int len, IntPtr FVagPtr, IntPtr FLokPtr,
                                  IntPtr FePtr, IntPtr FSumPtr);
 
[DllImport(@"DLL\OdeWrapDll.dll")]
static extern bool StartCalc();
 
[DllImport(@"DLL\OdeWrapDll.dll")]
static extern void DoExit();
 
//....
Сама dll-ка - черный ящик, я не могу просмотреть и отредактировать ее содержимое. Ее писал человек лет 10 назад ушедший на пенсию.

Работа с ней такова: сперва вызывается метод инициализации DoInit, потом StartCalc, метод DoExit по идее предусмотрен для выхода.
Если вызывать методы DoInit -> StartCalc один раз за время работы моей программы, то Dll-ка работает правильно.

Но. Теперь в моей программе надо несколько раз запускать методы из dll-ки с разными параметрами инициализации.
Когда я запускаю методы DoInit -> StartCalc второй раз, то dll-ка работает неправильно. На тех же параметрах инициализации.

Если вызывать после конца работы .dll-ки предусмотренный метод выхода DoExit(), то программа вообще вылетает в случайном месте с исключением
Кликните здесь для просмотра всего текста

Managed Debugging Assistant 'FatalExecutionEngineError' : 'В среде выполнения обнаружена критическая ошибка. Ошибка произошла по адресу 0x72129e77 в потоке 0x1dd0. Код ошибки 0xc0000005. Она может быть вызвана ошибкой в CLR или в небезопасных либо не поддающихся проверке фрагментах пользовательского кода. Обычно источниками таких ошибок бывают ошибки упаковки, допускаемые пользователями при COM-взаимодействии, либо PInvoke, повредивший стек.'

Если вызвать сразу после DoExit() метод GC.Collect(), то программа гарантированно вылетит на нем. Пробовал ждать несколько секунд.

Понятно, что это косяк .dll-ки, но как мне быть?

Добавлено через 4 минуты
Пробовал мутить с методом FreeLibrary из kernel32.dll, вернуло 1, но на работу .dll не повлияло.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
30.08.2018, 15:08
Ответы с готовыми решениями:

Как выполнить код только один раз (при запуске программы?)
Как известно, At module level, you can use only comments and declarative statements. Значит, весь исполняемый код должен лежать внутри...

Выводится картинка на view сразу при запуске программы и только один раз
Ну собственно это продолжение вопроса на мой предыдущий вопрос про вывод картинки, с выводом я почти разобрался, в свойстве customclass...

Как мне сделать так, чтобы данный текстовый файл был открыт один раз при запуске программы и закрыт при закрытии программы?
Привет! Возник следующий вопрос. Программа состоит из основного окна Form1 и нескольких Unit. По таймеру в Form1 запускается один из...

12
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,569
30.08.2018, 15:23
У методов в длл Calling Convention точно совпадает с используемым в .NET по умолчанию?
0
288 / 251 / 107
Регистрация: 26.10.2012
Сообщений: 796
30.08.2018, 15:47  [ТС]
Someone007, какой CallingConvention используется по умолчанию - не знаю
Перебрал все варианты: с CallingConvention.Winapi и CallingConvention.StdCall работает так же как описано в топике.
С остальными - вылетает при первом же вызове init() - "access violation exception попытка доступа в защищенную память".
0
288 / 251 / 107
Регистрация: 26.10.2012
Сообщений: 796
14.09.2018, 08:13  [ТС]
Пробовал сделать managed библиотеку обертку над загружаемой dll (зацените ход: C# библиотека-обертка над C++ библиотекой-оберткой над исходной библиотекой) и загружать-выгружать ее из своего домена приложения. Managed-библиотека, потому что C++ библиотеку загрузить в домен не получилось.

Итак: есть библиотека ViniizhtDynamicLibrary реализуующая интерфейс IVniizhtDynamicLibrary из основного проекта.
ViniizhtDynamicLibrary ссылается на наш проект, основной проект не ссылается на ViniizhtDynamicLibrary.
Создание IVniizhtDynamicLibrary проходит, класс работает но видимо не правильно выгружается, хотя я вызываю AppDomain.Unload.

Немного смущает, что в основной домен добавляется сборка ViniizhtDynamicLibrary.dll, хотя я явно ее в основной домен не загружаю.
C#
1
2
3
4
5
6
7
8
9
10
11
//сборки ViniizhtDynamicLibrary.dll нет
var assemblies1 = AppDomain.CurrentDomain.GetAssemblies();
currentDomain = AppDomain.CreateDomain("New domain");
 
var ass = _currentDomain.Load("ViniizhtDynamicLibrary");
_vniViniizhtDynamicLibrary =(IVniizhtDynamicLibrary)ass.CreateInstance("ViniizhtDynamicLibrary.ViniizhtDynamicLibrary");
//не понимаю этого метода, но так тоже не работает
//_vniViniizhtDynamicLibrary = (IVniizhtDynamicLibrary)_currentDomain.CreateInstanceAndUnwrap("ViniizhtDynamicLibrary", "ViniizhtDynamicLibrary.ViniizhtDynamicLibrary");
 
//добавилась сборка ViniizhtDynamicLibrary.dll
var assemblies2 = AppDomain.CurrentDomain.GetAssemblies();
Я правильно загружаю сборку в другой домен? Почему сборка ViniizhtDynamicLibrary.dll добавилась в основной домен?
0
 Аватар для V_Monomax
1406 / 1260 / 20
Регистрация: 09.08.2011
Сообщений: 2,319
Записей в блоге: 1
14.09.2018, 08:58
1. а вам не проще переписать библиотеку под себя? (вам все равно в вашей ситуации это придется сделать - нет исходных кодов и человека ее писавшего, при этом библиотека не работает стабильно).
2. А у вас там нет ли кода типа UnmanagedType?
1
288 / 251 / 107
Регистрация: 26.10.2012
Сообщений: 796
14.09.2018, 09:55  [ТС]
1. Подумываю над этим
Смущает то, что там библиотека физических рассчетов, а я всех нюансов и коэффицентов не знаю.

2. Есть: LPArray, I4, U4. Но не вижу подозрительного.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[DllImport(@"OdeWrapDll.dll")]
static extern bool DoInit([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] ar,
            int len, IntPtr fVagPtr, IntPtr fLokPtr,
            IntPtr fePtr, IntPtr fSumPtr);
[DllImport(@"OdeWrapDll.dll")]
static extern bool FinishCalc([MarshalAs(UnmanagedType.U4)] uint timeWaitShutdown);
 
//и в делегатах передающихся в функцию DoInit (fVagPtr, fLokPtr, fSumPtr)
delegate bool FnGetVagMassAndLen([MarshalAs(UnmanagedType.I4)] int vagonType,
            ref double pMass, ref double pLen);
 
delegate bool FnGetLokMassAndLen([MarshalAs(UnmanagedType.I4)] int locoType,
            ref double pMass, ref double pLen);
 
delegate bool SetResultForcesDelegate([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] 
            double[] ar, int len);
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18242 / 14156 / 5366
Регистрация: 17.03.2014
Сообщений: 28,844
Записей в блоге: 1
16.09.2018, 11:04
Лучший ответ Сообщение было отмечено jetyb как решение

Решение

Цитата Сообщение от jetyb Посмотреть сообщение
Но. Теперь в моей программе надо несколько раз запускать методы из dll-ки с разными параметрами инициализации.
Когда я запускаю методы DoInit -> StartCalc второй раз, то dll-ка работает неправильно. На тех же параметрах инициализации.
Видимо такое не было предусмотрено автором библиотеки и метод DoInit можно вызывать один раз. Попробуй явно загружать библиотеку с помощью LoadLibrary (pinvoke.net), получать адрес через GetProcAddress (pinvoke.net), далее получать делегат через Marshal.GetDelegateForFunctionPointer, вызывать метод(ы) и выгружать библиотеку с помощью FreeLibrary (pinvoke.net).

Другой вариант это использовать out of process хостинг dll. При необходимости вызова dll запускаем новый процесс который загружает библиотеку выполняет вызовы, передает результат родительскому процессу и завершается. В этом варианте dll главный процесс лучше изолирован от dll. Можно будет использовать pinvoke. Но! Ухудшится производительность и нужно будет написать код для обмена данными между процессами.
1
TheGreatCornholio
 Аватар для Woldemar89
1255 / 733 / 285
Регистрация: 30.07.2015
Сообщений: 2,408
16.09.2018, 11:19
jetyb, попробуйте проверить PE Explorer'ом таблицу экспорта DLL и сигнатуры экспортируемых функций на всякий случай.

Добавлено через 3 минуты
Цитата Сообщение от jetyb Посмотреть сообщение
Dll-ка работает правильно.
Цитата Сообщение от jetyb Посмотреть сообщение
Но. Теперь в моей программе надо несколько раз запускать методы из dll-ки с разными параметрами инициализации.
Извиняюсь, невнимательно прочитал. Присоединяюсь к совету OwenGlendower.
1
 Аватар для Wolflind
127 / 107 / 31
Регистрация: 17.03.2016
Сообщений: 445
Записей в блоге: 1
17.09.2018, 11:56
я реализовывал система плагин в в ней загружал dll и создавал объекты я делал в 1 домене а если загружать 1 и ту же dll в несколько доменов?
я не делал с так, но может кто то делал может и может сказать получится или нет.
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18242 / 14156 / 5366
Регистрация: 17.03.2014
Сообщений: 28,844
Записей в блоге: 1
17.09.2018, 16:06
Цитата Сообщение от Wolflind Посмотреть сообщение
а если загружать 1 и ту же dll в несколько доменов?
... может кто то делал может и может сказать получится или нет.
Я так тоже не делал, но должно получится. Только в данном случае это не поможет - у ТСа неуправляемая dll источник проблемы.
0
288 / 251 / 107
Регистрация: 26.10.2012
Сообщений: 796
18.09.2018, 11:13  [ТС]
Цитата Сообщение от OwenGlendower Посмотреть сообщение
Видимо такое не было предусмотрено автором библиотеки и метод DoInit можно вызывать один раз. Попробуй явно загружать библиотеку с помощью LoadLibrary (pinvoke.net), получать адрес через GetProcAddress (pinvoke.net), далее получать делегат через Marshal.GetDelegateForFunctionPointer, вызывать метод(ы) и выгружать библиотеку с помощью FreeLibrary (pinvoke.net).
Спасибо, не сразу понял, как тут надо было действовать, но все-таки это помогло.
Сделал примерно так.
C#
1
2
3
4
5
6
7
8
9
10
11
12
void Init()
{
      LibraryHandle = LoadLibrary("OdeWrapDll.dll");
      var pAddressOfFunctionToCall = GetProcAddress(LibraryHandle, "DoInit");
      DoInit = (DoInitHandler) Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall, typeof(DoInitHandler));
}
void Dispose()
{
            if (LibraryHandle == IntPtr.Zero) return;
            DoInit = null;
            FreeLibrary(LibraryHandle);
}
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18242 / 14156 / 5366
Регистрация: 17.03.2014
Сообщений: 28,844
Записей в блоге: 1
18.09.2018, 14:30
Цитата Сообщение от jetyb Посмотреть сообщение
Сделал примерно так.
Я бы вынес инициализацию в конструктор класса чтобы гарантировать что она точно выполняется и всего один раз. С методом Init можно допустить ошибку. Плюс в Dispose почему-то отсутствует зануление LibraryHandle после вызова FreeLibrary.
1
288 / 251 / 107
Регистрация: 26.10.2012
Сообщений: 796
18.09.2018, 14:40  [ТС]
У меня несколько конструкторов, в этой части совершенно одинаковых, поэтому сделал для них общий метод Init.

Я написал огрызки своих методов. Там на самом деле дальше обнуляется несколько делегатов, и в самом конце действительно есть LibraryHandle = IntPtr.Zero. Сюда просто первые строчки скопипастил, и это не попало.
Но за внимательность спасибо)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
18.09.2018, 14:40
Помогаю со студенческими работами здесь

В квадрате 4х4 расположить 16 букв, чтобы в каждом горизонтальном и каждом вертикальном ряду буква встречалась только один раз
В квадраті 4х4 розташувати 16 літер (чотири a, чотири b, чотири c, чотири d) так, щоб в кожному горизонтальному та кожному вертикальному...

Вывести буквы, которые встречаются в каждом слове только один раз
Вечер добрый! Помогите с решение задачи! Дано предложение. Требуется вывести буквы, которые встречаются в каждом слове только один раз. ...

Распечатать буквы, которые встречаются в каждом слове текста только один раз
Здравствуйте. Как распечатать буквы, которые встречаются в каждом слове набранного текста только один раз? Например, вводишь с клавиатуры...

Распечатайте буквы, которые встречаются в каждом слове текста только один раз
Пусть дан текст. Распечатайте те буквы, которые встречаются в каждом слове текста только один раз.

Распечатайте те буквы, которые встречаются в каждом слове текста только один раз
Пусть дан текст. Распечатайте те буквы, которые встречаются в каждом слове текста только один раз


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru