mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-16 00:05:53 +01:00
213 lines
5.6 KiB
ObjectPascal
213 lines
5.6 KiB
ObjectPascal
// ***************************************************************************
|
|
//
|
|
// Delphi MVC Framework
|
|
//
|
|
// Copyright (c) 2010-2023 Daniele Teti and the DMVCFramework Team
|
|
//
|
|
// https://github.com/danieleteti/delphimvcframework
|
|
//
|
|
// ***************************************************************************
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
// *************************************************************************** }
|
|
|
|
unit PGUtilsU;
|
|
|
|
interface
|
|
|
|
type
|
|
TPGUtil = class
|
|
private
|
|
fPGHome: string;
|
|
fPGDataDir: string;
|
|
fInitDBExecutable: string;
|
|
fPGCtlExecutable: String;
|
|
fPGPort: UInt16;
|
|
fCreateDBExecutable: string;
|
|
public
|
|
constructor Create(const PGHome, PGDataDir: String; const PGPort: UInt16);
|
|
procedure InitDB;
|
|
procedure StartPG;
|
|
procedure CreateDatabase(const DatabaseName: String);
|
|
procedure StopPG;
|
|
procedure RemoveDataDir;
|
|
function IsPGRunning: Boolean;
|
|
property PGHome: String read fPGHome;
|
|
property PGDataDir: String read fPGDataDir;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Winapi.Windows, System.IOUtils, System.SysUtils;
|
|
|
|
{ TPGUtil }
|
|
|
|
function SysExecute(const CommandLine: string; out StdOutput: String; const Work: string = 'C:\')
|
|
: Cardinal;
|
|
var
|
|
SA: TSecurityAttributes;
|
|
SI: TStartupInfo;
|
|
PI: TProcessInformation;
|
|
StdOutPipeRead, StdOutPipeWrite: THandle;
|
|
WasOK: Boolean;
|
|
Buffer: array [0 .. 255] of AnsiChar;
|
|
BytesRead: Cardinal;
|
|
WorkDir: string;
|
|
Handle: Boolean;
|
|
begin
|
|
StdOutput := '';
|
|
with SA do
|
|
begin
|
|
nLength := SizeOf(SA);
|
|
bInheritHandle := True;
|
|
lpSecurityDescriptor := nil;
|
|
end;
|
|
CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0);
|
|
try
|
|
with SI do
|
|
begin
|
|
FillChar(SI, SizeOf(SI), 0);
|
|
cb := SizeOf(SI);
|
|
dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
|
|
wShowWindow := SW_HIDE;
|
|
hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin
|
|
hStdOutput := StdOutPipeWrite;
|
|
hStdError := StdOutPipeWrite;
|
|
end;
|
|
WorkDir := Work;
|
|
Handle := CreateProcess(nil, PChar('cmd.exe /C ' + CommandLine), nil, nil, True, 0, nil,
|
|
PChar(WorkDir), SI, PI);
|
|
CloseHandle(StdOutPipeWrite);
|
|
if Handle then
|
|
try
|
|
repeat
|
|
WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
|
|
if BytesRead > 0 then
|
|
begin
|
|
Buffer[BytesRead] := #0;
|
|
StdOutput := StdOutput + String(Buffer);
|
|
end;
|
|
until not WasOK or (BytesRead = 0);
|
|
WaitForSingleObject(PI.hProcess, INFINITE);
|
|
GetExitCodeProcess(PI.hProcess, Result);
|
|
finally
|
|
CloseHandle(PI.hThread);
|
|
CloseHandle(PI.hProcess);
|
|
end;
|
|
finally
|
|
CloseHandle(StdOutPipeRead);
|
|
end;
|
|
end;
|
|
|
|
function SysStartExecute(const CommandLine: string; const Work: string = 'C:\'): Boolean;
|
|
var
|
|
SI: TStartupInfo;
|
|
PI: TProcessInformation;
|
|
WorkDir: string;
|
|
Handle: Boolean;
|
|
begin
|
|
with SI do
|
|
begin
|
|
FillChar(SI, SizeOf(SI), 0);
|
|
cb := SizeOf(SI);
|
|
dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
|
|
wShowWindow := SW_HIDE;
|
|
hStdInput := 0;
|
|
hStdOutput := 0;
|
|
hStdError := 0;
|
|
end;
|
|
WorkDir := Work;
|
|
Handle := CreateProcess(nil, PChar('cmd.exe /C ' + CommandLine), nil, nil, True, 0, nil,
|
|
PChar(WorkDir), SI, PI);
|
|
Result := Handle;
|
|
end;
|
|
|
|
constructor TPGUtil.Create(const PGHome, PGDataDir: String; const PGPort: UInt16);
|
|
begin
|
|
inherited Create;
|
|
fPGHome := PGHome;
|
|
fPGDataDir := PGDataDir;
|
|
if fPGDataDir.Contains(' ') then
|
|
begin
|
|
raise Exception.Create('Cannot RUN test in a path with spaces');
|
|
end;
|
|
fPGPort := PGPort;
|
|
fInitDBExecutable := TPath.Combine(fPGHome, 'bin\initdb.exe');
|
|
fPGCtlExecutable := TPath.Combine(fPGHome, 'bin\pg_ctl.exe');
|
|
fCreateDBExecutable := TPath.Combine(fPGHome, 'bin\createdb.exe');
|
|
end;
|
|
|
|
procedure TPGUtil.CreateDatabase(const DatabaseName: String);
|
|
var
|
|
lParams: string;
|
|
lOutput: string;
|
|
begin
|
|
lParams := ' -p ' + fPGPort.ToString + ' ' + DatabaseName;
|
|
if SysExecute(fCreateDBExecutable + lParams, lOutput) <> 0 then
|
|
begin
|
|
raise Exception.Create(lOutput);
|
|
end;
|
|
end;
|
|
|
|
procedure TPGUtil.InitDB;
|
|
var
|
|
lParams: string;
|
|
lOutput: string;
|
|
begin
|
|
lParams := ' -D ' + fPGDataDir +
|
|
' --encoding=UTF8 --lc-collate=en-US --lc-ctype=en-US --locale=en-US';
|
|
// ' --encoding=UTF8 --lc-collate=en_US.UTF-8 --lc-ctype=en_US.UTF-8 --locale=en_US';
|
|
if SysExecute(fInitDBExecutable + lParams, lOutput) <> 0 then
|
|
begin
|
|
raise Exception.Create(lOutput);
|
|
end;
|
|
end;
|
|
|
|
function TPGUtil.IsPGRunning: Boolean;
|
|
var
|
|
lParams: string;
|
|
lOutput: string;
|
|
begin
|
|
lParams := ' -D ' + fPGDataDir + ' status';
|
|
Result := SysExecute(fPGCtlExecutable + lParams, lOutput) = 0;
|
|
end;
|
|
|
|
procedure TPGUtil.RemoveDataDir;
|
|
begin
|
|
StopPG;
|
|
if TDirectory.Exists(fPGDataDir) then
|
|
begin
|
|
TDirectory.Delete(fPGDataDir, True);
|
|
end;
|
|
end;
|
|
|
|
procedure TPGUtil.StartPG;
|
|
begin
|
|
if not SysStartExecute(fPGCtlExecutable + ' -o "-F -p ' + fPGPort.ToString + '" -D ' + fPGDataDir
|
|
+ ' start') then
|
|
begin
|
|
raise Exception.Create('Cannot start postgresql');
|
|
end;
|
|
end;
|
|
|
|
procedure TPGUtil.StopPG;
|
|
var
|
|
lOutput: string;
|
|
begin
|
|
SysExecute(fPGCtlExecutable + ' -D ' + fPGDataDir + ' stop -m smart', lOutput);
|
|
end;
|
|
|
|
end.
|