472 lines
16 KiB
PowerShell
472 lines
16 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Installs asnetcore to IISExpress and IIS directory
|
|
.DESCRIPTION
|
|
Installs asnetcore to IISExpress and IIS directory
|
|
.PARAMETER Rollback
|
|
Default: $false
|
|
Rollback the updated files with the original files
|
|
.PARAMETER ForceToBackup
|
|
Default: $false
|
|
Force to do the initial backup again (this parameter is meaningful only when you want to replace the existing backup file)
|
|
.PARAMETER Extract
|
|
Default: $false
|
|
Search ANCM nugetfile and extract the file to the path of the ExtractFilesTo parameter value
|
|
.PARAMETER PackagePath
|
|
Default: $PSScriptRoot\..\..\artifacts
|
|
Root path where ANCM nuget package is placed
|
|
.PARAMETER ExtractFilesTo
|
|
Default: $PSScriptRoot\..\..\artifacts"
|
|
Output path where aspentcore.dll file is extracted
|
|
|
|
Example:
|
|
.\installancm.ps1 "C:\Users\jhkim\AppData\Local\Temp\ihvufnf1.atw\ancm\Debug"
|
|
|
|
#>
|
|
[cmdletbinding()]
|
|
param(
|
|
[Parameter(Mandatory=$false, Position = 0)]
|
|
[string] $ExtractFilesTo="$PSScriptRoot\..\artifacts\build\AspNetCore\bin\Debug",
|
|
[Parameter(Mandatory=$false, Position = 1)]
|
|
[string] $PackagePath="$PSScriptRoot\..\artifacts\build",
|
|
[Parameter(Mandatory=$false)]
|
|
[switch] $Rollback=$false,
|
|
[Parameter(Mandatory=$false)]
|
|
[switch] $ForceToBackup=$false,
|
|
[Parameter(Mandatory=$false)]
|
|
[switch] $Extract=$false
|
|
)
|
|
|
|
function Get-ANCMNugetFilePath() {
|
|
|
|
$NugetFilePath = Get-ChildItem $PackagePath -Recurse -Filter Microsoft.AspNetCore.AspNetCoreModule*.nupkg | Select-Object -Last 1
|
|
return ($NugetFilePath.FullName)
|
|
}
|
|
|
|
function Check-TargetFiles() {
|
|
$functionName = "Check-TargetFiles"
|
|
$LogHeader = "[$ScriptFileName::$functionName]"
|
|
$result = $true
|
|
|
|
if (-not $isIISExpressInstalled -and -not $isIISInstalled)
|
|
{
|
|
Say ("$LogHeader Both IIS and IISExpress does not have aspnetcore.dll file")
|
|
$result = $false
|
|
}
|
|
|
|
if ($isIISExpressInstalled)
|
|
{
|
|
if (-not (Test-Path $aspnetCorex64To))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to find the file $aspnetCorex64To")
|
|
$result = $false
|
|
}
|
|
if (-not (Test-Path $aspnetCoreSchemax64To))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to find the file $aspnetCoreSchemax64To")
|
|
$result = $false
|
|
}
|
|
if ($is64BitMachine)
|
|
{
|
|
if (-not (Test-Path $aspnetCoreWin32To))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to find the file $aspnetCoreWin32To")
|
|
$result = $false
|
|
}
|
|
if (-not (Test-Path $aspnetCoreSchemaWin32To))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to find the file $aspnetCoreSchemaWin32To")
|
|
$result = $false
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($isIISInstalled)
|
|
{
|
|
if (-not (Test-Path $aspnetCorex64IISTo))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to find the file $aspnetCorex64IISTo")
|
|
$result = $false
|
|
}
|
|
if (-not (Test-Path $aspnetCoreSchemax64IISTo))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to find the file $aspnetCoreSchemax64IISTo")
|
|
$result = $false
|
|
}
|
|
if ($is64BitMachine)
|
|
{
|
|
if (-not (Test-Path $aspnetCoreWin32IISTo))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to find the file $aspnetCoreWin32IISTo")
|
|
$result = $false
|
|
}
|
|
}
|
|
}
|
|
|
|
return $result
|
|
}
|
|
|
|
function Check-ExtractedFiles() {
|
|
$functionName = "Check-ExtractedFiles"
|
|
$LogHeader = "[$ScriptFileName::$functionName]"
|
|
$result = $true
|
|
|
|
if (-not (Test-Path $aspnetCorex64From))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to find the file $aspnetCorex64From")
|
|
$result = $false
|
|
}
|
|
if (-not (Test-Path $aspnetCoreWin32From))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to find the file $aspnetCoreWin32From")
|
|
$result = $false
|
|
}
|
|
if (-not (Test-Path $aspnetCoreSchemax64From))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to find the file $aspnetCoreSchemax64From")
|
|
$result = $false
|
|
}
|
|
if (-not (Test-Path $aspnetCoreSchemaWin32From))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to find the file $aspnetCoreSchemaWin32From")
|
|
$result = $false
|
|
}
|
|
return $result
|
|
}
|
|
|
|
function Extract-ANCMFromNugetPackage() {
|
|
$result = $true
|
|
|
|
$functionName = "Extract-ANCMFromNugetPackage"
|
|
$LogHeader = "[$ScriptFileName::$functionName]"
|
|
|
|
$backupAncmNugetFilePath = Join-Path $TempExtractFilesTo (get-item $ancmNugetFilePath).Name
|
|
if (Test-Path $backupAncmNugetFilePath)
|
|
{
|
|
Say ("$LogHeader Found backup file at $backupAncmNugetFilePath")
|
|
if ((get-item $ancmNugetFilePath).LastWriteTime -eq (get-item $backupAncmNugetFilePath).LastWriteTime)
|
|
{
|
|
if (Check-ExtractedFiles)
|
|
{
|
|
Say ("$LogHeader Skip to extract ANCM files because $ancmNugetFilePath is matched to the backup file $backupAncmNugetFilePath.")
|
|
return $result
|
|
}
|
|
}
|
|
}
|
|
|
|
Add-Type -Assembly System.IO.Compression.FileSystem
|
|
if (Test-Path $TempExtractFilesTo)
|
|
{
|
|
remove-item $TempExtractFilesTo -Force -Recurse -Confirm:$false | out-null
|
|
}
|
|
if (Test-Path $TempExtractFilesTo)
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to delete $TempExtractFilesTo")
|
|
$result = $false
|
|
return $result
|
|
}
|
|
else
|
|
{
|
|
new-item -Type directory $TempExtractFilesTo | out-null
|
|
}
|
|
if (-not (Test-Path $TempExtractFilesTo))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to create $TempExtractFilesTo")
|
|
$result = $false
|
|
return $result
|
|
}
|
|
|
|
#
|
|
Say ("$LogHeader Extract the ancm nuget file $ancmNugetFilePath to $TempExtractFilesTo ...")
|
|
[System.IO.Compression.ZipFile]::ExtractToDirectory($ancmNugetFilePath, $TempExtractFilesTo)
|
|
|
|
Say ("$LogHeader Create the backup file of the nuget file to $backupAncmNugetFilePath")
|
|
copy-item $ancmNugetFilePath $backupAncmNugetFilePath
|
|
|
|
return $result
|
|
}
|
|
|
|
function Update-ANCM() {
|
|
|
|
$functionName = "Update-ANCM -Rollback:$" + $Rollback.ToString()
|
|
$LogHeader = "[$ScriptFileName::$functionName]"
|
|
|
|
if ($isIISExpressInstalled)
|
|
{
|
|
if ($is64BitMachine)
|
|
{
|
|
Say ("$LogHeader Start updating ANCM files for IISExpress for amd64 machine...")
|
|
Update-File $aspnetCorex64From $aspnetCorex64To
|
|
Update-File $aspnetCoreWin32From $aspnetCoreWin32To
|
|
Update-File $aspnetCoreSchemax64From $aspnetCoreSchemax64To
|
|
Update-File $aspnetCoreSchemaWin32From $aspnetCoreSchemaWin32To
|
|
}
|
|
else
|
|
{
|
|
Say ("$LogHeader Start updating ANCM files for IISExpress for x86 machine...")
|
|
Update-File $aspnetCoreWin32From $aspnetCorex64To
|
|
Update-File $aspnetCoreSchemaWin32From $aspnetCoreSchemax64To
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Say ("$LogHeader Can't find aspnetcore.dll for IISExpress. Skipping updating ANCM files for IISExpress")
|
|
}
|
|
|
|
if ($isIISInstalled)
|
|
{
|
|
if ($is64BitMachine)
|
|
{
|
|
Say ("$LogHeader Start updating ANCM files for IIS for amd64 machine...")
|
|
Update-File $aspnetCorex64From $aspnetCorex64IISTo
|
|
Update-File $aspnetCoreWin32From $aspnetCoreWin32IISTo
|
|
Update-File $aspnetCoreSchemax64From $aspnetCoreSchemax64IISTo
|
|
}
|
|
else
|
|
{
|
|
Say ("$LogHeader Start updating ANCM files for IIS for x86 machine...")
|
|
Update-File $aspnetCoreWin32IISFrom $aspnetCorex64IISTo
|
|
Update-File $aspnetCoreSchemaWin32From $aspnetCoreSchemax64IISTo
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Say ("$LogHeader Can't find aspnetcore.dll for IIS. Skipping updating ANCM files for IIS server")
|
|
}
|
|
}
|
|
|
|
function Update-File([string]$SourceFilePath, [string]$DestinationFilePath) {
|
|
|
|
$Source = $SourceFilePath
|
|
$Destination = $DestinationFilePath
|
|
|
|
$BackupFilePath = $Destination + ".ancm_backup"
|
|
if ($Rollback)
|
|
{
|
|
$Source = $BackupFilePath
|
|
}
|
|
|
|
$functionName = "Update-File -Rollback:$" + $Rollback.ToString()
|
|
$LogHeader = "[$ScriptFileName::$functionName]"
|
|
|
|
if ($ForceToBackup)
|
|
{
|
|
if (Test-Path $BackupFilePath)
|
|
{
|
|
$backupFileRemoved = $false
|
|
if ( ((get-item $DestinationFilePath).CreationTime -gt (get-item $BackupFilePath).CreationTime) -and ((get-item $DestinationFilePath).CreationTime -gt (get-item $SourceFilePath).CreationTime) )
|
|
{
|
|
$backupFileRemoved = $true
|
|
Say (' Delete the existing "$BackupFilePath" because "$DestinationFilePath" is newer than both "$BackupFilePath" and "$SourceFilePath"')
|
|
Remove-Item $BackupFilePath -Force -Confirm:$false
|
|
}
|
|
else
|
|
{
|
|
Say-Verbose (' Skipping to delete the existing backupfile because "$DestinationFilePath" is not newer than $BackupFilePath"')
|
|
}
|
|
}
|
|
if ($backupFileRemoved -and (Test-Path $BackupFilePath))
|
|
{
|
|
throw ("$LogHeader Can't delete $BackupFilePath")
|
|
}
|
|
}
|
|
|
|
# Do the initial back up before updating file
|
|
if (-Not (Test-Path $BackupFilePath))
|
|
{
|
|
Say (" Create a backup $BackupFilePath")
|
|
Copy-Item $Destination $BackupFilePath -Force
|
|
|
|
$fileMatched = $null -eq (Compare-Object -ReferenceObject $(Get-Content $Destination) -DifferenceObject $(Get-Content $BackupFilePath))
|
|
if (-not $fileMatched)
|
|
{
|
|
throw ("$LogHeader File not matched!!! $Destination $BackupFilePath")
|
|
}
|
|
}
|
|
if (-Not (Test-Path $BackupFilePath))
|
|
{
|
|
throw ("$LogHeader Can't backup $Source to $BackupFilePath")
|
|
}
|
|
|
|
# Copy file from Source to Destination if those files are different each other
|
|
if (-Not (Test-Path $Destination))
|
|
{
|
|
throw ("$LogHeader Can't find $Destination")
|
|
}
|
|
$fileMatched = $null -eq (Compare-Object -ReferenceObject $(Get-Content $Source) -DifferenceObject $(Get-Content $Destination))
|
|
if (-not $fileMatched)
|
|
{
|
|
Say (" Copying $Source to $Desting...")
|
|
Copy-Item $Source $Destination -Force
|
|
|
|
# check file is correctly copied
|
|
$fileMatched = $null -eq (Compare-Object -ReferenceObject $(Get-Content $Source) -DifferenceObject $(Get-Content $Destination))
|
|
if (-not $fileMatched)
|
|
{
|
|
throw ("$LogHeader File not matched!!! $Source $Destination")
|
|
}
|
|
else
|
|
{
|
|
Say-Verbose ("$LogHeader File matched!!! $Source to $Destination")
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Say (" Skipping $Destination that is already identical to $Source ")
|
|
}
|
|
}
|
|
|
|
function Say($str) {
|
|
Write-Host $str
|
|
}
|
|
|
|
function Say-Verbose($str) {
|
|
Write-Verbose $str
|
|
}
|
|
|
|
#######################################################
|
|
# Start execution point
|
|
#######################################################
|
|
|
|
$EXIT_FAIL = 1
|
|
$EXIT_SUCCESS = 0
|
|
|
|
$ScriptFileName = "installancm.ps1"
|
|
$LogHeader = "[$ScriptFileName]"
|
|
|
|
if ($Extract -and (-Not $Rollback))
|
|
{
|
|
if (-not (Test-Path $PackagePath))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to find the directory $PackagePath")
|
|
exit $EXIT_FAIL
|
|
}
|
|
|
|
$ancmNugetFilePath = Get-ANCMNugetFilePath
|
|
if (-not (Test-Path $ancmNugetFilePath))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to find AspNetCoreModule nupkg file under $PackagePath nor its child directories")
|
|
exit $EXIT_FAIL
|
|
}
|
|
}
|
|
|
|
if (-Not $Rollback)
|
|
{
|
|
if (-not (Test-Path $ExtractFilesTo))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to find the directory $ExtractFilesTo")
|
|
exit $EXIT_FAIL
|
|
}
|
|
}
|
|
|
|
$TempExtractFilesTo = $ExtractFilesTo + "\.ancm"
|
|
$ExtractFilesRootPath = ""
|
|
if ($Extract)
|
|
{
|
|
$ExtractFilesRootPath = $TempExtractFilesTo + "\ancm\Debug"
|
|
}
|
|
else
|
|
{
|
|
$ExtractFilesRootPath = $ExtractFilesTo
|
|
}
|
|
|
|
# Try with solution output path
|
|
$aspnetCorex64From = $ExtractFilesRootPath + "\x64\aspnetcore.dll"
|
|
$aspnetCoreWin32From = $ExtractFilesRootPath + "\Win32\aspnetcore.dll"
|
|
$aspnetCoreSchemax64From = $ExtractFilesRootPath + "\x64\aspnetcore_schema.xml"
|
|
$aspnetCoreSchemaWin32From = $ExtractFilesRootPath + "\Win32\aspnetcore_schema.xml"
|
|
|
|
$aspnetCorex64To = "$env:ProgramFiles\IIS Express\aspnetcore.dll"
|
|
$aspnetCoreWin32To = "${env:ProgramFiles(x86)}\IIS Express\aspnetcore.dll"
|
|
$aspnetCoreSchemax64To = "$env:ProgramFiles\IIS Express\config\schema\aspnetcore_schema.xml"
|
|
$aspnetCoreSchemaWin32To = "${env:ProgramFiles(x86)}\IIS Express\config\schema\aspnetcore_schema.xml"
|
|
|
|
$aspnetCorex64IISTo = "$env:windir\system32\inetsrv\aspnetcore.dll"
|
|
$aspnetCoreWin32IISTo = "$env:windir\syswow64\inetsrv\aspnetcore.dll"
|
|
$aspnetCoreSchemax64IISTo = "$env:windir\system32\inetsrv\config\schema\aspnetcore_schema.xml"
|
|
|
|
# if this is not solution output path, use nuget package directory structure
|
|
if (-not (Test-Path $aspnetCorex64From))
|
|
{
|
|
$aspnetCorex64From = $ExtractFilesRootPath + "\runtimes\win7-x64\native\aspnetcore.dll"
|
|
$aspnetCoreWin32From = $ExtractFilesRootPath + "\runtimes\win7-x86\native\aspnetcore.dll"
|
|
$aspnetCoreSchemax64From = $ExtractFilesRootPath + "\aspnetcore_schema.xml"
|
|
$aspnetCoreSchemaWin32From = $ExtractFilesRootPath + "\aspnetcore_schema.xml"
|
|
|
|
$aspnetCorex64To = "$env:ProgramFiles\IIS Express\aspnetcore.dll"
|
|
$aspnetCoreWin32To = "${env:ProgramFiles(x86)}\IIS Express\aspnetcore.dll"
|
|
$aspnetCoreSchemax64To = "$env:ProgramFiles\IIS Express\config\schema\aspnetcore_schema.xml"
|
|
$aspnetCoreSchemaWin32To = "${env:ProgramFiles(x86)}\IIS Express\config\schema\aspnetcore_schema.xml"
|
|
|
|
$aspnetCorex64IISTo = "$env:windir\system32\inetsrv\aspnetcore.dll"
|
|
$aspnetCoreWin32IISTo = "$env:windir\syswow64\inetsrv\aspnetcore.dll"
|
|
$aspnetCoreSchemax64IISTo = "$env:windir\system32\inetsrv\config\schema\aspnetcore_schema.xml"
|
|
}
|
|
|
|
$is64BitMachine = $env:PROCESSOR_ARCHITECTURE.ToLower() -eq "amd64"
|
|
$isIISExpressInstalled = Test-Path $aspnetCorex64To
|
|
$isIISInstalled = Test-Path $aspnetCorex64IISTo
|
|
|
|
# Check expected files are available on IIS/IISExpress directory
|
|
if (-not (Check-TargetFiles))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to update ANCM files because AspnetCore.dll is not installed on IIS/IISExpress directory.")
|
|
exit $EXIT_FAIL
|
|
}
|
|
|
|
if ($Extract)
|
|
{
|
|
# Extrack nuget package when $DoExtract is true
|
|
if (-not (Extract-ANCMFromNugetPackage))
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to extract ANCM file")
|
|
exit $EXIT_FAIL
|
|
}
|
|
}
|
|
|
|
# clean up IIS and IISExpress worker processes and IIS services
|
|
Say ("$LogHeader Stopping w3wp.exe process")
|
|
Stop-Process -Name w3wp -ErrorAction Ignore -Force -Confirm:$false
|
|
|
|
Say ("$LogHeader Stopping iisexpress.exe process")
|
|
Stop-Process -Name iisexpress -ErrorAction Ignore -Force -Confirm:$false
|
|
|
|
$w3svcGotStopped = $false
|
|
$w3svcWindowsServce = Get-Service W3SVC -ErrorAction Ignore
|
|
if ($w3svcWindowsServce -and $w3svcWindowsServce.Status -eq "Running")
|
|
{
|
|
Say ("$LogHeader Stopping w3svc service")
|
|
$w3svcGotStopped = $true
|
|
Stop-Service W3SVC -Force -ErrorAction Ignore
|
|
Say ("$LogHeader Stopping w3logsvc service")
|
|
Stop-Service W3LOGSVC -Force -ErrorAction Ignore
|
|
}
|
|
|
|
if ($Rollback)
|
|
{
|
|
Say ("$LogHeader Rolling back ANCM files...")
|
|
}
|
|
else
|
|
{
|
|
Say ("Updating ANCM files...")
|
|
}
|
|
Update-ANCM
|
|
|
|
# Recover w3svc service
|
|
if ($w3svcGotStopped)
|
|
{
|
|
Say ("$LogHeader Starting w3svc service")
|
|
Start-Service W3SVC -ErrorAction Ignore
|
|
$w3svcServiceStopped = $false
|
|
|
|
$w3svcWindowsServce = Get-Service W3SVC -ErrorAction Ignore
|
|
if ($w3svcWindowsServce.Status -ne "Running")
|
|
{
|
|
Say ("$LogHeader Error!!! Failed to start w3svc service.")
|
|
exit $EXIT_FAIL
|
|
}
|
|
}
|
|
|
|
Say ("$LogHeader Finished!!!")
|
|
exit $EXIT_SUCCESS
|