How can I update ASP.NET Core app over an existing/running site without stopping the web server? - iis

We have an ASP.NET Core site running on our test server that we would like to auto-deploy by XCopy to our IIS web server as we do our current apps, where I already have the site running. I've added a publish profile that packages the site to a "publish-local" directory within the solution. Whenever I try to copy over the existing site, all DLLs are being used by another process, presumably Kestrel, so I am forced to deploy to a sibling directory and re-map IIS to look at the sibling. How does one update a running ASP.NET Core site without having to manually intervene and stop either the Kestrel or IIS web servers?

When running with IIS you can drop a file called app_offline.htm (case sensitive) to your application folder. IIS will stop your application and will serve the contents of the app_offline.html file. Now you can copy your application. Once finished remove the app_offline.htm and IIS will start your app. This is described in the docs and also in my post on running Asp.NET Core apps with IIS.

a little cheat we use is to rename the old files first (something like my.dll.old), then copy over the new dlls. Then you can either force or wait for an app pool restart.

Usually I take a backup of the existing version. Then I almost simultaneously recycle the app domain (if I'm using iis) and overwrite the entire contents of the root folder. This way the app restarts with the new version of the code. But it has to be super quick or else there can be issues. In case if anything fails backup can be used to restore to original state.

You can switch the physical path of your IIS site/application with PowerShell:
($curPath = Get-WebFilePath -PSPath "IIS:\Sites\www.example.com\MyApp")
if ($curPath -like "*Blue*") {
Copy-Item -Path "D:\inetpub\wwwroot\MyAppPath\Staging\*" -Destination "D:\inetpub\wwwroot\MyAppPath\Green" -Recurse -Force
Set-ItemProperty IIS:\Sites\www.example.com\MyApp -name physicalPath -value "D:\inetpub\wwwroot\MyAppPath\Green"
} else {
Copy-Item -Path "D:\inetpub\wwwroot\MyAppPath\Staging\*" -Destination "D:\inetpub\wwwroot\MyAppPath\Blue" -Recurse -Force
Set-ItemProperty IIS:\Sites\www.example.com\MyApp -name physicalPath -value "D:\inetpub\wwwroot\MyAppPath\Blue"
}
Use a staging folder to which you copy your new published files. Then, the above script switches between the green and blue folder. You don't have to stop or recycle your app.

Related

Trouble deploying multiple HTTPS sites to single host in TFS 2015

I'm trying to deploy multiple websites to a single host running IIS from TFS 2015. I'm trying to have all sites use the "Server Name Indication Required" option so that they all can run under the same IP address. (This setup works fine in IIS if I manually set everything up -- my question / problem comes from deploying from TFS 2015).
The FIRST site in the deploy chain works fine, but the any subsequent one seems to fail with the following error:
System.Exception: SSL Certificate add failed, Error: 183 Cannot create a file when that file already exists.
Each of the sites I'm deploying has a different SSL certificate and I've imported them all properly to the Local Machine\Personal store.
A screenshot of the release definition with the "IIS Web App Management" task highlighted is shown below.
Any suggestions on how to resolve this error within the release definition so that I can deploy cleanly without manual intervention?
I guess one thing I could try is to do ALL of the IIS management steps from PowerShell but was hoping to use the tools a little more fully rather than rolling new scripts to do what it seems that they SHOULD be able to do natively.
Any insight is appreciated.
The error message will appear if you try to bind the certificate to a port which is already binded to this or another certificate.
You can try to set different ports for the sites.
You can also try adding a step (Command line/Powershell step) to delete the existing binding before next deploy step if that does not affect the sites.
eg:
$> netsh http delete sslcert ipport:1.1.1.1:443
Reference below articles to delete the binding:
How to: Configure a Port with an SSL Certificate
Remove an SSL certificate from your server
How to remove SSL bindings using powershell
I got things working - but I had to basically eliminate the binding configuration from the WinRM - IIS App Management tasks. I kept everything the same but specified NO binding information at all in those tasks, then added a target machine power shell script that looked like this (thumbprints and site domains changed):
Import-Module WebAdministration
if ($null -eq (Get-WebBinding | Where-Object {$_.BindingInformation -eq "*:443:iddev.mydomain.com"}))
{
New-WebBinding -Name "Identity-B2B" -Port 443 -Protocol "https" -HostHeader "iddev.mydomain.com" -SslFlags 1
New-Item -Path "IIS:\SslBindings\!443!iddev.mydomain.com" -Thumbprint "88E811B7A9417DACAAAAAAAAAA1C36AA0BA238FF1E0F" -SSLFlags 1
}
if ($null -eq (Get-WebBinding | Where-Object {$_.BindingInformation -eq "*:443:iddev.myotherdomain.com"}))
{
New-WebBinding -Name "Identity-B2C" -Port 443 -Protocol "https" -HostHeader "iddev.myotherdomain.com" -SslFlags 1
New-Item -Path "IIS:\SslBindings\!443!iddev.myotherdomain.com" -Thumbprint "BE38195A2BBBBBBBBBBBBBBB1C2AB5762C9" -SSLFlags 1
}

Security Warning when running scripts - Unblock-File not unblocking file

I suddenly started to recceive this warning when running any script on my computer:
Run only scripts that you trust. While scripts from the internet can be useful, this script can potentially harm your computer...
Screenshot:
The files are not blocked.
I have
checked in File Explorer > Properties.
used the Unblock-File cmdlet to unblock as well.
checked streams using cmdlet: Get-Content -Path '\\Path\Script.ps1' -Stream Zone.Identifier. No Streams found.
used Streams.exe from Sysinternals: streams.exe -d \\Path\Script.ps1. No files with streams found.
Also tried to remove streams with Powershell:
Remove-Item -Path \\Path\Script.ps1 -Stream Zone.Identifier
Of course without success as there are no streams.
Execution policy is Unrestricted.
When I run Set-ExecutionPolicy Bypass it works without warning.
It should, however, also work when it's unrestricted.
I honestly don't know what's going on.
After searching i found someone with similar issues and it was explained that Classic UNC paths will work without prompting to unblock the file:
\\Servername\Path...
However FQDN paths are not seen as safe by default and will prompt:
\\Servername.foo.local\Path...
My own testing confirms this to be correct as removing the .foo.local from the path causes the Unblock-File prompts to stop.
LGPE > gpedit.msc
Computer Configuration > Administrative Templates, > Windows Components, > Internet Explorer>expand Internet Control Panel.
Security Page > Intranet Sites: Include all local (intranet) sites not listed in other zones, and then click Properties.
Click Enabled.
Turn on automatic detection of the intranet, and then click Properties.
Click Disabled, and then click OK.
or registry
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\"UNCAsIntranet" = "0"
The correct registry keys, name and value, to treat all local sites as part of the intranet zone, are:
Keys:
HKLM\Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap
HKCU\Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap
Name: IntranetName
Type: DWORD
Value: 1
You can set this via PowerShell for the local machine (in an elevated prompt) like this:
Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap" -Name "IntranetName" -Type DWord -Value 1
See Intranet Sites: Include all local (intranet) sites not listed in other zones for more information about the group policy.
PS doesnot allow Scripts to run on system ENV by default.
you need to set the policy to unrestricted or remote signed
Use:
Set-ExecutionPolicy Remotesigned
OR
Set-ExecutionPolicy Unrestricted
Open the PS console and type this and press enter and then try running your script.

How to configure IIS remotely using powershell?

I am trying to write a simple script that lets you remotely add an app pool, site, and app to IIS using powershell.
I figured out how to do this using APPCMD with a .bat on the local machine, but I need to do this remotely.
My bat file works and contains:
%systemroot%\system32\inetsrv\APPCMD add apppool /name:"WCF Integrated 4.0" /managedRuntimeVersion:"v4.0" /managedPipelineMode:Integrated /processModel.identityType:"NetworkService" /enable32BitAppOnWin64:True
%systemroot%\system32\inetsrv\APPCMD add site /name:"WCF Site" /bindings:"http/*:88:" /physicalPath:"D:\wcf"
%systemroot%\system32\inetsrv\APPCMD add app /site.name:"WCF Site" /path:/Service/Host /physicalPath:"D:\wcf\Service"
%systemroot%\system32\inetsrv\APPCMD set app /app.name:"WCF Site/Service/Host" /applicationPool:"WCF Integrated 4.0"
You didn't specify which version of IIS. If you are on 7.x, you can use the web administration module. Your script would resemble this:
$Session = New-PSSession -ComputerName '<ComputerName>'
$block = {
import-module 'webAdministration'
# Call IIS cmdlets here for adding app pools, creating web site and so on
}
Invoke-Command -Session $Session -ScriptBlock $block

Web/msdeploy sync from IIS to IISExpress fails

I have a a web site on a IIS on a remote machine. I would like to sync the website on the remote server to a local IISExpress. Currently I do not have the site on my local IISExpress. I am using the following msdeploy.exe command line (Here I formatted it in several lines, but of course the actual command is a single line):
msdeploy.exe
-verb:sync
-source:webApp="mysubdomain.mydomain.com",computername=mycomputer,userName=myuser,password=mypassword
-dest:auto
-apphostconfigdir=C:\Users\steen\Documents\IISExpress\config
-webserverdir="c:\program files (x86)\IIS Express"
I get following error returned:
Error: Application Definition with path 'mysubdomain.mydomain.com' does not exist.
Am I doing it wrong?
Do I need to have the site on my local IISExpress before I can sync (is there any workaround if I must have it locally first?)?
In the -source argument, try using the name of the web application for webApp (e.g. webApp="wordpress") and specifying the URL for your server in the computername argument. I don't think you need to have the site locally to begin with, but of course you'll need to have whatever web application the site uses installed locally.
Links: webApp: Web Deploy webApp Provider; computername: Web Deploy Provider Settings.

How to start IIS Express Manually

Is there a command line program or service that I can use to start IIS Express manually?
iisexpress program is responsible for that.
http://www.iis.net/learn/extensions/using-iis-express/running-iis-express-from-the-command-line
Once you have IIS Express installed (the easiest way is through Microsoft Web Platform Installer), you will find the executable file in %PROGRAMFILES%\IIS Express (%PROGRAMFILES(x86)%\IIS Express on x64 architectures) and its called iisexpress.exe.
To see all the possible command-line options, just run:
iisexpress /?
and the program detailed help will show up.
If executed without parameters, all the sites defined in the configuration file and marked to run at startup will be launched. An icon in the system tray will show which sites are running.
There are a couple of useful options once you have some sites created in the configuration file (found in %USERPROFILE%\Documents\IISExpress\config\applicationhost.config): the /site and /siteId.
With the first one, you can launch a specific site by name:
iisexpress /site:SiteName
And with the latter, you can launch by specifying the ID:
iisexpress /siteId:SiteId
With this, if IISExpress is launched from the command-line, a list of all the requests made to the server will be shown, which can be quite useful when debugging.
Finally, a site can be launched by specifying the full directory path. IIS Express will create a virtual configuration file and launch the site (remember to quote the path if it contains spaces):
iisexpress /path:FullSitePath
This covers the basic IISExpress usage from the command line.
From the links the others have posted, I'm not seeing an option. -- I just use powershell to kill it -- you can save this to a Stop-IisExpress.ps1 file:
get-process | where { $_.ProcessName -like "IISExpress" } | stop-process
There's no harm in it -- Visual Studio will just pop a new one up when it wants one.
Or you simply manage it like full IIS by using Jexus Manager for IIS Express, an open source project I work on
https://jexusmanager.com
Start a site and the process will be launched for you.
There is not a program but you can make a batch file and run a command like that :
powershell "start-process 'C:\Program Files (x86)\IIS Express\iisexpress.exe' -workingdirectory 'C:\Program Files (x86)\IIS Express\' -windowstyle Hidden"

Resources