Many companies and their developers use Azure DevOps platform for project deployment. Azure DevOps provides a big list of build-in tasks that can be useful, but very often it is not enough and you have to implement your own scripts. In this article I share my TOP of useful powershell scripts that can be helpful for everyone.
Disclaimer: avoid of using IIS Web App Manage taks for IIS and App Pool managing. Problem: it fails with error if current status is not the same as expected. Example: "Stop App Pool" task will fail if application pool is already stopped.
-
Stop Website (if exists) or Create new and Stop (if not exists)
Import-Module WebAdministration $siteName = 'website.com'; $path = "c:\inetpub\wwwroot\website.com" $exist = (Get-Website -name $siteName) -ne $null if($exist){ $status = Get-WebsiteState -name $siteName if ($status.Value -ne 'Stopped'){ Write-Output ('Stopping IIS Website: {0}' -f $siteName) Stop-WebSite -Name $siteName } } else{ # create new IIS website and 80 port binding New-Item IIS:\Sites\$siteName -bindings @{protocol="http";bindingInformation=":80:" + $siteName} -physicalPath $path $status = Get-WebsiteState -name $siteName if ($status.Value -ne 'Stopped'){ Write-Output ('Stopping IIS Website: {0}' -f $siteName) Stop-WebSite -Name $siteName } }
-
Stop App Pool (if exists) or Create new and Stop (if not exists)
Import-Module WebAdministration $siteName = 'website.com'; if(Test-Path IIS:\AppPools\$siteName){ $status = Get-WebAppPoolState -name $siteName if ($status.Value -ne 'Stopped'){ Write-Output ('Stopping Application Pool: {0}' -f $siteName) Stop-WebAppPool -Name $siteName } } else{ New-Item IIS:\AppPools\$siteName Set-ItemProperty IIS:\Sites\$siteName -name applicationPool -value $siteName $status = Get-WebAppPoolState -name $siteName if ($status.Value -ne 'Stopped'){ Write-Output ('Stopping Application Pool: {0}' -f $siteName) Stop-WebAppPool -Name $siteName } }
-
Ensure that Website and App Pool are both stopped
Import-Module WebAdministration $siteName = 'website.com'; $exist = (Get-Website -name $siteName) -ne $null if($exist){ if(Test-Path IIS:\AppPools\$siteName){ $success = $false; # timer in 60 sec $sec = 60; do{ $iisState = (Get-WebsiteState -name $siteName).Value $iisstopped = $iisState -eq "Stopped" $poolState = (Get-WebAppPoolState -name $siteName).Value $poolstopped = $poolState -eq "Stopped" Write-Output "Website state: $iisState" Write-Output "AppPoolstate: $poolState " $success = $iisstopped -and $poolstopped if(!$success){ Start-Sleep -s 1 $sec = $sec - 1; } } while (!$success -and $sec -gt 0) if(!$success){ throw "Can not stop IIS or App pool" } } }
-
Set App Pool Identity user
Import-Module WebAdministration $siteName = 'website.com'; $appUser = 'Apppool_User'; $appPassword = 'Apppool_User_Password'; Set-ItemProperty IIS:\AppPools\$siteName -name processModel -value @{userName=$appUser;password=$appPassword;identitytype=3}
-
Set SSL certificate and add HTTPS binding to Website
Import-Module WebAdministration $siteName = 'website.com'; $fqdn = 'website.com'; # get certificate by Subject $newCert = dir Cert:\localmachine\My | where-Object {$_.subject -like "*website.com*"}; # get certificate by thumbprint #$newCert = dir Cert:\localmachine\My | where-Object {$_.Thumbprint -eq "1d486045ed3af7513b62ae43135421268bcde3dd"}; $webbindings = Get-WebBinding -Name $siteName $webbindings $hasSsl = $webbindings | Where-Object { $_.protocol -like "*https*" } if($hasSsl) { Write-Output "An SSL certificate is already assigned." } else { Write-Output "Applying TLS/SSL Certificate" New-WebBinding -Name $siteName -Port 443 -Protocol https -HostHeader $fqdn; #could add -IPAddress here if needed (and for the get below) $httpsBinding = Get-WebBinding -Name $siteName -Port 443 -Protocol "https" -HostHeader $fqdn; Write-Output $httpsBinding $httpsBinding.AddSslCertificate($newCert.Thumbprint, "my") Write-Output "`r`n`r`nNew web bindings" $webbindings = Get-WebBinding -Name $siteName $webbindings }
-
Set environment variable
Import-Module WebAdministration $siteName = 'website.com'; $fqdn = 'website.com'; $envVariables = "/system.applicationHost/applicationPools/add[@name='$(SITE_NAME)']/environmentVariables" $configSection = $envVariables + "/add[@name='ASPNETCORE_ENVIRONMENT']" $subsections=get-webconfiguration $configSection -PSPath iis: $subsections | foreach { $_.attributes | select name,value } if($subsections -eq $null){ $cmd='c:\windows\system32\inetsrv\appcmd.exe' &$cmd set config -section:system.applicationHost/applicationPools /+"[name='$(SITE_NAME)'].environmentVariables.[name='ASPNETCORE_ENVIRONMENT',value='$(ENVIRONMENT)']" /commit:apphost }
-
Ping Website to be sure if it starts
$KeepAliveUrl = "https://website.come/keepAlive" $InitTimeoutSec = 300 $ReInitTimeoutSec = 60 $ThirdTimeoutSec = 5 Write-Host "KeepAliveUrl: " + $KeepAliveUrl; ## Enable TLS 1.2 to allow HTTPS communication [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ## The first request after the deployment may take a long time Write-Host "Request page to send a wake-up call and wait $InitTimeoutSec seconds to complete initialization" Invoke-WebRequest -Uri $KeepAliveUrl -TimeoutSec $InitTimeoutSec -UseBasicParsing ## Second request may still take a while as some initialization processes could ## have been started after first request (such as package installation via fridaycore), so smaller timeout here to make sure it is alright Write-Host "Requestto send another wake-up call and wait $ReInitTimeoutSec seconds to complete" Invoke-WebRequest -Uri $KeepAliveUrl -TimeoutSec $ReInitTimeoutSec -UseBasicParsing ## Third and any further requests must be responded within 5s Invoke-WebRequest -Uri $KeepAliveUrl -TimeoutSec $ThirdTimeoutSec -UseBasicParsing
-
Sometimes you need to install .Net Core related software with specific version, but you don`t have access to server and have to install in by pipeline tasks. The easiest way to do it is download dotnet-install.ps1 and use it for installations.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $WebClient = New-Object System.Net.WebClient $WebClient.DownloadFile("https://dotnet.microsoft.com/download/dotnet-core/scripts/v1/dotnet-install.ps1","D:\dotnet-install.ps1")
-
Install .NET Core Runtime version
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 d:\dotnet-install.ps1 -Runtime dotnet -Version 2.2.8
-
Install ASP.NET Core Runtime version
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 d:\dotnet-install.ps1 -Runtime aspnetcore -Version 2.2.8
-
Execute SQL script
$Query = "select * from [MyDatabase].[dbo].[MyTable]" Invoke-Sqlcmd -ConnectionString "$(ConnectionString)" -Query $Query | Out-File -FilePath "D:\temp\select_log.txt"
-
Show logs by mask (for specific date)
$logpath = "c:\inetpub\wwwroot\website.com\logs" $today = Get-Date -Format "yyyyMMdd" $userDate = $(Date) if(![string]::IsNullOrEmpty($userDate)){ $today = $userDate } if (Test-Path -Path $logpath ){ Get-ChildItem -Path $logpath Get-ChildItem $logpath -Filter *$today*.txt | Foreach-Object { Get-Content $_.FullName } }
-
Zip and Upload directory
$OutputDir = "$(System.DefaultWorkingDirectory)\output" Compress-Archive -Path $OutputDir -DestinationPath $OutputDir -Force Write-host "##vso[task.uploadfile]$OutputDir.zip"