Quick.Commons.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. { ***************************************************************************
  2. Copyright (c) 2016-2017 Kike Pérez
  3. Unit : Quick.Commons
  4. Description : Common functions
  5. Author : Kike Pérez
  6. Version : 1.2
  7. Created : 14/07/2017
  8. Modified : 11/11/2017
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.Commons;
  22. interface
  23. uses
  24. Classes,
  25. System.SysUtils,
  26. System.Types,
  27. {$IFDEF MSWINDOWS}
  28. Windows,
  29. Winapi.ShlObj,
  30. System.Win.Registry,
  31. {$ENDIF MSWINDOWS}
  32. System.IOUtils,
  33. System.DateUtils;
  34. type
  35. TEventType = (etInfo, etSuccess, etWarning, etError, etDebug, etTrace);
  36. TLogVerbose = set of TEventType;
  37. const
  38. LOG_ONLYERRORS = [etInfo,etError];
  39. LOG_ERRORSANDWARNINGS = [etInfo,etWarning,etError];
  40. LOG_TRACE = [etInfo,etError,etWarning,etTrace];
  41. LOG_ALL = [etInfo,etSuccess,etWarning,etError,etTrace];
  42. LOG_DEBUG = [etInfo,etSuccess,etWarning,etError,etDebug];
  43. EventStr : array of string = ['INFO','SUCC','WARN','ERROR','DEBUG','TRACE'];
  44. type
  45. TPasswordComplexity = set of (pfIncludeNumbers,pfIncludeSigns);
  46. {$IFDEF MSWINDOWS}
  47. TEnvironmentPath = record
  48. EXEPATH : string;
  49. WINDOWS : string;
  50. SYSTEM : string;
  51. PROGRAMFILES : string;
  52. COMMONFILES : string;
  53. HOMEDRIVE : string;
  54. TEMP : string;
  55. USERPROFILE : string;
  56. INSTDRIVE : string;
  57. DESKTOP : string;
  58. STARTMENU : string;
  59. DESKTOP_ALLUSERS : string;
  60. STARTMENU_ALLUSERS : string;
  61. STARTUP : string;
  62. APPDATA : String;
  63. PROGRAMDATA : string;
  64. ALLUSERSPROFILE : string;
  65. end;
  66. {$ENDIF MSWINDOWS}
  67. TFileHelper = record helper for TFile
  68. class function IsInUse(const FileName : string) : Boolean; static;
  69. class function GetSize(const FileName: String): Int64; static;
  70. end;
  71. TDirectoryHelper = record helper for TDirectory
  72. class function GetSize(const Path: String): Int64; static;
  73. end;
  74. TTextFileOperation = (tfOpenRead,tfOpenOverwrite,tfOpenAppend);
  75. TTextStreamFile = class
  76. private
  77. fReadStream : TStreamReader;
  78. fWriteStream : TStreamWriter;
  79. function GetEOF : Boolean;
  80. public
  81. constructor Create(const FileName : string; OpenMode : TTextFileOperation);
  82. destructor Destroy; override;
  83. function ReadLn: string; overload;
  84. function ReadLn(out Data: string): Boolean; overload;
  85. procedure WriteLn (const Data : string);
  86. procedure Close;
  87. property EOF: Boolean read GetEOF;
  88. end;
  89. //generates a random password with complexity options
  90. function RandomPassword(const PasswordLength : Integer; Complexity : TPasswordComplexity = [pfIncludeNumbers,pfIncludeSigns]) : string;
  91. //extracts file extension from a filename
  92. function ExtractFileNameWithoutExt(const FileName: String): String;
  93. //converts a Unix path to Windows path
  94. function UnixToWindowsPath(const UnixPath: string): string;
  95. //converts a Windows path to Unix path
  96. function WindowsToUnixPath(const WindowsPath: string): string;
  97. {$IFDEF MSWINDOWS}
  98. //get typical environment paths as temp, desktop, etc
  99. procedure GetEnvironmentPaths;
  100. function GetSpecialFolderPath(folderID : Integer) : string;
  101. //checks if running on a 64bit OS
  102. function Is64bitOS : Boolean;
  103. //checks if is a console app
  104. function IsConsole : Boolean;
  105. //checks if compiled in debug mode
  106. function IsDebug : Boolean;
  107. //checks if running as a service
  108. function IsService : Boolean;
  109. //gets number of seconds without user interaction (mouse, keyboard)
  110. function SecondsIdle: DWord;
  111. //frees process memory not needed
  112. procedure FreeUnusedMem;
  113. //changes screen resolution
  114. function SetScreenResolution(Width, Height: integer): Longint;
  115. {$ENDIF MSWINDOWS}
  116. //returns last day of current month
  117. function LastDayCurrentMonth: TDateTime;
  118. //checks if two datetimes are in same day
  119. function IsSameDay(cBefore, cNow : TDateTime) : Boolean;
  120. //returns n times a char
  121. function FillStr(const C : Char; const Count : Byte) : string;
  122. //returns a number leading zero
  123. function Zeroes(const Number, Len : Int64) : string;
  124. //converts a number to thousand delimeter string
  125. function NumberToStr(const Number : Int64) : string;
  126. //returns n spaces
  127. function Spaces(const Count : Integer) : string;
  128. //returns current date as a string
  129. function NowStr : string;
  130. //returns a new GUID as string
  131. function NewGuidStr : string;
  132. //compare a string with a wildcard pattern (? or *)
  133. function IsLike(cText, Pattern: string) : Boolean;
  134. //Upper case for first letter
  135. function Capitalize(s: string): string;
  136. function CapitalizeWords(s: string): string;
  137. //returns current logged user
  138. function GetLoggedUserName : string;
  139. //returns computer name
  140. function GetComputerName : string;
  141. //Changes incorrect delims in path
  142. function NormalizePathDelim(const cPath : string; const Delim : Char) : string;
  143. //Removes last segment of a path
  144. function RemoveLastPathSegment(cDir : string) : string;
  145. //finds swith in commandline params
  146. function ParamFindSwitch(const Switch : string) : Boolean;
  147. //gets value for a switch if exists
  148. function ParamGetSwitch(const Switch : string; var cvalue : string) : Boolean;
  149. //returns app version (major & minor)
  150. function GetAppVersionStr: string;
  151. //returns app version full (major, minor, release & compiled)
  152. function GetAppVersionFullStr: string;
  153. //UTC DateTime to Local DateTime
  154. function UTCToLocalTime(GMTTime: TDateTime): TDateTime;
  155. //Local DateTime to UTC DateTime
  156. function LocalTimeToUTC(LocalTime : TDateTime): TDateTime;
  157. //count number of digits of a Integer
  158. function CountDigits(anInt: Cardinal): Cardinal; inline;
  159. var
  160. {$IFDEF MSWINDOWS}
  161. path : TEnvironmentPath;
  162. {$ENDIF MSWINDOWS}
  163. implementation
  164. {TFileHelper}
  165. class function TFileHelper.IsInUse(const FileName : string) : Boolean;
  166. var
  167. HFileRes: HFILE;
  168. begin
  169. Result := False;
  170. if not FileExists(FileName) then Exit;
  171. try
  172. HFileRes := CreateFile(PChar(FileName)
  173. ,GENERIC_READ or GENERIC_WRITE
  174. ,0
  175. ,nil
  176. ,OPEN_EXISTING
  177. ,FILE_ATTRIBUTE_NORMAL
  178. ,0);
  179. Result := (HFileRes = INVALID_HANDLE_VALUE);
  180. if not(Result) then begin
  181. CloseHandle(HFileRes);
  182. end;
  183. except
  184. Result := True;
  185. end;
  186. end;
  187. class function TFileHelper.GetSize(const FileName: String): Int64;
  188. var
  189. info: TWin32FileAttributeData;
  190. begin
  191. Result := -1;
  192. if not GetFileAttributesEx(PWideChar(FileName), GetFileExInfoStandard, @info) then Exit;
  193. Result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
  194. end;
  195. {TDirectoryHelper}
  196. class function TDirectoryHelper.GetSize(const Path: String): Int64;
  197. var
  198. filename : string;
  199. begin
  200. Result := -1;
  201. for filename in TDirectory.GetFiles(Path) do
  202. begin
  203. Result := Result + TFile.GetSize(filename);
  204. end;
  205. end;
  206. {TTextStreamFile}
  207. constructor TTextStreamFile.Create(const FileName : string; OpenMode : TTextFileOperation);
  208. var
  209. Append : Boolean;
  210. begin
  211. if OpenMode = tfOpenRead then fReadStream := TStreamReader.Create(FileName,True)
  212. else
  213. begin
  214. if OpenMode = tfOpenAppend then Append := True
  215. else Append := False;
  216. fWriteStream := TStreamWriter.Create(FileName,Append);
  217. end;
  218. end;
  219. destructor TTextStreamFile.Destroy;
  220. begin
  221. if Assigned(fReadStream) then fReadStream.Free;
  222. if Assigned(fWriteStream) then fWriteStream.Free;
  223. inherited Destroy;
  224. end;
  225. function TTextStreamFile.ReadLn(out Data: string): Boolean;
  226. begin
  227. Data := fReadStream.ReadLine;
  228. Result := Data <> '';
  229. end;
  230. function TTextStreamFile.ReadLn: string;
  231. begin
  232. Result := fReadStream.ReadLine;
  233. end;
  234. procedure TTextStreamFile.WriteLn (const Data : string);
  235. begin
  236. fWriteStream.WriteLine(Data);
  237. end;
  238. function TTextStreamFile.GetEOF : Boolean;
  239. begin
  240. Result := fReadStream.EndOfStream;
  241. end;
  242. procedure TTextStreamFile.Close;
  243. begin
  244. if Assigned(fReadStream) then fReadStream.Close;
  245. if Assigned(fWriteStream) then fWriteStream.Close;
  246. end;
  247. {other functions}
  248. function RandomPassword(const PasswordLength : Integer; Complexity : TPasswordComplexity = [pfIncludeNumbers,pfIncludeSigns]) : string;
  249. const
  250. PassAlpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  251. PassSigns = '@!&$';
  252. PassNumbers = '1234567890';
  253. var
  254. MinNumbers,
  255. MinSigns : Integer;
  256. NumNumbers,
  257. NumSigns : Integer;
  258. begin
  259. Result := '';
  260. Randomize;
  261. //fill all alfa
  262. repeat
  263. Result := Result + PassAlpha[Random(Length(PassAlpha))+1];
  264. until (Length(Result) = PasswordLength);
  265. //checks if need include numbers
  266. if pfIncludeNumbers in Complexity then
  267. begin
  268. MinNumbers := Round(PasswordLength / 10 * 2);
  269. NumNumbers := 0;
  270. if MinNumbers = 0 then MinNumbers := 1;
  271. repeat
  272. Result[Random(PasswordLength)+1] := PassNumbers[Random(Length(PassNumbers))+1];
  273. Inc(NumNumbers);
  274. until NumNumbers = MinNumbers;
  275. end;
  276. //checks if need include signs
  277. if pfIncludeNumbers in Complexity then
  278. begin
  279. MinSigns := Round(PasswordLength / 10 * 1);
  280. NumSigns := 0;
  281. if MinSigns = 0 then MinSigns := 1;
  282. repeat
  283. Result[Random(PasswordLength)+1] := PassSigns[Random(Length(PassSigns))+1];
  284. Inc(NumSigns);
  285. until NumSigns = MinSigns;
  286. end;
  287. end;
  288. function ExtractFileNameWithoutExt(const FileName: String): String;
  289. begin
  290. Result := TPath.GetFileNameWithoutExtension(FileName);
  291. end;
  292. function UnixToWindowsPath(const UnixPath: string): string;
  293. begin
  294. Result:=StringReplace(UnixPath, '/', '\',[rfReplaceAll, rfIgnoreCase]);
  295. end;
  296. function WindowsToUnixPath(const WindowsPath: string): string;
  297. begin
  298. Result:=StringReplace(WindowsPath, '\', '/',[rfReplaceAll, rfIgnoreCase]);
  299. end;
  300. {$IFDEF MSWINDOWS}
  301. procedure GetEnvironmentPaths;
  302. begin
  303. //gets path
  304. path.EXEPATH := TPath.GetDirectoryName(ParamStr(0));
  305. path.WINDOWS := GetEnvironmentVariable('windir');
  306. path.PROGRAMFILES := GetEnvironmentVariable('ProgramFiles');
  307. path.COMMONFILES := GetEnvironmentVariable('CommonProgramFiles(x86)');
  308. path.HOMEDRIVE := GetEnvironmentVariable('SystemDrive');
  309. path.USERPROFILE := GetEnvironmentVariable('USERPROFILE');
  310. path.PROGRAMDATA := GetEnvironmentVariable('ProgramData');
  311. path.ALLUSERSPROFILE := GetEnvironmentVariable('AllUsersProfile');
  312. path.INSTDRIVE := path.HOMEDRIVE;
  313. path.TEMP := GetEnvironmentVariable('TEMP');
  314. path.SYSTEM := GetSpecialFolderPath(CSIDL_SYSTEM);
  315. path.APPDATA:=GetSpecialFolderPath(CSIDL_APPDATA);
  316. //these paths fail if user is SYSTEM
  317. try
  318. path.DESKTOP := GetSpecialFolderPath(CSIDL_DESKTOP);
  319. path.DESKTOP_ALLUSERS := GetSpecialFolderPath(CSIDL_COMMON_DESKTOPDIRECTORY);
  320. path.STARTMENU:=GetSpecialFolderPath(CSIDL_PROGRAMS);
  321. path.STARTMENU_ALLUSERS:=GetSpecialFolderPath(CSIDL_COMMON_PROGRAMS);
  322. path.STARTMENU_ALLUSERS := path.STARTMENU;
  323. path.STARTUP:=GetSpecialFolderPath(CSIDL_STARTUP);
  324. except
  325. //
  326. end;
  327. end;
  328. function GetSpecialFolderPath(folderID : Integer) : string;
  329. var
  330. ppidl: PItemIdList;
  331. begin
  332. SHGetSpecialFolderLocation(0, folderID, ppidl);
  333. SetLength(Result, MAX_PATH);
  334. if not SHGetPathFromIDList(ppidl, PChar(Result)) then
  335. begin
  336. raise exception.create(Format('GetSpecialFolderPath: Invalid PIPL (%d)',[folderID]));
  337. end;
  338. SetLength(Result, lStrLen(PChar(Result)));
  339. end;
  340. function Is64bitOS : Boolean;
  341. begin
  342. {$IFDEF WIN64}
  343. Result := True;
  344. {$ELSE}
  345. Result := False;
  346. {$ENDIF WIN64}
  347. end;
  348. function IsConsole: Boolean;
  349. begin
  350. {$IFDEF CONSOLE}
  351. Result := True;
  352. {$ELSE}
  353. Result := False;
  354. {$ENDIF CONSOLE}
  355. end;
  356. function IsDebug: Boolean;
  357. begin
  358. {$IFDEF DEBUG}
  359. Result := True;
  360. {$ELSE}
  361. Result := False;
  362. {$ENDIF DEBUG}
  363. end;
  364. function IsService : Boolean;
  365. begin
  366. //only working with my Quick.AppService unit
  367. try
  368. Result := (IsConsole) and (GetStdHandle(STD_OUTPUT_HANDLE) = 0);
  369. except
  370. Result := False;
  371. end;
  372. end;
  373. function SecondsIdle: DWord;
  374. var
  375. liInfo: TLastInputInfo;
  376. begin
  377. liInfo.cbSize := SizeOf(TLastInputInfo) ;
  378. GetLastInputInfo(liInfo) ;
  379. Result := (GetTickCount - liInfo.dwTime) DIV 1000;
  380. end;
  381. procedure FreeUnusedMem;
  382. begin
  383. if Win32Platform = VER_PLATFORM_WIN32_NT then SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
  384. end;
  385. function SetScreenResolution(Width, Height: integer): Longint;
  386. var
  387. DeviceMode: TDeviceMode;
  388. begin
  389. with DeviceMode do
  390. begin
  391. dmSize := SizeOf(TDeviceMode);
  392. dmPelsWidth := Width;
  393. dmPelsHeight := Height;
  394. dmFields := DM_PELSWIDTH or DM_PELSHEIGHT;
  395. end;
  396. Result := ChangeDisplaySettings(DeviceMode, CDS_UPDATEREGISTRY);
  397. end;
  398. {$ENDIF MSWINDOWS}
  399. function LastDayCurrentMonth: TDateTime;
  400. begin
  401. Result := EncodeDate(YearOf(Now),MonthOf(Now), DaysInMonth(Now));
  402. end;
  403. function IsSameDay(cBefore, cNow : TDateTime) : Boolean;
  404. begin
  405. Result := DateTimeInRange(cNow,StartOfTheDay(cBefore),EndOfTheDay(cNow),True);
  406. end;
  407. function FillStr(const C : Char; const Count : Byte) : string;
  408. var
  409. i : Byte;
  410. begin
  411. Result := '';
  412. for i := 1 to Count do Result := Result + C;
  413. end;
  414. function Zeroes(const Number, Len : Int64) : string;
  415. begin
  416. if Len > Length(IntToStr(Number)) then Result := FillStr('0',Len - Length(IntToStr(Number))) + IntToStr(Number)
  417. else Result := IntToStr(Number);
  418. end;
  419. function NumberToStr(const Number : Int64) : string;
  420. begin
  421. try
  422. Result := FormatFloat('0,',Number);
  423. except
  424. Result := '#Error';
  425. end;
  426. end;
  427. function Spaces(const Count : Integer) : string;
  428. begin
  429. Result := FillStr(' ',Count);
  430. end;
  431. function NowStr : string;
  432. begin
  433. Result := DateTimeToStr(Now());
  434. end;
  435. function NewGuidStr : string;
  436. var
  437. guid : TGUID;
  438. begin
  439. guid.NewGuid;
  440. Result := guid.ToString
  441. //GUIDToString(guid);
  442. end;
  443. function IsLike(cText, Pattern: string) : Boolean;
  444. var
  445. i, n : Integer;
  446. match : Boolean;
  447. wildcard : Boolean;
  448. CurrentPattern : Char;
  449. aux : string;
  450. begin
  451. Result := False;
  452. wildcard := False;
  453. cText := LowerCase(cText);
  454. Pattern := LowerCase(Pattern);
  455. match := False;
  456. if (Pattern.Length > cText.Length) or (Pattern = '') then Exit;
  457. if Pattern = '*' then
  458. begin
  459. Result := True;
  460. Exit;
  461. end;
  462. for i := 1 to cText.Length do
  463. begin
  464. CurrentPattern := Pattern[i];
  465. if CurrentPattern = '*' then wildcard := True;
  466. if wildcard then
  467. begin
  468. aux := Copy(Pattern,i+1,Pattern.Length);
  469. n := Pos(Copy(Pattern,i+1,Pattern.Length),cText);
  470. if (n > i) or (Pattern.Length = i) then
  471. begin
  472. Result := True;
  473. Exit;
  474. end;
  475. end
  476. else
  477. begin
  478. if (cText[i] = CurrentPattern) or (CurrentPattern = '?') then match := True
  479. else match := False;
  480. end;
  481. end;
  482. Result := match;
  483. end;
  484. function Capitalize(s: string): string;
  485. begin
  486. Result := '';
  487. if s.Length = 0 then Exit;
  488. s := LowerCase(s,loUserLocale);
  489. Result := UpperCase(s[1],loUserLocale) + Trim(Copy(s, 2, s.Length));
  490. end;
  491. function CapitalizeWords(s: string): string;
  492. var
  493. cword : string;
  494. begin
  495. Result := '';
  496. if s.Length = 0 then Exit;
  497. s := LowerCase(s,loUserLocale);
  498. for cword in s.Split([' ']) do
  499. begin
  500. if Result = '' then Result := Capitalize(cword)
  501. else Result := Result + ' ' + Capitalize(cword);
  502. end;
  503. end;
  504. function GetLoggedUserName : string;
  505. const
  506. cnMaxUserNameLen = 254;
  507. var
  508. sUserName : string;
  509. dwUserNameLen : DWord;
  510. begin
  511. dwUserNameLen := cnMaxUserNameLen-1;
  512. SetLength( sUserName, cnMaxUserNameLen );
  513. GetUserName(PChar( sUserName ),dwUserNameLen );
  514. SetLength( sUserName, dwUserNameLen );
  515. Result := sUserName;
  516. end;
  517. function GetComputerName : string;
  518. var
  519. dwLength: dword;
  520. begin
  521. dwLength := 253;
  522. SetLength(Result, dwLength+1);
  523. if not Windows.GetComputerName(pchar(result), dwLength) then Result := 'Not detected!';
  524. Result := pchar(result);
  525. end;
  526. function NormalizePathDelim(const cPath : string; const Delim : Char) : string;
  527. begin
  528. if Delim = '\' then Result := StringReplace(cPath,'/',Delim,[rfReplaceAll])
  529. else Result := StringReplace(cPath,'\',Delim,[rfReplaceAll]);
  530. end;
  531. function RemoveLastPathSegment(cDir : string) : string;
  532. var
  533. posi : Integer;
  534. delim : Char;
  535. EndsWithDelim : Boolean;
  536. begin
  537. if cDir.Contains('\') then delim := '\'
  538. else if cDir.Contains('/') then delim := '/'
  539. else
  540. begin
  541. Result := '';
  542. Exit;
  543. end;
  544. NormalizePathDelim(cDir,delim);
  545. if cDir.EndsWith(delim) then
  546. begin
  547. cDir := Copy(cDir,1,cDir.Length-1);
  548. EndsWithDelim := True;
  549. end
  550. else EndsWithDelim := False;
  551. if cDir.CountChar(delim) > 1 then posi := cDir.LastDelimiter(delim)
  552. else posi := Pos(delim,cDir)-1;
  553. if posi = cDir.Length then posi := 0;
  554. Result := Copy(cDir,1,posi);
  555. if (Result <> '') and (EndsWithDelim) then Result := Result + delim;
  556. end;
  557. function ParamFindSwitch(const Switch : string) : Boolean;
  558. begin
  559. Result := FindCmdLineSwitch(Switch,['-', '/'],True);
  560. end;
  561. function ParamGetSwitch(const Switch : string; var cvalue : string) : Boolean;
  562. begin
  563. Result := FindCmdLineSwitch(Switch,cvalue,True,[clstValueAppended]);
  564. end;
  565. function GetAppVersionStr: string;
  566. var
  567. Rec: LongRec;
  568. ver : Cardinal;
  569. begin
  570. ver := GetFileVersion(ParamStr(0));
  571. if ver <> Cardinal(-1) then
  572. begin
  573. Rec := LongRec(ver);
  574. Result := Format('%d.%d', [Rec.Hi, Rec.Lo]);
  575. end
  576. else Result := '';
  577. end;
  578. function GetAppVersionFullStr: string;
  579. var
  580. Exe: string;
  581. Size, Handle: DWORD;
  582. Buffer: TBytes;
  583. FixedPtr: PVSFixedFileInfo;
  584. begin
  585. Result := '';
  586. Exe := ParamStr(0);
  587. Size := GetFileVersionInfoSize(PChar(Exe), Handle);
  588. if Size = 0 then
  589. begin
  590. //RaiseLastOSError;
  591. //no version info in file
  592. Exit;
  593. end;
  594. SetLength(Buffer, Size);
  595. if not GetFileVersionInfo(PChar(Exe), Handle, Size, Buffer) then
  596. RaiseLastOSError;
  597. if not VerQueryValue(Buffer, '\', Pointer(FixedPtr), Size) then
  598. RaiseLastOSError;
  599. if (LongRec(FixedPtr.dwFileVersionLS).Hi = 0) and (LongRec(FixedPtr.dwFileVersionLS).Lo = 0) then
  600. begin
  601. Result := Format('%d.%d',
  602. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  603. LongRec(FixedPtr.dwFileVersionMS).Lo]); //minor
  604. end
  605. else if (LongRec(FixedPtr.dwFileVersionLS).Lo = 0) then
  606. begin
  607. Result := Format('%d.%d.%d',
  608. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  609. LongRec(FixedPtr.dwFileVersionMS).Lo, //minor
  610. LongRec(FixedPtr.dwFileVersionLS).Hi]); //release
  611. end
  612. else
  613. begin
  614. Result := Format('%d.%d.%d.%d',
  615. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  616. LongRec(FixedPtr.dwFileVersionMS).Lo, //minor
  617. LongRec(FixedPtr.dwFileVersionLS).Hi, //release
  618. LongRec(FixedPtr.dwFileVersionLS).Lo]); //build
  619. end;
  620. end;
  621. function UTCToLocalTime(GMTTime: TDateTime): TDateTime;
  622. begin
  623. Result := TTimeZone.Local.ToLocalTime(GMTTime);
  624. end;
  625. function LocalTimeToUTC(LocalTime : TDateTime): TDateTime;
  626. begin
  627. Result := TTimeZone.Local.ToUniversalTime(LocalTime);
  628. end;
  629. function CountDigits(anInt: Cardinal): Cardinal; inline;
  630. var
  631. cmp: Cardinal;
  632. begin
  633. cmp := 10;
  634. Result := 1;
  635. while (Result < 10) and (cmp <= anInt) do
  636. begin
  637. cmp := cmp*10;
  638. Inc(Result);
  639. end;
  640. end;
  641. initialization
  642. try
  643. GetEnvironmentPaths;
  644. except
  645. on E : Exception do if not IsService then raise Exception.Create(E.Message);
  646. end;
  647. end.