Quick.Commons.pas 20 KB

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