@@ -58,13 +58,16 @@ TPythonVersion = record
58
58
59
59
60
60
{ $IFDEF MSWINDOWS}
61
+ (* Checks whether a DLL was compiled for X64 *)
62
+ function Isx64 (const FileName: string): Boolean;
61
63
(* Checks whether a Python version is registered and returns the related info *)
62
64
function GetRegisteredPythonVersion (SysVersion: string;
63
65
out PythonVersion: TPythonVersion): Boolean;
64
66
(* Returns all registered Python versions *)
65
67
function GetRegisteredPythonVersions : TPythonVersions;
66
68
(* Returns the highest numbered registered Python version *)
67
69
function GetLatestRegisteredPythonVersion (out PythonVersion: TPythonVersion): Boolean;
70
+ function PythonVersionFromPath (const Path: string; out PythonVersion: TPythonVersion): Boolean;
68
71
{ $ENDIF}
69
72
70
73
implementation
@@ -217,6 +220,27 @@ function CompareVersions(A, B : String) : Integer;
217
220
end ;
218
221
219
222
{ $IFDEF MSWINDOWS}
223
+ function Isx64 (const FileName: string): Boolean;
224
+ var
225
+ Strm : TFileStream;
226
+ Header: TImageDosHeader;
227
+ ImageNtHeaders: TImageNtHeaders;
228
+ begin
229
+ Strm := TFileStream.Create(FileName, fmOpenRead);
230
+ try
231
+ Strm.ReadBuffer(Header, SizeOf(Header));
232
+ if (Header.e_magic <> IMAGE_DOS_SIGNATURE) or (Header._lfanew = 0 ) then
233
+ Exit(False);
234
+ Strm.Position := Header._lfanew;
235
+ Strm.ReadBuffer(ImageNtHeaders, SizeOf(ImageNtHeaders));
236
+ if ImageNtHeaders.Signature <> IMAGE_NT_SIGNATURE then
237
+ Exit(False);
238
+ Result := ImageNtHeaders.FileHeader.Machine <> IMAGE_FILE_MACHINE_I386;
239
+ finally
240
+ Strm.Free;
241
+ end ;
242
+ end ;
243
+
220
244
function GetRegisteredPythonVersion (SysVersion: string;
221
245
out PythonVersion: TPythonVersion): Boolean;
222
246
// Python provides for All user and Current user installations
@@ -275,6 +299,7 @@ function GetRegisteredPythonVersion(SysVersion: string;
275
299
var
276
300
key: string;
277
301
VersionSuffix: string;
302
+ APythonVersion: TPythonVersion;
278
303
begin
279
304
// Initialize PythohVersion
280
305
Finalize(PythonVersion);
@@ -303,6 +328,13 @@ function GetRegisteredPythonVersion(SysVersion: string;
303
328
PythonVersion.fSysArchitecture := PythonVersion.ExpectedArchitecture;
304
329
end ;
305
330
331
+ if Result and (PythonVersion.fSysArchitecture = ' ' ) then begin
332
+ // We need to check it is the proper platform
333
+ Result := PythonVersionFromPath(PythonVersion.InstallPath, APythonVersion);
334
+ if Result then
335
+ PythonVersion.fSysArchitecture := PythonVersion.ExpectedArchitecture;
336
+ end ;
337
+
306
338
PythonVersion.IsRegistered := Result;
307
339
end ;
308
340
@@ -334,7 +366,67 @@ function GetLatestRegisteredPythonVersion(out PythonVersion: TPythonVersion): Bo
334
366
end ;
335
367
end ;
336
368
337
- { $ENDIF}
369
+ function PythonVersionFromPath (const Path: string; out PythonVersion: TPythonVersion): Boolean;
370
+ function FindPythonDLL (APath : string): string;
371
+ Var
372
+ FindFileData: TWIN32FindData;
373
+ Handle : THandle;
374
+ DLLFileName: string;
375
+ begin
376
+ Result := ' ' ;
377
+ Handle := FindFirstFile(PWideChar(Path+' \python??.dll' ), FindFileData);
378
+ if Handle = INVALID_HANDLE_VALUE then Exit; // not python dll
379
+ DLLFileName:= FindFileData.cFileName;
380
+ // skip if python3.dll was found
381
+ if Length(DLLFileName) <> 12 then FindNextFile(Handle, FindFileData);
382
+ if Handle = INVALID_HANDLE_VALUE then Exit;
383
+ Windows.FindClose(Handle);
384
+ DLLFileName:= FindFileData.cFileName;
385
+ if Length(DLLFileName) = 12 then
386
+ Result := DLLFileName;
387
+ end ;
388
+
389
+ Var
390
+ DLLFileName: string;
391
+ DLLPath: string;
392
+ SysVersion: string;
393
+ I: integer;
394
+ begin
395
+ Result := False;
396
+ Finalize(PythonVersion);
397
+ FillChar(PythonVersion, SizeOf(TPythonVersion), 0 );
398
+ DLLPath := ExcludeTrailingPathDelimiter(Path);
399
+
400
+ PythonVersion.InstallPath := DLLPath;
401
+
402
+ DLLFileName := FindPythonDLL(DLLPath);
403
+ if DLLFileName = ' ' then begin
404
+ DLLPath := DLLPath + ' \Scripts' ;
405
+ DLLFileName := FindPythonDLL(DLLPath);
406
+ end ;
407
+ if DLLFileName = ' ' then Exit;
408
+
409
+ // check if same platform
410
+ try
411
+ if { $IFDEF CPUX64} not { $ENDIF} Isx64(DLLPath+' \' +DLLFileName) then Exit;
412
+ except
413
+ Exit;
414
+ end ;
415
+ PythonVersion.DLLPath := DLLPath;
338
416
417
+ SysVersion := Copy(DLLFileName, 7 , 2 );
418
+ Insert(' .' , SysVersion, 2 );
419
+
420
+ PythonVersion.SysVersion := SysVersion;
421
+ PythonVersion.fSysArchitecture := PythonVersion.ExpectedArchitecture;
422
+
423
+ for I := High(PYTHON_KNOWN_VERSIONS) downto COMPILED_FOR_PYTHON_VERSION_INDEX do
424
+ if PYTHON_KNOWN_VERSIONS[I].RegVersion = SysVersion then begin
425
+ Result := True;
426
+ break;
427
+ end ;
428
+ end ;
429
+
430
+ { $ENDIF}
339
431
340
432
end .
0 commit comments