Runc Ommand For Iis
Installing IIS Keeping with Microsoft modular design of, uhm, everything these days, IIS in Windows is still an optional “Windows Feature”. To install it, press the Windows + R key combination to bring up a run box, then type appwiz.cpl and press enter. If you want to run the site using IIS Express command line, you should install Windows 7 or newer release and IIS Express first. Then follow the.
At Octopus Deploy, we do a ton of work with IIS. If you add up the deployment telemetry from all of our customers, we’ve done over a million deployments of web sites and services. We’ve learned a lot along the way, about both how to use the PowerShell IIS modules, and how they work under the hood, as well as how to use them reliably. My goal in this post is to share that knowledge and build a single place that we can point people to when they need to use the PowerShell IIS modules.
This post covers:
- The
applicationHost.config
file and how IIS configuration works. - The new
IISAdministration
PowerShell module introduced in Windows Server 2016/Windows 10. - The older
WebAdministration
PowerShell module used since Windows 2008. - What we’ve learned from millions of real-world deployments using the PowerShell IIS modules.
- Lots and lots of practical examples, tested on all Windows Server OS from 2008 to 2016, as well as information about Nano Server.
The source for all of these examples lives in a GitHub repository, and we run the examples automatically against test machines running each of the different versions of Windows Server OS, so I’m fairly confident they work. Of course, if you run into any trouble, post an issue to the GitHub repository’s issue list, or send us a pull request! 😄
There’s quite a bit of theory at the start of this post before we get into the practical examples. There are plenty of sites that show how to do basic IIS tasks; my goal by the end of this post is to make you an expert at automated IIS configuration and the examples put that into context.
- IIS PowerShell modules and OS versions
- Recap IIS theory
- Examples
How IIS configuration is stored
If you open up the IIS Manager user interface and browse around any web site or application pool, you’ll find no shortage of knobs and dials you can tweak. There are thousands of potential settings, from what authentication methods to use, to how log files should be written, to how often the application pool that runs your process should recycle.
Where do all of these settings live?
Since IIS 7 (Windows 2008), nearly all of these settings live in one of two places:
- The
web.config
file that is deployed with your application. - An
applicationHost.config
file, which is server-wide.
If you are an ASP.NET developer you’re no-doubt familiar with the web.config
file, but you might not have seen applicationHost.config
before. You’ll usually find it under:
If you work with IIS, it’s worth taking the time to really look around this file, as you’ll discover all kinds of interesting settings. For example, here’s how your application pools are defined:
And the web sites:
Why is it important to be familiar with applicationHost.config
file? Well, it comes down to this:
All of the PowerShell modules for IIS that we discuss below are just fancy wrappers for editing this big XML file.
If you understand this, you’ll find it much easier to understand why the PowerShell IIS modules work the way they do, and you’ll be able to work out how to configure settings that aren’t obvious.
IIS PowerShell modules and OS versions
IIS relies heavily on services provided by the Windows kernel, so each version of IIS has been coupled to a release of Windows. And since each version of IIS brings new features, there have been different attempts at providing the PowerShell modules. The table below outlines each of these combinations:
Operating System | IIS version | PowerShell modules |
---|---|---|
Windows Server 2008 | 7 | Add-PsSnapIn WebAdministration |
Windows Server 2008 R2 | 7.5 | Import-Module WebAdministration |
Windows Server 2012 | 8 | Import-Module WebAdministration |
Windows Server 2012 R2 | 8.5 | Import-Module WebAdministration |
Windows Server 2016 | 10 | Import-Module WebAdministration or Import-Module IISAdministration |
Windows Server 2016 - Nano | 10 | Import-Module IISAdministration |
Let’s quickly run through the history.
IIS 7 and the WebAdministration 'SnapIn'
IIS 6 supported running ASP.NET applications but was written in unmanaged (non-.NET) code and all modules and extensions were unmanaged. IIS 7 was the first version of IIS to support .NET modules in the pipeline and the new Integrated pipeline mode. IIS 7 shipped with Windows Server 2008, but how is PowerShell installed?
PowerShell 1.0 used SnapIns (modules were introduced in PowerShell 2.0), but most of the supported commands are the same as those used in the later module versions. On Windows 2008 (prior to R2) you’d load the PowerShell IIS support with:
What complicated matters is that PowerShell 2.0 is available on Windows Server 2008 as an upgrade, but the PowerShell IIS module isn’t, you still have to use the snap-in.
IIS 7.5+ and the WebAdministration module
Windows Server 2008 R2 shipped in 2011 and included PowerShell 2.0 FC, which meant the IIS commands were now available as a module. You load them using the following command:
IIS 10 and the IISAdministration module
IIS 10, which ships with Windows Server 2016/Windows 10, provides you with two choices. You can continue to use the old module:
Or you can use the brand newIISAdministration
module:
Why the change? The diagram below explains how each of the modules are built.
Back when IIS 7 shipped, to make it easier to work with applicationHost.config
from managed code, Microsoft created a .NET library called Microsoft.Web.Administration.dll
. You’ll find it in the GAC, and you can reference it and use it from C# code:
If you look through the class library documentation, you’ll see that it’s very much a wrapper around the XML configuration file. For example, the Application
class inherits from a ConfigurationElement
base class.
For some reason, the WebAdministration
PowerShell module never built directly on top of this class library, but instead, duplicated much of it. This duplication is pretty obvious when you look at it in a decompiler.
With the new IISAdministration
module, Microsoft have basically:
- Rebuilt it on top of the
Microsoft.Web.Administration
DLL - Removed the
IIS:
drive PowerShell provider. - Created new
IIS*
cmdlets that provide a 'jumping point' into theMicrosoft.Web.Administration
classes.
As users, the IISAdministration
version of the module has one big advantage; the types returned by the commands are much more useful. While they are still XML wrappers, they are adorned with useful properties and methods that make the objects much more usable without relying on the commands:
If you’re using the old WebAdministration
, you pretty much have to do everything with the PowerShell CmdLets or by embracing the XML. There’s no way to navigate from a site returned by Get-Website
to its applications, as one simple example. The new module also works much better with PowerShell pipelining.
Overall, while I think the refactoring Microsoft did in the new module is a good move, I wish it wasn’t such a breaking change. I can imagine this simplifies maintenance for them, but instead of building a first-class PowerShell/IIS experience, they’ve built a handful of cmdlets that return .NET objects, and then you make standard method calls on them.
Nano Server broke everything!
Maybe that’s a bit harsh, but there’s some truth to it. It goes like this:
- Nano Server is a very cut-down version of Windows designed for containers or as a VM; it’s a few hundred MB and boots instantly. I’m pretty excited about it.
- Nano Server can’t run the full .NET Framework, it can only run .NET Core.
- PowerShell was built on the .NET Framework.
- To be able to run PowerShell on Nano Server (and Linux!), they rebuilt PowerShell on .NET Core.
- The old
WebAdministration
module also required the full .NET Framework. They ported a version ofMicrosoft.Web.Administration.dll
to .NET Core (after all, it’s just a big XML wrapper) so theIISAdministration
module could work, but they never ported theWebAdministration
module. - Microsoft have no plans to port WebAdministration to Nano Server.
This means that if your script needs to run on Nano Server, you’re limited to only using the IISAdministration
module, the old WebAdministration
module that we've come to know and love no longer works.
Writing scripts that run on multiple OSs
At Octopus, our code to deploy IIS websites has to support all of these operating systems. The simplest and most reliable way that we’ve found to load the WebAdministration
module is no matter what OS you’re on is:
If you want to be sure you’ve loaded at least one of the modules (IIS may not be installed), you can see how we do it in Octopus.
A script written this way should be portable between OSs, unless you are running it on Nano Server. In that case, you’ll need to use the new module, and the IIS*
CmdLets instead.
Recap IIS theory
Sites, applications, and virtual directories
We’re going to use these terms a lot throughout this post, so I think it’s worth a slight recap. Let’s take this IIS server:
Here we have one IIS server, which serves multiple web sites (Website1 and Website2). Each website has bindings that specify what protocol (HTTP/HTTPS, sometimes others), port (80/443/other), and host headers it listens on.
Website2 also has many applications (App1, App1.1, App1.2, App2) and virtual directories (App.1.1.vdir1, Vdir1, Vdir1.1, Vdir2).
Don’t let that screenshot from IIS Manager fool you. Under the hood, IIS thinks about the relationship between these sites, applications, and virtual directories quite differently. From the IIS team:
Briefly, a site contains one or more applications, an application contains one or more virtual directories, and a virtual directory maps to a physical directory on a computer.
This may take a few minutes to wrap your head around, but it’s important. IIS Manager presents the tree above because that’s how users think about their sites, apps, and vdirs, but here’s how IIS actually models the data:
- Site: Website1
- Application: /
- Virtual directory: /
- Application: /
- Site: Website2
- Application: /
- Virtual directory: /
- Virtual directory: /Vdir1
- Virtual directory: /Vdir1/Vdir1.1
- Virtual directory: /Vdir2
- Application: /App1
- Virtual directory: /
- Application: /App1/App1.1
- Virtual directory: /
- Virtual directory: /App1.1.vdir1
- Application: /App1/App1.1/App1.2
- Virtual directory: /
- Application: /App2
- Virtual directory: /
- Application: /Vdir1/Vdir1.App3
- Virtual directory: /
- Application: /
This is the object model that the Microsoft.Web.Administration .NET assembly presents, but it’s also the model used by the XML in applicationHost.config
:
Some notes:
- In IIS, the object model isn’t as crazy as the tree in IIS Manager presents. Sites have Applications. Applications have virtual directories. That’s that. Deeply nested relationships are modelled by storing the paths.
- Even though IIS Manager shows VDir1 as having an application inside it, the reality is that the application belongs to the site.
- Website1 is just a site, without any applications or virtual directories, but that’s just IIS Manager making life easy for us again. There’s actually an application and a virtual directory, they just use '/' as the path.
- The physical path for all these things is actually defined by the virtual directory.
The WebAdministration PowerShell module actually goes to quite some effort to hide this, you navigate IIS similar to IIS Manager. But the new IISAdministration module gives up on that leaky abstraction and presents the world to you this way.
Location sections
One of the confusing behaviors of IIS configuration is that as you make changes in IIS Manager, different settings get stored in different places:
- In the
<sites>
element shown above. - In
<location>
sections inside applicationHost.config. - In your own web.config file.
For example, when you change the physical path or bindings of a website, that’s stored in <sites>
.
When you change settings like whether directory browsing is enabled, that goes to the web.config
file in the physical path of whatever virtual directory (and remember, sites and apps all have virtual directories!).
When you change what authentication modes (anonymous, basic, Windows, etc.) should apply, that’s written to a <location>
section at the bottom of applicationHost.config
:
The rule that seems to apply is:
- If it’s a setting that should be local to the thing it applies to, it’s stored in
<sites>
. For example, when I change the application pool of Website2, I wouldn’t expect it to also change the application pool assigned to the applications inside it. - If it’s a setting that app developers are likely to want to set themselves, it goes to web.config.
- If it’s a setting that would be set by IIS administrators, and not by app developers, but it is something they would expect to inherit down the paths, then it’s set with the
<location>
inapplicationHost.config
. For example, if I disable anonymous authentication at the root website, I would expect that to apply to everything underneath it. If I then re-enable it for one virtual directory, I’d expect other apps and virtual directories under that path to inherit the new value.
It’s worth noting that you actually have some control over rule #3. IIS locks certain settings, the authentication settings for example, so that they can’t be overridden by a naughty application developer. But you can unlock them yourself and allow individual apps to override them in their own web.config files.
The easiest thing to do is make the change in IIS Manager, then go looking for whether it was applicationHost.config or your web.config that changed.
IIS: drive provider vs. CmdLets
There are two supported paradigms for working with the PowerShell IIS modules:
- The
IIS:
drive PowerShell provider, which lets you work with IIS as if it were a file system. - The task-based helper cmdlets, like
New-Website
.
In fact, if you decompile the cmdlets, most of the cmdlets actually wrap the IIS drive approach. When you call New-Website
, the cmdlet actually does this:
At Octopus, we’ve found that while we often start with the cmdlet approach, our scripts generally all turn into using the IIS
drive approach, because it allows for more advanced settings. That’s why most of the examples shown below use this approach.
Note that the IIS:
drive approach is not supported by the IISAdministration module, it’s effectively obsolete.
Retry, retry, retry
As I’ve discussed, all of the PowerShell IIS modules are really just wrappers over the XML file. And files don’t do very well when multiple processes read or write to them. All kinds of things can lock the file, virus scanners, backup solutions, IIS restarting, someone using the IIS Manager UI. For a while at Octopus, one of our most persistent support issues was problems that came up when the file was locked.
In practice, the only solution that has worked for us reliably across millions of customer deployments — and gotten rid of the support complaints — is to retry. Lots. Here’s how we do it. First, we make a function that can execute a block of PowerShell with a retry:
Then, each action we perform with IIS is wrapped in this function:
Examples
The rest of this post will be used to show lots of real-world examples of how to use the PowerShell IIS modules.
Creating sites (simple)
Creating sites (advanced)
Most likely, you’ll want to specify a few extra settings when you create a real site. To do that, you can get the site after creating it, and add the extra settings. Since we are making multiple changes, we can use delayed commits to write them all to applicationHost.config at once.
Here we’ll add an additional binding, and set the site ID:
Creating applications in virtual directories
Most of the time, when people think of deploying a .NET app to a virtual directory, they mean creating an application underneath a web site. The example below creates an application that would be viewable at http://site/MyApp
. We also assign an application pool:
Creating application pools
You need to assign each application (website or application in a virtual directory) to an application pool. The application pool defines the executable process in which requests to the application are handled.
IIS comes with a handful of application pools already defined for common options, but I always recommend creating your own application pool for each website or application that you deploy. This provides process-level isolation between applications and lets you set different permissions around what each application can do. The examples below show many of the common application pool settings. For the IIS Administration module, there are no built-in CmdLets to create application pools, so you have to do it with the ServerManager
object directly:
Assigning application pools
Once you’ve defined your application pool, you must assign applications to it. The examples below show you how to assign websites or applications in a virtual directory to your new application pool:
Check whether sites, virtual directories, or application pools already exist
You’ll re-deploy your application to IIS many times over the course of a project, so you can’t assume the script is being run for the first time. The examples below show a pattern for checking whether a site, application, or application pool already exists before making a change:
Change physical path of a site or application
When deploying a new version of an application, my preference (and the way Octopus Deploy works) is to deploy to a fresh new folder on disk, then update IIS to point to it. So you begin with:
You deploy the new version:
You can then make any necessary changes to configuration files, etc. and then update IIS to point to it:
Should you ever need to roll back in a hurry, you can leave the old folder on disk and point back to it:
Changing authentication methods
IIS supports a number of authentication methods. As described above, these are locked to applicationHost.config
by default, if you want to automatically enable them, the examples below show how to enable/disable:
- Anonymous authentication
- Basic authentication
- Digest authentication
- Windows authentication
IIS Manager also shows ASP.NET impersonation
and Forms authentication
as settings at the same level, but these are actually set in your app’s web.config
file so I’ve left them out here:
Changing logging settings
HTTP request logging is provided by IIS and can be specified server-wide or at the individual site level. Applications and virtual directories can disable logging, but they can’t do any logging of their own. The examples below show how to set logging at the site level.
Logging settings are stored in applicationHost.config
underneath the site:
Running application pools as a specific user
You can usually get by running your application pools as the ApplicationPoolIdentity
accounts. This creates a virtual account for each different application pool automatically, isolating them from each other. On the local machine, you can grant access to resources like the file system to each separate application pool. For remote resources (like an SQL Server on a different machine), the application pool identities act as Network Service, so you can grant access at the machine level. Learn more about application pool identities.
For more control over what the application pool can do, you should run it under a specific, custom user account. You’ll want to use aspnet_regiis
to give your custom account all the permissions it needs to run as an application pool and execute ASP.NET requests. You can then set your application pool to run as that user:
Summary
If you’re setting out to automate your IIS deployments for the first time, I hope you’ll find the background information and the examples in this post useful. As I mentioned, the examples are in a GitHub repository, and we run them against Windows 2008 R2 up to Windows Server 2016. If you find any problems or have ideas about other examples this post should include, let me know in the comments or send a pull request!
Learn more
- Using Octopus output variables in subsequent deployment steps.
- How to invoke an executable from PowerShell with a dynamic number of parameters.
- Tips and tricks for dealing with PowerShell exit codes.
- Configuration Management with Octopus and PowerShell DSC.
- Documentation: Running an Azure PowerShell script step.
IIS administrators often need to configure multiple IIS servers or make frequent changes to IIS configurations. IIS application developers might also need to configure an IIS server to test an application and then restore the previous configuration after they are done. IIS provides command-line tools to make these tasks faster than using IIS Manager or writing custom administration scripts.
Usage
For detailed instructions about using the IIS command-line tools, see Using Command-Line Administration Scripts in the IIS User Documentation.
To display the usage of a VBScript tool
Type the following text in a command window and press ENTER:
Cscript.exe /nologo <tool_name>.vbs /?
The only exception is AdsUtil.vbs, which does not need the /? to display its usage.
To display the usage of an executable tool
Type the following text in a command window and press ENTER:
<tool_name>.exe /?
Available Tools
IIS command-line tools are listed in the following table with the versions of IIS that they are included with.
Tool name | Description | IIS versions |
---|---|---|
%SystemDrive%InetpubAdminScriptsAdsUtil.vbs | AdsUtil.vbs is a popular tool because it is the most versatile, and it can be used on so many versions of IIS. AdsUtil.vbs uses ADSI to set, delete, create, and enumerate properties, find paths, and control the IIS server. One helpful parameter is ENUM_ALL, which enumerates the entire IIS configuration. AdsUtil.vbs cannot display properties of types IPSec, Binary, or NTAcl. AdsUtil.vbs does not display secure properties such as passwords. | IIS 4.0 IIS 5.0 IIS 5.1 IIS 6.0 |
%SystemDrive%InetpubAdminScriptsChAccess.vbs | ChAccess.vbs is used to set access permissions at metabase nodes. These access permissions include the AccessRead, AccessWrite, AccessScript, and AccessExecute flags of the AccessFlags property, and the EnableDirBrowsing flag of the DirBrowseFlags property. | IIS 5.1 |
%SystemDrive%InetpubAdminScriptsSyncIwam.vbs | SyncIwam.vbs is used to update the launching identity of all IIS COM+ application packages that run out of process. There are certain operations that may cause the IWAM account, which is the identity under which out of process IIS applications run, to become out of sync between the COM+ data store and IIS or the SAM. On IIS startup the account information stored in the IIS Metabase is synchronized with the local SAM, but the COM+ applications will not automatically be updated. The result of this is that requests to out of process applications will fail. For more information, open SyncIwam.vbs in Notepad to view the comments. | IIS 5.1 IIS 6.0 |
%SystemRoot%System32IISReset.exe | IISReset.exe is used to safely start, stop, enable, and disable the IIS services. Always use the /NOFORCE option when stopping or rebooting an IIS server. | IIS 5.1 IIS 6.0 |
%SystemRoot%System32ConvLog.exe | ConvLog.exe is used to convert log files to NCSA format. It can also replace IP addresses with Domain Name System (DNS) names during conversion, or it can be used to replace IP addresses with DNS names inside an NCSA Common log file. You can also use ConvLog.exe to convert time offsets. | IIS 5.1 IIS 6.0 |
%SystemRoot%System32IIsApp.vbs | IIsApp.vbs is used to list worker processes. Given an application pool identifier, it an report all of the process identifiers (PIDs) currently running w3wp.exe processes. IIS must be running in worker process isolation mode. This tool uses WMI. It cannot be used to configure a remote IIS server. | IIS 6.0 |
%SystemRoot%System32IIsBack.vbs | IIsBack.vbs is used to backup the metabase, restore the metabase, delete backups, or list all existing backup files. This tool uses WMI. It can be run remotely on any machine that supports WMI, but it must be passed the name of a server running IIS 6.0 or later. | IIS 6.0 |
%SystemRoot%System32IIsCnfg.vbs | IIsCnfg.vbs is used to import, export, copy, or save the IIS metabase configuration information, in whole or in part. This tool uses WMI. It can be run remotely on any machine that supports WMI, but it must be passed the name of a server running IIS 6.0 or later. | IIS 6.0 |
%SystemRoot%System32IIsExt.vbs | IIsExt.vbs is used to manages Web service extensions. When IIS is installed, only HTML Web content is allowed to be served. ASP, ASP.NET, CGI, and ISAPI applications must be enabled. This tool uses WMI. It can be run remotely on any machine that supports WMI, but it must be passed the name of a server running IIS 6.0 or later. | IIS 6.0 |
%SystemRoot%System32IIsFtp.vbs | IIsFtp.vbs is used to stop, start, pause, delete, or query the FTP service, or create an FTP site. This tool uses WMI. It can be run remotely on any machine that supports WMI, but it must be passed the name of a server running IIS 6.0 or later. | IIS 6.0 |
%SystemRoot%System32IIsFtpdr.vbs | IIsFtpdr.vbs is used to create, delete, or query and FTP virtual directory or directory. This tool uses WMI. It can be run remotely on any machine that supports WMI, but it must be passed the name of a server running IIS 6.0 or later. | IIS 6.0 |
%SystemRoot%System32IIsVdir.vbs | IIsVdir.vbs is used to create, delete, or query and Web virtual directory or directory. This tool uses WMI. It can be run remotely on any machine that supports WMI, but it must be passed the name of a server running IIS 6.0 or later. | IIS 6.0 |
%SystemRoot%System32IIsWeb.vbs | IIsWeb.vbs is used to stop, start, pause, delete, or query the Web service, or create a Web site. This tool uses WMI. It can be run remotely on any machine that supports WMI, but it must be passed the name of a server running IIS 6.0 or later. | IIS 6.0 |