Показать полную графическую версию : Скрипты Inno Setup. Помощь и советы [часть 8]
eromunald
09-08-2017, 14:31
Добавил IDPForm.FileProgressBar.Visible := False; IDPForm.TotalProgressBar.Visible := False; в результате получилось такое окно (на скрепке)
Nightwishh
10-08-2017, 00:09
Как сделать чтобы при изменении пути в DirEdit кнопка NewButton становилась активной, а при нажатии на кнопку NewButton
она становилась неактивной?
OldGamer
10-08-2017, 20:14
Господа, есть тут кто-нибудь, кто разбирается в Unicode-версии Inno Setup?
Или возможно ли отключить жёсткую проверку синтаксиса?
Установил Inno Setup с поддержкой Unicode, чтобы корректно отображалось название языков.
При компиляции появляются ошибки, а в обычной версии компиляция скрипта проходит без каких-либо проблем.
Что делать с этой строкой "record..."?
#include "botva2.iss"
#include "BASS_Module.iss"
#define GDFExe "{app}\Prog.exe"
#define GDFBinary "{app}\GDF.dll"
[Setup]
SourceDir=.
OutputDir=Setup
AppName=MyProg
AppVersion=1.0
AppPublisher=EmuGames
AppCopyright=EmuGames
AppPublisherURL=
AppSupportURL=
AppUpdatesURL=
DefaultDirName={pf64}\MyProg™
DefaultGroupName=\MyProg™
AllowNoIcons=yes
InfoBeforeFile=\System requirements.txt
InfoAfterFile=\Recommendation.txt
OutputBaseFilename=setup
WizardImageFile=\picture.bmp
WizardSmallImageFile=\small picture.bmp
SetupIconFile=\icon.ico
WindowVisible=no
WindowShowCaption=no
WindowResizable=no
Compression=none
CompressionThreads=4
DiskSpanning=yes
DiskSliceSize=2100000000
SlicesPerDisk=1
RestartIfNeededByRun=no
ShowUndisplayableLanguages=yes
[Languages]
Name: russian; MessagesFile: compiler:Languages\Russian.isl
Name: english; MessagesFile: compiler:Languages\English.isl
Name: french; MessagesFile: compiler:Languages\French.isl
Name: german; MessagesFile: compiler:Languages\German.isl
Name: spanish; MessagesFile: compiler:Languages\Spanish.isl
Name: italian; MessagesFile: compiler:Languages\Italian.isl
[Messages]
SelectLanguageTitle=MyProg
SelectLanguageLabel=Please select a language. Выберите язык установки.
[LangOptions]
russian.LanguageName=Русский / Russian
english.LanguageName=Английский / English
french.LanguageName=Французский / French
german.LanguageName=Немецкий / German
spanish.LanguageName=Испанский / Spanish
italian.LanguageName=Итальянский / Italian
[Tasks]
Name: desktopicon; Description: Создать ярлык на рабочем столе; GroupDescription: Ярлыки:
Name: pin; Description: Закрепить ярлык на панели задач; GroupDescription: Ярлыки:; Flags: unchecked
Name: DirectX; Description: Обновить DirectX; GroupDescription: Дополнительное программное обеспечение:; Flags: checkablealone
Name: Redist; Description: Установить Microsoft Visual C++ 2010 Redist; GroupDescription: Дополнительное программное обеспечение:; Flags: checkablealone
Name: desktopicon; Description: Русский | Английский | Multi6; GroupDescription: Язык интерфейса:; Flags: exclusive
[Files]
Source: include/GDF.dll; DestDir: {app};
Source: include/GameuxInstallHelper.dll; DestDir: {localappdata}; Flags: overwritereadonly
Source: CallbackCtrl.dll; DestDir: {tmp}; Flags: dontcopy
Source: BASS.dll; DestDir: {tmp}; Flags: dontcopy
Source: innocallback.dll; Flags: dontcopy
Source: botva2.dll; DestDir: {tmp}; Flags: dontcopy
Source: Bass_Files\*; DestDir: {tmp}; Flags: dontcopy
Source: OST.mp3; DestDir: {tmp}; Flags: dontcopy
Source: "\MyProg™.png"; DestDir: {tmp}; Flags: ignoreversion dontcopy nocompression
Source: "\miniature.png"; DestDir: {tmp}; Flags: ignoreversion dontcopy nocompression
Source: "\miniature-2.png"; DestDir: {tmp}; Flags: ignoreversion dontcopy nocompression
Source: "isgsg.dll"; DestDir: {tmp}; Flags: ignoreversion dontcopy nocompression
Source: "\Pakovano\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs sortfilesbyextension;
[Icons]
Name: "{userdesktop}\MyProg"; Filename: "{app}\MyProg.exe"; WorkingDir: "{app}"; Tasks: desktopicon;
Name: "{group}\MyProg"; Filename: "{app}\MyProg.exe";
Name: "{group}\{cm:UninstallProgram,MyProg}"; Filename: "{uninstallexe}"
[Run]
Description: {cm:LaunchProgram, MyProg}; Filename: {app}\MyProg.exe; WorkingDir: {app}; Flags: nowait postinstall skipifsilent
Filename: {src}\Soft\DirectX®\DXSETUP.exe; Parameters: /silent; Tasks: DirectX; StatusMsg: Обновление DirectX...
Filename: {src}\Soft\Vcredist\Vcredist_2010 (x64+x86).exe; Parameters: /q; Tasks: Redist; StatusMsg: Установка Microsoft Visual С++ 2010 Redistributable...
[UninstallDelete]
Type: filesandordirs; Name: "{app}";
Type: filesandordirs; Name: "{localappdata}\Spoon";
Type: filesandordirs; Name: "{localappdata}\VirtualStore";
[Сode]
type TGUID = record Data1: Cardinal; Data2, Data3: Word; Data4: array [0..8] of Char; end;
const PlayTask = 0;
SupportTask = 1;
var GameuxGUID: TGUID;
function GenerateGUID(var GUID: TGUID): Cardinal; external 'GenerateGUID@files:GameuxInstallHelper.dll stdcall setuponly';
function AddToGameExplorer(Binary: String; Path: String; InstallType: Integer; var GUID: TGUID): Cardinal; external 'AddToGameExplorerA@files:GameuxInstallHelper.dll stdcall setuponly';
function CreateTask(InstallType: Integer; var GUID: TGUID; TaskType: Integer; TaskNumber: Integer; TaskName: String; Binary: String; Parameters: String): Cardinal; external 'CreateTaskA@files:GameuxInstallHelper.dll stdcall setuponly';
function RetrieveGUIDForApplication(Binary: String; var GUID: TGUID): Cardinal; external 'RetrieveGUIDForApplicationA@{localappdata}\GameuxInstallHelper.dll stdcall uninstallonly';
function RemoveFromGameExplorer(var GUID: TGUID): Cardinal; external 'RemoveFromGameExplorer@{localappdata}\GameuxInstallHelper.dll stdcall uninstallonly';
function RemoveTasks(var GUID: TGUID): Cardinal; external 'RemoveTasks@{localappdata}\GameuxInstallHelper.dll stdcall uninstallonly';
function IntToHex(Int: Cardinal; Digits: Integer): String; var i, Digit: Integer; ch: Byte;
begin
result:='';
for i:=0 to Digits-1 do
begin
digit:=Int mod 16;
Int:=Int div 16;
if digit<0 then
digit:=digit+16;
ch:=Ord('0')+digit;
if digit>9 then
ch:=ch+7;
result:=chr(ch)+result;
end;
end;
function GetGUID(GGUID: TGUID): String; var i: Integer;
begin
result:='{'+IntToHex(GGUID.Data1, 8)+'-'+IntToHex(GGUID.Data2, 4)+'-'+IntToHex(GGUID.Data3, 4)+'-'+IntToHex(Ord(GGUID.Data4[0]), 2)+IntToHex(Ord(GGUID.Data4[1]), 2)+'-';
for i:=2 to 7 do result:=result+IntToHex(Ord(GGUID.Data4[i]), 2); result:=result+'}';
end;
procedure GDFInstall(Binary, MainExe: String);
begin
GenerateGUID(GameuxGUID);
AddToGameExplorer(ExpandConstant(Binary), ExpandConstant('{app}'), 3, GameuxGUID);
CreateTask(3, GameuxGUID, PlayTask, 0, 'Play', ExpandConstant(MainExe), '');
end;
procedure win7fix;
var regGDF: Cardinal;
var GUXPath: string;
begin
GUXPath := 'Software\Microsoft\Windows\CurrentVersion\GameUX\Games\' + GetGUID(GameuxGUID);
if isWin64 then
begin
if RegQueryDWordValue(HKLM64, GUXPath, 'IsSigned', regGDF) then
if regGDF=0 then
if RegDeleteValue(HKLM64, GUXPath, 'IsSigned') then
RegWriteDWordValue(HKLM64, GUXPath, 'IsSigned', 1);
end
else
begin
if RegQueryDWordValue(HKLM, GUXPath, 'IsSigned', regGDF) then
if regGDF=0 then
if RegDeleteValue(HKLM, GUXPath, 'IsSigned') then
RegWriteDWordValue(HKLM, GUXPath, 'IsSigned', 1);
end;
end;
type
TPBProc = function (h:hWnd;Msg,wParam,lParam:Longint):Longint;
var
TimeLeftLabel : TLabel;
PBOldProc : Longint;
eTime, sTime : DWORD;
var
BASS_Initialized: Boolean;
const
AW_BLEND = $00080000;
AW_HIDE = $00010000;
const
LOAD_LIBRARY_AS_DATAFILE = $2;
#define A = (Defined UNICODE) ? "W" : "A"
function AnimateWindow(hWnd: HWND; dwTime: DWORD; dwFlags: DWORD): Boolean;
external 'AnimateWindow@user32 stdcall';
function LoadLibraryEx(lpFileName: String; hFile: THandle; dwFlags: DWORD): THandle; external 'LoadLibraryEx{#A}@kernel32.dll stdcall';
function LoadString(hInstance: THandle; uID: SmallInt; var lpBuffer: Char; nBufferMax: Integer): Integer; external 'LoadString{#A}@user32.dll stdcall';
function SHGetNewLinkInfo(pszLinkTo, pszDir: String; var pszName: Char; var pfMustCopy: Longint; uFlags: UINT): BOOL; external 'SHGetNewLinkInfo{#A}@shell32.dll stdcall';
function PinToTaskbar(const szFilename: String; IsPin: Boolean): Boolean;
var
hInst: THandle;
buf: array [0..255] of Char;
i, res: Integer;
strLnk, strVerb: String;
objShell, colVerbs: Variant;
begin
Result := False;
if (GetWindowsVersion < $06010000) or not FileExists(szFilename) then Exit; { below Windows 7 }
{ String resources }
if IsPin then
begin
if SHGetNewLinkInfo(szFilename, ExpandConstant('{tmp}'), buf[0], res, 0) then
begin
while buf[Length(strLnk)] <> #0 do Insert(buf[Length(strLnk)], strLnk, Length(strLnk)+1);
if FileExists(ExpandConstant('{userappdata}\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\') + ExtractFileName(strLnk)) then Exit;
end;
res := 5386; { Pin to Tas&kbar }
end else res := 5387; { Unpin from Tas&kbar }
{ Load string resource }
hInst := LoadLibraryEx(ExpandConstant('{sys}\shell32.dll'), 0, LOAD_LIBRARY_AS_DATAFILE);
if hInst <> 0 then
try
for i := 0 to LoadString(hInst, res, buf[0], 255)-1 do Insert(buf[i], strVerb, i+1);
try
objShell := CreateOleObject('Shell.Application');
colVerbs := objShell.Namespace(ExtractFileDir(szFilename)).ParseName(ExtractFileName(szFilename)).Verbs;
for i := 1 to colVerbs.Count do if CompareText(colVerbs.Item[i].Name, strVerb) = 0 then
begin
colVerbs.Item[i].DoIt;
Result := True;
Break;
end;
except
Exit;
end;
finally
FreeDLL(hInst);
end;
end;
type
TTimerProc = procedure(HandleW, Msg, idEvent, TimeSys: LongWord);
var
PercentsTimer: LongWord;
PercentsLabel: TLabel;
function SetWindowLong(hWnd: HWND; nIndex: Integer; dwNewLong: Longint): Longint; external 'SetWindowLongA@user32.dll stdcall';
function CallBackProc(P:TPBProc;ParamCount:integer):LongWord; external 'wrapcallbackaddr@files:CallbackCtrl.dll stdcall';
function CallWindowProc(lpPrevWndFunc: Longint; hWnd: HWND; Msg: UINT; wParam, lParam: Longint): Longint; external 'CallWindowProcA@user32.dll stdcall';
function GetTickCount: DWORD; external 'GetTickCount@kernel32.dll stdcall';
function WrapTimerProc(callback: TTimerProc; Paramcount: Integer): longword; external 'wrapcallback@files:innocallback.dll stdcall';
function SetTimer(hWnd, nIDEvent, uElapse, lpTimerFunc: LongWord): longword; external 'SetTimer@user32';
function KillTimer(hWnd, nIDEvent: LongWord): LongWord; external 'KillTimer@user32 stdcall delayload';
function LongintToStringTime(t:Longint):string;
var
h,m,s:integer;
begin
h:=t div 3600;
t:=t-h*3600;
m:=t div 60;
s:=t-m*60;
Result:='';
if h>0 then Result:=Result+IntToStr(h)+' ч. ';
if (m>0) or (h>0) then Result:=Result+IntToStr(m)+' мин. ';
if (m>0) or (h>0) or (s>0) then Result:=Result+IntToStr(s)+' сек.';
end;
function PBProc(h:hWnd;Msg,wParam,lParam:Longint):Longint;
var
lt:Longint;
dt,at,pr,i1,i2:Extended;
p:string;
tc:DWORD;
begin
Result:=CallWindowProc(PBOldProc,h,Msg,wParam,lParam);
if (Msg=$402) and (WizardForm.ProgressGauge.Position>WizardForm.ProgressGauge.Min) then begin
i1:=WizardForm.ProgressGauge.Position-WizardForm.ProgressGauge.Min;
i2:=WizardForm.ProgressGauge.Max-WizardForm.ProgressGauge.Min;
tc:=GetTickCount;
if (tc-eTime)>=1000 then begin //???????????? ????? ?????????? ?? ????? ????????? ?? ????, ??? ??? ? 1 ???????
dt:=(tc-sTime)/1000;
at:=i2*dt/i1;
lt:=Round(at-dt)
TimeLeftLabel.Caption:='Осталось - '+LongintToStringTime(lt);
eTime:=tc;
end;
pr:=i1*100/i2;
p:=' - ['+Format('%f',[pr])+'%]';
StringChange(p,',','.');
end;
end;
procedure AllCancel;
begin
SetWindowLong(WizardForm.ProgressGauge.Handle,-4,PBOldProc);
TimeLeftLabel.Free;
end;
function InitializeSetup:boolean;
begin
if not FileExists(ExpandConstant('{tmp}\CallbackCtrl.dll')) then ExtractTemporaryFile('CallbackCtrl.dll');
Result:=True;
end;
Function NumToStr(Float: Extended): String;
Begin
Result:= Format('%.1n', [Float]); StringChange(Result, ',', '.');
while ((Result[Length(Result)] = '0') or (Result[Length(Result)] = '.')) and (Pos('.', Result) > 0) do
SetLength(Result, Length(Result)-1);
End;
Procedure PercentsProc(h, msg, idevent, dwTime: Longword);
Begin
with WizardForm.ProgressGauge do
begin
PercentsLabel.Caption:= 'Выполнено ' + NumToStr((Position*100)/Max) + ' %';
end;
End;
const
Indent=25;
function GetWindowLong(hWnd: HWND; nIndex: Integer): Longint; external 'GetWindowLongA@user32.dll stdcall delayload';
function ssInitialize(hParent:HWND;ssTimeShow:integer;FadeOut:boolean;StretchMode:integer;BkgColor:DWORD):boo lean; external 'ssInitialize@files:isgsg.dll stdcall delayload';
procedure ssDeInitialize; external 'ssDeInitialize@files:isgsg.dll stdcall delayload';
procedure ssSetBkgImage(FileName:PChar); external 'ssSetBkgImage@files:isgsg.dll stdcall delayload';
procedure ssAddImage(FileName:PChar); external 'ssAddImage@files:isgsg.dll stdcall delayload';
procedure ssStartShow; external 'ssStartShow@files:isgsg.dll stdcall delayload';
procedure ssStopShow; external 'ssStopShow@files:isgsg.dll stdcall delayload';
procedure ShowSplashScreen(p1:HWND;p2:string;p3,p4,p5,p6,p7:integer;p8:boolean;p9:Cardinal;p10:integer); external 'ShowSplashScreen@files:isgsg.dll stdcall delayload';
function GetSystemMetrics(nIndex:Integer):integer; external 'GetSystemMetrics@user32.dll stdcall delayload';
procedure RunListClickCheck(Sender: TObject);
var
i:integer;
begin
if WizardForm.RunList.Checked[WizardForm.RunList.ItemIndex] then begin
for i:=0 to WizardForm.RunList.Items.Count-1 do
WizardForm.RunList.Checked[i]:=False;
WizardForm.RunList.Checked[WizardForm.RunList.ItemIndex]:=True;
end;
end;
procedure InitializeWizard();
begin
ExtractTemporaryFile('Bass.dll');
ExtractTemporaryFile('botva2.dll');
ExtractTemporaryFile('volmax.png');
ExtractTemporaryFile('volmin.png');
ExtractTemporaryFile('volpb.png');
ExtractTemporaryFile('voldote.png');
ExtractTemporaryFile('OST.mp3');
ExtractTemporaryFile('MusicButton.png');
ExtractTemporaryFile('miniature.png');
ExtractTemporaryFile('miniature-2.png');
ShowSplashScreen(WizardForm.Handle,ExpandConstant('{tmp}')+'\miniature.png',4000,4000,2000,0,255,Fal se,$FFFFFF,10);
ShowSplashScreen(WizardForm.Handle,ExpandConstant('{tmp}')+'\miniature-2.png',4000,4000,2000,0,255,False,$FFFFFF,10);
ssInitialize(GetWindowLong(MainForm.Handle,-8),5,True,1,$FF000000);
WizardForm.RunList.OnClickCheck:=@RunListClickCheck;
BASS_Init('{tmp}\OST.mp3')
BASS_CreateMediaPlayer(WizardForm, '{tmp}\volmax.png', '{tmp}\volmin.png', '{tmp}\volpb.png', '{tmp}\voldote.png', 20, 325)
BASS_Initialized := True;
ExtractTemporaryFile('MyProg™.png');
ssSetBkgImage(ExpandConstant('{tmp}')+'\MyProg™.png');
WizardForm.TypesCombo.ItemIndex:=0;
PercentsLabel:= TLabel.Create(WizardForm);
with PercentsLabel do
begin
Left:= WizardForm.ProgressGauge.Left;
Top:= WizardForm.ProgressGauge.Top + WizardForm.ProgressGauge.Height + ScaleY(10);
Width:= WizardForm.StatusLabel.Width;
Height:= WizardForm.StatusLabel.Height;
AutoSize:= False;
Transparent := True;
Parent:= WizardForm.InstallingPage;
end;
end;
procedure CurStepChanged(CurStep: TSetupStep);
var Version: TWindowsVersion;
begin
GetWindowsVersionEx(Version);
if (CurStep = ssPostInstall) and Version.NTPlatform and (Version.Major > 5) then begin
GDFInstall('{#GDFBinary}', '{#GDFExe}');
win7fix;
end;
begin
case CurStep of
ssInstall: begin
TimeLeftLabel:=TLabel.Create(nil);
with TimeLeftLabel do begin
Parent:=WizardForm.InstallingPage;
AutoSize:=True;
SetBounds(WizardForm.ProgressGauge.Left + ScaleX(250),WizardForm.ProgressGauge.Top + ScaleY(30),ScaleY(80),ScaleY(21));
end;
sTime:=GetTickCount;
eTime:=sTime;
PBOldProc:=SetWindowLong(WizardForm.ProgressGauge.Handle,-4,CallBackProc(@PBProc,4));
end;
ssPostInstall: AllCancel;
end;
begin
if CurStep=ssInstall then begin
PercentsTimer:= SetTimer(0, 0, 100, WrapTimerProc(@PercentsProc, 4));
ExtractTemporaryFile('MyProg™.png');
ssAddImage(ExpandConstant('{tmp}')+'\MyProg™.png');
end;
if CurStep=ssPostInstall then ssStopShow;
end;
end;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
case CurPageID of
wpFinished: end
if IsTaskSelected('Pin') then
PinToTaskbar(ExpandConstant('{app}\MyProg.exe'), True);
if CurPageID=wpInstalling then begin;
WizardForm.MainPanel.Visible:=False;
WizardForm.Bevel1.Visible:=False;
WizardForm.Width:=ScaleX(395);
WizardForm.Height:=ScaleY(142);
WizardForm.Left:=ScaleX(GetSystemMetrics(0)-WizardForm.Width-Indent);
WizardForm.Top:=ScaleY(GetSystemMetrics(1)-WizardForm.Height-Indent);
WizardForm.InnerNotebook.Left:=ScaleX(10);
WizardForm.InnerNotebook.Top:=ScaleY(10);
WizardForm.InnerNotebook.Width:=ScaleX(370);
WizardForm.StatusLabel.Left:=ScaleX(0);
WizardForm.StatusLabel.Top:=ScaleY(0);
WizardForm.StatusLabel.Width:=WizardForm.InnerNotebook.Width;
WizardForm.FileNameLabel.Left:=ScaleX(0);
WizardForm.FileNameLabel.Top:=ScaleY(20);
WizardForm.FileNameLabel.Width:=WizardForm.InnerNotebook.Width;
WizardForm.ProgressGauge.Top:=ScaleY(40);
WizardForm.ProgressGauge.Width:=WizardForm.InnerNotebook.Width;
WizardForm.CancelButton.Left:=ScaleX(154);
WizardForm.CancelButton.Top:=ScaleY(80);
end;
if (CurPageID=wpFinished) or (CurPageID=wpInfoAfter) then begin
WizardForm.RunList.Checked[0]:=True;
if WizardForm.Width<>502 then begin
WizardForm.Visible:=False;
WizardForm.Width:=ScaleX(502);
WizardForm.Height:=ScaleY(392);
WizardForm.Left:=(GetSystemMetrics(0)-WizardForm.Width) div 2;
WizardForm.Top:=(GetSystemMetrics(1)-WizardForm.Height) div 2;
WizardForm.MainPanel.Visible:=True;
WizardForm.Bevel1.Visible:=True;
WizardForm.InnerNotebook.Left:=ScaleX(40);
WizardForm.InnerNotebook.Top:=ScaleY(72);
WizardForm.InnerNotebook.Width:=ScaleX(417);
WizardForm.Visible:=True;
end;
end;
end;
function NextButtonClick(CurPageID: Integer): Boolean;
begin
Result := True;
if CurPageID=wpFinished then
begin
if WizardForm.RunList.Checked[0] then
Result := True;
end;
end;
procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
begin
if MsgBox(SetupMessage(msgExitSetupMessage), mbConfirmation, MB_OKCANCEL) = IDOK then
begin
Confirm := False;
AnimateWindow(WizardForm.Handle, 2500, AW_BLEND or AW_HIDE);
Cancel := True;
end else
Cancel := False;
end;
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
Binary: String;
GUID: TGUID;
begin
if CurUninstallStep=usUninstall then
begin
Binary:=ExpandConstant('{#GDFBinary}');
RetrieveGUIDForApplication(Binary, GUID);
RemoveFromGameExplorer(GUID);
RemoveTasks(GUID);
UnloadDll(ExpandConstant('{localappdata}\GameuxInstallHelper.dll'));
end;
begin
if (CurUninstallStep=usUninstall) then
begin
case CurUninstallStep of
usUninstall: begin
PinToTaskbar(ExpandConstant('{app}\MyProg.exe'), False);
end;
end;
end;
end;
end;
procedure DeinitializeSetup();
begin
if BASS_Initialized then
begin
KillTimer(0, PercentsTimer);
ssDeInitialize;
BASS_DeInit;
gdipShutdown
end;
end;
Буду очень благодарен за помощь.
usermode
15-08-2017, 14:23
Пытаюсь прикрутить к Inno чтение с консоли, причем нужна реализация через пайпы и чтобы текст построчно отображался в Memo.
Пытаюсь адаптировать следующий пример, 3-ий на странице (RunDosInMemo):
http://decoding.dax.ru/faq/vcl/console/console001.html
Вроде почти перевел, но осталась заморочка именно с чтением через ReadFile и вывод, соответственно в Memo, да, там должны передаваться символы и строки, у меня счас там цифры, содрал с одного примера, но подружить с текстом не удается.
Просьба продвинутых поправить пример, если это возможно.
[Setup]
AppName=MyApp
Appvername=MyApp
DefaultDirname={pf}\MyApp
[_Code]
const
ReadBuffer = 2400;
STARTF_USESTDHANDLES = $100;
STARTF_USESHOWWINDOW = 1;
NORMAL_PRIORITY_CLASS = $00000020;
HEAP_ZERO_MEMORY = $0008;
WAIT_TIMEOUT = $00000102;
type
TMyMsg = record hWnd: HWND; msg, wParam: Word; lParam: LongWord; Time: TFileTime; pt: TPoint; end;
type
TSecurityAttributes = record
nLength: DWord;
lpSecurityDescriptor: longint;
bInheritHandle: Boolean;
end;
TProcessInformation = record
hProcess:DWORD;
hThread:DWORD;
dwProcessId:DWORD;
dwThreadId:DWORD;
end;
TStartupInfo = record
cb:DWORD;
lpReserved:DWORD; // not PChar; - need NULL pointer
lpDesktop:DWORD; // not PChar; - need NULL pointer
lpTitle:DWORD; // not PChar; - need NULL pointer
dwX:DWORD;
dwY:DWORD;
dwXSize:DWORD;
dwYSize:DWORD;
dwXCountChars:DWORD;
dwYCountChars:DWORD;
dwFillAttribute:DWORD;
dwFlags:DWORD;
wShowWindow:WORD;
cbReserved2:WORD;
lpReserved2:DWORD;
hStdInput:DWORD;
hStdOutput:DWORD;
hStdError:DWORD;
end;
// ----------------------------------------------------------- //
function PeekMessage(var lpMsg: TMyMsg; hWnd: HWND; wMsgFilterMin, wMsgFilterMax, wRemoveMsg: UINT): BOOL;
external 'PeekMessageW@user32.dll stdcall';
function TranslateMessage(const lpMsg: TMyMsg): BOOL;
external 'TranslateMessage@user32.dll stdcall';
function DispatchMessage(const lpMsg: TMyMsg): Longint;
external 'DispatchMessageW@user32.dll stdcall';
// ----------------------------------------------------------- //
function CloseHandle(hObject: THandle): BOOLEAN;
external 'CloseHandle@kernel32.dll stdcall';
function CreateProcess(lpApplicationName: String; lpCommandLine: string; lpProcAttrib,lpThreadAttrib: TSecurityAttributes; bInheritHandles: Boolean; dwCreationFlags: DWORD; lpEnvironment:DWORD; lpCurrentDirectory: String; var lpStartupInfo:TStartupInfo; var lpProcessInfo:TProcessInformation): Boolean;
external 'CreateProcessW@kernel32.dll stdcall';
function CreatePipe(out hReadPipe,hWritePipe: THandle; lpPipeAttributes: TSecurityAttributes; nSize: dword): BOOLEAN;
external 'CreatePipe@kernel32.dll stdcall';
function WaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD;
external 'WaitForSingleObject@kernel32.dll stdcall';
function ReadFile(hFile: THandle; lpBuffer: Longint; nNumberOfBytesToRead: DWORD; var lpNumberOfBytesRead: DWORD; lpOverlapped: Longint): BOOL;
external 'ReadFile@kernel32.dll stdcall';
function GetProcessHeap: THandle;
external 'GetProcessHeap@kernel32.dll stdcall';
function HeapAlloc(hHeap: THandle; dwFlags, dwBytes: DWORD): Longint;
external 'HeapAlloc@kernel32.dll stdcall';
function HeapSize(hHeap: THandle; dwFlags: DWORD; lpMem: Longint): DWORD;
external 'HeapSize@kernel32.dll stdcall';
function HeapFree(hHeap: THandle; dwFlags: DWORD; lpMem: Longint): BOOL;
external 'HeapFree@kernel32.dll stdcall';
Function OemToChar(lpszSrc, lpszDst: AnsiString): longint;
external 'OemToCharA@user32.dll stdcall';
procedure AppProcessMessage;
var
Msg: TMyMsg;
begin
while PeekMessage(Msg, 0, 0, 0, 1) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
function OemToAnsiStr(strSource: AnsiString): AnsiString;
var
nRet: longint;
begin
SetLength(Result, Length(strSource));
nRet:= OemToChar(strSource, Result);
end;
procedure InitializeWizard;
var
MyMemo: TMemo;
Security: TSecurityAttributes;
ReadPipe, WritePipe: THandle;
Start: TStartUpInfo;
ProcessInfo: TProcessInformation;
Buffer: PAnsiChar;
BytesRead: DWord;
Apprunning: DWord;
appName, commandLine,workingDirectory: string;
hFile, hHeap: THandle;
lpBuffer: Longint;
dwBufferSize, dwRead: DWORD;
begin
WizardForm.InnerNoteBook.Hide;
WizardForm.OuterNotebook.Hide;
MyMemo:=TMemo.Create(WizardForm);
MyMemo.SetBounds(30, 30, 440, 260);
MyMemo.Parent:=WizardForm;
MyMemo.Text:='Hello!';
{
with Security do
begin
nlength := SizeOf(Security);
binherithandle := true;
lpsecuritydescriptor := 0;
end;
}
Security.nlength := SizeOf( Security );
Security.binherithandle := true;
Security.lpSecurityDescriptor := 0;
if Createpipe( ReadPipe, WritePipe, Security, 0 ) then
begin
hHeap := GetProcessHeap;
lpBuffer := HeapAlloc(hHeap, HEAP_ZERO_MEMORY, ReadBuffer);
dwBufferSize := HeapSize(hHeap, 0, lpBuffer);
//Buffer := AllocMem( ReadBuffer+1 );
//FillChar( Start, Sizeof( Start ), #0 );
Start.cb := SizeOf( Start );
Start.hStdOutput := WritePipe;
Start.hStdInput := ReadPipe;
Start.dwFlags := STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW;
Start.wShowWindow := SW_HIDE;
if CreateProcess('c:\windows\System32\PING.EXE', ' ' + 'ya.ru', Security, Security, True, NORMAL_PRIORITY_CLASS, 0, 'c:\windows\System32', Start, ProcessInfo) then
begin
repeat
Apprunning := WaitForSingleObject( ProcessInfo.hProcess, 100 );
ReadFile(ReadPipe, lpBuffer, dwBufferSize, dwRead, 0);
//ReadFile( ReadPipe, lpBuffer[0], ReadBuffer, BytesRead, nil );
//lpBuffer[BytesRead] := #0;
MyMemo.Text := MyMemo.text + OemToAnsiStr(lpBuffer);
AppProcessMessage;
until ( Apprunning <> WAIT_TIMEOUT );
// until ( BytesRead < ReadBuffer );
end;
HeapFree(hHeap, 0, lpBuffer);
CloseHandle( ProcessInfo.hProcess );
CloseHandle( ProcessInfo.hThread );
CloseHandle( ReadPipe );
CloseHandle( WritePipe );
end;
end;
Здравствуйте, у меня вопрос, а можно ли на финишной странице установщика сделать пункт, который удаляет файлы в определённых папках?(Решено)
El Sanchez
16-08-2017, 15:23
чтение с консоли, причем нужна реализация через пайпы и чтобы текст построчно отображался в Memo. »
usermode,
[Setup]
AppName=test
AppVerName=test
CreateAppDir=false
DefaultDirName={tmp}
Uninstallable=false
DisableWelcomePage=no
[Languages]
Name: ru; MessagesFile: compiler:Languages\russian.isl
[Code]
#define A = (Defined UNICODE) ? "W" : "A"
const
WM_QUIT = $0012;
PM_REMOVE = $1;
MSGF_SLEEPMSG = $5300;
STARTF_USESTDHANDLES = $0100;
STARTF_USESHOWWINDOW = $0001;
QS_ALLINPUT = $04FF;
WAIT_TIMEOUT = $00000102;
EM_LINESCROLL = $B6;
type
#ifndef IS_ENHANCED
TMsg = record
hwnd: HWND;
message: LongWord;
wParam: Longint;
lParam: Longint;
time: LongWord;
pt: TPoint;
end;
#endif
TSecurityAttributes = record
nLength: DWORD;
lpSecurityDescriptor: Longint;
bInheritHandle: BOOL;
end;
TStartupInfo = record
cb: DWORD;
lpReserved: Longint;
lpDesktop: Longint;
lpTitle: Longint;
dwX: DWORD;
dwY: DWORD;
dwXSize: DWORD;
dwYSize: DWORD;
dwXCountChars: DWORD;
dwYCountChars: DWORD;
dwFillAttribute: DWORD;
dwFlags: DWORD;
wShowWindow: Word;
cbReserved2: Word;
lpReserved2: Longint;
hStdInput: THandle;
hStdOutput: THandle;
hStdError: THandle;
end;
TProcessInformation = record
hProcess: THandle;
hThread: THandle;
dwProcessId: DWORD;
dwThreadId: DWORD;
end;
// Message Functions
function PeekMessage(var lpMsg: TMsg; hWnd: HWND; wMsgFilterMin, wMsgFilterMax, wRemoveMsg: UINT): BOOL; external 'PeekMessage{#A}@user32.dll stdcall';
function TranslateMessage(const lpMsg: TMsg): BOOL; external 'TranslateMessage@user32.dll stdcall';
function DispatchMessage(const lpmsg: TMsg): Longint; external 'DispatchMessage{#A}@user32.dll stdcall';
procedure PostQuitMessage(nExitCode: Integer); external 'PostQuitMessage@user32.dll stdcall';
// Hook Functions
function CallMsgFilter(lpMsg: TMsg; nCode: Integer): BOOL; external 'CallMsgFilter{#A}@user32.dll stdcall';
// Synchronization Functions
function WaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD; external 'WaitForSingleObject@kernel32.dll stdcall';
// Handle and Object Functions
function CloseHandle(hObject: THandle): BOOL; external 'CloseHandle@kernel32.dll stdcall';
// Process and Thread Functions
function CreateProcess(lpApplicationName, lpCommandLine: string; lpProcessAttributes, lpThreadAttributes: TSecurityAttributes; bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Longint; lpCurrentDirectory: string; lpStartupInfo: TStartupInfo; out lpProcessInformation: TProcessInformation): BOOL; external 'CreateProcess{#A}@kernel32.dll stdcall';
// Pipe Functions
function CreatePipe(out hReadPipe, hWritePipe: THandle; lpPipeAttributes: TSecurityAttributes; nSize: DWORD): BOOL; external 'CreatePipe@kernel32.dll stdcall';
function PeekNamedPipe(hNamedPipe: THandle; lpBuffer: AnsiString; nBufferSize: DWORD; out lpBytesRead: DWORD; lpTotalBytesAvail, lpBytesLeftThisMessage: DWORD): BOOL; external 'PeekNamedPipe@kernel32.dll stdcall';
// File Management Functions
function ReadFile(hFile: THandle; lpBuffer: AnsiString; nNumberOfBytesToRead: DWORD; var lpNumberOfBytesRead: DWORD; lpOverlapped: Longint): BOOL; external 'ReadFile@kernel32.dll stdcall';
var
OutputMemo: TMemo;
RunButton: TButton;
//////////////////////////////////
function ProcessMessages: Boolean;
var
Msg: TMsg;
begin
Result := True;
while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
begin
if (Msg.Message = WM_QUIT) then
begin
PostQuitMessage(Msg.wParam);
Result := False;
Exit;
end;
if not CallMsgFilter(Msg, MSGF_SLEEPMSG) then
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
end;
/////////////////////////////// ///////////////////////////////////
procedure CaptureConsoleOutput(const ACommand, AParameters: string;
const AOEMConvert: Boolean; AMemo: TMemo);
var
SecurityAttributes: TSecurityAttributes;
StartupInfo: TStartupInfo;
ProcessInformation: TProcessInformation;
ReadHandle, WriteHandle: THandle;
BufSize, ResultCode, BytesRead: DWORD;
Buffer: AnsiString;
begin
SecurityAttributes.nLength := SizeOf(SecurityAttributes);
SecurityAttributes.bInheritHandle := True;
if CreatePipe(ReadHandle, WriteHandle, SecurityAttributes, 0) then
try
StartupInfo.cb := SizeOf(StartupInfo);
StartupInfo.hStdInput := ReadHandle;
StartupInfo.hStdOutput := WriteHandle;
StartupInfo.hStdError := WriteHandle;
StartupInfo.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := SW_HIDE;
if CreateProcess('', Format('%s %s', [ACommand, AParameters]), SecurityAttributes, SecurityAttributes, True, 0, 0, '', StartupInfo, ProcessInformation) then
try
CloseHandle(WriteHandle);
BufSize := 1024; // 1KB
Buffer := StringOfChar(#0, BufSize);
repeat
ResultCode := WaitForSingleObject(ProcessInformation.hProcess, 0);
PeekNamedPipe(ReadHandle, Buffer, BufSize, BytesRead, 0, 0);
while ProcessMessages and (BytesRead > 0) do
begin
#ifdef IS_ENHANCED
AMemo.Lines.BeginUpdate;
#endif
ReadFile(ReadHandle, Buffer, BytesRead, BytesRead, 0);
if AOEMConvert then
OemToCharBuff(Buffer);
AMemo.Text := AMemo.Text + Copy(Buffer, 1, BytesRead);
SendMessage(AMemo.Handle, EM_LINESCROLL, 0, AMemo.Lines.Count);
#ifdef IS_ENHANCED
AMemo.Lines.EndUpdate;
#endif
end;
until not ProcessMessages or (ResultCode <> WAIT_TIMEOUT);
finally
CloseHandle(ProcessInformation.hProcess);
CloseHandle(ProcessInformation.hThread);
end;
finally
CloseHandle(ReadHandle);
end;
end;
////////////////////////////////////////////
procedure RunButtonOnClick(Sender: TObject);
begin
CaptureConsoleOutput('cmd.exe', '/c ping ya.ru', True, OutputMemo);
end;
///////////////////////////
procedure InitializeWizard;
begin
WizardForm.OuterNotebook.Hide;
OutputMemo := TMemo.Create(WizardForm);
with OutputMemo do
begin
Parent := WizardForm;
SetBounds(WizardForm.OuterNotebook.Left, WizardForm.OuterNotebook.Top, WizardForm.OuterNotebook.Width, WizardForm.OuterNotebook.Height);
ScrollBars := ssVertical;
ReadOnly := True;
#ifdef IS_ENHANCED
DoubleBuffered := True;
#endif
end;
RunButton := TButton.Create(WizardForm);
with RunButton do
begin
Parent := WizardForm;
SetBounds(WizardForm.OuterNotebook.Left, WizardForm.NextButton.Top, WizardForm.NextButton.Width, WizardForm.NextButton.Height);
Caption := 'Run';
OnClick := @RunButtonOnClick;
end;
end;
//////////////////////////////////////////////////////
function NextButtonClick(CurPageID: Integer): Boolean;
begin
Result := False;
end;
usermode
16-08-2017, 16:21
El Sanchez, а что за компилятор используется? Пробовал расширенную версию от ResTools - не понимает многих параметров. (В Inno Ultra, все хорошо.)
Привык к стандартной официальной версии, буду пробовать адаптировать, за пример огромное спасибо!
добавлено
подскажите, какой изврат можно использовать в стандартной версии Unicode вместо:
Buffer := CastIntegerToString(BufPtr);
чтобы перевести содержимое в ANSI.
Адаптировал пример под официальную ANSI версию компилятора - все нормально, отображает символы корректно, но UNICODE не содержит CastIntegerToAnsiString.
Что нужно учесть, чтобы написать свою функцию CastIntegerToAnsiString, либо как решить задачу другим способом?
======================================================================================
usermode, адаптировал под официальную версию. »
респект! рука профессионала!
El Sanchez, а вывод с консоли заголовка окна возможен? Скажем, проценты выполнения процесса? Было бы здорово.
El Sanchez
16-08-2017, 21:44
Что нужно учесть, чтобы написать свою функцию CastIntegerToAnsiString, либо как решить задачу другим способом? »
usermode, адаптировал под официальную версию.
а вывод с консоли заголовка окна возможен? Скажем, проценты выполнения процесса? »
nik1967, а фиг его знает. После CreateProcess известны PID и дескриптор процесса, по одному из них искать дескриптор окна, далее текст заголовка.
El Sanchez, спасибо за направление, но это не мой уровень, увы.
postal1703
17-08-2017, 03:59
Ребята, нужна помощь. как и где указать файлы уже установленные инсталятором, которые должны остаться на компьютере пользователя после удаления основной программы? т.е нужно указать файлы которые деинсталятор будит обходить стороной.
т.е нужно указать файлы которые деинсталятор будит обходить стороной. »Используйте флаг uninsneveruninstall
Пример:
[Files]
Source: MyProg.exe; DestDir: {app}; Flags: uninsneveruninstall
Dodakaedr
17-08-2017, 10:48
можно ли на финишной странице установщика сделать пункт, который удаляет файлы в определённых папках? »
Пример очистки локальной папки Temp, для удаления файлов используйте вместо команды DelTree команду DeleteFile:
[Setup]
AppName=My Application
AppVersion=1.5
DefaultDirName={pf}\My Application
[code]
var
DelTmp: TNewCheckBox;
function DelTmpCheck(): boolean;
begin
result := DelTmp.Checked;
end;
procedure InitializeWizard();
begin
DelTmp := TNewCheckBox.Create(WizardForm);
DelTmp.Parent := WizardForm.FinishedPage;
DelTmp.Caption := 'Очистить папку Temp';
DelTmp.SetBounds(ScaleX(WizardForm.RunList.Left), ScaleY(WizardForm.RunList.Top), ScaleX(140), ScaleY(15));
DelTmp.Checked := true;
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
case CurStep of
ssDone:
begin
if DelTmpCheck then
begin
DelTree(ExpandConstant('{localappdata}\Temp'), false, true, true);
end;
end;
end;
end;
Dodakaedr, спасибо вам большое.
Dodakaedr, теперь возникла другая проблема, код накладывается на секцию [run] на финишной странице, решил передвинуть текст, вроде получилось, но белый фон кода закрывает секцию [run]. Да, и как мне передвинуть текст немного правее(чтобы был в столбик с секцией [run])? Заранее спасибо!)http://s019.radikal.ru/i615/1708/8d/1b16e4c75f4d.jpg
белый фон кода закрывает секцию [run]. Да, и как мне передвинуть текст немного правее »
Замените одну строку в секции Code (процедура InitializeWizard):
DelTmp.SetBounds(ScaleX(WizardForm.RunList.Left), ScaleY(WizardForm.RunList.Top), ScaleX(140), ScaleY(15));
на эти строки:
DelTmp.Left := ScaleX(180);
DelTmp.Top := ScaleY(155);
DelTmp.Width := ScaleX(300);
DelTmp.Height := ScaleY(15);
При необходимости можете поиграться числами (координатами и размерами).
Dodakaedr
17-08-2017, 23:01
код накладывается на секцию [run] на финишной странице »
[Setup]
AppName=My Application
AppVersion=1.5
DefaultDirName={pf}\My Application
[Run]
FileName: "Test.exe"; Description: "бла-бла"; Flags: postinstall
[code]
var
DelTmp: TNewCheckBox;
function DelTmpCheck(): boolean;
begin
result := DelTmp.Checked;
end;
procedure InitializeWizard();
begin
WizardForm.RunList.Height := ScaleY(WizardForm.RunList.Height-100); //здесь указываем ширину RunList
DelTmp := TNewCheckBox.Create(WizardForm);
DelTmp.Parent := WizardForm.FinishedPage;
DelTmp.Caption := 'Очистить папку Temp';
DelTmp.SetBounds(ScaleX(WizardForm.RunList.Left+4), ScaleY(WizardForm.RunList.Top+WizardForm.RunList.Height+4), ScaleX(140), ScaleY(15)); //здесь указываем расположение чекбокса
DelTmp.Checked := true;
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
case CurStep of
ssDone:
begin
if DelTmpCheck then
begin
DelTree(ExpandConstant('{localappdata}\Temp'), false, true, true);
end;
end;
end;
end;
boss911 и Dodakaedr, спасибо вам большое!
pollipen
20-08-2017, 13:46
парни как сделать папку только для чтения или системную
как сделать папку только для чтения или системную »
[Dirs]
Name: {app}MyFolder; Attribs: readonly system
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.