Out with the Windows.old

over-the-hill Over the last few days I’ve started the process of upgrading my test virtual machines to Windows Server 2012 R2, or in the case of my mini Hyper-V server, to the final bits of Windows Hyper-V Server 2012 R2. In many cases I had been running the preview bits. I know I probably should have done clean installs, but I decided to upgrade in-place. The upgrade itself is easy and quick. However, the upgrade comes with a price.

The upgrade process will leave a folder called Windows.old which essentially contains files from the previous installation. As you might expect this file can take up a lot of space. Unfortunately, you can’t simply delete the folder as many of the files and folders have special permissions and owners. If you search, you’ll find a number of articles that explain the proper way to remove this folder is to use the disk clean up wizard or the Cleanmgr.exe command line tool. But some of my systems are running Server Core which means no GUI for the clean up wizard and no command line tool. Eventually I came across this solution.

His solution requires junction.exe from the Sysinternals website. His solution was also a mix of PowerShell and CMD commands. I decided this could all be done with PowerShell, plus I could take advantage of ShouldProcess so the script supports -WhatIf.

You will need to make sure junction.exe is somewhere in your path. I put a copy C:\Windows. I’ve used this a few times and it works pretty well. You will probably get prompted to continue and it will take a few minutes to run. But it gets the job done when other options are not available. I hope you’ll let me know how it works for you, but please test in a virtual environment where you can roll back and/or make sure you have a verified backup.

Runspaces, Remoting and Workflow, Oh My!

talkbubbleThe other day on Twitter I saw a message about new script in the Microsoft Script Center on getting remote event logs with WMI. So I took a look at the script. If you take a minute to look at the script you’ll quickly realize this is not a script for beginners. My initial thought was “Why?”. We already have cmdlets in PowerShell for querying event logs on remote computers. I realize the script was trying to avoid some of the issues we run into with WMI and I can’t question the effectiveness of his function. It works and with out a doubt using runspaces like this is faster than cmdlets.

My concern when I see scripts like this is that someone new to PowerShell will see it and run to the hills thinking they’ll never be able to use PowerShell and that is definitely not the case. So I decided to see what I could come up with that used a more IT Pro friendly cmdlet-based approach. I wanted to write something that most of you could have come up with.

My first attempt is a function that uses Invoke-Command to run the Get-Eventlog cmdlets in a remote session. In the function I define a scriptblock that gets all the event logs with records, and then gets all non-information or SuccessAudit events from those logs that have happended since midnight yesterday. My function supports credentials and takes advantage of a few other features from Invoke-Command.

The function works and took a about 1 1/2 min to query 8 machines in my virtual test environment. There is definitely some overhead when using Invoke-Command, but the trade off is a script that is a little easier to develop and maintain.

Then I thought, what about a workflow? I’m querying event logs but there’s no reason I can’t query all of them simultaneously. Here’s my workflow that does essentially the same thing as my function.

Interestingly, in my tests the workflow took about the same amount of time to run. But this is a shorter script to develop because all of the features like remoting, credentials and jobs are automatically part of the workflow. There is a potential downside in that all the remote machines must be running PowerShell 3.0. This workflow is also a great example in that workflows aren’t always the answer. There’s nothing really here, other than potentially the use of parallelism, that makes this a better choice than my function.

My last concern with the gallery script, and I don’t know if this would have an effect on its performance, is that all the event logs are rolled up in a property for each computer. This means you have to take some further steps to expand and format the results. My function and workflow, because they rely on Get-Eventlog, are formatted and ready to go.

What I haven’t tried yet, is how this same task can be done with Get-WinEvent or Get-CimInstance. The latter helps avoid some of the issues with WMI and might perform better. If I have time, I’ll get back to you with my results. But in the meantime, what do you think about all of this?

Using runspaces in PowerShell has a place, but definitely requires an advanced skill set and a willingness to accept a tradeoff of a more complicated script to develop and maintain (especially if someone else has to) with improved performance. I can see where using a runspace approach makes sense when you have 1000s of computers. But I might also argue that if that is your environment, you probably have full-blown management suites. Yes, I know there will always be exceptions. But for the majority of you, are you happy writing scripts that use existing cmdlets or do you feel obligated to learn .NET before you can use PowerShell?

I tried this using Get-CIMInstance. Yes, this requires PowerShell 3 remotely (unless you take an extra step to setup a DCOM CIM session) and the use of the WSMan protocol, but this performs suprisingly well and only takes a few lines of PowerShell.

I ran this in my test environment and it took about 30 seconds to return 188 event log entries. Because we’re using WSMAN we avoid some of the issues with RPC and DCOM. So here is a solution, at least in this case, that is as fast as using runspaces but only took a few minutes to write and is easy to follow.

Everything we do as IT Pros is a matter of balancing trade-offs and working within a set of limitations.

Mini Hyper-V Benchmarks

I’ve received a lot of interest in my mini Hyper-V project. I’m still running preview bits of Microsoft Hyper-V Server 2012 R2. Once final bits are released I’ll do a clean re-install. But until then I’ve been using it running about 4 virtual machines without a hiccup. I was getting some questions about benchmarks so I thought I’d post what information I could.

Part of the challenge in using a benchmarking tool is that I’m running Server Core so most tools won’t run. I was able to install Dacris Benchmarks on the server and run some benchmarks. I didn’t bother with the video tests and not all features of the tool work on Server Core. But I was able to gather enough information if you are interested.

Overall, it looks like a pretty good system for what I need.


I hope it’s obvious this isn’t a production-level server for a datacenter. But for testing and lab work it is more than adequate. and personally, the portable form factor was the driving force. Dacris Benchmarks confirms my theory.


Here are the results from some of the advanced tests.
Memory Transfer Rate for Large Blocks

Memory Transfer Rate for Small Blocks

CPU Parallel Scaling

CPU Pi Calculation

I also decided to grab system information with MSINFO32.EXE.


While not a benchmark, some of you may be interested in the nitty-gritty. You can also download a zip file with the complete NFO file.

Finally, if you missed any of the earlier articles on my project here they are:

Part 1: Intro and Specs
Part 2: Hardware Build
Part 3: Setup
Part 4: Operating System

I expect just about anywhere I will be presenting or training I’ll have this with me so please feel free to find me if you want a closer look.

Techmentor Las Vegas 2013 Session Materials

TMVSK4I had a terrific time at Techmentor last week in Las Vegas. I did 2 3-hour sessions. The longer sessions are intended to allow speakers time to go deeper into content and offer more detailed coverage than what you might get at a conference like TechEd. From my informal survey of attendees, many people enjoyed the longer sessions with a few wanting even longer. I expect we’ll see this longer format at the Techmentor conference next year.

Because I had 3 hours I was able to cover a lot of material. One of my sessions was a hands-on-lab with some exercises. As promised I’ve updated my slide decks (primarily for clarity) and assembled all of my PowerShell scripts and demos. While anyone is welcome to download them, unless you were in my session you won’t have the necessary context. For example, most of my presentations were live demonstrations with the slides serving as notes and an agenda. But feel free to download and try it all out.

Much of the content for my sessions are drawn from my books.

Each zip file contains a PDF of my slide deck and all of my PowerShell samples. Put all the samples in the same directory. All samples are provided as learning material and are not intended for immediate production use.

Techmentor Las Vegas 2013 PowerShell Workflows
Techmentor Las Vegas 2013 Automating AD with PowerShell

Mini Hyper-V: Operating System

When we left my project, the new mini server had booted up using Windows Hyper-V Server 2012 R2. This is a server core installation intended to only run Hyper-V, which is perfect for my needs. The server booted up with a temporary name and a DHCP assigned IP address. The next step is configure the server and join it to my test domain.

I could do this all interactively using the sconfig script, but where’s the challenge in that! So I’m going to configure the server from a Windows 8 client with RSAT installed in my target domain. There are ways to configure Hyper-V in workgroup environment but I want to take advantage of domain. It shouldn’t really make any difference but my test domain, Globomantics.local, is running in a Hyper-V environment on my Windows 8 laptop. My mini Hyper-V server will belong to this domain, as will any virtual machines it ends up hosting.

To get started I know the IP address of the new server and credentials for the local administrator account. With this I can use PowerShell remoting, since it is enabled by default in Windows Server 2012. However, on my client, I need to temporarily add the host to the TrustedHosts list. Otherwise, the client won’t trust the server and I won’t be able to connect. In an elevated I’ll run this command.

Using -Force suppresses confirmation prompts. This setting will allow me to connect to any host using an IP address that starts with 172.16. I should now be able to use Invoke-Command or run any configuration workflows. In fact, I’m going to use some basic workflows to set the computer name and IP configuration. First, I’ll verify remote connectivity.

Looks good. Next, I’ll define some PowerShell variables to use with my workflows.

The first workflow I want to run will perform some basic configuration.

Once this workflow is loaded into my session I can run it and configure the new server.

Next, I want to configure the IP configuration. The new server only has a single NIC which simplifies matters a great deal. Here’s the workflow I’m going to use.

To execute, I’ll splat a hashtable of parameters to it.

One caveat here is that when you change the IP address you’ll lose your connection to the remote computer. PowerShell will keep retrying. What I probably should have done was to include some parameters to limit the retry count. Eventually, the command will timeout and I can continue.

Next, I want to rename the computer and join it to the domain.

Again, I’ll splat a hashtable of parameters, this time connecting to the new IP address.

Eventually the computer will reboot and I’ll get a positive result.


Excellent. Now that the server has rebooted it belongs to the domain and I can use the new name to verify a few things.


I used the new server’s FQDN for the CIMSession name as I couldn’t get the NETBIOS name to work. Probably because I didn’t wait long enough for browser stats to get updated. Anyway, it works and I can also verify Hyper-V is working.


The last thing I should do is remove the trusted hosts settings on the client. But because I trust my network and I might need to do this again, I think I’ll leave it for now. But I did it! I now have a Hyper-V server ready for me to use.