The two things that jumped out at me are the wall of calls to Write-Host that can be cleaned up using Here-Strings, and how you are implementing the -Help switch.
Here-Strings in PowerShell are just multi-line string literals. The begin with @" and end with "@. The opening block of text when running the script is a prime candidate for this:
Write-Host = @"
###########################################
# #
# Automatic Python Installation #
# #
###########################################
# #
# 1. Downloading and Installing Python #
# 2. Creating a Virtual Environment #
# 3. Installing Necessary Libraries #
# #
###########################################
@" -ForegroundColor Yellow
Write-Host "Several gigabytes of free space may be required to continue the installation." -ForegroundColor Red
Write-Host @"
Current script run parameters:
---------------------------------
Scan System: $ScanSystem
Scan Drives: $ScanDrives
Allow Cancel: $AllowCancel
Install Python: $InstallPython
Setup Environment: $SetupEnvironment
Install Dependencies: $InstallDependencies
Python Version: $PythonVersion
Update Pip: $UpdatePip
Required Space: $RequiredSpaceInGB GB
Recreate Environment: $RecreateEnvironment
Remove Environment: $RemoveEnvironment
---------------------------------
@" -ForegroundColor Yellow
The -Help parameter is an interesting problem in PowerShell. The get-help commandlet is the idiomatic way to implement help text, in conjunction with writing comment-based help topics. From experience, I've found that nobody (except me) remembers this command exists, or they habitually pass -Help to the script, because every other command line utility supports some variation of this. You can still implement your own -Help param while also utilizing the get-help commandlet:
if ($Help)
{
get-help $PSCommandPath -Full
exit
}
The remainder of the script looks as straight forward as any other installation wrapper script. The only improvement I would suggest is to define local functions in lieu of a myriad Write-Host "..." -ForgroundColor XXXX calls, but this would only serve to clean things up.
function WriteError([string] $message)
{
Write-Host $message -ForegroundColor Red
}
function WriteWarning([string] $message)
{
Write-Host $message -ForegroundColor Yellow
}
function WriteSuccess([string] $message)
{
Write-Host $message -ForegroundColor Green
}
This simplifies things like
Write-Host "Not enough disk space to continue the installation. At least $RequiredSpaceInGB GB is required." -ForegroundColor Red
to:
WriteError "Not enough disk space to continue the installation. At least $RequiredSpaceInGB GB is required."
Not a dramatic difference, but at least you can tell at the beginning of the line of code that you are writing an error, as opposed to reading to the end to see -ForegroundColo Red.
I suppose you could put the forground color first, but then you need to pass the message with a parameter name:
Write-Host -ForegroundColor Red -Object "Not enough disk space..."
Defining local functions allows you to give them meaningful names, which also makes the code easier to understand.