Know it, Prove it

Microsoft is kicking off a challenge on 2/1/2015 via the Microsoft Virtual Academy training site. The Microsoft Virtual Academy offers free Microsoft training delivered by experts in their fields. There are training courses aimed at the IT Pro, developers and even students.

During the challenge, there are 8 different tracks with 28 days of learning topics in each one. Personally, I will be rocking my skills on the Hybrid Cloud path.

Take a look and sign up to join me in my quest to Know it. Prove it. You have less than 12 days to accept the challenge.

Terri is a Microsoft MVP (ASP .NET/IIS), an MCSA: Windows Server 2012, and a Cloud Administrator at OrcsWeb, a hosted server company providing managed hosting solutions

IIS Manager and Script generation

There are always questions on the forums related to scripting settings related to IIS configuration files. In IIS7 and above, there is a nifty feature called the Configuration Editor.  For reference, this blog post is written and pertains to IIS 8.5. This is important because some settings mentioned in this post are not available on any versions prior to IIS 8.5.

This feature allows you to ‘look’ at your configuration files and even update them via the GUI interface. This can be very handy since you are not manually updating one of the configuration files for either the entire IIS Server or one of your websites or applications. Since the format of the file requires specific items, using a tested script or GUI interface can aid in ensuring that you do not accidentally forget a “ or  < in the file which renders it unusable by IIS.

You access this feature by opening Internet Information Services (IIS) Manager. There is a Configuration Editor feature at the server level, the web site level, and for any folder, virtual directory or application within a website.


The location of the feature determines what configuration file will be modified by any changes made. Changes made at the server level will impact the primary configuration documents for the IIS installation. For example, if you would like to view the default settings for the application pools, you would access the Server name and double click on the Configuration Editor icon to open the feature. As you can see from the screenshot below, I have selected the section related to applicationPools. At the bottom of the screenshot, the active configuration file is listed as applicationhost.config.


The screenshot below shows the default settings for application pools as shown in both the configuration editor and the applicationhost.config file.


Making a change in the Configuration Editor updates the applicationhost.config file once you select Apply.

Let’s say for instance, you decide you would like to modify the default settings for your application pools but would like to script it so you can implement it at a later time or across multiple systems. Rather than the defaults for idleTimeout and idleTimeoutAction, you want to implement a longer timeout value and rather than terminating the process, you want to suspend it. The idleTimeoutAction item is only relative to IIS 8.5. For prior versions, you can change the idleTimeout following this same process as well. You are going to set the idleTimeout to 60 minutes rather than the default of 20. You are also going to change the idleTimeoutAction to Suspend rather than Terminate. This comes in handy when you have a website that takes a while to load but only has certain periods of time where it is active. By suspending the process, you do not have to wait for the initial spin-up which occurs after a worker process has been terminated. Any changes that are made in the editor are shown in BOLD in the GUI.

You will now notice that there are multiple actions available (Apply, Cancel, Generate Script). This is where the cool stuff happens. You are going to click Generate Script since you really want the PowerShell commands needed to make this change rather than applying the changes now. This will open a Script Dialog box that provides the auto-generated script in multiple languages including C#, AppCmd, and PowerShell.


You can now copy the script and integrate it into initial build scripts for creating a new IIS server or even as a stand alone script to simply update the settings that you have chosen.

The generated PowerShell script contains this code:

Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST'  -filter "system.applicationHost/applicationPools/applicationPoolDefaults/processModel" -name "idleTimeout" -value "01:00:00"

Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST'  -filter "system.applicationHost/applicationPools/applicationPoolDefaults/processModel" -name "idleTimeoutAction" -value "Suspend"

You will then open a PowerShell command window ran as Administrator. Paste the code into the window and run it. Voila, your updates were inserted into the applicationhost.config file and the default settings for new application pools are now configured the way that you want.

There are many settings that can be scripted following these same steps for websites. The Configuration Editor feature at the website level accesses the web.config file for the specified site or application. For example, if you want to change the way that customErrors are handled for your website, you can access the customErrors section of the web.config via the Configuration Editor and change the mode from the default RemoteOnly to On or Off. Once again, you can either apply the setting manually or Generate Script for your script repository or for future use.

I hope you find this blog post helpful, especially if you are just learning PowerShell and working with IIS.

Terri is a Microsoft MVP (ASP .NET/IIS), an MCSA: Windows Server 2012, and a Cloud Administrator at OrcsWeb, a hosted server company providing managed hosting solutions

Website Encryption

I was asked a curious question the other day related to the number of websites that have SSL certificates installed. After thinking about it, big companies have SSL but most personal websites don’t. Based on my own feelings, the reason things are this way is due to the upfront and yearly costs of SSL certificates as well as not realizing the benefits of encrypting your website content.

During this discussion, a friend told me about the Let’s Encrypt project. This is an exciting new FREE Certificate Authority that will be arriving in the Summer of 2015.

Let’s Encrypt will not be for everyone.  There will still be needs for the Extended Validation, wildcard, and multiple –domain certificates that are provided by Certificate Authorities such as VeriSign and GoDaddy to name a few.

The current application only supports apache but IIS is in the works. A small piece of management software is installed on the server that handles everything from proving control of the website, to requesting the certificate and installing it on the site. It also tracks certificate expiration dates ,handles auto renewal of the certificate and provides the ability to revoke the certificate if needed.

Since there is not a Windows/IIS version currently available, I do not have hands on experience with it. I am definitely looking forward to taking it for a test drive once it is available to see how it handles multiple websites on the same machine, host header sites, or even servers that have SNI and CCS installed.

Terri is a Microsoft MVP (ASP .NET/IIS), an MCSA: Windows Server 2012, and a Cloud Administrator at OrcsWeb, a hosted server company providing managed hosting solutions

HTTP/2–Through the looking glass

One of the things discussed at the MVP Summit this year was HTTP/2. The IIS group had a great session related to this upcoming protocol. Since this is being worked on across multiple companies to develop the new standard, we are able to blog about certain aspects of the protocol. The community is asking that people take an early look at the protocol. Test your applications. Try to find breaking changes so they can be addressed early in the process.

The Internet Engineering Task Force (IETF) works to produce high quality technical documents. The draft document for HTTP/2 is a great resource  to gather additional information related to this undertaking.

The Windows 10 Technical Preview supports HTTP/2 on the client and server side. I decided to spin up a cloud server on my Azure account to take this for a spin. To begin with, there are a few things required in order to test. The Web Server role has to be enabled. HTTP/2 also only works over the TLS cryptographic protocol so an SSL certificate has to be bound to the testing website.  I did not have to complete any of the additional steps in this blog post to ensure that HTTP/2 was enabled. Depending on the version of Technical Preview that you are using, you may need to set the registry key.

Since I want to take a look at all aspects of IIS on this version of Windows, I broke my cardinal rule of ‘Never enable all IIS Features’. The quick way to perform the install is by using PowerShell. I ran the command Add-WindowsFeature –IncludeAllSubFeature –IncludeManagementTools from Windows PowerShell. Once the installation completed, I launched IIS Manager so that I could bind an SSL certificate to the Default Web Site.

Once this was done, I opened Internet Explorer. I then pressed the F12 key to open the F12 Developer Tools so I could watch the network traffic. In the below screenshot, you can see the icon for Network. Click that icon and then click the Green start arrow. This will allow you to see the protocol that is being used between the client and the server.



Now that I had everything setup and ready to go, I navigated to https://localhost. The default IIS page is loaded over TLS and the network trace shows the protocol is HTTP2.



This is a quick way to verify that HTTP/2 is the negotiated protocol between the client and the server.

If you are interested in following the progress of the development of this protocol, here is a list of URLs that provide additional information and testing capabilities.

Terri is a Microsoft MVP (ASP .NET/IIS), an MCSA: Windows Server 2012, and a Cloud Administrator at OrcsWeb, a hosted server company providing managed hosting solutions

Why Upgrade to PowerShell 4.0

If you have browsed my blog site, you see that I occasionally like to do a little PS scripting. It is fun to challenge yourself to learn other things. Over on the Hey, Scripting Guy! Blog, they are doing a ‘Why should I upgrade to PowerShell 4.0? blog series. Today, my guest post is the featured post in the series. Hop on over and check it out.

Terri is a Microsoft MVP (ASP .NET/IIS), an MCSA: Windows Server 2012, and a Cloud Administrator at OrcsWeb, a hosted server company providing managed hosting solutions

Blog Migration

With the impending shutdown of Cytanium, the time had come for me to migrate my site to a new host. I decided to check out the SherWeb offerings based on the discount they are providing for Cytanium customers. Since I use WordPress as my blogging application, my new host had to support php and MySQL.

After looking at the plans offered by SherWeb, I decided to go with Linux Expert hosting. To save you one contact with support, be sure to mention in the order that you are going to be using WordPress and need php safe mode set to Off. There were a few contributing factors to this decision. The Starter Hosting options (for both Windows and Linux hosting) do not include MySQL database support and you can not upgrade to include this support. The Windows Expert hosting plan supports MySQL and php as an optional add-on product but not within the base cost of the hosting package. Honestly, this just placed SherWeb out of what I was willing to pay for my hosting solution. Luckily, WordPress is a php/MySQL application so the underlying web server has less impact on a migration than other web applications may have.

I started working on my migration. There are a few things to be aware of before beginning. The installation location of the WordPress files on your existing host is important to know. If it is installed in a folder rather than the root, you will have to account for that folder structure when you migrate your site to the new host. Also, if your domain will be changing, you will also need to make those changes in the database for migration. Here is the guide that I followed to complete the migration over to SherWeb. A few notes, I did move my site to the root of my hosting before starting the migration. This was for ease of migration only since I do not have any other application that I am hosting.

I used the free BackWPup plugin to complete the migration. I enabled backing up everything. Once the backup was completed, I copied the zip file to my local hard drive and unzipped it to be ready to ftp my data up to SherWeb once I was ready for that step.

I logged into my Control Panel at SherWeb and installed WordPress with the click of a button.



This was the easiest way for me to configure my database name and user and ensure that all rights were assigned correctly. I used the same db name, user, and password as my previous host so I would not have to manually update any configuration files. Once the the install was completed, the fun part started.

I used FTP to upload my web files into the root of my hosting plan. SherWeb provides phpMyAdmin for administering your MySQL databases. From the interface, I was able to import my existing data into the new database.

I was able to preview my site and ensure functionality before updating DNS to point to the new location. Today, my blog is running on our parent company’s shared platform. All in all, it was a easy migration. Hopefully this information will make your migration from Cytanium over to SherWeb painless as well.

Terri is a Microsoft MVP (ASP .NET/IIS), an MCSA: Windows Server 2012, and a Cloud Administrator at OrcsWeb, a hosted server company providing managed hosting solutions

Group Membership and PowerShell

Recently I was tasked with writing a PowerShell script that would gather both local and AD users/groups from Local Groups and return the total number of users. This was needed for accurate reporting of SPLA licensing for Remote Desktop Services and Office implementations. I had blogged previously about listing group membership from AD but this is taking the process a step further. I originally started out writing a script that would run on each machine, meaning locally on that machine.  What really needed to happen, was to run the script from the administrative tools server,  remotely connecting to each member server to gather the users from the local server groups and create a server specific file for each. The administrative tools server then parses those files for AD groups and adds those users to the appropriate server file. Once all users have been gathered, the final step is to count the rows in the CSV file and write it to the file.

The two scripts are included below. There is only one domain involved where this script is run.  I needed to get all local and AD users and groups that are in the Administrators, Power Users, and Remote Desktop Users groups for the listed computers. That process is handled by the Get-UsersRemote script.  The last line of the Get-UsersRemote calls the Get-ADGroupInfo script that runs locally on the administration tools server to complete the gathering of the AD group data. The ADUserList is updated and the final step is to add the count as the last line of each respective file.


#    Written by Terri Donahue
#    This script gathers local group members retrieved from local computer groups remotely using the Invoke-Command
#    with a computername parameter
#    You can add any other computers to the $computers array

#array of computers
$computers = @(“computer1″,”computer2”)

Foreach ($computer in $computers) {

#Runs the script block on the remote computer
Invoke-Command -ComputerName $computer -scriptblock {

#Creates new files locally on the machine where the script is running
$UserList = New-Item -Type file -Force “c:adminGet-GroupMembershipUserList.csv”
$ADUserList = New-Item -Type file -Force “c:adminGet-GroupMembershipADUserList.csv”
“Users” | Out-File $UserList -Encoding ASCII

#List of groups to gather members from. New Groups can be added to the array as needed
#The members of the group are written to the UserList.csv file
#on the machine where the command is running
$groupnames = @(“administrators”,”remote desktop users”,”power users”)
foreach ($group in $groupnames) {
$members = net localgroup $group |
where {$_ -AND $_ -notmatch “command completed successfully”} |
select -skip 4
$members | Out-File $UserList -Encoding ASCII -Append #writes retrieved group membership to UserList file

#This section writes all local users (non-domain users) to the ADUserList file
#which is the master list for the audit
if ($members -notlike “domain*”){ #replace domain with your domain designation
$member.Name | Out-File $ADUserList -Encoding ASCII -Append
& C:adminGet-GroupMembershipGet-ADGroupInfo.ps1


#    Written by Terri Donahue
#    8/13/2014
#    This script is called by the Get-User.ps1 script to gather and count AD group members retrieved from local computer groups
#    You can add any other needed computers to the $computers array

#Import AD Module
Import-Module ActiveDirectory

#change to the AD provider
cd AD:

#List of computers for which to gather group data
$computers = @(“computer1″,”computer2”)

foreach ($computer in $computers) {
$UserList = “c:adminGet-GroupMembership” + $computer + “_UserList.csv”
$ADUserList = “c:adminGet-GroupMembership” + $computer + “_ADUserList.csv”
New-PSDrive -Name S -Root \$computerc$ -PSProvider FileSystem
Move-Item -Path s:adminGet-GroupMembershipUserList.csv -Destination $UserList -Force
Move-Item -Path s:adminGet-GroupMembershipADUserList.csv -Destination $ADUserList -Force
Remove-PSDrive S

Import-Csv $UserList | ForEach-Object {
foreach ($UName in $UserList) {
$UName =$_.Users

#This section excludes the local administrator and any groups with Admins or Users in the name. Any other entries
#are copied over to the ADUserList file for the specific computer and the count is incremented
if (($UName -notlike “Administrator”) -and ($UName -notlike “domain*Admins”) -and ($UName -notlike “domain*Users”)) {
     $UName | Out-File $ADUserList -Encoding ASCII -Append

#This section test to see if the name matches Users or Admins while excluding Domain Admins
#If it matches, it removes the OW from the group name and queries AD to gather the users that
#are members of the group. Each user is copied to the ADUserList file for the specific
#computer. Domain Admins is excluded from the total count as well for SPLA reporting
if ((($UName -like “domain*Users”) -or ($UName -like “domain*Admins”)) -and ($UName -ne “domainDomain Admins”)){
$newUName = $UName.replace(“domain”,””) #strips the domain from the group name for the AD query
$group = Get-ADGroup $newUName

foreach ($member in Get-ADGroupMember $group){
$enabled = Get-ADUser $member | select -ExpandProperty Enabled
if ($enabled -like “True”) { #checks if the user is enabled
“domain” + $member.Name | Out-File $ADUserList -Encoding ASCII -Append #adds the domain information back and writes the user to the file

$a = (Get-Content $ADUserList | Measure-Object)
$count = $a.Count
#Adds the count to the end of the ADUserList file for the specific computer
“User Count = ” +$count | Out-File $ADUserList -Encoding ASCII -Append

Disclaimer: I am not a PowerShell guru but do try my hand occasionally at automating recurring tasks. This script is provided as a guide and may need tweaking for your specific environment. Test before running in production.

Terri is a Microsoft MVP (ASP .NET/IIS), an MCSA: Windows Server 2012, and a Cloud Administrator at OrcsWeb, a hosted server company providing managed hosting solutions

Microsoft MVP Renewal

Last year on July 1st, I was anxiously waiting to hear if I had been awarded my first Microsoft MVP award for ASP.Net/IIS. Fast forward a year, and here I was waiting again to see if the ‘Congratulations 2014 Microsoft MVP!’ email was received. The MVP Award is for the previous year of community work in which you participated. For me, this included providing assistance via, actively working with the Center for Internet Security on IIS related security benchmarks, doing my first speaking engagement for the Dallas User Group (thanks for the invitation Toi Wright – we’ll have to do it again), technical reviewer for a Microsoft IIS Administration training class, and blogging on my personal blog site and my company’s blog sites. I have been fairly active in the community but also know people that have been nominated that did not receive the award. I am pleased to announce that I have again received the award.


Once again, thank you Microsoft for the Award and I look forward to the upcoming year.

Terri is a Microsoft MVP (ASP .NET/IIS), an MCSA: Windows Server 2012, and a Support Specialist at OrcsWeb, a hosted server company providing managed hosting solutions

IIS8 Security features

I recently wrote two blog posts for around new IIS8 security features. The first was about Dynamic IP Restrictions and how they can be implemented to provide an additional layer of security for your site against brute force DDoS type attacks. The second was about the new FTP Login restrictions that can be implemented to actively block brute force FTP attacks.

Both of these new features in IIS can be easily implemented and configured to provide another layer for security to your websites and applications.

Terri is a Microsoft MVP (ASP .NET/IIS), an MCSA: Windows Server 2012, and a Support Specialist at OrcsWeb, a hosted server company providing managed hosting solutions

WPI PHP Manager installation failure

I have noticed a few questions on related to being unable to install PHP Manager using the Web Platform Installer. The WPI logs are usually pretty good at showing why an install failed. In this instance, the following was listed:

ERROR : [01/24/2014 09:37:49:386] [VsdLaunchConditions ]: Custom Action failed with code: ‘1603’
INFO : [01/24/2014 09:37:49:386] [VsdLaunchConditions ]: Custom Action completed with return code: ‘1603’

This return code points to an issue with the MSI installer and I was unable to locate anything even remotely associated with what was causing the failure after multiple web searches. In the same forums thread, another user mentioned performing a manual install of PHP Manager on the same server and received a much more descriptive and helpful error. The install failed stating that .Net Framework v2.0 is required.

The .Net framework versions are not enabled by default on the newer server operating systems. To remedy this issue, use the Add Roles and Features option within Server Manager. Add the .NET Framework 3.5 Features (and any required dependencies). Once you have completed this install, you will be able to successfully install PHP Manager using WPI.

Terri is a Microsoft MVP (ASP .NET/IIS), an MCSA: Windows Server 2012, and a Support Specialist at OrcsWeb, a hosted server company providing managed hosting solutions