www.adept7.kiev.ua
| Форум| Гостевая| Ссылки| Программы| Исходные тексты| Наши партнеры|
   
| Главная| Рассылки| Услуги| Библиотека| Новости| Авторам| Программистам| Студентам|
delphi c++ assembler
 

Советы для написания программ-инсталляторов

Регистрация программ в меню "Пуск" Windows 95
Копирование файлов
Как скопировать все файлы вместе с подкаталогами
Удаление каталога со всем содержимым
Определение системной информации
Как проинсталлировать свои шрифты?
Вставить какую-нибудь программу внутрь EXE файла
Хочется создать ну очень маленький инсталлятор
Как зарегистрировать новый тип файла за своим приложением.
Добавление программы в автозапуск
Удалить файл в корзину? Запросто!
Добавить ссылку на мой файл в меню Пуск|Документы
Устанавливаем свой WallPaper для Windows
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


Регистрация программ в меню "Пуск" Windows 95.
Подобная проблема возникает при создании инсталляторов и деинсталляторов.
Наиболее простой и гибкий путь - использование DDE.
При этом посылаются запросы к PROGMAN. 
Для этого необходимо поместить на форму компонент для посылки DDE запросов - объект 
типа TDdeClientConv. Для определенности назовем его DDEClient.
Затем добавим метод для запросов к PROGMAN:
Function TForm2.ProgmanCommand(Command:string):boolean;
i
 macrocmd:array[0..88] of char;
begin
 DDEClient.SetLink('PROGMAN','PROGMAN');
 DDEClient.OpenLink; { Устанавливаем связь по DDE }
 strPCopy(macrocmd,'['+Command+']'); { Подготавливаем ASCIIZ строку }
 ProgmanCommand :=DDEClient.ExecuteMacro(MacroCmd,false);
 DDEClient.CloseLink; { Закрываем связь по DDE }
end;

При вызове ProgmanCommand возвращает true, если посылка макроса была успешна. Система команд (основных) приведена ниже:
Create(Имя группы, путь к GRP файлу)
Создать группу с именем "Имя группы", причем в нем могут быть пробелы и знаки препинания. Путь к GRP файлу можно не указывать, тогда он создастся в каталоге Windows.
Delete(Имя группы)
Удалить группу с именем "Имя группы"
ShowGroup(Имя группы, состояние)
Показать группу в окне, причем состояние - число, определяющее параметры окна:
1-нормальное состояние + активация
2-миним.+ активация
3-макс. + активация
4-нормальное состояние
5-Активация
AddItem(командная строка, имя раздела, путь к иконке, индекс иконки (с 0), Xpos,Ypos, рабочий каталог, HotKey, Mimimize)
Добавить раздел к активной группе. В командной строке, имени размера и путях допустимы пробелы, Xpos и Ypos - координаты иконки в окне, лучше их не задавать, тогда PROGMAN использует значения по умолчанию для свободного места. HotKey - виртуальный код горячей клавиши. Mimimize - тип запуска, 0-в обычном окне, <>0 - в минимизированном.
DeleteItem(имя раздела)
Удалить раздел с указанным именем в активной группе
Пример использования:
ProgmanCommand('CreateGroup(Комплекс программ для каталогизации литературы,)');
ProgmanCommand('AddItem('+path+'vbase.hlp,Справка по VBase,'+ path +' vbase.hlp, 0, , , '+ path + ',,)');
где path - строка типа String, содержащая полный путь к каталогу ('C:\Catalog\');
 

Наверх к содержанию



Копирование файлов

Копирование методом TurboPascal

Type
  TCallBack=procedure (Position,Size:Longint); {Для индикации процесса копирования}
procedure FastFileCopy(Const InfileName, OutFileName: String; CallBack: TCallBack);
Const BufSize=3*4*4096; { 48Kbytes дает прекрасный результат }
Type
  PBuffer=^TBuffer;
  TBuffer=array [1..BufSize] of Byte;
i
  Size            : integer;
  Buffer          : PBuffer;
  infile, outfile  : File;
  SizeDone,SizeFile: Longint;
begin
  if (InFileName <> OutFileName) then
  begin
  buffer :=Nil;
  AssignFile(infile, InFileName);
  System.Reset(infile, 1);
  try
    SizeFile :=FileSize(infile);
    AssignFile(outfile, OutFileName);
    System.Rewrite(outfile, 1);
    try
      SizeDone :=0; New(Buffer);
      repeat
        BlockRead(infile, Buffer^, BufSize, Size);
        Inc(SizeDone, Size);
        CallBack(SizeDone, SizeFile);
        BlockWrite(outfile,Buffer^, Size)
      until Size < BufSize;
      FileSetDate(TFileRec(outfile).Handle,
        FileGetDate(TFileRec(infile).Handle));
    finally
      if Buffer <> Nil then Dispose(Buffer);
      System.close(outfile)
    end;
  finally
    System.close(infile);
  end;
 end else
  Raise EInOutError.Create('File cannot be copied into itself');
end;
Копирование методом потока
Procedure FileCopy(Const SourceFileName, TargetFileName: String);
i
  S,T  : TFileStream;
Begin
 S :=TFileStream.Create(sourcefilename, fmOpenRead );
 try
  T :=TFileStream.Create(targetfilename, fmOpenWrite or fmCreate);
  try
    T.CopyFrom(S, S.Size ) ;
    FileSetDate(T.Handle, FileGetDate(S.Handle));
  finally
  T.Free;
  end;
 finally
  S.Free;
 end;
end;
Копирование методом LZExpand
uses LZExpand;
procedure CopyFile(FromFileName, ToFileName  : string);
i
  FromFile, ToFile: File;
begin
  AssignFile(FromFile, FromFileName);
  AssignFile(ToFile, ToFileName);
  Reset(FromFile);
  try
  Rewrite(ToFile);
  try
    if LZCopy(TFileRec(FromFile).Handle, TFileRec(ToFile).Handle)<0 then
    raise Exception.Create('Error using LZCopy')
  finally
    CloseFile(ToFile);
  end;
  finally
  CloseFile(FromFile);
  end;
end;
Копирование методами Windows
uses ShellApi; // !!! важно
function WindowsCopyFile(FromFile, ToDir : string) : boolean;
i F : TShFileOpStruct;
begin
  F.Wnd :=0; F.wFunc :=FO_COPY;
  FromFile:=FromFile+#0; F.pFrom:=pchar(FromFile);
  ToDir:=ToDir+#0; F.pTo:=pchar(ToDir);
  F.fFlags :=FOF_ALLOWUNDO or FOF_NOCONFIRMATION;
  result:=ShFileOperation(F)=0;
end;
 // пример копирования
procedure TForm1.Button1Click(Sender: TObject);
begin
 if not WindowsCopyFile('C:\UTIL\ARJ.EXE', GetCurrentDir) then
  ShowMessage('Copy Failed');
end;
Наверх к содержанию


Как скопировать все файлы вместе с подкаталогами
uses ShellApi;
procedure TForm1.Button1Click(Sender: TObject);
i
  OpStruc: TSHFileOpStruct;
  frombuf, tobuf: Array [0..128] of Char;
Begin
 FillChar( frombuf, Sizeof(frombuf), 0 );
 FillChar( tobuf, Sizeof(tobuf), 0 );
 StrPCopy( frombuf, 'h:\hook\*.*' );
 StrPCopy( tobuf, 'd:\temp\brief' );
 With OpStruc DO Begin
  Wnd:=Handle;
  wFunc:=FO_COPY;
  pFrom:=@frombuf;
  pTo:=@tobuf;
  fFlags:=FOF_NOCONFIRMATION or FOF_RENAMEONCOLLISION;
  fAnyOperationsAborted:=False;
  hNameMappings:=Nil;
  lpszProgressTitle:=Nil;
 end;
 ShFileOperation( OpStruc );
end;
Наверх к содержанию


Удаление каталога со всем содержимым
{ Удалить каталог со всем содержимым }
function DeleteDir(Dir  : string)  : boolean;
i
 Found  : integer;
 SearchRec : TSearchRec;
begin
  result:=false;
  if IOResult<>0 then ;
  ChDir(Dir);
  if IOResult<>0 then begin
  ShowMessage('Не могу войти в каталог: '+Dir); exit;
  end;
  Found :=FindFirst('*.*', faAnyFile, SearchRec);
  while Found=0 do
  begin
  if (SearchRec.Name<>'.')and(SearchRec.Name<>'..') then
    if (SearchRec.Attr and faDirectory)<>0 then begin
    if not DeleteDir(SearchRec.Name) then exit;
    end else
    if not DeleteFile(SearchRec.Name) then begin
      ShowMessage('Не могу удалить файл: '+SearchRec.Name); exit;
    end;
    Found :=FindNext(SearchRec);
  end;
  FindClose(SearchRec);
  ChDir('..'); RmDir(Dir);
  result:=IOResult=0;
end;
Наверх к содержанию


Определение системной информации.
Часто при создании систем привязки программ к компьютеру или окон типа
System Info или About Box необходимо определить данные о пользователе и
о системе. Это можно сделать следующим образом (из примеров по Delphi -
программа COA):
Procedure GetInfo;
i
 WinVer, WinFlags : LongInt;            { Версия Windows и флаги }
 hInstUser, Fmt : Word;                { Дескриптор  }
 Buffer : ARRAY[0..30] OF Char; { Буфер под ASCIIZ строку }
begin
 hInstUser :=LoadLibrary('USER');      { Открыли библиотеку User }
 LoadString(hInstUser, 514, Buffer, 30);
 LabelUserName.Caption :=StrPas(Buffer);      { Имя пользователя }
 LoadString(hInstUser, 515, Buffer, 30);
 FreeLibrary(hInstUser);
 LabelCompName.Caption :=StrPas(Buffer);      { Компания }
 WinVer :=GetVersion;
 LabelWinVer.Caption :=Format('Windows %u.%.2u',      { Версия Windows }
        [LoByte(LoWord(WinVer)), HiByte(LoWord(WinVer))]);
 LabelDosVer.Caption :=Format('DOS %u.%.2u',  { Версия DOS }
        [HiByte(HiWord(WinVer)), LoByte(HiWord(WinVer))]);
 WinFlags :=GetWinFlags;
 IF WinFlags AND WF_ENHANCED > 0 THEN
  LabelWinMode.Caption :='386 Enhanced Mode'  { Режим }
 ELSE IF WinFlags AND WF_PMODE > 0 THEN
  LabelWinMode.Caption :='Standard Mode'
 ELSE LabelWinMode.Caption :='Real Mode';
 IF WinFlags AND WF_80x87 > 0 THEN            { Сопроцессор }
  ValueMathCo.Caption :='Present'
 ELSE ValueMathCo.Caption :='Absent';
 Fmt :=GetFreeSystemResources(GFSR_SYSTEMRESOURCES);
 ValueFSRs.Caption :=Format('%d%% Free', [Fmt1]);      { Свободно ресурсов }
{ Свободно памяти}
 ValueMemory.Caption :=FormatFloat(',#######', MemAvail DIV 1024) + ' KB Free';       
end;
Наверх к содержанию


Как проинсталлировать свои шрифты?
Добавить фонт (.fon, .fot, .fnt, .ttf) в систему можно след. образом:
{$IFDEF WIN32}
    AddFontResource( PChar( my_font_PathName { AnsiString } ) );
{$ELSE}
i
    ss  : array [ 0..255 ] of Char;
    AddFontResource ( StrPCopy ( ss, my_font_PathName ));
{$ENDIF}
    SendMessage ( HWND_BROADCAST, WM_FONTCHANGE, 0, 0 );
Убрать его по окончании работы:
{$IFDEF WIN32}
    RemoveFontResource ( PChar(my_font_PathName) );
{$ELSE}
    RemoveFontResource ( StrPCopy ( ss, my_font_PathName ));
{$ENDIF}
    SendMessage ( HWND_BROADCAST, WM_FONTCHANGE, 0, 0 );
При этом не надо никаких перезагрузок и прочего, после добавления фонт
сразу можно использовать. my_font_PathName : string ( не string[nn] для
D2+) - содержит полный путь с именем и расширением необходимого фонта.
После удаления фонта форточки о нем забывают. Если его не удалить, он (кажется)
так и останется проинсталенным, во всяком случае, я это не проверял.
 
 

Наверх к содержанию


Вставить
какую-нибудь программу внутрь EXE файла

1. Пишем в блокноте RC-файл, куда прописываем все нужные нам программы, например:
ARJ EXEFILE C:\UTIL\ARJ.EXE
2. Компилируем его в ресурс при помощи Brcc32.exe. Получаем RES-файл.
3. Далее в тексте нашей программы:

implementation
{$R *.DFM}
{$R test.res} //Это наш RES-файл
procedure ExtractRes(ResType, ResName, ResNewName : String);
i
  Res : TResourceStream;
begin
  Res :=TResourceStream.Create(Hinstance, Resname, Pchar(ResType));
  Res.SavetoFile(ResNewName);
  Res.Free;
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
 // Записывает в текущую папку arj.exe
 ExtractRes('EXEFILE', 'ARJ', 'ARJ.EXE');
end;
Наверх к содержанию

Как написать маленький инсталлятор ?
Мне понравился следующий вариант: главное приложение само выполняет функции
инсталлятора. Первоначально файл называется Setup.exe. При запуске под
этим именем приложение устанавливает себя, после установки программа переименовывает
себя и перестает быть инсталлятором.
Пример:
 Application.Initialize;
 if UpperCase(ExtractFileName(Application.ExeName))='SETUP.EXE'
  then Application.CreateForm(TSetupForm, SetupForm) // форма
инсталлятора
  else Application.CreateForm(TMainForm, MainForm);  // форма
основной программы
 Application.Run;

Наверх к содержанию



Вопрос:
Как зарегистрировать расширение файла за своим приложением и контекстное
меню,
связанное с этим типом?

Ответ:
Пример регистрирует расширение файла(.myext) - файлы этого типа будут открываться
приложением MyApp.Exe. Также регнстрируется одно действие (action) по умолчанию
для файлов этого типа и два дополнительных пункта контекстного меню, связанного с
этим типом файлов. Возможно, потребуется перезайти в систему чтобы изменения
вступили в силу.

Пример:

uses
        Registry;

procedure TForm1.Button1Click(Sender: TObject);
i
        R : TRegIniFile;
begin
        R :=TRegIniFile.Create('');
        with R do
                begin
                        RootKey :=HKEY_CLASSES_ROOT;
                        WriteString('.myext','','MyExt');
                        WriteString('MyExt','','Some description of MyExt files');
                        WriteString('MyExt\DefaultIcon','','C:\MyApp.Exe,0');
                        WriteString('MyExt\Shell','','This_Is_Our_Default_Action');
                        WriteString('MyExt\Shell\First_Action',
                                                '','This is our first action');
                        WriteString('MyExt\Shell\First_Action\command','',
                                                'C:\MyApp.Exe /LotsOfParamaters %1');
                        WriteString('MyExt\Shell\This_Is_Our_Default_Action','',
                                                'This is our default action');
                        WriteString('MyExt\Shell\This_Is_Our_Default_Action\command',
                                                '','C:\MyApp.Exe %1');
                        WriteString('MyExt\Shell\Second_Action',
                                                '','This is our second action');
                        WriteString('MyExt\Shell\Second_Action\command',
                                                '','C:\MyApp.Exe /TonsOfParameters %1');
                        Free;
                end;
end;
 


 
 

Добавление программы в автозапуск

sProgTitle: Название для программы
sCmdLine: Имя EXE файла с путем доступа
bRunOnce:  Запустить только один раз или постоянно при загрузке Windows
procedure RunOnStartup(sProgTitle, sCmdLine : string; bRunOnce : boolean );
i
  sKey : string;
  reg  : TRegIniFile;
begin
  if( bRunOnce )then sKey :='Once'
  else sKey :='';
  reg :=TRegIniFile.Create( '' );
  reg.RootKey :=HKEY_LOCAL_MACHINE;
  reg.WriteString(
    'Software\Microsoft'
    + '\Windows\CurrentVersion\Run' 
    + sKey + #0,
    sProgTitle,
    sCmdLine );
  reg.Free;
end;
// Например
RunOnStartup('Title of my program','MyProg.exe',False );
Примечание. Этот пример удобно использовать при написании деинсталляторов
- добавить однократный вызов деинсталлятора и запросить от пользователя
перезагрузку. Этот прием позволит безболезненно удалять DLL и им подобные
файлы, которые обычном способом удалить невозможно (они загружены в силу
того, что использовались деинсталлируемой программой или работают в момент
деинсталляции).

Удаляет файл в корзину


uses ShellAPI;
function DeleteFileWithUndo( sFileName : string ) : boolean;
i fos : TSHFileOpStruct;
begin
 sFileName:=sFileName+#0;
  FillChar( fos, SizeOf( fos ), 0 );
  with fos do begin
    wFunc  :=FO_DELETE;
    pFrom  :=PChar( sFileName );
    fFlags :=FOF_ALLOWUNDO or FOF_NOCONFIRMATION or FOF_SILENT;
  end;
  Result :=( 0=ShFileOperation( fos ) );
end;

Добавить ссылку на мой файл в меню Пуск|Документы


uses ShellAPI, ShlOBJ;
procedure AddToStartDocumentsMenu( sFilePath : string );
begin
  SHAddToRecentDocs(  SHARD_PATH, PChar( sFilePath ) );
end;
// Например
AddToStartDocumentsMenu( 'c:\windows\MyWork.txt' );

Устанавливаем свой WallPaper для Windows


program wallpapr;
uses Registry, WinProcs;
procedure SetWallpaper(sWallpaperBMPPath : String; bTile : boolean );
i
  reg : TRegIniFile;
begin
// Изменяем ключи реестра
// HKEY_CURRENT_USER
//  Control Panel\Desktop
//    TileWallpaper (REG_SZ)
//    Wallpaper (REG_SZ)
  reg :=TRegIniFile.Create('Control Panel\Desktop' );
  with reg do begin
    WriteString( '', 'Wallpaper', 
      sWallpaperBMPPath );
    if( bTile )then
    begin
      WriteString('', 'TileWallpaper', '1' );
    end else begin
      WriteString('', 'TileWallpaper', '0' );
    end;
  end;
  reg.Free;
// Оповещаем всех о том, что мы 
// изменили системные настройки
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, Nil, SPIF_SENDWININICHANGE );
end;
begin
 // пример установки WallPaper по центру рабочего стола
 SetWallpaper('c:\winnt\winnt.bmp', False );
end.

 





57

Используются технологии uCoz
Используются технологии uCoz

Rambler's Top100 Rambler's Top100
Используются технологии uCoz

Rambler's Top100 Rambler's Top100

©  Adept Design Studio

Используются технологии uCoz