PDA

Показать полную графическую версию : .: NSIS - все вопросы :. часть 2.


Страниц : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 [69] 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146

Sann-X!
24-11-2014, 07:36
Есть у меня старый проект, который создается инсталлятором Install Aware Express 7 R2. При удалении длл, даже если они используются другими приложениями, эти длл удаляются без перезагрузки. Как мне так же сделать в NSIS? Есть идеи?

MKN
25-11-2014, 11:00
При удалении длл, даже если они используются другими приложениями, эти длл удаляются без перезагрузки. »
Несколько страниц назад я уже задавался похожим вопросом. Есть предположение, что поможет System::Call 'Ole32::CoFreeUnusedLibraries() v'
Как это дело довести до ума, пока неизвестно...

Но ,если "по правилам", ситуации, когда при удалении\установки ПО, DLL этого ПО занята чем либо - быть не должно. Раз DLL занята, то следовательно открыто какое то приложение, которое использует эту DLL.

А, как известно "из азбуки", перед установкой\удалением любого ПО, сначала должны быть закрыты все открытые приложения ! ( Причины этого не раз рассматривались... ) О чём пользователь получает соответсвующее предупреждение (если ПО написано нормальным программером :) ). В NSIS это легко организовать с помощью LockedList плагина.

Вероятно некоторые разработчики при удалении\установки своего ПО принудительно закрывают, именно те приложения/процессы, которые мешают удалению\установке... Что не всегда допустимо...

Наверно, правильнее было бы получать сообщение, типа - такая то конкретная DLL не может быть удалена, пока Вы не закроете такое то конкретное приложение. (LockedList, к слову, так не умеет... Но можно привлечь для этого утилитку WhoUses.exe, что не оч интересно... )
Если кто подскажет, как в NSIS организовать именно такое сообщение - будет здОрово и полезно. :)

Sann-X!
25-11-2014, 12:15
Я решил сделать так:
- удалить файл длл
- если не удалился, то показать, какие процессы его держат (я написал плагин на Делфи, который в стеке возвращает процессы). Показываю окошко "MessageBox MB_ABORTRETRYIGNORE|MB_ICONEXCLAMATION"
- если юзер нажал "Пропустить", то я удаляю файл через "Delete /REBOOTOK", в реестре в "RunOnce" прописываю прогу, которая заменит файлы.

Если коротко, то так.

MKN
25-11-2014, 12:23
- если юзер нажал "Пропустить", то я удаляю файл через "Delete /REBOOTOK" »
А разве, если закрыть "удерживающий" DLL процесс и повторить удаление - DLL не удалится без перезагрузки ?

Sann-X!
25-11-2014, 12:27
Удалится без перезагрузки. Я, как пользователь, ненавижу эту штуку в инсталляторах. Поэтому в моем случае можно все норм. установить без перезагрузки: юзер видит, какие процессы держат файл, юзер может закрыть их и нажать кнопку "Повтор" - в этом случае длл будет заменена норм, без перезагрузки.

MKN
25-11-2014, 12:33
Удалится. Но зачем делать перезагрузку? »
Не надо никакой презагрузки, про то ведь и речь. :) Просто не совсем ясно, каким образом в твоём плагине пользователь манипулирует выбором действий...
Если получает сообщение о том, какой процесс удерживает DLL и закрыть ли этот процесс и удалить DLL ? - то тогда всё нормально, всё понятно. Других действий и не нужно...
(закрытие процесса и удаление DLL ведь предполагается нажатием одной кнопки в сообщении ? )

Sann-X!
25-11-2014, 12:38
Не, плагин только выдает список процесссов, которые держат файл. А в самом NSIS уже вывожу "MessageBox MB_ABORTRETRYIGNORE|MB_ICONEXCLAMATION" и анализирую действие юзера. А так да, в самом сообщении прошу закрыть указанные процессы.

MKN
25-11-2014, 12:41
прошу закрыть указанные процессы. »
По моему, это не дело - самому пользователю заниматься закрытием процесса... (зачем дублировать уже имеющийся LockedList ? ) Это что же, он должен залезать в диспетчер задач или самому тыркаться по списку процессов (кстати, как этот список у тебя организован ? ) ? Зачем ? Раз уж процесс, удерживающий DLL определён - вывел сообщение, кликнул кнопку и всё...

Sann-X!
25-11-2014, 12:44
Ну, юзер выберет из 2х зол меньшее: либо самому закрыть процессы или сделать перезагрузку компа. А разве есть 3й вариант?

MKN
25-11-2014, 12:49
А разве есть 3й вариант? »
Мне видится так - либо пользователь игнорирует удаление, т.е. DLL всё равно удалится, но после перезагрузки, либо выбирает удаление без перезагрузки, т.е. с автозакрытием процесса и последующим удалением DLL. Два варианта.

Sann-X!
25-11-2014, 12:51
Автозакрытие - это уже будет больше походить на хак. А если это будет какой-нить Word? Тогда слишком усложняется весь процесс инсталлятора: надо всем процессам (приложения и службы) послать команду "закрыть" (как это сделать пока не знаю), а потом ждать закрытия каждого процесса... Долго будет и муторно программировать.

MKN
25-11-2014, 12:54
Автозакрытие - это уже будет больше походить на хак. А если это будет какой-нить Word? »
Дык для того и будет предложен выбор - пользователь видит какое приложение мешает удалению и сам решает, будет ли оно закрыто немедленно или можно пропустить его закрытие , нажав игнор и продолжив процесс удаления. (а DLL удалится когда нибудь потом , после перезагрузки) Абсолютно добровольный выбор и никакого хака...

Sann-X!
25-11-2014, 12:59
Хак в том, чтобы инсталлятор закрыл приложение. Я не знаю, как это сделать (WM_CLOSE для приложения, а для службы как, имея хэндл процесса?). Лучше я оставлю как есть. А то больно сложный код инсталлятора получается.

Хотя вот есть плагин KillProcDLL_plug-in (http://nsis.sourceforge.net/KillProcDLL_plug-in)

MKN
25-11-2014, 13:03
Хак в том, чтобы инсталлятор закрыл приложение. »
Ну ты даёшь... Для отыскания-закрытия конкретных процессов есть и плагины, и есть код Nsis... Посмотри в теме. Фишка в определении конкретного процесса , удерживающего конкретную указанную DLL. Т.е. что то аналогично tasklist /m My.dll , только кодом NSIS . А уж закрыть найденный процесс, разве проблема...

Sann-X!
25-11-2014, 13:04
У меня наоборот: процессы нужные есть (полный путь к файлу), а вот кода по закрытию пока нет. Попробую, поищу.

Я так понял, что для закрытия процессов (приложений и служб) мне одного LockedList хватит?

MKN
25-11-2014, 13:20
для закрытия процессов (приложений и служб) мне одного LockedList хватит? »
Хватит. Только LockedList отобразит ВСЕ открытые приложения (или процессы) , а хотелось бы только то (те) конкретное приложение , которое удерживает конкретную указанную DLL.

Sann-X!
25-11-2014, 13:20
А в LockedList есть возможность самому составить список процессов?

Вроде есть:
Adds a custom item to the list with a callback function.

Значит, буду шаманить.

Только LockedList отобразит ВСЕ открытые приложения (или процессы)
Вроде не так. Через LockedList::AddModule добавли свою длл и в окне показались только процессы, которые держат мою длл.

MKN
25-11-2014, 13:40
LockedList::AddModule добавли свою длл и в окне показались только процессы, которые держат мою длл. »
Точно , появилось такое дело в плагине. У меня старинная версия оказалась... Оч. хорошо, будем использовать...

Sann-X!
25-11-2014, 15:17
Нашел минус в LockedList: если процесс - служба, то он завершает ее принудительно, хотя можно это сделать мягко.

Sann-X!
27-11-2014, 13:01
Как создать массив данных (или просто переменная) в длл на делфи так, чтобы потом с этим массивом/переменной можно было работать в NSIS?
Например, у меня в длл есть такая переменная:
library libname;

type
TProcessInfo = record
..
end;
TProcessesInfo = array of TProcessInfo;

var
Processes: TProcessesInfo;
b: Byte;

...

procedure proba1(const hwndParent: HWND; const string_size: integer; const variables: PAnsiChar; const stacktop: pointer); cdecl;
var
Descr: AnsiString;
i: Integer;
begin
// setup global variables
g_stringsize := string_size;
g_hwndParent := hwndParent;
g_stacktop := stacktop;
g_variables := variables;

Inc(b);
NSISDialog(Format('%d', [b]), 'proba', MB_OK);
end;

exports
proba1;

begin
end.

При вызове в NSIS так:
My_dll::proba1
Всегда показывает "1", т.е. значение предыдущего вызова теряется. Как так?




© OSzone.net 2001-2012