|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
||||
|
||||
Установка программ по списку из ini-файла
Добрый день!
Нужно написать утилиту, которая будет при нажатии кнопки устанавливать программы по списку из ini-файла. Пример содержания файла: [soft] 7zip=7zip\7z.exe WinRAR=winrar\setup.exe При нажатии кнопки установки, утилита должна читать ini-файл, а затем, следуя списку, запускать по очереди инсталляторы. При этом хочется, чтобы это происходило в отдельном потоке, основная программа была бы доступна, и имелась возможность прервать процесс установки по нажатию соответствующей кнопки. Собственно, вопрос: как правильно считать значения ключей из секции ini-файла и запихнуть их в CreateProcess, снабдив все это отдельным потоком? Последний раз редактировалось nerZEROn, 23.12.2013 в 13:25. |
#2
|
||||
|
||||
Цитата:
CreateProcess используешь примерно так: Код:
var SI: TStartupInfo; PI: TProcessInformation; ..... begin ..... FillChar(SI, SizeOf(SI), 0); SI.cb := SizeOf(SI); SI.wShowWindow := SW_NORMAL; SI.dwFlags := STARTF_USESHOWWINDOW; if CreateProcess('Запускаемое приложение', nil, nil, nil, False, 0, nil, nil, SI, PI) then try while True do begin if (WaitForSingleObject(PI.hProcess, 100) <> WAIT_TIMEOUT) or Terminated then Break; end; finally CloseHandle(PI.hProcess); CloseHandle(PI.hThread); end; ..... end; Для создания отдельного потока, используй BeginThread или создавай своего потомка от TThread или можешь использовать дополнительные компоненты - просто бросаешь такую компоненту на форму и задаёшь ей нужные обработчики событий. Например в библиотеке RxLib есть такая компонента, или вот здесь есть подобная (TBMDThread). |
Этот пользователь сказал Спасибо poli-smen за это полезное сообщение: | ||
nerZEROn (23.12.2013)
|
#3
|
||||
|
||||
А можно поподробнее по поводу цикла и считывания через ReadString? Я не особо хорошо в этом разбираюсь Нужно ведь сделать считывание по порядку из списка значений... но как это сделать и избавиться от бесконечного цикла?
|
#4
|
||||
|
||||
Цитата:
Код:
procedure TForm1.Button1Click(Sender: TObject); var ini: TMemIniFile; sl: TStringList; i: Integer; Ident, Value: String; begin ini := TMemIniFile.Create('ИмяФайла.ini'); try sl := TStringList.Create; try ini.ReadSection('soft', sl); for i := 0 to sl.Count - 1 do begin Ident := sl[i]; Value := ini.ReadString('soft', Ident, '???'); ShowMessageFmt('Для установки "%s" запускаем "%s"', [Ident, Value]); end; finally sl.Free; end; finally ini.Free; end; end; |
Этот пользователь сказал Спасибо poli-smen за это полезное сообщение: | ||
nerZEROn (26.12.2013)
|
#5
|
||||
|
||||
Цитата:
На этом этапе получаю сообщения типа 'Для установки "7Zip" запускаем "???"'. Выходит, Value не считывается? А нет, нашел свой косяк Все нормально работает! Спасибо! Последний раз редактировалось nerZEROn, 26.12.2013 в 13:22. |
#6
|
||||
|
||||
Итак, я пришел к такому обработчику кнопки "Установить":
Код:
procedure TForm1.btn_instClick(Sender: TObject); var ini: TMemIniFile; sl: TStrings; i: Integer; Ident, Value: String; SI: TStartupInfo; PI: TProcessInformation; begin ini := TMemIniFile.Create('install.ini'); FillChar(SI, SizeOf(SI), 0); SI.cb := SizeOf(SI); SI.wShowWindow := SW_NORMAL; SI.dwFlags := STARTF_USESHOWWINDOW; try sl := TStringList.Create; try ini.ReadSection('soft', sl); for i := 0 to sl.Count - 1 do begin Ident := sl[i]; Value := ini.ReadString('soft', Ident, ''); if CreateProcess(PChar(Ident), PChar(' ' + Value), nil, nil, False, 0, nil, nil, SI, PI) then try while True do begin if (WaitForSingleObject(PI.hProcess, 100) <> WAIT_TIMEOUT) then Break; end; finally CloseHandle(PI.hProcess); CloseHandle(PI.hThread); end; end; finally sl.Free; end; finally ini.Free; end; end; В целом программа работает исправно: читает ini и запускает по порядку дистрибутивы программ с параметрами. Но снова столкнулся с проблемой. Гуглил пол дня, копался в примерах и исходниках, но так и не понял, как вывести это все в отдельный поток. Также, я не смог найти никакой документации к компоненту BMDThread. Поскольку приложение будет выполнять у меня по несколько функций сразу, жизненно необходимо, чтобы основная форма была доступна во время инсталляции сторонних программ. |
#7
|
||||
|
||||
Цитата:
В событии OnExecute у BMDThread пиши то, что должно выполняться в отдельном потоке (thread), а для запуска потока просто вызови например по нажатию кнопки метод Start: Код:
procedure TForm1.btn_instClick(Sender: TObject); begin BMDThread1.Start; end; |
#8
|
||||
|
||||
Цитата:
|
#9
|
||||
|
||||
Цитата:
|
#10
|
||||
|
||||
Цитата:
Код:
TMyThread = class(TThread) private { Private declarations } protected procedure Execute; override; end; Запихнул в процедуру код на инсталляцию и ура! Приложение не виснет во время выполнения |