Skip to content

Commit b93a769

Browse files
committed
Check (and install if needed) required Visual C++ Redistributables when installing PHP
1 parent c00fc4a commit b93a769

File tree

4 files changed

+96
-5
lines changed

4 files changed

+96
-5
lines changed

PhpManager/private/Constants.ps1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,5 @@ New-Variable -Option Constant -Scope Script -Name 'PEARSTATE_SNAPSHOT' -Value 's
4242
New-Variable -Option Constant -Scope Script -Name 'CACERT_PEM_URL' -Value 'https://curl.haxx.se/ca/cacert.pem'
4343
New-Variable -Option Constant -Scope Script -Name 'CACERT_CHECKSUM_URL' -Value 'https://curl.haxx.se/ca/cacert.pem.sha256'
4444
New-Variable -Option Constant -Scope Script -Name 'CACERT_CHECKSUM_ALGORITHM' -Value 'SHA256'
45+
46+
New-Variable -Option Constant -Scope Script -Name 'STATUS_DLL_NOT_FOUND' -Value 0xC0000135

PhpManager/private/Install-PhpFromUrl.ps1

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ function Install-PhpFromUrl() {
88
99
.Parameter Path
1010
The path where the archive should be extracted to.
11+
12+
.Parameter PhpVersion
13+
The instance of PphVersion we are going to install.
14+
15+
.Parameter InstallVCRedist
16+
Install the Visual C++ Redistributables if they are missing?
1117
#>
1218
Param(
1319
[Parameter(Mandatory = $True, Position = 0, HelpMessage = 'The URL where the binary archive can be downloaded from')]
@@ -17,17 +23,96 @@ function Install-PhpFromUrl() {
1723
[Parameter(Mandatory = $true, Position = 1, HelpMessage = 'The path where the archive should be extracted to')]
1824
[ValidateNotNull()]
1925
[ValidateLength(1, [int]::MaxValue)]
20-
[string] $Path
26+
[string] $Path,
27+
[Parameter(Mandatory = $true, Position = 2, HelpMessage = 'The instance of PphVersion we are going to install')]
28+
[ValidateNotNull()]
29+
[psobject] $PhpVersion,
30+
[Parameter(Mandatory = $true, Position = 3, HelpMessage = 'Install the Visual C++ Redistributables if they are missing?')]
31+
[bool] $InstallVCRedist
2132
)
2233
Begin {
2334
}
2435
Process {
2536
$temporaryFile = Get-ZipFromUrl -Url $Url
2637
Try {
27-
Write-Debug "Extracting $temporaryFile"
38+
$temporaryDirectory = New-TempDirectory
39+
Try {
40+
Write-Debug "Extracting $temporaryFile to temporary directory"
41+
Expand-Archive -LiteralPath $temporaryFile -DestinationPath $temporaryDirectory -Force
42+
$exePath = Join-Path -Path $temporaryDirectory -ChildPath 'php.exe'
43+
If (-Not(Test-Path -Path $exePath -PathType Leaf)) {
44+
Throw "Unable to find php.exe in the downloaded archive"
45+
}
46+
& $exePath @('-n', '-v') | Out-Null
47+
If ($LASTEXITCODE -eq $Script:STATUS_DLL_NOT_FOUND) {
48+
Switch ($PhpVersion.VCVersion) {
49+
6 { $redistName = '6' } # PHP 5.2, PHP 5.3
50+
7 { $redistName = '2002' }
51+
7.1 { $redistName = '2003' }
52+
8 { $redistName = '2005' }
53+
9 { $redistName = '2008' } # PHP 5.4
54+
10 { $redistName = '2010' }
55+
11 { $redistName = '2012' } # PHP 5.5, PHP 5.6
56+
12 { $redistName = '2013' }
57+
14 { $redistName = '2015' } # PHP 7.0, PHP 7.1
58+
15 { $redistName = '2017' } # PHP 7.2
59+
default {
60+
Throw ('The Visual C++ ' + $PhpVersion.VCVersion + ' Redistributable seems to be missing: you have to install it manually (we can''t recognize its version)')
61+
}
62+
}
63+
If (-Not($InstallVCRedist)) {
64+
Throw "The Visual C++ $redistName Redistributable seems to be missing: you have to install it manually"
65+
}
66+
If (-Not(Get-Module -Name VcRedist)) {
67+
Throw "The Visual C++ $redistName Redistributable seems to be missing: you have to manually install it (if you install the VcRedist PowerShell module we could try to install it automatically)"
68+
}
69+
$vcListKind = 'Supported'
70+
$vcList = Get-VcList -Export $vcListKind | Where-Object { $_.Release -eq $redistName -and $_.Architecture -eq $PhpVersion.Architecture }
71+
If (-Not($vcList)) {
72+
$vcListKind = 'All'
73+
$vcList = Get-VcList -Export $vcListKind | Where-Object { $_.Release -eq $redistName -and $_.Architecture -eq $PhpVersion.Architecture }
74+
If (-Not($vcList)) {
75+
Throw "The Visual C++ $redistName Redistributable seems to be missing: you have to manually install it (the VcRedist PowerShell module doesn't support it)"
76+
}
77+
}
78+
Write-Output "Downloading the Visual C++ $redistName Redistributable (it's required by this version of PHP)"
79+
$temporaryDirectory2 = New-TempDirectory
80+
Try {
81+
$vcList | Get-VcRedist -Path $temporaryDirectory2
82+
Write-Output "Installing the Visual C++ $redistName Redistributable"
83+
$currentUser = [System.Security.Principal.WindowsPrincipal] [System.Security.Principal.WindowsIdentity]::GetCurrent()
84+
If ($currentUser.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) {
85+
$vcList | Install-VcRedist -Path $temporaryDirectory2
86+
} Else {
87+
$exeCommand = "Get-VcList -Export $vcListKind"
88+
$exeCommand += " | Where-Object { `$_.Release -eq '$redistName' -and `$_.Architecture -eq '" + $PhpVersion.Architecture + "'}"
89+
$exeCommand += " | Install-VcRedist -Path '" + ($temporaryDirectory2 -replace "'", "''") + "'"
90+
Start-Process -FilePath 'powershell.exe' -ArgumentList "-Command ""$exeCommand""" -Verb RunAs -Wait
91+
}
92+
} Finally {
93+
Try {
94+
Remove-Item -Path $temporaryDirectory2 -Recurse -Force
95+
} Catch {
96+
Write-Debug 'Failed to remove temporary folder'
97+
}
98+
}
99+
}
100+
}
101+
Finally {
102+
Try {
103+
Remove-Item -Path $temporaryDirectory -Recurse -Force
104+
} Catch {
105+
Write-Debug 'Failed to remove temporary folder'
106+
}
107+
}
108+
Write-Debug "Extracting $temporaryFile to destination directory"
28109
Expand-Archive -LiteralPath $temporaryFile -DestinationPath $Path -Force
29110
} Finally {
30-
Remove-Item -Path $temporaryFile
111+
Try {
112+
Remove-Item -Path $temporaryFile
113+
} Catch {
114+
Write-Debug 'Failed to remove temporary file'
115+
}
31116
}
32117
}
33118
End {

PhpManager/public/Install-Php.ps1

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ function Install-Php() {
3434
Specify if you want to add the PHP installation folder to the user ('User') or system ('System') PATH environment variable.
3535
Please remark that using 'System' usually requires administrative rights.
3636
37+
.Parameter InstallVC
38+
Specify this switch to try to install automatically the required Visual C++ Redistributables (requires the VcRedist PowerShell package, and to run the process as an elevated user).
39+
3740
.Parameter Force
3841
Use this switch to enable installing PHP even if the destination directory already exists and it's not empty.
3942
#>
@@ -54,6 +57,7 @@ function Install-Php() {
5457
[Parameter(Mandatory = $false, Position = 5, HelpMessage = 'Specify if you want to add the PHP installation folder to the user (''User'') or system (''System'') PATH environment variable')]
5558
[ValidateSet('User', 'System')]
5659
[string] $AddToPath,
60+
[switch] $InstallVC,
5761
[switch] $Force
5862
)
5963
Begin {
@@ -122,7 +126,7 @@ function Install-Php() {
122126
}
123127
# Install the found PHP version
124128
Write-Output $('Installing PHP ' + $versionToInstall.DisplayName)
125-
Install-PhpFromUrl -Url $versionToInstall.DownloadUrl -Path $Path
129+
Install-PhpFromUrl -Url $versionToInstall.DownloadUrl -Path $Path -PhpVersion $versionToInstall -InstallVCRedist $InstallVC
126130
# Initialize the php.ini
127131
$IniPath = [System.IO.Path]::Combine($Path, 'php.ini');
128132
If (-Not(Test-Path -Path $IniPath -PathType Leaf)) {

PhpManager/public/Update-Php.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ function Update-Php() {
8484
$updated = $false
8585
} else {
8686
Write-Output $('Installing new version: ' + $bestNewVersion.DisplayName)
87-
Install-PhpFromUrl -Url $bestNewVersion.DownloadUrl -Path ([System.IO.Path]::GetDirectoryName($installedVersion.ExecutablePath))
87+
Install-PhpFromUrl -Url $bestNewVersion.DownloadUrl -Path ([System.IO.Path]::GetDirectoryName($installedVersion.ExecutablePath)) -PhpVersion $bestNewVersion -InstallVCRedist $false
8888
$updated = $true
8989
}
9090
}

0 commit comments

Comments
 (0)