我正在尝试使用PowerShell将Python 3安装程序从Python网站下载到特定目录中,然后在同一目录中静默运行/安装.exe,然后将相应的目录添加到系统的PATH变量中。
到目前为止,我已提出:
start cmd /k powershell -Command "(New-Object Net.WebClient).DownloadFile('https://www.python.org/ftp/python/3.6.2/python-3.6.2.exe', 'C:/Tools/python-3.6.2.exe')" &&
c:\Tools\python-3.6.2.exe /quiet InstallAllUsers=1 PrependPath=1 Include_test=0 TargetDir=c:\Tools\Python362 &&
setx path "%PATH%;C:\Tools\Python362\" /M
不幸的是,这不起作用。命令窗口将打开,然后立即退出。我已经分别运行了这些命令,当我这样做时它们工作,但是当我尝试在同一个文件中按顺序运行它们时它不起作用。任何帮助都会非常感激。
注意:
我认为问题源于使用&&
,因为如果我使用&
,CMD提示将会持续存在并执行。但是,这对我没有帮助,因为我需要在第一个命令完成后执行第二个命令,否则第二个命令没有.exe运行。我希望这只是一个语法错误,因为我是创建批处理文件和使用Windows命令行的新手。
答案 0 :(得分:2)
我个人在Powershell中做到这一切。
我很想把它放在一个脚本中,就像这样:
[CmdletBinding()] Param(
$pythonVersion = "3.6.2"
$pythonUrl = "https://www.python.org/ftp/python/$pythonVersion/python-$pythonVersion.exe"
$pythonDownloadPath = 'C:\Tools\python-$pythonVersion.exe'
$pythonInstallDir = "C:\Tools\Python$pythonVersion"
)
(New-Object Net.WebClient).DownloadFile($pythonUrl, $pythonDownloadPath)
& $pythonDownloadPath /quiet InstallAllUsers=1 PrependPath=1 Include_test=0 TargetDir=$pythonInstallDir
if ($LASTEXITCODE -ne 0) {
throw "The python installer at '$pythonDownloadPath' exited with error code '$LASTEXITCODE'"
}
# Set the PATH environment variable for the entire machine (that is, for all users) to include the Python install dir
[Environment]::SetEnvironmentVariable("PATH", "${env:path};${pythonInstallDir}", "Machine")
然后你可以像这样从cmd.exe调用脚本:
Powershell.exe -File X:\Path\to\Install-Python.ps1
Param()
块定义了Python版本的默认值,从中下载的URL,保存它的位置以及安装它的位置,但是如果它变得有用,则允许您覆盖这些选项。您可以传递这样的参数:
Powershell.exe -File X:\Path\to\Install-Python.ps1 -version 3.4.0 -pythonInstallDir X:\Somewhere\Else\Python3.4.0
那就是说,你绝对可以在纯粹的Powershell中做一个单线程。根据您的描述,我认为您不应该使用start cmd /k
前缀 - 您应该可以直接调用Powershell.exe,如下所示:
powershell -command "(New-Object Net.WebClient).DownloadFile('https://www.python.org/ftp/python/3.6.2/python-3.6.2.exe', 'C:/Tools/python-3.6.2.exe'); & c:\Tools\python-3.6.2.exe /quiet InstallAllUsers=1 PrependPath=1 Include_test=0 TargetDir=c:\Tools\Python362; [Environment]::SetEnvironmentVariable('PATH', ${env:path} + ';C:\Tools\Python362', 'Machine')"
答案 1 :(得分:0)
在PowerShell中完成所有操作,包括安装库。
# This is the link to download Python 3.6.7 from Python.org
# See https://www.python.org/downloads/
$pythonUrl = "https://www.python.org/ftp/python/3.6.7/python-3.6.7-amd64.exe"
# This is the directory that the exe is downloaded to
$tempDirectory = "C:\temp_provision\"
# Installation Directory
# Some packages look for Python here
$targetDir = "C:\Python36"
# create the download directory and get the exe file
$pythonNameLoc = $tempDirectory + "python367.exe"
New-Item -ItemType directory -Path $tempDirectory -Force | Out-Null
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
(New-Object System.Net.WebClient).DownloadFile($pythonUrl, $pythonNameLoc)
# These are the silent arguments for the install of python
# See https://docs.python.org/3/using/windows.html
$Arguments = @()
$Arguments += "/i"
$Arguments += 'InstallAllUsers="1"'
$Arguments += 'TargetDir="' + $targetDir + '"'
$Arguments += 'DefaultAllUsersTargetDir="' + $targetDir + '"'
$Arguments += 'AssociateFiles="1"'
$Arguments += 'PrependPath="1"'
$Arguments += 'Include_doc="1"'
$Arguments += 'Include_debug="1"'
$Arguments += 'Include_dev="1"'
$Arguments += 'Include_exe="1"'
$Arguments += 'Include_launcher="1"'
$Arguments += 'InstallLauncherAllUsers="1"'
$Arguments += 'Include_lib="1"'
$Arguments += 'Include_pip="1"'
$Arguments += 'Include_symbols="1"'
$Arguments += 'Include_tcltk="1"'
$Arguments += 'Include_test="1"'
$Arguments += 'Include_tools="1"'
$Arguments += 'Include_launcher="1"'
$Arguments += 'Include_launcher="1"'
$Arguments += 'Include_launcher="1"'
$Arguments += 'Include_launcher="1"'
$Arguments += 'Include_launcher="1"'
$Arguments += 'Include_launcher="1"'
$Arguments += "/passive"
#Install Python
Start-Process $pythonNameLoc -ArgumentList $Arguments -Wait
Function Get-EnvVariableNameList {
[cmdletbinding()]
$allEnvVars = Get-ChildItem Env:
$allEnvNamesArray = $allEnvVars.Name
$pathEnvNamesList = New-Object System.Collections.ArrayList
$pathEnvNamesList.AddRange($allEnvNamesArray)
return ,$pathEnvNamesList
}
Function Add-EnvVarIfNotPresent {
Param (
[string]$variableNameToAdd,
[string]$variableValueToAdd
)
$nameList = Get-EnvVariableNameList
$alreadyPresentCount = ($nameList | Where{$_ -like $variableNameToAdd}).Count
if ($alreadyPresentCount -eq 0)
{
[System.Environment]::SetEnvironmentVariable($variableNameToAdd, $variableValueToAdd, [System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable($variableNameToAdd, $variableValueToAdd, [System.EnvironmentVariableTarget]::Process)
[System.Environment]::SetEnvironmentVariable($variableNameToAdd, $variableValueToAdd, [System.EnvironmentVariableTarget]::User)
$message = "Enviromental variable added to machine, process and user to include $variableNameToAdd"
}
else
{
$message = 'Environmental variable already exists. Consider using a different function to modify it'
}
Write-Information $message
}
Function Get-EnvExtensionList {
[cmdletbinding()]
$pathExtArray = ($env:PATHEXT).Split("{;}")
$pathExtList = New-Object System.Collections.ArrayList
$pathExtList.AddRange($pathExtArray)
return ,$pathExtList
}
Function Add-EnvExtension {
Param (
[string]$pathExtToAdd
)
$pathList = Get-EnvExtensionList
$alreadyPresentCount = ($pathList | Where{$_ -like $pathToAdd}).Count
if ($alreadyPresentCount -eq 0)
{
$pathList.Add($pathExtToAdd)
$returnPath = $pathList -join ";"
[System.Environment]::SetEnvironmentVariable('pathext', $returnPath, [System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('pathext', $returnPath, [System.EnvironmentVariableTarget]::Process)
[System.Environment]::SetEnvironmentVariable('pathext', $returnPath, [System.EnvironmentVariableTarget]::User)
$message = "Path extension added to machine, process and user paths to include $pathExtToAdd"
}
else
{
$message = 'Path extension already exists'
}
Write-Information $message
}
Function Get-EnvPathList {
[cmdletbinding()]
$pathArray = ($env:PATH).Split("{;}")
$pathList = New-Object System.Collections.ArrayList
$pathList.AddRange($pathArray)
return ,$pathList
}
Function Add-EnvPath {
Param (
[string]$pathToAdd
)
$pathList = Get-EnvPathList
$alreadyPresentCount = ($pathList | Where{$_ -like $pathToAdd}).Count
if ($alreadyPresentCount -eq 0)
{
$pathList.Add($pathToAdd)
$returnPath = $pathList -join ";"
[System.Environment]::SetEnvironmentVariable('path', $returnPath, [System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('path', $returnPath, [System.EnvironmentVariableTarget]::Process)
[System.Environment]::SetEnvironmentVariable('path', $returnPath, [System.EnvironmentVariableTarget]::User)
$message = "Path added to machine, process and user paths to include $pathToAdd"
}
else
{
$message = 'Path already exists'
}
Write-Information $message
}
Add-EnvExtension '.PY'
Add-EnvExtension '.PYW'
Add-EnvPath 'C:\Python36\'
# Install a library using Pip
python -m pip install numpy