-
-
Save CJHarmath/b2af0f50700ce9fbdd8c5c3e582fd41b to your computer and use it in GitHub Desktop.
# Setup | |
Import-Module WebAdministration | |
# create 2 site root directories | |
$a = 'C:\inetpub\AspNetCoreSampleA' | |
$b = 'C:\inetpub\AspNetCoreSampleB' | |
$siteRoot = 'C:\inetpub\aspnetcoresample' | |
$siteName = 'AspNetCoreSample' | |
$poolName = "aspnetcore" | |
New-Item -Type Directory $a | |
New-Item -Type Directory $b | |
# create a symlink to targeting one side | |
New-Item -Type SymbolicLink -Path $siteRoot -Target $a | |
# point the site root to the symlink | |
Set-ItemProperty "IIS:\Sites\$siteName" -name physicalPath -value $siteRoot | |
# make sure it get's picked up | |
Restart-WebAppPool -Name $poolName | |
# this tells you the active side | |
Get-Item -Path $siteRoot | Select-Object -ExpandProperty target | |
# Flip the symlink | |
$current = (Get-Item -Path $siteRoot).Target | |
$newTarget = if ($current -eq $a) {$b} else {$a} | |
New-Item -Type SymbolicLink -Path $siteRoot -Target $newTarget -Force | |
# at this point w3wp.exe still locks the current target folder until it's getting recycled | |
# Deploy new version to the symlink which is now pointing to the other side which should have no locks | |
robocopy \\myshare\myapp $siteRoot /mir | |
# recycle app pool, so it picks up the new files | |
Restart-WebAppPool -Name $poolName | |
# bonus point: rollback is easy | |
$current = (Get-Item -Path $siteRoot).Target | |
$newTarget = if ($current -eq $a) {$b} else {$a} | |
New-Item -Type SymbolicLink -Path $siteRoot -Target $newTarget -Force | |
Restart-WebAppPool -Name $poolName |
Is line 14 supposed to point to $a instead of $siteRoot?
Set-ItemProperty "IIS:\Sites\$siteName" -name physicalPath -value $siteRoot
This line points the IIS Site root path to the symlink which was created in line 12 pointing to $a.
So by pointing it at the siteroot, it's technically pointing at the A side until you swap.
Is this possible to do on the same IIS Site root path and instead do it on same site but on differet webapp-folders?
I.E:
Default Web Site\Production folder
Default Web Site\Staging.
Here a paste from me copy pasting the first few lines.
c:\temp> $a = 'C:\inetpub\AspNetCoreSampleA'
c:\temp> $b = 'C:\inetpub\AspNetCoreSampleB'
c:\temp> $siteRoot = 'C:\inetpub\aspnetcoresample'
c:\temp> $siteName = 'AspNetCoreSample'
c:\temp> $poolName = "aspnetcore"
c:\temp> New-Item -Type Directory $a
Directory: C:\inetpub
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 1/5/2021 2:28 PM AspNetCoreSampleA
c:\temp> New-Item -Type Directory $b
Directory: C:\inetpub
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 1/5/2021 2:28 PM AspNetCoreSampleB
c:\temp> # create a symlink to targeting one side
c:\temp> New-Item -Type SymbolicLink -Path $siteRoot -Target $a
Directory: C:\inetpub
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----l 1/5/2021 2:28 PM aspnetcoresample
c:\temp> New-Item -Type SymbolicLink -Path $siteRoot -Target $b
New-Item : NewItemIOError
At line:1 char:1
+ New-Item -Type SymbolicLink -Path $siteRoot -Target $b
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceExists: (C:\inetpub\aspnetcoresample:String) [New-Item], IOException
+ FullyQualifiedErrorId : NewItemIOError,Microsoft.PowerShell.Commands.NewItemCommand
c:\temp> New-Item -Type SymbolicLink -Path $siteRoot -Target $b -Force
Directory: C:\inetpub
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----l 1/5/2021 2:28 PM aspnetcoresample
c:\temp>
Once you've created a folder or a symlink, yes you will see these errors.
To update the symlink, you need to use the -Force option.
To avoid trying to create the same folders, use if (-not Test-Path $a) { New-Item -Type Directory $a }
i.e.: first check if the folder is there and if not create it.
Okay thx for your reply. But why is the script creating the directories $a and $b?
It throws an exception creating symbolic link target $a because that is a folder.
Okay, I think I got it now. The site root is supposed to be a symbolic link that points to the newly created folder $a.
Anyway having a hard time understanding the concept. I will dig into this again.
keep on playing with it until it clicks.
Create 2 folders with 2 different files, then create a symlink pointing to the first, confirm. then update the symlink to the second folder then confirm that you now see the second folder contents.
I've added a diagram here showing that the IIS site root points to a symlink.
dotnet/aspnetcore#3793 (comment)
Thanks for the script, (and for the comment on the GH issue at MS repo) used it as an inspiration for our deploy script! I owe you.
PS. we used to switch IIS application path during deploys, but symlinks are so much better and in-flight requests are not being dropped. Thanks again. ❤ 🙌
Sure thing, glad it helped someone!
Is line 14 supposed to point to $a instead of $siteRoot?