Quick.Commons.pas 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271
  1. { ***************************************************************************
  2. Copyright (c) 2016-2019 Kike Pérez
  3. Unit : Quick.Commons
  4. Description : Common functions
  5. Author : Kike Pérez
  6. Version : 1.5
  7. Created : 14/07/2017
  8. Modified : 18/01/2019
  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. {$i QuickLib.inc}
  23. interface
  24. uses
  25. Classes,
  26. SysUtils,
  27. Types,
  28. {$IFDEF MSWINDOWS}
  29. Windows,
  30. ShlObj,
  31. Registry,
  32. {$ENDIF MSWINDOWS}
  33. {$IFDEF FPC}
  34. Quick.Files,
  35. {$IFDEF LINUX}
  36. FileInfo,
  37. {$ENDIF}
  38. {$ELSE}
  39. IOUtils,
  40. {$ENDIF}
  41. {$IFDEF ANDROID}
  42. Androidapi.JNI.Os,
  43. Androidapi.Helpers,
  44. Androidapi.JNI.JavaTypes,
  45. Androidapi.JNI.GraphicsContentViewText,
  46. {$ENDIF}
  47. {$IFDEF IOS}
  48. iOSapi.UIKit,
  49. Posix.SysSysctl,
  50. Posix.StdDef,
  51. iOSapi.Foundation,
  52. Macapi.ObjectiveC,
  53. Macapi.Helpers,
  54. {$ENDIF}
  55. {$IFDEF OSX}
  56. Macapi.Foundation,
  57. Macapi.Helpers,
  58. FMX.Helpers.Mac,
  59. Macapi.ObjectiveC,
  60. {$ENDIF}
  61. DateUtils;
  62. type
  63. TLogEventType = (etInfo, etSuccess, etWarning, etError, etDebug, etTrace);
  64. TLogVerbose = set of TLogEventType;
  65. const
  66. LOG_ONLYERRORS = [etInfo,etError];
  67. LOG_ERRORSANDWARNINGS = [etInfo,etWarning,etError];
  68. LOG_TRACE = [etInfo,etError,etWarning,etTrace];
  69. LOG_ALL = [etInfo,etSuccess,etWarning,etError,etTrace];
  70. LOG_DEBUG = [etInfo,etSuccess,etWarning,etError,etDebug];
  71. {$IFDEF DELPHIXE7_UP}
  72. EventStr : array of string = ['INFO','SUCC','WARN','ERROR','DEBUG','TRACE'];
  73. {$ELSE}
  74. EventStr : array[0..5] of string = ('INFO','SUCC','WARN','ERROR','DEBUG','TRACE');
  75. {$ENDIF}
  76. type
  77. TPasswordComplexity = set of (pfIncludeNumbers,pfIncludeSigns);
  78. {$IFDEF MSWINDOWS}
  79. TEnvironmentPath = record
  80. EXEPATH : string;
  81. WINDOWS : string;
  82. SYSTEM : string;
  83. PROGRAMFILES : string;
  84. COMMONFILES : string;
  85. HOMEDRIVE : string;
  86. TEMP : string;
  87. USERPROFILE : string;
  88. INSTDRIVE : string;
  89. DESKTOP : string;
  90. STARTMENU : string;
  91. DESKTOP_ALLUSERS : string;
  92. STARTMENU_ALLUSERS : string;
  93. STARTUP : string;
  94. APPDATA : String;
  95. PROGRAMDATA : string;
  96. ALLUSERSPROFILE : string;
  97. end;
  98. {$ENDIF MSWINDOWS}
  99. {$IFNDEF FPC}
  100. TFileHelper = record helper for TFile
  101. {$IF DEFINED(MSWINDOWS) OR DEFINED(DELPHILINUX)}
  102. class function IsInUse(const FileName : string) : Boolean; static;
  103. {$ENDIF}
  104. class function GetSize(const FileName: String): Int64; static;
  105. end;
  106. TDirectoryHelper = record helper for TDirectory
  107. class function GetSize(const Path: String): Int64; static;
  108. end;
  109. {$ENDIF}
  110. {$IFDEF FPC}
  111. {$IFDEF LINUX}
  112. UINT = cardinal;
  113. {$ENDIF}
  114. PLASTINPUTINFO = ^LASTINPUTINFO;
  115. tagLASTINPUTINFO = record
  116. cbSize: UINT;
  117. dwTime: DWORD;
  118. end;
  119. LASTINPUTINFO = tagLASTINPUTINFO;
  120. TLastInputInfo = LASTINPUTINFO;
  121. type
  122. TCmdLineSwitchType = (clstValueNextParam, clstValueAppended);
  123. TCmdLineSwitchTypes = set of TCmdLineSwitchType;
  124. {$ENDIF}
  125. TCounter = record
  126. private
  127. fMaxValue : Integer;
  128. fCurrentValue : Integer;
  129. public
  130. property MaxValue : Integer read fMaxValue;
  131. procedure Init(aMaxValue : Integer);
  132. function Count : Integer;
  133. function CountIs(aValue : Integer) : Boolean;
  134. function Check : Boolean;
  135. procedure Reset;
  136. end;
  137. TTimeCounter = record
  138. private
  139. fCurrentTime : TDateTime;
  140. fDoneEvery : Integer;
  141. public
  142. property DoneEvery : Integer read fDoneEvery;
  143. procedure Init(MillisecondsToReach : Integer);
  144. function Check : Boolean;
  145. procedure Reset;
  146. end;
  147. EEnvironmentPath = class(Exception);
  148. EShellError = class(Exception);
  149. //generates a random password with complexity options
  150. function RandomPassword(const PasswordLength : Integer; Complexity : TPasswordComplexity = [pfIncludeNumbers,pfIncludeSigns]) : string;
  151. //extracts file extension from a filename
  152. function ExtractFileNameWithoutExt(const FileName: string): string;
  153. //converts a Unix path to Windows path
  154. function UnixToWindowsPath(const UnixPath: string): string;
  155. //converts a Windows path to Unix path
  156. function WindowsToUnixPath(const WindowsPath: string): string;
  157. //corrects malformed urls
  158. function CorrectURLPath(cUrl : string) : string;
  159. {$IFDEF MSWINDOWS}
  160. //get typical environment paths as temp, desktop, etc
  161. procedure GetEnvironmentPaths;
  162. function GetSpecialFolderPath(folderID : Integer) : string;
  163. //checks if running on a 64bit OS
  164. function Is64bitOS : Boolean;
  165. //checks if is a console app
  166. function IsConsole : Boolean;
  167. //checks if compiled in debug mode
  168. {$ENDIF}
  169. function IsDebug : Boolean;
  170. {$IFDEF MSWINDOWS}
  171. //checks if running as a service
  172. function IsService : Boolean;
  173. //gets number of seconds without user interaction (mouse, keyboard)
  174. function SecondsIdle: DWord;
  175. //frees process memory not needed
  176. procedure FreeUnusedMem;
  177. //changes screen resolution
  178. function SetScreenResolution(Width, Height: integer): Longint;
  179. {$ENDIF MSWINDOWS}
  180. //returns last day of current month
  181. function LastDayCurrentMonth: TDateTime;
  182. {$IFDEF FPC}
  183. function DateTimeInRange(ADateTime: TDateTime; AStartDateTime, AEndDateTime: TDateTime; aInclusive: Boolean = True): Boolean;
  184. {$ENDIF}
  185. //checks if two datetimes are in same day
  186. function IsSameDay(cBefore, cNow : TDateTime) : Boolean;
  187. //change Time of a DateTime
  188. function ChangeTimeOfADay(aDate : TDateTime; aHour, aMinute, aSecond : Word; aMilliSecond : Word = 0) : TDateTime;
  189. //change Date of a DateTime
  190. function ChangeDateOfADay(aDate : TDateTime; aYear, aMonth, aDay : Word) : TDateTime;
  191. //returns n times a char
  192. function FillStr(const C : Char; const Count : Byte) : string;
  193. //checks if string exists in array of string
  194. function StrInArray(const aValue : string; const aInArray : array of string) : Boolean;
  195. //checks if integer exists in array of integer
  196. function IntInArray(const aValue : Integer; const aInArray : array of Integer) : Boolean;
  197. //returns a number leading zero
  198. function Zeroes(const Number, Len : Int64) : string;
  199. //converts a number to thousand delimeter string
  200. function NumberToStr(const Number : Int64) : string;
  201. //returns n spaces
  202. function Spaces(const Count : Integer) : string;
  203. //returns current date as a string
  204. function NowStr : string;
  205. //returns a new GUID as string
  206. function NewGuidStr : string;
  207. //compare a string with a wildcard pattern (? or *)
  208. function IsLike(cText, Pattern: string) : Boolean;
  209. //Upper case for first letter
  210. function Capitalize(s: string): string;
  211. function CapitalizeWords(s: string): string;
  212. //returns current logged user
  213. function GetLoggedUserName : string;
  214. //returns computer name
  215. function GetComputerName : string;
  216. //Changes incorrect delims in path
  217. function NormalizePathDelim(const cPath : string; const Delim : Char) : string;
  218. //Removes last segment of a path
  219. function RemoveLastPathSegment(cDir : string) : string;
  220. //finds swith in commandline params
  221. function ParamFindSwitch(const Switch : string) : Boolean;
  222. //gets value for a switch if exists
  223. function ParamGetSwitch(const Switch : string; var cvalue : string) : Boolean;
  224. //returns app name (filename based)
  225. function GetAppName : string;
  226. //returns app version (major & minor)
  227. function GetAppVersionStr: string;
  228. //returns app version full (major, minor, release & compiled)
  229. function GetAppVersionFullStr: string;
  230. //convert UTC DateTime to Local DateTime
  231. function UTCToLocalTime(GMTTime: TDateTime): TDateTime;
  232. //convert Local DateTime to UTC DateTime
  233. function LocalTimeToUTC(LocalTime : TDateTime): TDateTime;
  234. //convert DateTime to GTM Time string
  235. function DateTimeToGMT(aDate : TDateTime) : string;
  236. //convert GMT Time string to DateTime
  237. function GMTToDateTime(aDate : string) : TDateTime;
  238. //convert DateTime to Json Date format
  239. function DateTimeToJsonDate(aDateTime : TDateTime) : string;
  240. //convert Json Date format to DateTime
  241. function JsonDateToDateTime(const aJsonDate : string) : TDateTime;
  242. //count number of digits of a Integer
  243. function CountDigits(anInt: Cardinal): Cardinal; inline;
  244. //save stream to file
  245. procedure SaveStreamToFile(stream : TStream; const filename : string);
  246. //returns a real comma separated text from stringlist
  247. function CommaText(aList : TStringList) : string;
  248. {$IFDEF MSWINDOWS}
  249. //process messages on console applications
  250. procedure ProcessMessages;
  251. //get last error message
  252. function GetLastOSError : String;
  253. {$ENDIF}
  254. {$IF DEFINED(FPC) AND DEFINED(MSWINDOWS)}
  255. function GetLastInputInfo(var plii: TLastInputInfo): BOOL;stdcall; external 'user32' name 'GetLastInputInfo';
  256. {$ENDIF}
  257. function RemoveLastChar(const aText : string) : string;
  258. function DateTimeToSQL(aDateTime : TDateTime) : string;
  259. {$IFDEF MSWINDOWS}
  260. var
  261. path : TEnvironmentPath;
  262. {$ENDIF}
  263. implementation
  264. {TFileHelper}
  265. {$IFNDEF FPC}
  266. {$IFDEF MSWINDOWS}
  267. class function TFileHelper.IsInUse(const FileName : string) : Boolean;
  268. var
  269. HFileRes: HFILE;
  270. begin
  271. Result := False;
  272. if not FileExists(FileName) then Exit;
  273. try
  274. HFileRes := CreateFile(PChar(FileName)
  275. ,GENERIC_READ or GENERIC_WRITE
  276. ,0
  277. ,nil
  278. ,OPEN_EXISTING
  279. ,FILE_ATTRIBUTE_NORMAL
  280. ,0);
  281. Result := (HFileRes = INVALID_HANDLE_VALUE);
  282. if not(Result) then begin
  283. CloseHandle(HFileRes);
  284. end;
  285. except
  286. Result := True;
  287. end;
  288. end;
  289. {$ENDIF}
  290. {$IFDEF DELPHILINUX}
  291. class function TFileHelper.IsInUse(const FileName : string) : Boolean;
  292. var
  293. fs : TFileStream;
  294. begin
  295. try
  296. fs := TFileStream.Create(FileName, fmOpenReadWrite, fmShareExclusive);
  297. Result := True;
  298. fs.Free;
  299. except
  300. Result := False;
  301. end;
  302. end;
  303. {$ENDIF}
  304. {$IFDEF MSWINDOWS}
  305. class function TFileHelper.GetSize(const FileName: String): Int64;
  306. var
  307. info: TWin32FileAttributeData;
  308. begin
  309. Result := -1;
  310. if not GetFileAttributesEx(PWideChar(FileName), GetFileExInfoStandard, @info) then Exit;
  311. Result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
  312. end;
  313. {$ELSE}
  314. class function TFileHelper.GetSize(const FileName: String): Int64;
  315. var
  316. sr : TSearchRec;
  317. begin
  318. if FindFirst(fileName, faAnyFile, sr ) = 0 then Result := sr.Size
  319. else Result := -1;
  320. end;
  321. {$ENDIF}
  322. {TDirectoryHelper}
  323. class function TDirectoryHelper.GetSize(const Path: String): Int64;
  324. var
  325. filename : string;
  326. begin
  327. Result := -1;
  328. for filename in TDirectory.GetFiles(Path) do
  329. begin
  330. Result := Result + TFile.GetSize(filename);
  331. end;
  332. end;
  333. {$ENDIF}
  334. {other functions}
  335. function RandomPassword(const PasswordLength : Integer; Complexity : TPasswordComplexity = [pfIncludeNumbers,pfIncludeSigns]) : string;
  336. const
  337. PassAlpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  338. PassSigns = '@!&$';
  339. PassNumbers = '1234567890';
  340. var
  341. MinNumbers,
  342. MinSigns : Integer;
  343. NumNumbers,
  344. NumSigns : Integer;
  345. begin
  346. Result := '';
  347. Randomize;
  348. //fill all alfa
  349. repeat
  350. Result := Result + PassAlpha[Random(Length(PassAlpha))+1];
  351. until (Length(Result) = PasswordLength);
  352. //checks if need include numbers
  353. if pfIncludeNumbers in Complexity then
  354. begin
  355. MinNumbers := Round(PasswordLength / 10 * 2);
  356. NumNumbers := 0;
  357. if MinNumbers = 0 then MinNumbers := 1;
  358. repeat
  359. Result[Random(PasswordLength)+1] := PassNumbers[Random(Length(PassNumbers))+1];
  360. Inc(NumNumbers);
  361. until NumNumbers = MinNumbers;
  362. end;
  363. //checks if need include signs
  364. if pfIncludeNumbers in Complexity then
  365. begin
  366. MinSigns := Round(PasswordLength / 10 * 1);
  367. NumSigns := 0;
  368. if MinSigns = 0 then MinSigns := 1;
  369. repeat
  370. Result[Random(PasswordLength)+1] := PassSigns[Random(Length(PassSigns))+1];
  371. Inc(NumSigns);
  372. until NumSigns = MinSigns;
  373. end;
  374. end;
  375. function ExtractFileNameWithoutExt(const FileName: string): string;
  376. begin
  377. Result := TPath.GetFileNameWithoutExtension(FileName);
  378. end;
  379. function UnixToWindowsPath(const UnixPath: string): string;
  380. begin
  381. Result := StringReplace(UnixPath, '/', '\',[rfReplaceAll, rfIgnoreCase]);
  382. end;
  383. function WindowsToUnixPath(const WindowsPath: string): string;
  384. begin
  385. Result := StringReplace(WindowsPath, '\', '/',[rfReplaceAll, rfIgnoreCase]);
  386. end;
  387. function CorrectURLPath(cUrl : string) : string;
  388. var
  389. nurl : string;
  390. begin
  391. nurl := WindowsToUnixPath(cUrl);
  392. nurl := StringReplace(nurl,'//','/',[rfReplaceAll]);
  393. Result := StringReplace(nurl,' ','%20',[rfReplaceAll]);
  394. //TNetEncoding.Url.Encode()
  395. end;
  396. {$IFDEF MSWINDOWS}
  397. procedure GetEnvironmentPaths;
  398. begin
  399. //gets path
  400. path.EXEPATH := TPath.GetDirectoryName(ParamStr(0));
  401. path.WINDOWS := SysUtils.GetEnvironmentVariable('windir');
  402. path.PROGRAMFILES := SysUtils.GetEnvironmentVariable('ProgramFiles');
  403. path.COMMONFILES := SysUtils.GetEnvironmentVariable('CommonProgramFiles(x86)');
  404. path.HOMEDRIVE := SysUtils.GetEnvironmentVariable('SystemDrive');
  405. path.USERPROFILE := SysUtils.GetEnvironmentVariable('USERPROFILE');
  406. path.PROGRAMDATA := SysUtils.GetEnvironmentVariable('ProgramData');
  407. path.ALLUSERSPROFILE := SysUtils.GetEnvironmentVariable('AllUsersProfile');
  408. path.INSTDRIVE := path.HOMEDRIVE;
  409. path.TEMP := SysUtils.GetEnvironmentVariable('TEMP');
  410. path.SYSTEM := GetSpecialFolderPath(CSIDL_SYSTEM);
  411. path.APPDATA:=GetSpecialFolderPath(CSIDL_APPDATA);
  412. //these paths fail if user is SYSTEM
  413. try
  414. path.DESKTOP := GetSpecialFolderPath(CSIDL_DESKTOP);
  415. path.DESKTOP_ALLUSERS := GetSpecialFolderPath(CSIDL_COMMON_DESKTOPDIRECTORY);
  416. path.STARTMENU:=GetSpecialFolderPath(CSIDL_PROGRAMS);
  417. path.STARTMENU_ALLUSERS:=GetSpecialFolderPath(CSIDL_COMMON_PROGRAMS);
  418. path.STARTMENU_ALLUSERS := path.STARTMENU;
  419. path.STARTUP:=GetSpecialFolderPath(CSIDL_STARTUP);
  420. except
  421. //
  422. end;
  423. end;
  424. function GetSpecialFolderPath(folderID : Integer) : string;
  425. var
  426. ppidl: PItemIdList;
  427. begin
  428. SHGetSpecialFolderLocation(0, folderID, ppidl);
  429. SetLength(Result, MAX_PATH);
  430. if not SHGetPathFromIDList(ppidl,{$IFDEF FPC}PAnsiChar(Result){$ELSE}PChar(Result){$ENDIF}) then
  431. begin
  432. raise EShellError.create(Format('GetSpecialFolderPath: Invalid PIPL (%d)',[folderID]));
  433. end;
  434. SetLength(Result, lStrLen({$IFDEF FPC}PAnsiChar(Result){$ELSE}PChar(Result){$ENDIF}));
  435. end;
  436. function Is64bitOS : Boolean;
  437. begin
  438. {$IFDEF WIN64}
  439. Result := True;
  440. {$ELSE}
  441. Result := False;
  442. {$ENDIF WIN64}
  443. end;
  444. function IsConsole: Boolean;
  445. begin
  446. {$IFDEF CONSOLE}
  447. Result := True;
  448. {$ELSE}
  449. Result := False;
  450. {$ENDIF CONSOLE}
  451. end;
  452. {$ENDIF}
  453. function IsDebug: Boolean;
  454. begin
  455. {$IFDEF DEBUG}
  456. Result := True;
  457. {$ELSE}
  458. Result := False;
  459. {$ENDIF DEBUG}
  460. end;
  461. {$IFDEF MSWINDOWS}
  462. function IsService : Boolean;
  463. begin
  464. //only working with my Quick.AppService unit
  465. try
  466. Result := (IsConsole) and (GetStdHandle(STD_OUTPUT_HANDLE) = 0);
  467. except
  468. Result := False;
  469. end;
  470. end;
  471. function SecondsIdle: DWord;
  472. var
  473. liInfo: TLastInputInfo;
  474. begin
  475. liInfo.cbSize := SizeOf(TLastInputInfo) ;
  476. GetLastInputInfo(liInfo) ;
  477. Result := (GetTickCount - liInfo.dwTime) DIV 1000;
  478. end;
  479. procedure FreeUnusedMem;
  480. begin
  481. if Win32Platform = VER_PLATFORM_WIN32_NT then SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
  482. end;
  483. function SetScreenResolution(Width, Height: integer): Longint;
  484. var
  485. DeviceMode: TDeviceMode;
  486. begin
  487. with DeviceMode do
  488. begin
  489. dmSize := SizeOf(TDeviceMode);
  490. dmPelsWidth := Width;
  491. dmPelsHeight := Height;
  492. dmFields := DM_PELSWIDTH or DM_PELSHEIGHT;
  493. end;
  494. Result := ChangeDisplaySettings(DeviceMode, CDS_UPDATEREGISTRY);
  495. end;
  496. {$ENDIF MSWINDOWS}
  497. function LastDayCurrentMonth: TDateTime;
  498. begin
  499. Result := EncodeDate(YearOf(Now),MonthOf(Now), DaysInMonth(Now));
  500. end;
  501. {$IFDEF FPC}
  502. function DateTimeInRange(ADateTime: TDateTime; AStartDateTime, AEndDateTime: TDateTime; aInclusive: Boolean = True): Boolean;
  503. begin
  504. if aInclusive then
  505. Result := (AStartDateTime <= ADateTime) and (ADateTime <= AEndDateTime)
  506. else
  507. Result := (AStartDateTime < ADateTime) and (ADateTime < AEndDateTime);
  508. end;
  509. {$ENDIF}
  510. function IsSameDay(cBefore, cNow : TDateTime) : Boolean;
  511. begin
  512. //Test: Result := MinutesBetween(cBefore,cNow) < 1;
  513. Result := DateTimeInRange(cNow,StartOfTheDay(cBefore),EndOfTheDay(cBefore),True);
  514. end;
  515. function ChangeTimeOfADay(aDate : TDateTime; aHour, aMinute, aSecond : Word; aMilliSecond : Word = 0) : TDateTime;
  516. var
  517. y, m, d : Word;
  518. begin
  519. DecodeDate(aDate,y,m,d);
  520. Result := EncodeDateTime(y,m,d,aHour,aMinute,aSecond,aMilliSecond);
  521. end;
  522. function ChangeDateOfADay(aDate : TDateTime; aYear, aMonth, aDay : Word) : TDateTime;
  523. var
  524. h, m, s, ms : Word;
  525. begin
  526. DecodeTime(aDate,h,m,s,ms);
  527. Result := EncodeDateTime(aYear,aMonth,aDay,h,m,s,0);
  528. end;
  529. function FillStr(const C : Char; const Count : Byte) : string;
  530. var
  531. i : Byte;
  532. begin
  533. Result := '';
  534. for i := 1 to Count do Result := Result + C;
  535. end;
  536. function StrInArray(const aValue : string; const aInArray : array of string) : Boolean;
  537. var
  538. s : string;
  539. begin
  540. for s in aInArray do
  541. begin
  542. if s = aValue then Exit(True);
  543. end;
  544. Result := False;
  545. end;
  546. function IntInArray(const aValue : Integer; const aInArray : array of Integer) : Boolean;
  547. var
  548. i : Integer;
  549. begin
  550. for i in aInArray do
  551. begin
  552. if i = aValue then Exit(True);
  553. end;
  554. Result := False;
  555. end;
  556. function Zeroes(const Number, Len : Int64) : string;
  557. begin
  558. if Len > Length(IntToStr(Number)) then Result := FillStr('0',Len - Length(IntToStr(Number))) + IntToStr(Number)
  559. else Result := IntToStr(Number);
  560. end;
  561. function NumberToStr(const Number : Int64) : string;
  562. begin
  563. try
  564. Result := FormatFloat('0,',Number);
  565. except
  566. Result := '#Error';
  567. end;
  568. end;
  569. function Spaces(const Count : Integer) : string;
  570. begin
  571. Result := FillStr(' ',Count);
  572. end;
  573. function NowStr : string;
  574. begin
  575. Result := DateTimeToStr(Now());
  576. end;
  577. function NewGuidStr : string;
  578. var
  579. guid : TGUID;
  580. begin
  581. guid.NewGuid;
  582. Result := guid.ToString
  583. //GUIDToString(guid);
  584. end;
  585. function IsLike(cText, Pattern: string) : Boolean;
  586. var
  587. i, n : Integer;
  588. match : Boolean;
  589. wildcard : Boolean;
  590. CurrentPattern : Char;
  591. begin
  592. Result := False;
  593. wildcard := False;
  594. cText := LowerCase(cText);
  595. Pattern := LowerCase(Pattern);
  596. match := False;
  597. if (Pattern.Length > cText.Length) or (Pattern = '') then Exit;
  598. if Pattern = '*' then
  599. begin
  600. Result := True;
  601. Exit;
  602. end;
  603. for i := 1 to cText.Length do
  604. begin
  605. CurrentPattern := Pattern[i];
  606. if CurrentPattern = '*' then wildcard := True;
  607. if wildcard then
  608. begin
  609. n := Pos(Copy(Pattern,i+1,Pattern.Length),cText);
  610. if (n > i) or (Pattern.Length = i) then
  611. begin
  612. Result := True;
  613. Exit;
  614. end;
  615. end
  616. else
  617. begin
  618. if (cText[i] = CurrentPattern) or (CurrentPattern = '?') then match := True
  619. else match := False;
  620. end;
  621. end;
  622. Result := match;
  623. end;
  624. function Capitalize(s: string): string;
  625. begin
  626. Result := '';
  627. if s.Length = 0 then Exit;
  628. s := LowerCase(s,loUserLocale);
  629. Result := UpperCase(s[1],loUserLocale) + Trim(Copy(s, 2, s.Length));
  630. end;
  631. function CapitalizeWords(s: string): string;
  632. var
  633. cword : string;
  634. begin
  635. Result := '';
  636. if s.Length = 0 then Exit;
  637. s := LowerCase(s,loUserLocale);
  638. for cword in s.Split([' ']) do
  639. begin
  640. if Result = '' then Result := Capitalize(cword)
  641. else Result := Result + ' ' + Capitalize(cword);
  642. end;
  643. end;
  644. function GetLoggedUserName : string;
  645. {$IFDEF MSWINDOWS}
  646. const
  647. cnMaxUserNameLen = 254;
  648. var
  649. sUserName : string;
  650. dwUserNameLen : DWord;
  651. begin
  652. dwUserNameLen := cnMaxUserNameLen-1;
  653. SetLength( sUserName, cnMaxUserNameLen );
  654. GetUserName(PChar( sUserName ),dwUserNameLen );
  655. SetLength( sUserName, dwUserNameLen );
  656. Result := sUserName;
  657. end;
  658. {$ELSE}
  659. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  660. begin
  661. Result := GetEnvironmentVariable('USERNAME');
  662. end;
  663. {$ELSE}
  664. begin
  665. Result := 'N/A';
  666. //raise ENotImplemented.Create('Not Android GetLoggedUserName implemented!');
  667. end;
  668. {$ENDIF}
  669. {$ENDIF}
  670. {$IFDEF IOS}
  671. function GetDeviceModel : String;
  672. var
  673. size : size_t;
  674. buffer : array of Byte;
  675. begin
  676. sysctlbyname('hw.machine',nil,@size,nil,0);
  677. if size > 0 then
  678. begin
  679. SetLength(buffer, size);
  680. sysctlbyname('hw.machine',@buffer[0],@size,nil,0);
  681. Result := UTF8ToString(MarshaledAString(buffer));
  682. end
  683. else Result := EmptyStr;
  684. end;
  685. {$ENDIF}
  686. function GetComputerName : string;
  687. {$IFDEF MSWINDOWS}
  688. var
  689. dwLength: dword;
  690. begin
  691. dwLength := 253;
  692. SetLength(Result, dwLength+1);
  693. if not Windows.GetComputerName(pchar(result), dwLength) then Result := 'Not detected!';
  694. Result := pchar(result);
  695. end;
  696. {$ELSE}
  697. {$IF DEFINED(FPC) OR DEFINED(LINUX)}
  698. begin
  699. Result := GetEnvironmentVariable('COMPUTERNAME');
  700. end;
  701. {$ELSE} //Android gets model name
  702. begin
  703. {$IFDEF NEXTGEN}
  704. {$IFDEF ANDROID}
  705. Result := JStringToString(TJBuild.JavaClass.MODEL);
  706. {$ELSE} //IOS
  707. Result := GetDeviceModel;
  708. {$ENDIF}
  709. {$ELSE} //OSX
  710. Result := NSStrToStr(TNSHost.Wrap(TNSHost.OCClass.currentHost).localizedName);
  711. {$ENDIF}
  712. end;
  713. {$ENDIF}
  714. {$ENDIF}
  715. function NormalizePathDelim(const cPath : string; const Delim : Char) : string;
  716. begin
  717. if Delim = '\' then Result := StringReplace(cPath,'/',Delim,[rfReplaceAll])
  718. else Result := StringReplace(cPath,'\',Delim,[rfReplaceAll]);
  719. end;
  720. function RemoveLastPathSegment(cDir : string) : string;
  721. var
  722. posi : Integer;
  723. delim : Char;
  724. EndsWithDelim : Boolean;
  725. begin
  726. if cDir.Contains('\') then delim := '\'
  727. else if cDir.Contains('/') then delim := '/'
  728. else
  729. begin
  730. Result := '';
  731. Exit;
  732. end;
  733. NormalizePathDelim(cDir,delim);
  734. if cDir.EndsWith(delim) then
  735. begin
  736. cDir := Copy(cDir,1,cDir.Length-1);
  737. EndsWithDelim := True;
  738. end
  739. else EndsWithDelim := False;
  740. if cDir.CountChar(delim) > 1 then posi := cDir.LastDelimiter(delim)
  741. else posi := Pos(delim,cDir)-1;
  742. if posi = cDir.Length then posi := 0;
  743. Result := Copy(cDir,1,posi);
  744. if (Result <> '') and (EndsWithDelim) then Result := Result + delim;
  745. end;
  746. function ParamFindSwitch(const Switch : string) : Boolean;
  747. begin
  748. Result := FindCmdLineSwitch(Switch,['-', '/'],True);
  749. end;
  750. {$IFDEF FPC}
  751. function FindCmdLineSwitch(const Switch: string; var Value: string; IgnoreCase: Boolean = True;
  752. const SwitchTypes: TCmdLineSwitchTypes = [clstValueNextParam, clstValueAppended]): Boolean; overload;
  753. type
  754. TCompareProc = function(const S1, S2: string): Boolean;
  755. var
  756. Param: string;
  757. I, ValueOfs,
  758. SwitchLen, ParamLen: Integer;
  759. SameSwitch: TCompareProc;
  760. begin
  761. Result := False;
  762. Value := '';
  763. if IgnoreCase then
  764. SameSwitch := SameText else
  765. SameSwitch := SameStr;
  766. SwitchLen := Switch.Length;
  767. for I := 1 to ParamCount do
  768. begin
  769. Param := ParamStr(I);
  770. if CharInSet(Param.Chars[0], SwitchChars) and SameSwitch(Param.SubString(1,SwitchLen), Switch) then
  771. begin
  772. ParamLen := Param.Length;
  773. // Look for an appended value if the param is longer than the switch
  774. if (ParamLen > SwitchLen + 1) then
  775. begin
  776. // If not looking for appended value switches then this is not a matching switch
  777. if not (clstValueAppended in SwitchTypes) then
  778. Continue;
  779. ValueOfs := SwitchLen + 1;
  780. if Param.Chars[ValueOfs] = ':' then
  781. Inc(ValueOfs);
  782. Value := Param.SubString(ValueOfs, MaxInt);
  783. end
  784. // If the next param is not a switch, then treat it as the value
  785. else if (clstValueNextParam in SwitchTypes) and (I < ParamCount) and
  786. not CharInSet(ParamStr(I+1).Chars[0], SwitchChars) then
  787. Value := ParamStr(I+1);
  788. Result := True;
  789. Break;
  790. end;
  791. end;
  792. end;
  793. {$ENDIF}
  794. function ParamGetSwitch(const Switch : string; var cvalue : string) : Boolean;
  795. begin
  796. Result := FindCmdLineSwitch(Switch,cvalue,True,[clstValueAppended]);
  797. end;
  798. function GetAppName : string;
  799. begin
  800. Result := ExtractFilenameWithoutExt(ParamStr(0));
  801. end;
  802. function GetAppVersionStr: string;
  803. {$IFDEF MSWINDOWS}
  804. var
  805. Rec: LongRec;
  806. ver : Cardinal;
  807. begin
  808. ver := GetFileVersion(ParamStr(0));
  809. if ver <> Cardinal(-1) then
  810. begin
  811. Rec := LongRec(ver);
  812. Result := Format('%d.%d', [Rec.Hi, Rec.Lo]);
  813. end
  814. else Result := '';
  815. end;
  816. {$ELSE}
  817. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  818. var
  819. version : TProgramVersion;
  820. begin
  821. if GetProgramVersion(version) then Result := Format('%d.%d', [version.Major, version.Minor])
  822. else Result := '';
  823. end;
  824. {$ELSE}
  825. {$IFDEF NEXTGEN}
  826. {$IFDEF ANDROID}
  827. var
  828. PkgInfo : JPackageInfo;
  829. begin
  830. PkgInfo := SharedActivity.getPackageManager.getPackageInfo(SharedActivity.getPackageName,0);
  831. Result := IntToStr(PkgInfo.VersionCode);
  832. end;
  833. {$ELSE} //IOS
  834. var
  835. AppKey: Pointer;
  836. AppBundle: NSBundle;
  837. BuildStr : NSString;
  838. begin
  839. try
  840. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  841. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  842. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  843. Result := UTF8ToString(BuildStr.UTF8String);
  844. except
  845. Result := 'N/A';
  846. end;
  847. end;
  848. {$ENDIF}
  849. {$ELSE} //OSX
  850. {$IFDEF OSX}
  851. var
  852. AppKey: Pointer;
  853. AppBundle: NSBundle;
  854. BuildStr : NSString;
  855. begin
  856. try
  857. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  858. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  859. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  860. Result := UTF8ToString(BuildStr.UTF8String);
  861. except
  862. Result := 'N/A';
  863. end;
  864. end;
  865. {$ENDIF}
  866. {$ENDIF}
  867. {$ENDIF}
  868. {$ENDIF}
  869. function GetAppVersionFullStr: string;
  870. {$IFDEF MSWINDOWS}
  871. var
  872. Exe: string;
  873. Size, Handle: DWORD;
  874. Buffer: TBytes;
  875. FixedPtr: PVSFixedFileInfo;
  876. begin
  877. Result := '';
  878. Exe := ParamStr(0);
  879. Size := GetFileVersionInfoSize(PChar(Exe), Handle);
  880. if Size = 0 then
  881. begin
  882. //RaiseLastOSError;
  883. //no version info in file
  884. Exit;
  885. end;
  886. SetLength(Buffer, Size);
  887. if not GetFileVersionInfo(PChar(Exe), Handle, Size, Buffer) then
  888. RaiseLastOSError;
  889. if not VerQueryValue(Buffer, '\', Pointer(FixedPtr), Size) then
  890. RaiseLastOSError;
  891. if (LongRec(FixedPtr.dwFileVersionLS).Hi = 0) and (LongRec(FixedPtr.dwFileVersionLS).Lo = 0) then
  892. begin
  893. Result := Format('%d.%d',
  894. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  895. LongRec(FixedPtr.dwFileVersionMS).Lo]); //minor
  896. end
  897. else if (LongRec(FixedPtr.dwFileVersionLS).Lo = 0) then
  898. begin
  899. Result := Format('%d.%d.%d',
  900. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  901. LongRec(FixedPtr.dwFileVersionMS).Lo, //minor
  902. LongRec(FixedPtr.dwFileVersionLS).Hi]); //release
  903. end
  904. else
  905. begin
  906. Result := Format('%d.%d.%d.%d',
  907. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  908. LongRec(FixedPtr.dwFileVersionMS).Lo, //minor
  909. LongRec(FixedPtr.dwFileVersionLS).Hi, //release
  910. LongRec(FixedPtr.dwFileVersionLS).Lo]); //build
  911. end;
  912. end;
  913. {$ELSE}
  914. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  915. var
  916. version : TProgramVersion;
  917. begin
  918. if GetProgramVersion(version) then Result := Format('%d.%d.%d.%d', [version.Major, version.Minor, version.Revision, version.Build])
  919. else Result := '';
  920. end;
  921. {$ELSE}
  922. {$IFDEF NEXTGEN}
  923. {$IFDEF ANDROID}
  924. var
  925. PkgInfo : JPackageInfo;
  926. begin
  927. PkgInfo := SharedActivity.getPackageManager.getPackageInfo(SharedActivity.getPackageName,0);
  928. Result := JStringToString(PkgInfo.versionName);
  929. end;
  930. {$ELSE} //IOS
  931. var
  932. AppKey: Pointer;
  933. AppBundle: NSBundle;
  934. BuildStr : NSString;
  935. begin
  936. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  937. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  938. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  939. Result := UTF8ToString(BuildStr.UTF8String);
  940. end;
  941. {$ENDIF}
  942. {$ELSE} //OSX
  943. var
  944. AppKey: Pointer;
  945. AppBundle: NSBundle;
  946. BuildStr : NSString;
  947. begin
  948. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  949. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  950. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  951. Result := UTF8ToString(BuildStr.UTF8String);
  952. end;
  953. {$ENDIF}
  954. {$ENDIF}
  955. {$ENDIF}
  956. function UTCToLocalTime(GMTTime: TDateTime): TDateTime;
  957. begin
  958. {$IFDEF FPC}
  959. Result := LocalTimeToUniversal(GMTTime);
  960. {$ELSE}
  961. Result := TTimeZone.Local.ToLocalTime(GMTTime);
  962. {$ENDIF}
  963. end;
  964. function LocalTimeToUTC(LocalTime : TDateTime): TDateTime;
  965. begin
  966. {$IFDEF FPC}
  967. Result := UniversalTimeToLocal(Localtime);
  968. {$ELSE}
  969. Result := TTimeZone.Local.ToUniversalTime(LocalTime);
  970. {$ENDIF}
  971. end;
  972. function DateTimeToGMT(aDate : TDateTime) : string;
  973. var
  974. FmtSettings : TFormatSettings;
  975. begin
  976. FmtSettings.DateSeparator := '-';
  977. FmtSettings.TimeSeparator := ':';
  978. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ" GMT"';
  979. Result := DateTimeToStr(aDate,FmtSettings);
  980. end;
  981. function GMTToDateTime(aDate : string) : TDateTime;
  982. var
  983. FmtSettings : TFormatSettings;
  984. begin
  985. FmtSettings.DateSeparator := '-';
  986. FmtSettings.TimeSeparator := ':';
  987. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ" GMT"';
  988. Result := StrToDateTime(aDate,FmtSettings);
  989. end;
  990. function DateTimeToJsonDate(aDateTime : TDateTime) : string;
  991. {$IFNDEF DELPHIXE7_UP}
  992. var
  993. FmtSettings : TFormatSettings;
  994. {$ENDIF}
  995. begin
  996. {$IFDEF DELPHIXE7_UP}
  997. Result := DateToISO8601(aDateTime);
  998. {$ELSE}
  999. FmtSettings.DateSeparator := '-';
  1000. FmtSettings.TimeSeparator := ':';
  1001. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ"Z"';
  1002. Result := DateTimeToStr(aDateTime,FmtSettings);
  1003. {$ENDIF}
  1004. end;
  1005. function JsonDateToDateTime(const aJsonDate : string) : TDateTime;
  1006. {$IFNDEF DELPHIXE7_UP}
  1007. var
  1008. FmtSettings : TFormatSettings;
  1009. {$ENDIF}
  1010. {$IFDEF FPC}
  1011. var
  1012. jdate : string;
  1013. {$ENDIF}
  1014. begin
  1015. {$IFDEF DELPHIXE7_UP}
  1016. Result := ISO8601ToDate(aJsonDate);
  1017. {$ELSE}
  1018. FmtSettings.DateSeparator := '-';
  1019. FmtSettings.TimeSeparator := ':';
  1020. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ"Z"';
  1021. {$IFDEF FPC}
  1022. jdate := StringReplace(aJsondate,'T',' ',[rfIgnoreCase]);
  1023. jdate := Copy(jdate,1,Pos('.',jdate)-1);
  1024. Result := StrToDateTime(jdate,FmtSettings);
  1025. {$ELSE}
  1026. Result := StrToDateTime(aJsonDate,FmtSettings);
  1027. {$ENDIF}
  1028. {$ENDIF}
  1029. end;
  1030. function CountDigits(anInt: Cardinal): Cardinal; inline;
  1031. var
  1032. cmp: Cardinal;
  1033. begin
  1034. cmp := 10;
  1035. Result := 1;
  1036. while (Result < 10) and (cmp <= anInt) do
  1037. begin
  1038. cmp := cmp*10;
  1039. Inc(Result);
  1040. end;
  1041. end;
  1042. procedure SaveStreamToFile(stream : TStream; const filename : string);
  1043. var
  1044. fs : TFileStream;
  1045. begin
  1046. fs := TFileStream.Create(filename,fmCreate);
  1047. try
  1048. stream.Seek(0,soBeginning);
  1049. fs.CopyFrom(stream,stream.Size);
  1050. finally
  1051. fs.Free;
  1052. end;
  1053. end;
  1054. function CommaText(aList : TStringList) : string;
  1055. var
  1056. value : string;
  1057. sb : TStringBuilder;
  1058. begin
  1059. if aList.Text = '' then Exit;
  1060. sb := TStringBuilder.Create;
  1061. try
  1062. for value in aList do
  1063. begin
  1064. sb.Append(value);
  1065. sb.Append(',');
  1066. end;
  1067. if sb.Length > 1 then Result := sb.ToString(0, sb.Length - 1);
  1068. finally
  1069. sb.Free;
  1070. end;
  1071. end;
  1072. { TCounter }
  1073. procedure TCounter.Init(aMaxValue : Integer);
  1074. begin
  1075. fMaxValue := aMaxValue;
  1076. fCurrentValue := 0;
  1077. end;
  1078. function TCounter.Count : Integer;
  1079. begin
  1080. Result := fCurrentValue;
  1081. end;
  1082. function TCounter.CountIs(aValue : Integer) : Boolean;
  1083. begin
  1084. Result := fCurrentValue = aValue;
  1085. end;
  1086. function TCounter.Check : Boolean;
  1087. begin
  1088. if fCurrentValue = fMaxValue then
  1089. begin
  1090. Result := True;
  1091. Reset;
  1092. end
  1093. else
  1094. begin
  1095. Result := False;
  1096. Inc(fCurrentValue);
  1097. end;
  1098. end;
  1099. procedure TCounter.Reset;
  1100. begin
  1101. fCurrentValue := fMaxValue;
  1102. end;
  1103. { TimeCounter }
  1104. procedure TTimeCounter.Init(MillisecondsToReach : Integer);
  1105. begin
  1106. fDoneEvery := MillisecondsToReach;
  1107. end;
  1108. function TTimeCounter.Check : Boolean;
  1109. begin
  1110. if MilliSecondsBetween(fCurrentTime,Now) > fDoneEvery then
  1111. begin
  1112. fCurrentTime := Now();
  1113. Result := True;
  1114. end
  1115. else Result := False;
  1116. end;
  1117. procedure TTimeCounter.Reset;
  1118. begin
  1119. fCurrentTime := Now();
  1120. end;
  1121. {$IFDEF MSWINDOWS}
  1122. procedure ProcessMessages;
  1123. var
  1124. Msg: TMsg;
  1125. begin
  1126. while integer(PeekMessage(Msg, 0, 0, 0, PM_REMOVE)) <> 0 do
  1127. begin
  1128. TranslateMessage(Msg);
  1129. DispatchMessage(Msg);
  1130. end;
  1131. end;
  1132. function GetLastOSError: String;
  1133. begin
  1134. Result := SysErrorMessage(Windows.GetLastError);
  1135. end;
  1136. {$ENDIF}
  1137. function RemoveLastChar(const aText : string) : string;
  1138. begin
  1139. Result := aText.Remove(aText.Length - 1);
  1140. end;
  1141. function DateTimeToSQL(aDateTime : TDateTime) : string;
  1142. begin
  1143. Result := FormatDateTime('YYYYMMDD hh:mm:ss',aDateTime);
  1144. end;
  1145. {$IFDEF MSWINDOWS}
  1146. initialization
  1147. try
  1148. GetEnvironmentPaths;
  1149. except
  1150. on E : Exception do
  1151. begin
  1152. if not IsService then
  1153. begin
  1154. if IsConsole then Writeln(Format('[WARN] GetEnvironmentPaths: %s',[E.Message]))
  1155. else raise EEnvironmentPath.Create(Format('Get environment path error: %s',[E.Message]));
  1156. end;
  1157. end;
  1158. end;
  1159. {$ENDIF}
  1160. end.