kopia lustrzana https://github.com/espressif/esp-idf
Merge branch 'bugfix/win_inst_defender_check' into 'master'
Tools: Windows Installer add pre-installation screen with System checks for Python and Windows Defender Closes IDF-1819 See merge request espressif/esp-idf!11152pull/6365/head
commit
17b9fca02f
|
@ -0,0 +1,40 @@
|
|||
; Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD
|
||||
; SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
[LangOptions]
|
||||
LanguageName=English
|
||||
LanguageID=$0409
|
||||
|
||||
[CustomMessages]
|
||||
PreInstallationCheckTitle=Pre-installation system check
|
||||
PreInstallationCheckSubtitle=Verification of environment
|
||||
SystemCheckStart=Starting system check ...
|
||||
SystemCheckForDefender=Checking Windows Defender
|
||||
SystemCheckHint=Hint
|
||||
SystemCheckResultFound=FOUND
|
||||
SystemCheckResultNotFound=NOT FOUND
|
||||
SystemCheckResultOk=OK
|
||||
SystemCheckResultFail=FAIL
|
||||
SystemCheckResultError=ERR
|
||||
SystemCheckResultWarn=WARN
|
||||
SystemCheckStopped=Check stopped.
|
||||
SystemCheckStopButtonCaption=Stop
|
||||
SystemCheckComplete=Check complete.
|
||||
SystemCheckForComponent=Checking installed
|
||||
SystemCheckUnableToExecute=Unable to execute
|
||||
SystemCheckUnableToFindFile=Unable to find file
|
||||
SystemCheckRemedyMissingPip=Please use a supported version of Python available on the next screen.
|
||||
SystemCheckRemedyMissingVirtualenv=Please install virtualenv and retry the installation. Suggested commands:
|
||||
SystemCheckRemedyCreateVirtualenv=Please use the supported Python version that is available on the next screen.
|
||||
SystemCheckRemedyPythonInVirtualenv=Please use the supported Python version that is available on the next screen.
|
||||
SystemCheckRemedyBinaryPythonWheel=Please use the supported Python version that is available on the next screen.
|
||||
SystemCheckRemedyFailedHttpsDownload=Please use the supported Python version that is available on the next screen.
|
||||
SystemCheckRemedyFailedSubmoduleRun=Python contains a subprocess.run module intended for Python 2. Please uninstall the module. Suggested command:
|
||||
SystemCheckApplyFixesButtonCaption=Apply Fixes
|
||||
SystemCheckFullLogButtonCaption=Full log
|
||||
SystemCheckApplyFixesConsent=Do you want to apply the commands with the suggested fixes to update your Windows environment and start a new System Check?
|
||||
SystemCheckFixesSuccessful=Successful application of Fixes.
|
||||
SystemCheckFixesFailed=Failed application of Fixes. Please refer to the Full log.
|
||||
SystemCheckNotCompleteConsent=System check is not complete. Do you want to proceed by skipping checks?
|
||||
SystemCheckRootCertificates=Checking certificates
|
||||
SystemCheckRootCertificateWarning=Unable to load data from server dl.espressif.com.
|
|
@ -14,6 +14,14 @@ Some functionality of the installer depends on additional programs:
|
|||
|
||||
* [cmdlinerunner](cmdlinerunner/cmdlinerunner.c) — a helper DLL used to run external command line programs from the installer, capture live console output, and get the exit code.
|
||||
|
||||
## Instalation of dependencies via Chocolatey
|
||||
|
||||
Run with Administrator privileges:
|
||||
|
||||
```
|
||||
choco install inno-download-plugin
|
||||
```
|
||||
|
||||
## Building the installer
|
||||
|
||||
### In Docker
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
var
|
||||
ChoicePagePrepare: array of TNotifyEvent;
|
||||
ChoicePageSelectionChange: array of TNotifyEvent;
|
||||
ChoicePageValidate: array of TWizardPageButtonEvent;
|
||||
ChoicePageMaxTag: Integer;
|
||||
ChoicePages: array of TInputOptionWizardPage;
|
||||
ChoicePages: array of TWizardPage;
|
||||
|
||||
procedure ChoicePageOnClickCheck(Sender: TObject);
|
||||
var
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Progress & log page for command line tools ------------------------------ }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Find installed copies of Git ------------------------------ }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Page to select Git ------------------------------ }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Page to select the version of ESP-IDF to download ------------------------------ }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Page to select whether to download ESP-IDF, or use an existing copy ------------------------------ }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Downloading ESP-IDF ------------------------------ }
|
||||
|
@ -90,6 +90,24 @@ begin
|
|||
FindFileRecursive(Path + '\.git', 'alternates', @RemoveAlternatesFile);
|
||||
end;
|
||||
|
||||
{
|
||||
Run git config fileMode is repairing problem when git repo was zipped on Linux and extracted on Windows.
|
||||
The repo and submodules are marked as dirty which confuses users that fresh installation already contains changes.
|
||||
More information: https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-config.html
|
||||
}
|
||||
procedure GitRepoFixFileMode(Path: String);
|
||||
var
|
||||
CmdLine: String;
|
||||
begin
|
||||
CmdLine := GitExecutablePath + ' -C ' + Path + ' config --local core.fileMode false';
|
||||
Log('Setting core.fileMode on repository: ' + CmdLine);
|
||||
DoCmdlineInstall('Finishing ESP-IDF installation', 'Updating fileMode', CmdLine);
|
||||
|
||||
Log('Setting core.fileMode on repository for submodules: ' + CmdLine);
|
||||
CmdLine := GitExecutablePath + ' -C ' + Path + ' submodule foreach --recursive git config --local core.fileMode false';
|
||||
DoCmdlineInstall('Finishing ESP-IDF installation', 'Updating fileMode in submodules', CmdLine);
|
||||
end;
|
||||
|
||||
{ Run git reset --hard in the repo and in the submodules, to fix the newlines. }
|
||||
procedure GitRepoFixNewlines(Path: String);
|
||||
var
|
||||
|
@ -183,6 +201,7 @@ begin
|
|||
}
|
||||
CmdLine := ExpandConstant('cmd.exe /c ""xcopy" /s /e /i /h /q "' + IDFTempPath + '" "' + IDFPath + '""');
|
||||
DoCmdlineInstall('Extracting ESP-IDF', 'Copying ESP-IDF into the destination directory', CmdLine);
|
||||
GitRepoFixFileMode(IDFPath);
|
||||
GitRepoFixNewlines(IDFPath);
|
||||
DelTree(IDFTempPath, True, True, True);
|
||||
end;
|
||||
|
@ -248,20 +267,95 @@ begin
|
|||
DoCmdlineInstall('Installing Python environment', '', CmdLine);
|
||||
end;
|
||||
|
||||
{ Find Major and Minor version in esp_idf_version.h file. }
|
||||
function GetIDFVersionFromHeaderFile():String;
|
||||
var
|
||||
HeaderFileName: String;
|
||||
HeaderLines: TArrayOfString;
|
||||
LineIndex: Integer;
|
||||
LineCount: Longint;
|
||||
Line: String;
|
||||
MajorVersion: String;
|
||||
MinorVersion: String;
|
||||
begin
|
||||
HeaderFileName := GetIDFPath('') + '\components\esp_common\include\esp_idf_version.h';
|
||||
if (not FileExists(HeaderFileName)) then begin
|
||||
Result := '';
|
||||
Exit;
|
||||
end;
|
||||
|
||||
LoadStringsFromFile(HeaderFileName, HeaderLines);
|
||||
LineCount := GetArrayLength(HeaderLines);
|
||||
for LineIndex := 0 to LineCount - 1 do begin
|
||||
Line := HeaderLines[LineIndex];
|
||||
if (pos('define ESP_IDF_VERSION_MAJOR', Line) > 0) then begin
|
||||
Delete(Line, 1, 29);
|
||||
MajorVersion := Trim(Line);
|
||||
end else if (pos('define ESP_IDF_VERSION_MINOR', Line) > 0) then begin
|
||||
Delete(Line, 1, 29);
|
||||
MinorVersion := Trim(Line);
|
||||
Result := MajorVersion + '.' + MinorVersion;
|
||||
Exit;
|
||||
end
|
||||
end;
|
||||
end;
|
||||
|
||||
{ ------------------------------ Start menu shortcut ------------------------------ }
|
||||
|
||||
procedure CreateIDFCommandPromptShortcut(LnkString: String);
|
||||
var
|
||||
Destination: String;
|
||||
Description: String;
|
||||
VersionIndex: Integer;
|
||||
MajorString: String;
|
||||
MinorString: String;
|
||||
DotIndex: Integer;
|
||||
IDFVersionString: String;
|
||||
PythonVirtualEnvPath: String;
|
||||
Command: String;
|
||||
begin
|
||||
ForceDirectories(ExpandConstant(LnkString));
|
||||
Destination := ExpandConstant(LnkString + '\{#IDFCmdExeShortcutFile}');
|
||||
Description := '{#IDFCmdExeShortcutDescription}';
|
||||
|
||||
IDFVersionString := IDFDownloadVersion;
|
||||
{ Transform version vx.y or release/vx.y to x.y }
|
||||
VersionIndex := pos('v', IDFVersionString);
|
||||
if (VersionIndex > 0) then begin
|
||||
Delete(IDFVersionString, 1, VersionIndex);
|
||||
end;
|
||||
|
||||
{ Transform version x.y.z to x.y }
|
||||
DotIndex := pos('.', IDFVersionString);
|
||||
if (DotIndex > 0) then begin
|
||||
MajorString := Copy(IDFVersionString, 1, DotIndex - 1);
|
||||
Delete(IDFVersionString, 1, DotIndex);
|
||||
{ Trim trailing version numbers. }
|
||||
DotIndex := pos('.', IDFVersionString);
|
||||
if (DotIndex > 0) then begin
|
||||
MinorString := Copy(IDFVersionString, 1, DotIndex - 1);
|
||||
IDFVersionString := MajorString + '.' + MinorString;
|
||||
end else begin
|
||||
IDFVersionString := MajorString + '.' + IDFVersionString;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Transform master to x.y }
|
||||
if (IDFVersionString = 'master') then begin
|
||||
IDFVersionString := GetIDFVersionFromHeaderFile();
|
||||
end;
|
||||
|
||||
{ The links should contain reference to Python vitual env }
|
||||
PythonVirtualEnvPath := ExpandConstant('{app}\python_env\idf') + IDFVersionString + '_py' + PythonVersion + '_env\Scripts';
|
||||
|
||||
{ Fallback in case of not existing environment. }
|
||||
if (not FileExists(PythonVirtualEnvPath + '\python.exe')) then begin
|
||||
PythonVirtualEnvPath := PythonPath;
|
||||
end;
|
||||
|
||||
{ If cmd.exe command argument starts with a quote, the first and last quote chars in the command
|
||||
will be removed by cmd.exe; each argument needs to be surrounded by quotes as well. }
|
||||
Command := ExpandConstant('/k ""{app}\idf_cmd_init.bat" "') + PythonPath + '" "' + GitPath + '""';
|
||||
Command := ExpandConstant('/k ""{app}\idf_cmd_init.bat" "') + PythonVirtualEnvPath + '" "' + GitPath + '""';
|
||||
Log('CreateShellLink Destination=' + Destination + ' Description=' + Description + ' Command=' + Command)
|
||||
try
|
||||
CreateShellLink(
|
||||
|
@ -290,47 +384,22 @@ begin
|
|||
end;
|
||||
|
||||
|
||||
|
||||
<event('CurPageChanged')>
|
||||
procedure CheckWinDefenderAvailable(CurPageID: Integer);
|
||||
var
|
||||
bHasWD: Boolean;
|
||||
szHasWD: String;
|
||||
szWDPath: String;
|
||||
listPSModulePath: TStringList;
|
||||
x: Integer;
|
||||
begin
|
||||
if CurPageID = wpSelectTasks then
|
||||
begin
|
||||
listPSModulePath := TStringList.Create;
|
||||
listPSModulePath.Delimiter := ';';
|
||||
listPSModulePath.StrictDelimiter := True;
|
||||
listPSModulePath.DelimitedText := GetEnv('PsModulePath');
|
||||
|
||||
Log('Checking PSMODULEPATH for Windows Defender module...');
|
||||
|
||||
for x:=0 to (listPSModulePath.Count-1) do
|
||||
begin
|
||||
szWDPath := listPSModulePath[x] + '\Defender'
|
||||
bHasWD := DirExists(szWDPath);
|
||||
if bHasWD then
|
||||
begin
|
||||
szHasWD := 'YES (' + szWDPath + ')';
|
||||
Break;
|
||||
end
|
||||
else
|
||||
szHasWD := 'NO';
|
||||
end;
|
||||
|
||||
Log('CheckWinDefenderAvailable: ' + szHasWD);
|
||||
|
||||
{ WD registration checkbox is identified by 'Windows Defender' substring anywhere in its caption.
|
||||
Please, keep this in mind when making changes }
|
||||
for x:=0 to (WizardForm.TasksList.Items.Count-1) do
|
||||
begin
|
||||
if Pos('Windows Defender', WizardForm.TasksList.ItemCaption[x]) > 0 then
|
||||
begin
|
||||
WizardForm.TasksList.ItemEnabled[x] := bHasWD;
|
||||
WizardForm.TasksList.Checked[x] := bHasWD;
|
||||
WizardForm.TasksList.ItemEnabled[x] := isWindowsDefenderEnabled;
|
||||
WizardForm.TasksList.Checked[x] := isWindowsDefenderEnabled;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
; Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD
|
||||
; SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#pragma include __INCLUDE__ + ";" + ReadReg(HKLM, "Software\Mitrich Software\Inno Download Plugin", "InstallDir")
|
||||
|
@ -51,7 +51,7 @@ ChangesEnvironment=yes
|
|||
WizardStyle=modern
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl,Languages/idf_tool_en-US.islu"
|
||||
|
||||
[Dirs]
|
||||
Name: "{app}\dist"
|
||||
|
@ -65,6 +65,11 @@ Source: "..\..\idf_tools.py"; DestDir: "{app}"; DestName: "idf_tools_fallback.py
|
|||
Source: "tools_fallback.json"; DestDir: "{app}"; DestName: "tools_fallback.json"
|
||||
Source: "idf_cmd_init.bat"; DestDir: "{app}"
|
||||
Source: "dist\*"; DestDir: "{app}\dist"
|
||||
; Helper Python files for sanity check of Python environment - used by system_check_page
|
||||
Source: "system_check\system_check_download.py"; Flags: dontcopy
|
||||
Source: "system_check\system_check_subprocess.py"; Flags: dontcopy
|
||||
Source: "system_check\system_check_virtualenv.py"; Flags: dontcopy
|
||||
; Helper PowerShell scripts for managing exceptions in Windows Defender
|
||||
Source: "tools_WD_excl.ps1"; DestDir: "{app}\dist"
|
||||
Source: "tools_WD_clean.ps1"; DestDir: "{app}\dist"
|
||||
|
||||
|
@ -104,6 +109,7 @@ Root: HKCU; Subkey: "Environment"; ValueType: string; ValueName: "IDF_TOOLS_PATH
|
|||
#include "idf_page.iss.inc"
|
||||
#include "git_page.iss.inc"
|
||||
#include "python_page.iss.inc"
|
||||
#include "system_check_page.iss.inc"
|
||||
#include "idf_download_page.iss.inc"
|
||||
#include "idf_setup.iss.inc"
|
||||
#include "summary.iss.inc"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Custom steps before the main installation flow ------------------------------ }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Find installed Python interpreters in Windows Registry (see PEP 514) ------------------------------ }
|
||||
|
@ -19,7 +19,8 @@ end;
|
|||
function GetPythonVersionInfoFromKey(RootKey: Integer; SubKeyName, CompanyName, TagName: String;
|
||||
var Version: String;
|
||||
var DisplayName: String;
|
||||
var ExecutablePath: String): Boolean;
|
||||
var ExecutablePath: String;
|
||||
var BaseDir: String): Boolean;
|
||||
var
|
||||
TagKey, InstallPathKey, DefaultPath: String;
|
||||
begin
|
||||
|
@ -39,6 +40,8 @@ begin
|
|||
ExecutablePath := DefaultPath + '\python.exe';
|
||||
end;
|
||||
|
||||
BaseDir := DefaultPath;
|
||||
|
||||
if not RegQueryStringValue(RootKey, TagKey, 'SysVersion', Version) then
|
||||
begin
|
||||
if CompanyName = 'PythonCore' then
|
||||
|
@ -59,55 +62,3 @@ begin
|
|||
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
procedure FindPythonVersionsFromKey(RootKey: Integer; SubKeyName: String);
|
||||
var
|
||||
CompanyNames: TArrayOfString;
|
||||
CompanyName, CompanySubKey, TagName, TagSubKey: String;
|
||||
ExecutablePath, DisplayName, Version: String;
|
||||
TagNames: TArrayOfString;
|
||||
CompanyId, TagId: Integer;
|
||||
begin
|
||||
if not RegGetSubkeyNames(RootKey, SubKeyName, CompanyNames) then
|
||||
begin
|
||||
Log('Nothing found in ' + IntToStr(RootKey) + '\' + SubKeyName);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
for CompanyId := 0 to GetArrayLength(CompanyNames) - 1 do
|
||||
begin
|
||||
CompanyName := CompanyNames[CompanyId];
|
||||
|
||||
if CompanyName = 'PyLauncher' then
|
||||
continue;
|
||||
|
||||
CompanySubKey := SubKeyName + '\' + CompanyName;
|
||||
Log('In ' + IntToStr(RootKey) + '\' + CompanySubKey);
|
||||
|
||||
if not RegGetSubkeyNames(RootKey, CompanySubKey, TagNames) then
|
||||
continue;
|
||||
|
||||
for TagId := 0 to GetArrayLength(TagNames) - 1 do
|
||||
begin
|
||||
TagName := TagNames[TagId];
|
||||
TagSubKey := CompanySubKey + '\' + TagName;
|
||||
Log('In ' + IntToStr(RootKey) + '\' + TagSubKey);
|
||||
|
||||
if not GetPythonVersionInfoFromKey(RootKey, SubKeyName, CompanyName, TagName, Version, DisplayName, ExecutablePath) then
|
||||
continue;
|
||||
|
||||
PythonVersionAdd(Version, DisplayName, ExecutablePath);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure FindInstalledPythonVersions();
|
||||
begin
|
||||
InstalledPythonVersions := TStringList.Create();
|
||||
InstalledPythonDisplayNames := TStringList.Create();
|
||||
InstalledPythonExecutables := TStringList.Create();
|
||||
|
||||
FindPythonVersionsFromKey(HKEY_CURRENT_USER, 'Software\Python');
|
||||
FindPythonVersionsFromKey(HKEY_LOCAL_MACHINE, 'Software\Python');
|
||||
FindPythonVersionsFromKey(HKEY_LOCAL_MACHINE, 'Software\Wow6432Node\Python');
|
||||
end;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Page to select Python interpreter ------------------------------ }
|
||||
|
@ -50,8 +50,6 @@ begin
|
|||
if Page.CheckListBox.Items.Count > 0 then
|
||||
exit;
|
||||
|
||||
FindInstalledPythonVersions();
|
||||
|
||||
VersionToInstall := '{#PythonVersion}';
|
||||
OfferToInstall := True;
|
||||
FirstEnabledIndex := -1;
|
||||
|
@ -119,11 +117,11 @@ end;
|
|||
|
||||
procedure PythonExecutablePathUpdateAfterInstall();
|
||||
var
|
||||
Version, DisplayName, ExecutablePath: String;
|
||||
Version, DisplayName, ExecutablePath, BaseDir: String;
|
||||
begin
|
||||
if not GetPythonVersionInfoFromKey(
|
||||
HKEY_CURRENT_USER, 'Software\Python', 'PythonCore', '{#PythonVersion}',
|
||||
Version, DisplayName, ExecutablePath) then
|
||||
Version, DisplayName, ExecutablePath, BaseDir) then
|
||||
begin
|
||||
Log('Failed to find ExecutablePath for the installed copy of Python');
|
||||
exit;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Installation summary page ------------------------------ }
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/env python
|
||||
import sys
|
||||
download_url = sys.argv[1]
|
||||
output_filename = sys.argv[2]
|
||||
if (sys.version_info > (3, 0)):
|
||||
import urllib.request
|
||||
urllib.request.urlretrieve(download_url, output_filename)
|
||||
else:
|
||||
import urllib2
|
||||
response = urllib2.urlopen(download_url)
|
||||
with open(output_filename, "w") as output_file:
|
||||
output_file.write(response.read())
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
import sys
|
||||
if (sys.version_info > (3, 0)):
|
||||
import subprocess
|
||||
subprocess.run("cmd /c echo hello")
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
expected_executable = sys.argv[1]
|
||||
active_executable = sys.executable
|
||||
if expected_executable != active_executable:
|
||||
print("Failure. Expected executable does not match current executable.")
|
||||
print("Expected:", expected_executable)
|
||||
print("Active: ", active_executable)
|
||||
sys.exit(1)
|
|
@ -0,0 +1,688 @@
|
|||
{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ SystemCheck states }
|
||||
const
|
||||
SYSTEM_CHECK_STATE_INIT = 0; { No check was executed yet. }
|
||||
SYSTEM_CHECK_STATE_RUNNING = 1; { Check is in progress and can be cancelled. }
|
||||
SYSTEM_CHECK_STATE_COMPLETE = 2; { Check is complete. }
|
||||
SYSTEM_CHECK_STATE_STOPPED = 3; { User stopped the check. }
|
||||
|
||||
var
|
||||
{ RTF View to display content of system check. }
|
||||
SystemCheckViewer: TNewMemo;
|
||||
{ Indicate state of System Check. }
|
||||
SystemCheckState:Integer;
|
||||
{ Text representation of log messages which are then converte to RTF. }
|
||||
SystemLogText: TStringList;
|
||||
{ Message for user which gives a hint how to correct the problem. }
|
||||
SystemCheckHint: String;
|
||||
{ Setup Page which displays progress/result of system check. }
|
||||
SystemCheckPage: TOutputMsgWizardPage;
|
||||
{ TimeCounter for Spinner animation invoked during command execution. }
|
||||
TimeCounter:Integer;
|
||||
{ Spinner is TStringList, because characters like backslash must be escaped and stored on two bytes. }
|
||||
Spinner: TStringList;
|
||||
{ Button to request display of full log of system check/installation. }
|
||||
FullLogButton: TNewButton;
|
||||
{ Button to request application of available fixtures. }
|
||||
ApplyFixesButton: TNewButton;
|
||||
{ Commands which should be executed to fix problems discovered during system check. }
|
||||
Fixes: TStringList;
|
||||
{ Button to request Stop of System Checks manually. }
|
||||
StopSystemCheckButton: TNewButton;
|
||||
{ Count number of createde virtualenv to avoid collision with previous runs. }
|
||||
VirtualEnvCounter: Integer;
|
||||
|
||||
{ Indicates whether system check was able to find running Windows Defender. }
|
||||
var IsWindowsDefenderEnabled: Boolean;
|
||||
|
||||
{ Const values for user32.dll which allows scrolling of the text view. }
|
||||
const
|
||||
WM_VSCROLL = $0115;
|
||||
SB_BOTTOM = 7;
|
||||
|
||||
type
|
||||
TMsg = record
|
||||
hwnd: HWND;
|
||||
message: UINT;
|
||||
wParam: Longint;
|
||||
lParam: Longint;
|
||||
time: DWORD;
|
||||
pt: TPoint;
|
||||
end;
|
||||
|
||||
const
|
||||
PM_REMOVE = 1;
|
||||
|
||||
{ Functions to communicate via Windows API. }
|
||||
function PeekMessage(var lpMsg: TMsg; hWnd: HWND; wMsgFilterMin, wMsgFilterMax, wRemoveMsg: UINT): BOOL; external 'PeekMessageW@user32.dll stdcall';
|
||||
function TranslateMessage(const lpMsg: TMsg): BOOL; external 'TranslateMessage@user32.dll stdcall';
|
||||
function DispatchMessage(const lpMsg: TMsg): Longint; external 'DispatchMessageW@user32.dll stdcall';
|
||||
|
||||
procedure AppProcessMessage;
|
||||
var
|
||||
Msg: TMsg;
|
||||
begin
|
||||
while PeekMessage(Msg, WizardForm.Handle, 0, 0, PM_REMOVE) do begin
|
||||
TranslateMessage(Msg);
|
||||
DispatchMessage(Msg);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Render text message for view, add spinner if necessary and scroll the window. }
|
||||
procedure SystemLogRefresh();
|
||||
begin
|
||||
SystemCheckViewer.Lines := SystemLogText;
|
||||
|
||||
{ Add Spinner to message. }
|
||||
if ((TimeCounter > 0) and (TimeCounter < 6)) then begin
|
||||
SystemCheckViewer.Lines[SystemCheckViewer.Lines.Count - 1] := SystemCheckViewer.Lines[SystemCheckViewer.Lines.Count - 1] + ' [' + Spinner[TimeCounter - 1] + ']';
|
||||
end;
|
||||
|
||||
{ Scroll window to the bottom of the log - https://stackoverflow.com/questions/64587596/is-it-possible-to-display-the-install-actions-in-a-list-in-inno-setup }
|
||||
SendMessage(SystemCheckViewer.Handle, WM_VSCROLL, SB_BOTTOM, 0);
|
||||
end;
|
||||
|
||||
{ Log message to file and display just a '.' to user so that user is not overloaded by details. }
|
||||
procedure SystemLogProgress(message:String);
|
||||
begin
|
||||
Log(message);
|
||||
if (SystemLogText.Count = 0) then begin
|
||||
SystemLogText.Append('');
|
||||
end;
|
||||
|
||||
SystemLogText[SystemLogText.Count - 1] := SystemLogText[SystemLogText.Count - 1] + '.';
|
||||
SystemLogRefresh();
|
||||
end;
|
||||
|
||||
{ Log message to file and display it to user as title message with asterisk prefix. }
|
||||
procedure SystemLogTitle(message:String);
|
||||
begin
|
||||
message := '* ' + message;
|
||||
Log(message);
|
||||
SystemLogText.Append(message);
|
||||
SystemLogRefresh();
|
||||
end;
|
||||
|
||||
{ Log message to file and display it to user. }
|
||||
procedure SystemLog(message:String);
|
||||
begin
|
||||
Log(message);
|
||||
if (SystemLogText.Count = 0) then begin
|
||||
SystemLogText.Append('');
|
||||
end;
|
||||
|
||||
SystemLogText[SystemLogText.Count - 1] := SystemLogText[SystemLogText.Count - 1] + message;
|
||||
SystemLogRefresh();
|
||||
end;
|
||||
|
||||
{ Process timer tick during command execution so that the app keeps communicating with user. }
|
||||
procedure TimerTick();
|
||||
begin
|
||||
{ TimeCounter for animating Spinner. }
|
||||
TimeCounter:=TimeCounter+1;
|
||||
if (TimeCounter = 5) then begin
|
||||
TimeCounter := 1;
|
||||
end;
|
||||
|
||||
{ Redraw Log with Spinner animation. }
|
||||
SystemLogRefresh();
|
||||
|
||||
{ Give control back to UI so that it can be updated. https://gist.github.com/jakoch/33ac13800c17eddb2dd4 }
|
||||
AppProcessMessage;
|
||||
end;
|
||||
|
||||
{ --- Command line nonblocking exec --- }
|
||||
function NonBlockingExec(command, workdir: String): Integer;
|
||||
var
|
||||
Res: Integer;
|
||||
Handle: Longword;
|
||||
ExitCode: Integer;
|
||||
LogTextAnsi: AnsiString;
|
||||
LogText, LeftOver: String;
|
||||
|
||||
begin
|
||||
if (SystemCheckState = SYSTEM_CHECK_STATE_STOPPED) then begin
|
||||
ExitCode := -3;
|
||||
Exit;
|
||||
end;
|
||||
try
|
||||
ExitCode := -1;
|
||||
{ SystemLog('Workdir: ' + workdir); }
|
||||
SystemLogProgress(' $ ' + command);
|
||||
Handle := ProcStart(command, workdir)
|
||||
if Handle = 0 then
|
||||
begin
|
||||
SystemLog('[' + CustomMessage('SystemCheckResultError') + ']');
|
||||
Result := -2;
|
||||
Exit;
|
||||
end;
|
||||
while (ExitCode = -1) and (SystemCheckState <> SYSTEM_CHECK_STATE_STOPPED) do
|
||||
begin
|
||||
ExitCode := ProcGetExitCode(Handle);
|
||||
SetLength(LogTextAnsi, 4096);
|
||||
Res := ProcGetOutput(Handle, LogTextAnsi, 4096)
|
||||
if Res > 0 then
|
||||
begin
|
||||
SetLength(LogTextAnsi, Res);
|
||||
LogText := LeftOver + String(LogTextAnsi);
|
||||
SystemLogProgress(LogText);
|
||||
end;
|
||||
TimerTick();
|
||||
Sleep(200);
|
||||
end;
|
||||
ProcEnd(Handle);
|
||||
finally
|
||||
if (SystemCheckState = SYSTEM_CHECK_STATE_STOPPED) then
|
||||
begin
|
||||
Result := -1;
|
||||
end else begin
|
||||
Result := ExitCode;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Execute command for SystemCheck and reset timer so that Spinner will disappear after end of execution. }
|
||||
function SystemCheckExec(command, workdir: String): Integer;
|
||||
begin
|
||||
TimeCounter := 0;
|
||||
Result := NonBlockingExec(command, workdir);
|
||||
TimeCounter := 0;
|
||||
end;
|
||||
|
||||
{ Get formated line from SystemCheck for user. }
|
||||
function GetSystemCheckHint(Command: String; CustomCheckMessageKey:String):String;
|
||||
begin
|
||||
Result := CustomMessage('SystemCheckUnableToExecute') + ' ' + Command + #13#10 + CustomMessage(CustomCheckMessageKey);
|
||||
end;
|
||||
|
||||
{ Add command to list of fixes which can be executed by installer. }
|
||||
procedure AddFix(Command:String);
|
||||
begin
|
||||
{ Do not add possible fix command when check command was stopped by user. }
|
||||
if (SystemCheckState = SYSTEM_CHECK_STATE_STOPPED) then begin
|
||||
Exit;
|
||||
end;
|
||||
Fixes.Append(Command);
|
||||
end;
|
||||
|
||||
{ Execute checks to determine whether Python installation is valid so thet user can choose it to install IDF. }
|
||||
function IsPythonInstallationValid(displayName: String; pythonPath:String): Boolean;
|
||||
var
|
||||
ResultCode: Integer;
|
||||
ScriptFile: String;
|
||||
TempDownloadFile: String;
|
||||
Command: String;
|
||||
VirtualEvnPath: String;
|
||||
VirtualEnvPython: String;
|
||||
RemedyCommand: String;
|
||||
begin
|
||||
SystemLogTitle(CustomMessage('SystemCheckForComponent') + ' ' + displayName + ' ');
|
||||
SystemCheckHint := '';
|
||||
|
||||
pythonPath := pythonPath + ' ';
|
||||
|
||||
Command := pythonPath + '-m pip --version';
|
||||
ResultCode := SystemCheckExec(Command, ExpandConstant('{tmp}'));
|
||||
if (ResultCode <> 0) then begin
|
||||
SystemCheckHint := GetSystemCheckHint(Command, 'SystemCheckRemedyMissingPip');
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
Command := pythonPath + '-m virtualenv --version';
|
||||
ResultCode := SystemCheckExec(Command, ExpandConstant('{tmp}'));
|
||||
if (ResultCode <> 0) then begin
|
||||
SystemCheckHint := GetSystemCheckHint(Command, 'SystemCheckRemedyMissingVirtualenv') + #13#10 + pythonPath + '-m pip install --upgrade pip' + #13#10 + pythonPath + '-m pip install virtualenv';
|
||||
AddFix(pythonPath + '-m pip install --upgrade pip');
|
||||
AddFix(pythonPath + '-m pip install virtualenv');
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
VirtualEnvCounter := VirtualEnvCounter + 1;
|
||||
VirtualEvnPath := ExpandConstant('{tmp}\') + IntToStr(VirtualEnvCounter) + '-idf-test-venv\';
|
||||
VirtualEnvPython := VirtualEvnPath + 'Scripts\python.exe ';
|
||||
Command := pythonPath + '-m virtualenv ' + VirtualEvnPath;
|
||||
ResultCode := SystemCheckExec(Command, ExpandConstant('{tmp}'));
|
||||
if (ResultCode <> 0) then begin
|
||||
SystemCheckHint := GetSystemCheckHint(Command, 'SystemCheckRemedyCreateVirtualenv');
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
ScriptFile := ExpandConstant('{tmp}\system_check_virtualenv.py')
|
||||
Command := VirtualEnvPython + ScriptFile + ' ' + VirtualEnvPython;
|
||||
ResultCode := SystemCheckExec(Command, ExpandConstant('{tmp}'));
|
||||
if (ResultCode <> 0) then begin
|
||||
SystemCheckHint := GetSystemCheckHint(Command, 'SystemCheckRemedyPythonInVirtualenv');
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
Command := VirtualEnvPython + '-m pip install --only-binary ":all:" "cryptography>=2.1.4" --no-binary future';
|
||||
ResultCode := SystemCheckExec(Command, ExpandConstant('{tmp}'));
|
||||
if (ResultCode <> 0) then begin
|
||||
SystemCheckHint := GetSystemCheckHint(Command, 'SystemCheckRemedyBinaryPythonWheel');
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
TempDownloadFile := IntToStr(VirtualEnvCounter) + '-idf-exe-v1.0.1.zip';
|
||||
ScriptFile := ExpandConstant('{tmp}\system_check_download.py');
|
||||
Command := VirtualEnvPython + ScriptFile + ExpandConstant(' https://dl.espressif.com/dl/idf-exe-v1.0.1.zip ' + TempDownloadFile);
|
||||
ResultCode := SystemCheckExec(Command , ExpandConstant('{tmp}'));
|
||||
if (ResultCode <> 0) then begin
|
||||
SystemCheckHint := GetSystemCheckHint(Command, 'SystemCheckRemedyFailedHttpsDownload');
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if (not FileExists(ExpandConstant('{tmp}\') + TempDownloadFile)) then begin
|
||||
SystemLog(' [' + CustomMessage('SystemCheckResultFail') + '] - ' + CustomMessage('SystemCheckUnableToFindFile') + ' ' + ExpandConstant('{tmp}\') + TempDownloadFile);
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
ScriptFile := ExpandConstant('{tmp}\system_check_subprocess.py');
|
||||
Command := pythonPath + ScriptFile;
|
||||
ResultCode := SystemCheckExec(Command, ExpandConstant('{tmp}'));
|
||||
if (ResultCode <> 0) then begin
|
||||
RemedyCommand := pythonPath + '-m pip uninstall subprocess.run';
|
||||
SystemCheckHint := GetSystemCheckHint(Command, 'SystemCheckRemedyFailedSubmoduleRun') + #13#10 + RemedyCommand;
|
||||
AddFix(RemedyCommand);
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
SystemLog(' [' + CustomMessage('SystemCheckResultOk') + ']');
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
procedure FindPythonVersionsFromKey(RootKey: Integer; SubKeyName: String);
|
||||
var
|
||||
CompanyNames: TArrayOfString;
|
||||
CompanyName, CompanySubKey, TagName, TagSubKey: String;
|
||||
ExecutablePath, DisplayName, Version: String;
|
||||
TagNames: TArrayOfString;
|
||||
CompanyId, TagId: Integer;
|
||||
BaseDir: String;
|
||||
begin
|
||||
if not RegGetSubkeyNames(RootKey, SubKeyName, CompanyNames) then
|
||||
begin
|
||||
Log('Nothing found in ' + IntToStr(RootKey) + '\' + SubKeyName);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
for CompanyId := 0 to GetArrayLength(CompanyNames) - 1 do
|
||||
begin
|
||||
CompanyName := CompanyNames[CompanyId];
|
||||
|
||||
if CompanyName = 'PyLauncher' then
|
||||
continue;
|
||||
|
||||
CompanySubKey := SubKeyName + '\' + CompanyName;
|
||||
Log('In ' + IntToStr(RootKey) + '\' + CompanySubKey);
|
||||
|
||||
if not RegGetSubkeyNames(RootKey, CompanySubKey, TagNames) then
|
||||
continue;
|
||||
|
||||
for TagId := 0 to GetArrayLength(TagNames) - 1 do
|
||||
begin
|
||||
TagName := TagNames[TagId];
|
||||
TagSubKey := CompanySubKey + '\' + TagName;
|
||||
Log('In ' + IntToStr(RootKey) + '\' + TagSubKey);
|
||||
|
||||
if not GetPythonVersionInfoFromKey(RootKey, SubKeyName, CompanyName, TagName, Version, DisplayName, ExecutablePath, BaseDir) then
|
||||
continue;
|
||||
|
||||
if (SystemCheckState = SYSTEM_CHECK_STATE_STOPPED) then begin
|
||||
Exit;
|
||||
end;
|
||||
|
||||
{ Verify Python installation and display hint in case of invalid version or env. }
|
||||
if not IsPythonInstallationValid(DisplayName, ExecutablePath) then begin
|
||||
if ((Length(SystemCheckHint) > 0) and (SystemCheckState <> SYSTEM_CHECK_STATE_STOPPED)) then begin
|
||||
SystemLogTitle(CustomMessage('SystemCheckHint') + ': ' + SystemCheckHint);
|
||||
end;
|
||||
continue;
|
||||
end;
|
||||
|
||||
PythonVersionAdd(Version, DisplayName, ExecutablePath);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure FindInstalledPythonVersions();
|
||||
begin
|
||||
FindPythonVersionsFromKey(HKEY_CURRENT_USER, 'Software\Python');
|
||||
FindPythonVersionsFromKey(HKEY_LOCAL_MACHINE, 'Software\Python');
|
||||
FindPythonVersionsFromKey(HKEY_LOCAL_MACHINE, 'Software\Wow6432Node\Python');
|
||||
end;
|
||||
|
||||
|
||||
{ Get Boolean for UI to determine whether it make sense to register exceptions to Defender. }
|
||||
function GetWindowsDefenderStatus(): Boolean;
|
||||
var
|
||||
bHasWD: Boolean;
|
||||
szWDPath: String;
|
||||
listPSModulePath: TStringList;
|
||||
ResultCode: Integer;
|
||||
x: Integer;
|
||||
begin
|
||||
Log('Checking PSMODULEPATH for Windows Defender module');
|
||||
|
||||
listPSModulePath := TStringList.Create;
|
||||
listPSModulePath.Delimiter := ';';
|
||||
listPSModulePath.StrictDelimiter := True;
|
||||
listPSModulePath.DelimitedText := GetEnv('PsModulePath');
|
||||
|
||||
for x:=0 to (listPSModulePath.Count-1) do
|
||||
begin
|
||||
szWDPath := listPSModulePath[x] + '\Defender'
|
||||
bHasWD := DirExists(szWDPath);
|
||||
if bHasWD then
|
||||
begin
|
||||
break;
|
||||
end
|
||||
end;
|
||||
|
||||
if not bHasWD then begin
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
Log('Checking Windows Services Defender is enabled: (Get-MpComputerStatus).AntivirusEnabled');
|
||||
ResultCode := SystemCheckExec('powershell -ExecutionPolicy Bypass "if((Get-MpComputerStatus).AntivirusEnabled) { Exit 0 } else { Exit 1 }"', ExpandConstant('{tmp}'));
|
||||
if (ResultCode <> 0) then begin
|
||||
Log('Result code: ' + IntToStr(ResultCode));
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
{ Process user request to stop system checks. }
|
||||
function SystemCheckStopRequest():Boolean;
|
||||
begin
|
||||
{ In case of stopped check by user, procees to next/previous step. }
|
||||
if (SystemCheckState = SYSTEM_CHECK_STATE_STOPPED) then begin
|
||||
Result := True;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if (SystemCheckState = SYSTEM_CHECK_STATE_RUNNING) then begin
|
||||
if (MsgBox(CustomMessage('SystemCheckNotCompleteConsent'), mbConfirmation, MB_YESNO) = IDYES) then begin
|
||||
SystemCheckState := SYSTEM_CHECK_STATE_STOPPED;
|
||||
Result := True;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
if (SystemCheckState = SYSTEM_CHECK_STATE_COMPLETE) then begin
|
||||
Result := True;
|
||||
end else begin
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Process request to proceed to next page. If the scan is running ask user for confirmation. }
|
||||
function OnSystemCheckValidate(Sender: TWizardPage): Boolean;
|
||||
begin
|
||||
Result := SystemCheckStopRequest();
|
||||
end;
|
||||
|
||||
{ Process request to go to previous screen (license). Prompt user for confirmation when system check is running. }
|
||||
function OnSystemCheckBackButton(Sender: TWizardPage): Boolean;
|
||||
begin
|
||||
Result := SystemCheckStopRequest();
|
||||
end;
|
||||
|
||||
{ Process request to stop System Check directly on the screen with System Check by Stop button. }
|
||||
procedure StopSystemCheckButtonClick(Sender: TObject);
|
||||
begin
|
||||
SystemCheckStopRequest();
|
||||
end;
|
||||
|
||||
{ Check whether site is reachable and that system trust the certificate. }
|
||||
procedure VerifyRootCertificates();
|
||||
var
|
||||
ResultCode: Integer;
|
||||
Command: String;
|
||||
OutFile: String;
|
||||
begin
|
||||
SystemLogTitle(CustomMessage('SystemCheckRootCertificates') + ' ');
|
||||
|
||||
{ It's necessary to invoke PowerShell *BEFORE* Python. Invoke-Request will retrieve and add Root Certificate if necessary. }
|
||||
{ Without the certificate Python is failing to connect to https. }
|
||||
{ Windows command to list current certificates: certlm.msc }
|
||||
OutFile := ExpandConstant('{tmp}\check');
|
||||
Command := 'powershell -ExecutionPolicy Bypass ';
|
||||
Command := Command + 'Invoke-WebRequest -Uri "https://dl.espressif.com/dl/?system_check=win' + GetWindowsVersionString + '" -OutFile "' + OutFile + '-1.txt";';
|
||||
Command := Command + 'Invoke-WebRequest -Uri "https://github.com/espressif" -OutFile "' + OutFile + '-2.txt";';
|
||||
{Command := Command + 'Invoke-WebRequest -Uri "https://www.s3.amazonaws.com/" -OutFile "' + OutFile + '-3.txt";';}
|
||||
ResultCode := SystemCheckExec(Command, ExpandConstant('{tmp}'));
|
||||
if (ResultCode <> 0) then begin
|
||||
SystemLog(' [' + CustomMessage('SystemCheckResultWarn') + ']');
|
||||
SystemLog(CustomMessage('SystemCheckRootCertificateWarning'));
|
||||
end else begin
|
||||
SystemLog(' [' + CustomMessage('SystemCheckResultOk') + ']');
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Execute system check }
|
||||
procedure ExecuteSystemCheck();
|
||||
begin
|
||||
{ Execute system check only once. Avoid execution in case of back button. }
|
||||
if (SystemCheckState <> SYSTEM_CHECK_STATE_INIT) then begin
|
||||
Exit;
|
||||
end;
|
||||
|
||||
SystemCheckState := SYSTEM_CHECK_STATE_RUNNING;
|
||||
SystemLogTitle(CustomMessage('SystemCheckStart'));
|
||||
StopSystemCheckButton.Enabled := True;
|
||||
|
||||
VerifyRootCertificates();
|
||||
|
||||
FindInstalledPythonVersions();
|
||||
|
||||
if (SystemCheckState <> SYSTEM_CHECK_STATE_STOPPED) then begin
|
||||
SystemLogTitle(CustomMessage('SystemCheckForDefender') + ' ');
|
||||
IsWindowsDefenderEnabled := GetWindowsDefenderStatus();
|
||||
if (IsWindowsDefenderEnabled) then begin
|
||||
SystemLog(' [' + CustomMessage('SystemCheckResultFound') + ']');
|
||||
end else begin
|
||||
SystemLog(' [' + CustomMessage('SystemCheckResultNotFound') + ']');
|
||||
end;
|
||||
end else begin
|
||||
{ User cancelled the check, let's enable Defender script so that use can decide to disable it. }
|
||||
IsWindowsDefenderEnabled := True;
|
||||
end;
|
||||
|
||||
if (SystemCheckState = SYSTEM_CHECK_STATE_STOPPED) then begin
|
||||
SystemLog('');
|
||||
SystemLogTitle(CustomMessage('SystemCheckStopped'));
|
||||
end else begin
|
||||
SystemLogTitle(CustomMessage('SystemCheckComplete'));
|
||||
SystemCheckState := SYSTEM_CHECK_STATE_COMPLETE;
|
||||
end;
|
||||
|
||||
{ Enable Apply Script button if some fixes are available. }
|
||||
if (Fixes.Count > 0) then begin
|
||||
ApplyFixesButton.Enabled := True;
|
||||
end;
|
||||
|
||||
StopSystemCheckButton.Enabled := False;
|
||||
end;
|
||||
|
||||
{ Invoke scan of system environment. }
|
||||
procedure OnSystemCheckActivate(Sender: TWizardPage);
|
||||
begin
|
||||
{ Display special controls. For some reason the first call of the page does not invoke SystemCheckOnCurPageChanged. }
|
||||
FullLogButton.Visible := True;
|
||||
ApplyFixesButton.Visible := True;
|
||||
StopSystemCheckButton.Visible := True;
|
||||
SystemCheckViewer.Visible := True;
|
||||
|
||||
ExecuteSystemCheck();
|
||||
end;
|
||||
|
||||
{ Handle request to display full log from the installation. Open the log in notepad. }
|
||||
procedure FullLogButtonClick(Sender: TObject);
|
||||
var
|
||||
ResultCode: Integer;
|
||||
begin
|
||||
Exec(ExpandConstant('{win}\notepad.exe'), ExpandConstant('{log}'), '', SW_SHOW, ewNoWait, ResultCode);
|
||||
end;
|
||||
|
||||
{ Handle request to apply available fixes. }
|
||||
procedure ApplyFixesButtonClick(Sender: TObject);
|
||||
var
|
||||
ResultCode: Integer;
|
||||
FixIndex: Integer;
|
||||
AreFixesApplied: Boolean;
|
||||
begin
|
||||
if (MsgBox(CustomMessage('SystemCheckApplyFixesConsent'), mbConfirmation, MB_YESNO) = IDNO) then begin
|
||||
Exit;
|
||||
end;
|
||||
|
||||
ApplyFixesButton.Enabled := false;
|
||||
SystemCheckState := SYSTEM_CHECK_STATE_INIT;
|
||||
SystemLog('');
|
||||
SystemLogTitle('Starting application of fixes');
|
||||
|
||||
AreFixesApplied := True;
|
||||
for FixIndex := 0 to Fixes.Count - 1 do
|
||||
begin
|
||||
ResultCode := SystemCheckExec(Fixes[FixIndex], ExpandConstant('{tmp}'));
|
||||
if (ResultCode <> 0) then begin
|
||||
AreFixesApplied := False;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
|
||||
SystemLog('');
|
||||
if (AreFixesApplied) then begin
|
||||
SystemLogTitle(CustomMessage('SystemCheckFixesSuccessful'));
|
||||
end else begin
|
||||
SystemLogTitle(CustomMessage('SystemCheckFixesFailed'));
|
||||
end;
|
||||
|
||||
SystemLog('');
|
||||
Fixes.Clear();
|
||||
|
||||
{ Restart system check. }
|
||||
ExecuteSystemCheck();
|
||||
end;
|
||||
|
||||
{ Add Page for System Check so that user is informed about readiness of the system. }
|
||||
<event('InitializeWizard')>
|
||||
procedure CreateSystemCheckPage();
|
||||
begin
|
||||
{ Initialize data structure for Python }
|
||||
InstalledPythonVersions := TStringList.Create();
|
||||
InstalledPythonDisplayNames := TStringList.Create();
|
||||
InstalledPythonExecutables := TStringList.Create();
|
||||
|
||||
{ Create Spinner animation. }
|
||||
Spinner := TStringList.Create();
|
||||
Spinner.Append('-');
|
||||
Spinner.Append('\');
|
||||
Spinner.Append('|');
|
||||
Spinner.Append('/');
|
||||
|
||||
VirtualEnvCounter := 0;
|
||||
Fixes := TStringList.Create();
|
||||
SystemCheckState := SYSTEM_CHECK_STATE_INIT;
|
||||
SystemCheckPage := CreateOutputMsgPage(wpLicense, CustomMessage('PreInstallationCheckTitle'), CustomMessage('PreInstallationCheckSubtitle'), '');
|
||||
|
||||
with SystemCheckPage do
|
||||
begin
|
||||
OnActivate := @OnSystemCheckActivate;
|
||||
OnBackButtonClick := @OnSystemCheckBackButton;
|
||||
OnNextButtonClick := @OnSystemCheckValidate;
|
||||
end;
|
||||
|
||||
SystemCheckViewer := TNewMemo.Create(WizardForm);
|
||||
with SystemCheckViewer do
|
||||
begin
|
||||
Parent := WizardForm;
|
||||
Left := ScaleX(10);
|
||||
Top := ScaleY(60);
|
||||
ReadOnly := True;
|
||||
Font.Name := 'Courier New';
|
||||
Height := WizardForm.CancelButton.Top - ScaleY(40);
|
||||
Width := WizardForm.ClientWidth + ScaleX(80);
|
||||
WordWrap := True;
|
||||
Visible := False;
|
||||
end;
|
||||
|
||||
SystemLogText := TStringList.Create;
|
||||
|
||||
FullLogButton := TNewButton.Create(WizardForm);
|
||||
with FullLogButton do
|
||||
begin
|
||||
Parent := WizardForm;
|
||||
Left := WizardForm.ClientWidth;
|
||||
Top := SystemCheckViewer.Top + SystemCheckViewer.Height + ScaleY(5);
|
||||
Width := WizardForm.CancelButton.Width;
|
||||
Height := WizardForm.CancelButton.Height;
|
||||
Caption := CustomMessage('SystemCheckFullLogButtonCaption');
|
||||
OnClick := @FullLogButtonClick;
|
||||
Visible := False;
|
||||
end;
|
||||
|
||||
ApplyFixesButton := TNewButton.Create(WizardForm);
|
||||
with ApplyFixesButton do
|
||||
begin
|
||||
Parent := WizardForm;
|
||||
Left := WizardForm.ClientWidth - FullLogButton.Width;
|
||||
Top := FullLogButton.Top;
|
||||
Width := WizardForm.CancelButton.Width;
|
||||
Height := WizardForm.CancelButton.Height;
|
||||
Caption := CustomMessage('SystemCheckApplyFixesButtonCaption');
|
||||
OnClick := @ApplyFixesButtonClick;
|
||||
Visible := False;
|
||||
Enabled := False;
|
||||
end;
|
||||
|
||||
StopSystemCheckButton := TNewButton.Create(WizardForm);
|
||||
with StopSystemCheckButton do
|
||||
begin
|
||||
Parent := WizardForm;
|
||||
Left := ApplyFixesButton.Left - ApplyFixesButton.Width;
|
||||
Top := FullLogButton.Top;
|
||||
Width := WizardForm.CancelButton.Width;
|
||||
Height := WizardForm.CancelButton.Height;
|
||||
Caption := CustomMessage('SystemCheckStopButtonCaption');
|
||||
OnClick := @StopSystemCheckButtonClick;
|
||||
Visible := False;
|
||||
Enabled := False;
|
||||
end;
|
||||
|
||||
{ Extract helper files for sanity check of Python environment. }
|
||||
ExtractTemporaryFile('system_check_download.py')
|
||||
ExtractTemporaryFile('system_check_subprocess.py')
|
||||
ExtractTemporaryFile('system_check_virtualenv.py')
|
||||
end;
|
||||
|
||||
{ Process Cancel Button Click event. Prompt user to confirm Cancellation of System check. }
|
||||
{ Then continue with normal cancel window. }
|
||||
procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
|
||||
begin
|
||||
if ((CurPageId = SystemCheckPage.ID) and (SystemCheckState = SYSTEM_CHECK_STATE_RUNNING)) then begin
|
||||
SystemCheckStopRequest();
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Display control specific for System Check page. }
|
||||
<event('CurPageChanged')>
|
||||
procedure SystemCheckOnCurPageChanged(CurPageID: Integer);
|
||||
begin
|
||||
FullLogButton.Visible := CurPageID = SystemCheckPage.ID;
|
||||
ApplyFixesButton.Visible := CurPageID = SystemCheckPage.ID;
|
||||
StopSystemCheckButton.Visible := CurPageID = SystemCheckPage.ID;
|
||||
SystemCheckViewer.Visible := CurPageID = SystemCheckPage.ID;
|
||||
end;
|
|
@ -1,4 +1,4 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Helper functions from libcmdlinerunner.dll ------------------------------ }
|
||||
|
|
Ładowanie…
Reference in New Issue