Исходники.Ру - Программирование
Исходники
Статьи
Книги и учебники
Скрипты
Новости RSS
Магазин программиста

Главная » Статьи по программированию » Delphi - Приложения и распространение программ »

Обсудить на форуме Обсудить на форуме

INSTALL'им программы по списку

Постановка задачи. Подготовка

Писать будем на Delphi. Исходя из идеи, мы должны создать список программ, которые будут видны в нашей программе, и предоставить возможность выбора(какие программы устанавливать), после чего начать устанавливать их по очереди, не отвлекаясь на поиск setup'ного файла в папках. Список программ будет создан заранее и ручками. Хранить названия программ, путь доступа к ним, относительно нашего exe'шника, и краткое описание, будем в ini файле. Структура ini файла:

[Название программы]
Path=путь к программе
Text=краткое описание

Например:

[winamp.exe]
Path=soft\winamp.exe
Text=плейер

К тому же наша программа будет сохранять введенные пользователем данные, в случае перезагрузки компьютера (что часто бывает после установки драйверов), и запускать после неё для продолжения операций. Для хранения настроек будем использовать спецкаталог для временных файлов. На этом, пожалуй, подготовительный этап закончен.

Реализация

Нам естественно понадобится форма, назовем её installform. Также бросить на неё компоненты: ChtckListBox, 4 Button'a , Memo ( по желанию добавьте, что-нибудь что будет пояснять что для чего). Присвоим имена в том же порядке, в котором положили на форму компоненты: filelist, startbutton, closebutton, allbutton, nonebutton, textlist. После старта программы сразу должны отображаться доступные программы, для этого пишем следующее:

procedure TInstallForm.FormCreate(Sender: TObject);
var s:string;
    f:textfile;
    i:integer;
    res:word;
begin
// определяем местоположение папки Temp
temppath := StrAlloc(255);
res:= gettemppath(255,temppath);
// ассоциируем переменную inifile типа TIniFile с нашим ini файлом
INIFile:=TIniFile.Create(extractfilepath(application.ExeName)+'installlist.ini');
// создаем tstr:TStringList для хранения названия программ
tstr:=TStringList.Create;
// считываем названия прог в tstr
inifile.ReadSections(tstr);
// отображаем в filelist'е
filelist.Items.AddStrings(tstr);
// проверяем были ли до этого сохранены какие-нибудь данные (в случае
//перезагрузки компа или его отключения до окончания операции установки)
if fileexists(temppath+'\installlist.txt')=true then
    begin
      assignfile(f,temppath+'\installlist.txt');
      reset(f);
      readln(f,s);
      while not eof(f) do
        begin
          readln(f,s);
          for i:=0 to filelist.count-1 do
            if filelist.Items.Strings[i]=s then
               filelist.Checked[i]:=true;
        end;
      closefile(f);
    end;

end;

Как видно, данные о предшествующей загрузке будем хранить в txt файле. Если файл существует, то применяем соответствующие настройки. Теперь рассмотрим случай, когда понадобится сбросить выбор всех программ или же наоборот поставить в очередь сразу все проги. Вот для этого мы будем использовать allbutton и nonebutton: при нажатии на первую будут устанавливаться флажки, а на вторую сниматься. Пишем этот код:

procedure TInstallForm.AllButtonClick(Sender: TObject);
var i:integer;
begin
for i:=0 to filelist.Count-1 do
 filelist.Checked[i]:=true;
end;

procedure TInstallForm.NoneButtonClick(Sender: TObject);
var i:integer;
begin
for i:=0 to filelist.Count-1 do
 filelist.Checked[i]:=false;
end;

Несложно, правда. Теперь займемся отображением описания каждой программы. Для этого код вот этот:

procedure TInstallForm.FileListClick(Sender: TObject);
var def:string;
begin
textlist.Clear;
textlist.LineS.add(
   inifile.ReadString(filelist.Items.strings[filelist.itemindex],'Text',def));
end;

Кстати, переменная inifile распространяется на всю нашу прогу. Здесь мы просто выводим в textlist, то что считали из ini файла (это происходит при клике по надписи выбранной строки). Ну, теперь опишем кнопку closebutton:

procedure TInstallForm.CloseButtonClick(Sender: TObject);
var
    reg:tregistry;
begin
reg:=tregistry.Create;
reg.RootKey:=HKEY_LOCAL_MACHINE;
 if reg.openkey('SOFTWARE\Microsoft\Windows\CurrentVersion\Run',false)=true then
   begin
     reg.DeleteValue('AutoInstall') ;
   end;
reg.CloseKey;
reg.Destroy;
deletefile(temppath+'\installlist.txt');
application.Terminate;
end;

А что так много спросите вы? Казалось бы application.terminate и все, но не так все просто, а вот почему: дело в том, что если выход из программы корректен, то нам нужно удалить из реестра следы нами оставленные (оставим мы их только при незавершенных операция установки), или просто удостовериться, что их там нет(и рам и пользователю спокойно). Также удаляем файл с настройками. Почему application.terminate, а не installform.close, потому что мне полгода твердили в институте, что так правильнее (хотя кто как хочет). переходим к самому сложному в коде - описанию кнопки startbutton. Хотя если хоть немного читать и иметь под рукой MSDN и это несложно (сам проверял). Итак, пишем вот это:

procedure TInstallForm.StartButtonClick(Sender: TObject);
var k,i:integer;
    def:string;
    f:textfile;
    reg:tregistry;
    pres:string;
begin
// сохраняем себя в реестре (на всякий случай)
reg:=tregistry.Create;
reg.RootKey:=HKEY_LOCAL_MACHINE;
 if reg.openkey('SOFTWARE\Microsoft\Windows\CurrentVersion\Run',false)=true then
   begin
     pres:=reg.ReadString('AutoInstall');
     if (pres='')or(pres<>application.exename) then
             if reg.CreateKey('AutoInstall')=true then
                     reg.WriteString('AutoInstall',application.exename);
   end;
reg.CloseKey;
reg.Destroy;
// минимизируемся
showwindow(installform.Handle,2);
// обрабатываем все отмеченные флаги по очереди
for k:=0 to tstr.count-1 do
 begin
// предварительно сохраняем настройки в installlist.txt
  assignfile(f,temppath+'\installlist.txt');
  rewrite(f);
  for i:=0 to filelist.count-1 do
    if filelist.Checked[i]=true then
       writeln(f,filelist.items.strings[i]);
  closefile(f);
  if filelist.Checked[k]=true then
   begin
    filelist.Checked[k]:=false;
    StartAndWaitEnd(extractfilepath(application.ExeName)+
          inifile.ReadString(tstr.Strings[k],'Path',def));
   end;
 end;
// после окончания операции устраняем себя из реестра
reg:=tregistry.Create;
reg.RootKey:=HKEY_LOCAL_MACHINE;
 if reg.openkey('SOFTWARE\Microsoft\Windows\CurrentVersion\Run',false)=true then
   begin
     reg.DeleteValue('AutoInstall') ;
   end;
reg.CloseKey;
reg.Destroy;
// возвращаем окно к исходному виду и положению
showwindow(installform.Handle,1);
// убиваем файл с настройками
deletefile(temppath+'\installlist.txt');
end;

Вот и все. А нет не все я еще не рассказал о функции StartAndWaitEnd. Она нужна для того, чтобы запустить приложение, передать ему управление и, дождавшись его закрытия, передать управление нашей проге для продолжения работы. Вот и код этой функции:

function TInstallForm.StartAndWaitEnd(cmdline:string):boolean;
var  si:TSTARTUPINFO;
     pi:TPROCESSINFORMATION;
begin
ZeroMemory(@si,sizeof(si));
si.cb:=SizeOf(si);
si.dwFlags := startf_UseShowWindow;
si.wShowWindow:=1;
if not CreateProcess( nil,PChar(cmdline),nil,nil,False,0,nil,nil,si,pi ) then
        begin
         StartAndWaitEnd:=false;
        end
else
        StartAndWaitEnd:=true;
    application.ProcessMessages;
    WaitForSingleObject( pi.hProcess, INFINITE );
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
end;

Здесь CreatePorcess запускает выбранное приложение, а WaitForSingleObject ожидает, пока процесс завершится. Кто хочет знать больше - читайте MSDN, есть еще много всякой литературы по этому поводу. Вот теперь все!

Заключение

Это вроде все, но если кто знает способ по-лучше с удовольствием ознакомлясь. Не забудьте подключить модули Registry и IniFiles. Кстати, сама наша прога будет недоступна пока работает запущенное с помощью неё приложение (много пытался не получилось "оживить"), а так все работает корректно, а нажимать "да", "далее", "готово" придется все равно самому. Пишите комментарии, почитаю. Если у кого-то есть предложения (например, как и Abigor'а оставьте сообщение kosfiz'у или в комментарии опишите). Если у кого есть вопросы, то пишите мне на ящик, обязательно отвечу. Прошу прощение за возможные опечатки.


Может пригодится:


Автор: Панков Константин
Прочитано: 5991
Рейтинг:
Оценить: 1 2 3 4 5

Комментарии: (1)

Прислал: Дмитрий
Использую Borland Delphi 7. Вообще я новичок в программировании и никогда не сталкивался. Модули подключил, все написал, при нажатии F9 выделяет красным строку: temppath := StrAlloc(255); (пробел нужен перед ":"? - убирал - не помогает)

Добавить комментарий
Ваше имя*:
Ваш email:
URL Вашего сайта:
Ваш комментарий*:
Код безопастности*:

Рассылка новостей
Рейтинги
© 2007, Программирование Исходники.Ру