原文地址:http://stackoverflow.com/questions/16922272/unknown-identifier-and-wpselectdir
// Variables Globales var TimeZone: String; type SERVICE_STATUS = record dwServiceType : cardinal; dwCurrentState : cardinal; dwControlsAccepted : cardinal; dwWin32ExitCode : cardinal; dwServiceSpecificExitCode : cardinal; dwCheckPoint : cardinal; dwWaitHint : cardinal; end; HANDLE = cardinal; const SERVICE_QUERY_CONFIG = $1; SERVICE_CHANGE_CONFIG = $2; SERVICE_QUERY_STATUS = $4; SERVICE_START = $10; SERVICE_STOP = $20; SERVICE_ALL_ACCESS = $f01ff; SC_MANAGER_ALL_ACCESS = $f003f; SERVICE_WIN32_OWN_PROCESS = $10; SERVICE_WIN32_SHARE_PROCESS = $20; SERVICE_WIN32 = $30; SERVICE_INTERACTIVE_PROCESS = $100; SERVICE_BOOT_START = $0; SERVICE_SYSTEM_START = $1; SERVICE_AUTO_START = $2; SERVICE_DEMAND_START = $3; SERVICE_DISABLED = $4; SERVICE_DELETE = $10000; SERVICE_CONTROL_STOP = $1; SERVICE_CONTROL_PAUSE = $2; SERVICE_CONTROL_CONTINUE = $3; SERVICE_CONTROL_INTERROGATE = $4; SERVICE_STOPPED = $1; SERVICE_START_PENDING = $2; SERVICE_STOP_PENDING = $3; SERVICE_RUNNING = $4; SERVICE_CONTINUE_PENDING = $5; SERVICE_PAUSE_PENDING = $6; SERVICE_PAUSED = $7; // ####################################################################################### // nt based service utilities // ####################################################################################### function OpenSCManager(lpMachineName, lpDatabaseName: string; dwDesiredAccess :cardinal): HANDLE; external 'OpenSCManagerA@advapi32.dll stdcall'; function OpenService(hSCManager :HANDLE;lpServiceName: string; dwDesiredAccess :cardinal): HANDLE; external 'OpenServiceA@advapi32.dll stdcall'; function CloseServiceHandle(hSCObject :HANDLE): boolean; external 'CloseServiceHandle@advapi32.dll stdcall'; function CreateService(hSCManager :HANDLE;lpServiceName, lpDisplayName: string;dwDesiredAccess,dwServiceType,dwStartType,dwErrorControl: cardinal;lpBinaryPathName,lpLoadOrderGroup: String; lpdwTagId : cardinal;lpDependencies,lpServiceStartName,lpPassword :string): cardinal; external 'CreateServiceA@advapi32.dll stdcall'; function DeleteService(hService :HANDLE): boolean; external 'DeleteService@advapi32.dll stdcall'; function StartNTService(hService :HANDLE;dwNumServiceArgs : cardinal;lpServiceArgVectors : cardinal) : boolean; external 'StartServiceA@advapi32.dll stdcall'; function ControlService(hService :HANDLE; dwControl :cardinal;var ServiceStatus :SERVICE_STATUS) : boolean; external 'ControlService@advapi32.dll stdcall'; function QueryServiceStatus(hService :HANDLE;var ServiceStatus :SERVICE_STATUS) : boolean; external 'QueryServiceStatus@advapi32.dll stdcall'; function QueryServiceStatusEx(hService :HANDLE;ServiceStatus :SERVICE_STATUS) : boolean; external 'QueryServiceStatus@advapi32.dll stdcall'; function OpenServiceManager() : HANDLE; begin if UsingWinNT() = true then begin Result := OpenSCManager('','ServicesActive',SC_MANAGER_ALL_ACCESS); if Result = 0 then MsgBox('the servicemanager is not available', mbError, MB_OK) end else begin MsgBox('only nt based systems support services', mbError, MB_OK) Result := 0; end end; function IsServiceInstalled(ServiceName: string) : boolean; var hSCM : HANDLE; hService: HANDLE; begin hSCM := OpenServiceManager(); Result := false; if hSCM <> 0 then begin hService := OpenService(hSCM,ServiceName,SERVICE_QUERY_CONFIG); if hService <> 0 then begin Result := true; CloseServiceHandle(hService) end; CloseServiceHandle(hSCM) end end; function InstallService(FileName, ServiceName, DisplayName, Description : string;ServiceType,StartType :cardinal) : boolean; var hSCM : HANDLE; hService: HANDLE; begin hSCM := OpenServiceManager(); Result := false; if hSCM <> 0 then begin hService := CreateService(hSCM,ServiceName,DisplayName,SERVICE_ALL_ACCESS,ServiceType,StartType,0,FileName,'',0,'','',''); if hService <> 0 then begin Result := true; // Win2K & WinXP supports aditional description text for services if Description<> '' then RegWriteStringValue(HKLM,'System\CurrentControlSet\Services' + ServiceName,'Description',Description); CloseServiceHandle(hService) end; CloseServiceHandle(hSCM) end end; function RemoveService(ServiceName: string) : boolean; var hSCM : HANDLE; hService: HANDLE; begin hSCM := OpenServiceManager(); Result := false; if hSCM <> 0 then begin hService := OpenService(hSCM,ServiceName,SERVICE_DELETE); if hService <> 0 then begin Result := DeleteService(hService); CloseServiceHandle(hService) end; CloseServiceHandle(hSCM) end end; function StartService(ServiceName: string) : boolean; var hSCM : HANDLE; hService: HANDLE; begin hSCM := OpenServiceManager(); Result := false; if hSCM <> 0 then begin hService := OpenService(hSCM,ServiceName,SERVICE_START); if hService <> 0 then begin Result := StartNTService(hService,0,0); CloseServiceHandle(hService) end; CloseServiceHandle(hSCM) end; end; function StopService(ServiceName: string) : boolean; var hSCM : HANDLE; hService: HANDLE; Status : SERVICE_STATUS; begin hSCM := OpenServiceManager(); Result := false; if hSCM <> 0 then begin hService := OpenService(hSCM,ServiceName,SERVICE_STOP); if hService <> 0 then begin Result := ControlService(hService,SERVICE_CONTROL_STOP,Status); CloseServiceHandle(hService) end; CloseServiceHandle(hSCM) end; end; function IsServiceRunning(ServiceName: string) : boolean; var hSCM : HANDLE; hService: HANDLE; Status : SERVICE_STATUS; begin hSCM := OpenServiceManager(); Result := false; if hSCM <> 0 then begin hService := OpenService(hSCM,ServiceName,SERVICE_QUERY_STATUS); if hService <> 0 then begin if QueryServiceStatus(hService,Status) then begin Result :=(Status.dwCurrentState = SERVICE_RUNNING) end; CloseServiceHandle(hService) end; CloseServiceHandle(hSCM) end end; // ####################################################################################### // create an entry in the services file // ####################################################################################### function SetupService(service, port, comment: string) : boolean; var filename : string; s : string; lines : TArrayOfString; n : longint; i : longint; errcode : integer; servnamlen : integer; error : boolean; begin if UsingWinNT() = true then filename := ExpandConstant('{sys}\drivers\etc\services') else filename := ExpandConstant('{win}\services'); if LoadStringsFromFile(filename,lines) = true then begin Result := true; n := GetArrayLength(lines) - 1; servnamlen := Length(service); error := false; for i:=0 to n do begin if Copy(lines[i],1,1) <> '#' then begin s := Copy(lines[i],1,servnamlen); if CompareText(s,service) = 0 then exit; // found service-entry if Pos(port,lines[i]) > 0 then begin error := true; lines[i] := '#' + lines[i] + ' # disabled because collision with ' + service + ' service'; end; end else if CompareText(Copy(lines[i],2,servnamlen),service) = 0 then begin // service-entry was disabled Delete(lines[i],1,1); Result := SaveStringsToFile(filename,lines,false); exit; end; end; if error = true then begin // save disabled entries if SaveStringsToFile(filename,lines,false) = false then begin Result := false; exit; end; end; // create new service entry s := service + ' ' + port + ' # ' + comment + #13#10; if SaveStringToFile(filename,s,true) = false then begin Result := false; exit; end; if error = true then begin MsgBox('the ' + service + ' port was already used. The old service is disabled now. You should check the services file manually now.',mbInformation,MB_OK); //InstExec('notepad.exe',filename,GetCurrentDir(),true,false,SW_SHOWNORMAL,errcode); end; end else Result := false; end; // ####################################################################################### // version functions // ####################################################################################### function CheckVersion(Filename : string;hh,hl,lh,ll : integer) : boolean; var VersionMS : cardinal; VersionLS : cardinal; CheckMS : cardinal; CheckLS : cardinal; begin if GetVersionNumbers(Filename,VersionMS,VersionLS) = false then Result := false else begin CheckMS := (hh shl $10) or hl; CheckLS := (lh shl $10) or ll; Result := (VersionMS > CheckMS) or ((VersionMS = CheckMS) and (VersionLS >= CheckLS)); end; end; // Some examples for version checking function NeedShellFolderUpdate() : boolean; begin Result := CheckVersion('ShFolder.dll',5,50,4027,300) = false; end; function NeedVCRedistUpdate() : boolean; begin Result := (CheckVersion('mfc42.dll',6,0,8665,0) = false) or (CheckVersion('msvcrt.dll',6,0,8797,0) = false) or (CheckVersion('comctl32.dll',5,80,2614,3600) = false); end; function NeedHTMLHelpUpdate() : boolean; begin Result := CheckVersion('hh.exe',4,72,0,0) = false; end; function NeedWinsockUpdate() : boolean; begin Result := (UsingWinNT() = false) and (CheckVersion('mswsock.dll',4,10,0,1656) = false); end; function NeedDCOMUpdate() : boolean; begin Result := (UsingWinNT() = false) and (CheckVersion('oleaut32.dll',2,30,0,0) = false); end; // ####################################################################################### // Replace substring in a string functions // ####################################################################################### procedure FileReplace(SrcFile, sFrom, sTo: String); var FileContent: String; begin //Load srcfile to a string LoadStringFromFile(SrcFile, FileContent); //Replace Fraomstring by toString in file string content StringChange (sTo,'/', '\'); StringChange (FileContent, sFrom, sTo); //Replace old content srcfile by the new content DeleteFile(SrcFile); SaveStringToFile(SrcFile,FileContent, True); end; // ####################################################################################### // Replace in file functions // ####################################################################################### procedure FileWrite(SrcFile, sFrom, sTo: String); var FileContent: String; begin //Load srcfile to a string LoadStringFromFile(SrcFile, FileContent); //Replace Fraomstring by toString in file string content //StringChange (sTo,'/', '\'); StringChange (FileContent, sFrom, sTo); //Replace old content srcfile by the new content DeleteFile(SrcFile); SaveStringToFile(SrcFile,FileContent, True); end; // ####################################################################################### // Custumized page for apache config // ####################################################################################### procedure CreateTheWizardPages; // variables locales var Lbl: TLabel; Page: TWizardPage; Edit: TEdit; PortNbr: String; // boites begin Page := CreateCustomPage(wpSelectComponents, 'Apache configuration', 'Please enter your parameter for the apache server (Default is 80)'); Lbl := TLabel.Create(Page); Lbl.Top := ScaleY(11); Lbl.Caption := 'Apache server port :'; Lbl.AutoSize := True; Lbl.Parent := Page.Surface; Edit := TEdit.Create(Page); Edit.Top := ScaleY(8); Edit.Left := Lbl.Left + ScaleX(70); Edit.Width := Page.SurfaceWidth div 2 - ScaleX(8); Edit.Text := PortNbr; Edit.Text := '80'; Edit.Parent := Page.Surface; end; // ####################################################################################### // Custumized page for Password enter // ####################################################################################### procedure CreateTheWizardPagesPwd; // variables locales var PasWd: TLabel; PagePwd: TWizardPage; EditPw: TEdit; //MailHostName: String; // boites begin PagePwd := CreateCustomPage(wpSelectComponents, 'Password for the data base user', 'Please enter the password for the data base'); PasWd := TLabel.Create(PagePwd); PasWd.Top := ScaleY(11); PasWd.Caption := 'PassWord : '; PasWd.AutoSize := True; PasWd.Parent := PagePwd.Surface; EditPw := TEdit.Create(PagePwd); EditPw.Top := ScaleY(8); EditPw.Left := PasWd.Left + ScaleX(70); EditPw.Width := PagePwd.SurfaceWidth div 2 - ScaleX(8); EditPw.Parent := PagePwd.Surface; end; // ####################################################################################### // Custumized page for Enter the path of the backup file // ####################################################################################### procedure CreateTheWizardPagesBkpDir; var PageBkpDir: TInputDirWizardPage; // boites begin PageBkpDir := CreateInputDirPage(wpSelectDir,'Select Backup Data Directory','Where should Backup data files be installed?','Select the folder in which Setup should copy backup data files, then click Next.', False, ''); PageBkpDir.Add(''); PageBkpDir.Values[0] := ExpandConstant('{userdesktop}\dbBackup'); end; // ####################################################################################### // Custumized page for Time zone enter // ####################################################################################### procedure CreateTheWizardPagesTimeZone; // variables locales var Panel: TPanel; PageTimeZone: TWizardPage; ListBTimeZone: TNewListBox; // boites begin PageTimeZone := CreateCustomPage(wpWelcome, 'Time zone of your location', 'Please choose your time zone'); Panel := TPanel.Create(PageTimeZone); Panel.Width := PageTimeZone.SurfaceWidth div 2 - ScaleX(8); Panel.Left := PageTimeZone.SurfaceWidth - Panel.Width; Panel.Caption := 'TPanel'; Panel.Color := clWindow; Panel.ParentBackground := False; Panel.Parent := PageTimeZone.Surface; ListBTimeZone := TNewListBox.Create(PageTimeZone); ListBTimeZone.Width := PageTimeZone.SurfaceWidth; ListBTimeZone.Height := ScaleY(200); ListBTimeZone.Parent := PageTimeZone.Surface; ListBTimeZone.Items.Add('Etc/UTC'); ListBTimeZone.Items.Add('Europe/Paris'); ListBTimeZone.ItemIndex := 2; end; // Initialisation procedure InitializeWizard(); begin CreateTheWizardPages; CreateTheWizardPagesTimeZone; CreateTheWizardPagesPwd; CreateTheWizardPagesBkpDir; end; // ####################################################################################### // Function to stop and delete de service by uninstallation procedur // ####################################################################################### procedure CurUninstallStepChanged(CurStep: TUninstallStep); var ErrorCode: Integer; begin if CurStep = usUninstall then begin //Uninstall process ShellExec('open','taskkill.exe','/f /im MyApplicationService.exe','',SW_HIDE,ewNoWait,ErrorCode); ShellExec('open','taskkill.exe','/f /im httpd.exe','',SW_HIDE,ewNoWait,ErrorCode); ShellExec('open','taskkill.exe','/f /im mysqld.exe','',SW_HIDE,ewNoWait,ErrorCode); // stop all affected services StopService('MyApplicationService'); StopService('MySqld'); StopService('Apache'); // remove all affected services RemoveService('MyApplicationService'); RemoveService('MySqld'); RemoveService('Apache'); end; end; // ####################################################################################### // Function to check and replace the string in the file at the end of the installation // ####################################################################################### procedure CurStepChanged(CurStep: TSetupStep); var ErrorCode: Integer; WorkingDir: String; PathOfDir: String; begin //juste aprés installation if CurStep = ssPostInstall then begin PathOfDir := GetShortName(PathOfDir2); FileReplace(ExpandConstant('{app}\create_db.sql'), '@@Pwd@@', EditPw.Text); FileReplace(ExpandConstant('{app}\webserver\bin\apache\Apache2.2.22\conf\httpd.conf'), '@@Port@@', PortNbr); FileReplace(ExpandConstant('{app}\webserver\bin\apache\Apache2.2.22\conf\httpd.conf'), '@@Path@@', PathOfDir+'\webserver'); FileReplace(ExpandConstant('{app}\webserver\bin\apache\Apache2.2.22\bin\php.ini'), '@@Path@@', PathOfDir+'\webserver'); FileWrite(ExpandConstant('{app}\webserver\bin\apache\Apache2.2.22\bin\php.ini'), '@@TimeZone@@', TimeZone); FileReplace(ExpandConstant('{app}\webserver\bin\mysql\mysql5.5.24\my.ini'), '@@Path@@', PathOfDir+'\webserver'); FileReplace(ExpandConstant('{app}\webserver\bin\mysql\mysql5.5.24\bin\dbexport.bat'), '@@Path@@', PathOfBackupDir); FileReplace(ExpandConstant('{app}\webserver\bin\mysql\mysql5.5.24\bin\create_db.bat'), '@@Path@@', PathOfDir + '\webserver\bin\mysql\mysql5.5.24'); FileReplace(ExpandConstant('{app}\webserver\bin\mysql\mysql5.5.24\bin\create_db.bat'), '@@PathOfDir@@', PathOfDir); FileReplace(ExpandConstant('{app}\webserver\bin\php\php5.4.3\php.ini'), '@@Path@@', PathOfDir+'\webserver'); FileReplace(ExpandConstant('{app}\webserver\bin\php\php5.4.3\phpForApache.ini'), '@@Path@@', PathOfDir+'\webserver'); if InstallService(ExpandConstant('"{app}\webserver\bin\mysql\mysql5.5.24\bin\mysqld.exe" MySqld'),'MySqld','MySqld','The mysql service',SERVICE_WIN32_OWN_PROCESS,SERVICE_AUTO_START) = true then begin StartService('MySqld'); Sleep(8000); end else MsgBox('MySqld service could not be installed',mbInformation, MB_OK); if InstallService(ExpandConstant('"{app}\webserver\bin\apache\apache2.2.22\bin\httpd.exe" -k runservice'),'Apache','Apache','The apache service',SERVICE_WIN32_OWN_PROCESS,SERVICE_AUTO_START) = true then begin StartService('Apache'); Sleep(5000); end else MsgBox('Apache service could not be installed',mbInformation, MB_OK); if InstallService(ExpandConstant('"{app}\MyApplicationService.exe"'),'MyApplicationService','MyApplicationService','The server',SERVICE_WIN32_OWN_PROCESS,SERVICE_AUTO_START) = true then begin StartService('MyApplicationService'); Sleep(5000); end else MsgBox('The MyApplicationService service could not be installed',mbInformation, MB_OK); end; if CurStep = ssInstall then begin //Uninstall process ShellExec('open','taskkill.exe','/f /im MyApplicationService.exe','',SW_HIDE,ewNoWait,ErrorCode); ShellExec('open','taskkill.exe','/f /im httpd.exe','',SW_HIDE,ewNoWait,ErrorCode); ShellExec('open','taskkill.exe','/f /im mysqld.exe','',SW_HIDE,ewNoWait,ErrorCode); // stop all affected services StopService('MyApplicationService'); StopService('MySqld'); StopService('Apache'); // remove all affected services RemoveService('MyApplicationService'); RemoveService('MySqld'); RemoveService('Apache'); end; if CurStep = ssDone then begin Exec(ExpandConstant('{app}\webserver\bin\mysql\mysql5.5.24\bin\create_db.bat'),'','', SW_SHOW, ewWaitUntilTerminated, ErrorCode); end; end; // ####################################################################################### // Function to check the values entered // ####################################################################################### function NextButtonClick(CurPageID: Integer): Boolean; var ErrorCode: Integer; begin Result := True; case CurPageID of Page.ID: begin if (Edit.Text = '') then begin MsgBox('Port number check:'#13#13 'The port number is empty. The default port << 80 >> will be applied. Please click on the back button to change if needed ', mbError, MB_OK); Edit.Text := '80'; end else begin Result := True; PortNbr := Edit.Text; end end; //End page.id PagesEmailSt.ID: begin if (EditPwd.Text = EditPwd2.Text) then begin MailHostName := EditMailHostName.Text; MailUserName := EditUserName.Text; MailPwd := EditPwd.Text; MailFrom := EditFromMail.Text; MailSmtpPort := EditSmtpPort.Text; end else begin MsgBox('Password check:'#13#13 'The password entered is not the same. Please click on back and check ', mbError, MB_OK); Result := false; end end; //End PagesEmailSt.id //Time zone add beginn PageTimeZone.ID: begin Result := false; TimeZone := ListBTimeZone.Items.Strings[ListBTimeZone.ItemIndex]; end; //End time zone add //Beginn dir selector PageBkpDir.ID: begin //PageBkpDir.Values[0] := ExpandConstant('{userdesktop}\dbBackup'); PathOfBackupDir := PageBkpDir.Values[0]; end; wpSelectDir: begin PathOfDir2 := WizardDirValue; //MsgBox('NextButtonClick:' #13#13 'You selected: ''' + PathOfDir + '''.', mbInformation, MB_OK); end; //End dir selector end; //End case Result := True; end; function GetDataDir(Param: String): String; begin //Return the selected DataDir Result := PageBkpDir.Values[0]; end;