diff --git a/nuget/AspNetCore.nuspec b/nuget/AspNetCore.nuspec index c4298b6822..f19743a8c5 100644 --- a/nuget/AspNetCore.nuspec +++ b/nuget/AspNetCore.nuspec @@ -15,5 +15,6 @@ + \ No newline at end of file diff --git a/tools/installancm.ps1 b/tools/installancm.ps1 new file mode 100644 index 0000000000..a2b5bdd0e8 --- /dev/null +++ b/tools/installancm.ps1 @@ -0,0 +1,442 @@ +<# +.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", + [Parameter(Mandatory=$false, Position = 1)] + [string] $PackagePath="$PSScriptRoot\..\artifacts", + [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]$DestineFilePath) { + + $Source = $SourceFilePath + $Destine = $DestineFilePath + + $BackupFilePath = $Destine + ".ancm_backup" + if ($Rollback) + { + $Source = $BackupFilePath + } + + $functionName = "Update-File -Rollback:$" + $Rollback.ToString() + $LogHeader = "[$ScriptFileName::$functionName]" + + if ($ForceToBackup) + { + if (Test-Path $BackupFilePath) + { + Say (" Delete the existing backup file: $BackupFilePath") + Remove-Item $BackupFilePath -Force -Confirm:$false + } + if (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 $Destine $BackupFilePath -Force + + $fileMatched = $null -eq (Compare-Object -ReferenceObject $(Get-Content $Destine) -DifferenceObject $(Get-Content $BackupFilePath)) + if (-not $fileMatched) + { + throw ("$LogHeader File not matched!!! $Destine $BackupFilePath") + } + } + if (-Not (Test-Path $BackupFilePath)) + { + throw ("$LogHeader Can't backup $Source to $BackupFilePath") + } + + # Copy file from Source to Destine if those files are different each other + if (-Not (Test-Path $Destine)) + { + throw ("$LogHeader Can't find $Destine") + } + $fileMatched = $null -eq (Compare-Object -ReferenceObject $(Get-Content $Source) -DifferenceObject $(Get-Content $Destine)) + if (-not $fileMatched) + { + Say (" Copying $Source to $Desting...") + Copy-Item $Source $Destine -Force + + # check file is correctly copied + $fileMatched = $null -eq (Compare-Object -ReferenceObject $(Get-Content $Source) -DifferenceObject $(Get-Content $Destine)) + if (-not $fileMatched) + { + throw ("$LogHeader File not matched!!! $Source $Destine") + } + else + { + Say-Verbose ("$LogHeader File matched!!! $Source to $Destine") + } + } + else + { + Say (" Skipping the file $Destine 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 +} +$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" + +$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