Generic filters
Exact matches only
Filter by Custom Post Type

Making Awesome Dashboards from Windows Performance Counters

Having an understanding of your systems performance is a crucial part of running IT infrastructure.

If a user comes to us and says "why is my application running slowly?", where do we start? Is it their machine? Is it the database server? Is it the file server?

The first thing we usually do is open up perfmon.exe and take a look at some performance counters. You then see the CPU on the database server is 100% and think  "was the CPU always at 100% or did this issue just start today? Was it something I changed? If only I could see what was happening at this time yesterday when the application was running fine!". It might take you a few hours to find the performance issue on your infrastructure, and you are probably going to need to open up perfmon.exe on a couple of other systems. There is a better way!

What if you could turn your Windows performance counters into dashboards that look like this? How much time would you save?

Full Hyper-V Dashboard

Using a combination of the open source tools InfluxDB to store the performance counter data, Grafana to graph the data and the Telegraf agent to collect Windows performance counters, you will be a master of your metrics in no time!

Read the detailed walk through over at



Get Last Reboot or Computer Up Time With PowerShell

Hey everyone, hope you had a great 2015 and I am back with I hope to be weekly updates for everyone at I wrote up a quick article on how to retrieve the last reboot time or the current up time for any local or remote computer. I also include a function that can be used to query remote computers as well. There may be a situation where you want to determine whether you take action depending on the last reboot time, or you may simply want it to be displayed for debugging or logging purposes.

You can check out the full article over on


Testing PowerShell Direct with Windows Server 2016 TP3 Hyper-V

Hey there! I  thought we could test PowerShell Direct together today. Here's the elevator pitch: In Windows Server 2016 and Windows 10, we can send PowerShell commands from the Hyper-V host directly to its corresponding virtual machines (VMs), even in the absence of guest VM networking. Yeah, that's cool, isn't it?

What's just as impressive is that PowerShell Direct works even if PowerShell remoting is disabled on the guest VM! PowerShell Direct also circumvents Windows Firewall. Note that PowerShell Direct requires that commands are sent only from a Hyper-V host to its local VMs.

Also, PowerShell Direct is supported at this point only by Windows Server 2016 TP3 and Windows 10. That means a Windows Server 2016 TP3 Hyper-V host cannot leverage PowerShell Direct against, say, Windows Server 2012 R2 virtual machines (give the Hyper-V, PowerShell, and Windows Server teams time; I'm sure this will be supported in the future).

The secret sauce behind PowerShell Direct is PowerShell Remoting Protocol (MS-PSRP), which used to be called just plain ol' garden variety "PowerShell remoting."

The Lab Setup

In my test lab, I started with a domain controller and Hyper-V host (yeah, I'm combining server roles--what of it?) named That server's running Windows Server 2016 Technical Preview 3.

In Hyper-V I created a single virtual switch named Internal that is connected to the host/guest network. Of course, we don't care about the switch fabric because we're going to use PowerShell Direct.

Next, I built a Windows Server 2016 TP3-based guest VM named server1 and disabled the network adapter as you can see in the following screenshot. No smoke and mirrors here!

Our lab is set up and ready to test PowerShell Direct.

Our lab is set up and ready to test PowerShell Direct.

As a final "sanity check" to ensure the guest VM is as theoretically inaccessible as possible, I blocked access to all remote access session configurations and disabled the Windows Remote Management (WinRM) service by running the following command from within the guest (thanks to PowerShell MVP Aleksandar Nikolić for clarification on this point):

Disable-PSRemoting -Force

Get-Service -Name WinRM | Stop-Service -Force | Set-Service -StartupType Disabled

Okay. Let's move onto the next phase of our experiment.

Sending Commands to the Guest VM

Let's obtain the name and globally unique identifier (GUID) of our Windows Server 2016 VM (you'll see why in just a moment):

Get-VM | Select-Object -Property Name, VMid

Name        VMId
----        ----
server1     31d787fe-02cd-4363-b50b-16bc8243fc77

PowerShell Direct makes itself manifest by means of two new parameters:

  • VMname
  • VMGuid

Handy, eh? The following two cmdlets support the -VMname and -VMGuid parameters as of this writing in October 2016:

Time to test! Let's start a remote session with the server1 guest VM by specifying its GUID. Note that you will need:

  • Hyper-V administrative privileges on the host
  • Local administrative privileges on the guest
$cred = Get-Credential
Enter-PSSession -VMGuid 31d787fe-02cd-4363-b50b-16bc8243fc77 -Credential $cred

[server1]: PS C:\Users\Administrator\Documents>

We'll finish by using Invoke-Command to send ad-hoc PowerShell pipelines and entire scripts from host to guest:

Invoke-Command -VMName 'server1' -Credential $cred -ScriptBlock { Get-Service | Where-Object {$_.Status -eq 'Stopped'} }

Invoke-Command -VMName 'server1' -FilePath 'D:\scripts\setup-ip.ps1' -Credential $cred


Convenience is the primary advantage that PowerShell Direct brings to us Hyper-V administrators. We can connect to and fully administer our guest virtual machines regardless of their networking, firewall, or WS-Man state. Thanks for reading, and more power to the shell!

Delete Specific E-Mail or E-Mails From All Exchange Mailboxes

Well this is week number two in my quest to post an article once a week and I am back with a common request for Exchange administrators. There are a lot of scenarios that bring up a need to remove an e-mail or e-mails from all mailboxes in your environment. Perhaps there was a disgruntled employee, a virus outbreak, or a reply all to the whole company. We all know that the "Retract" button is best effort (yes I still miss GroupWise for that purpose).

As always we can turn to PowerShell for our scripting needs. The Search-Mailbox command is your best friend for these scenarios. With a simple Get-Mailbox | Search-Mailbox you can take control of all your mailboxes. Be extremely cautious when executing, with great power comes great responsibility. For a full run down on how to accomplish this head on over to I look forward to seeing everyone again next week!

Find Location of Locked Out Accounts

I'm Locked Out, Help!

If you've been a sys admin for more than a week you've probably heard this..."I'm locked-out, help!".  Normally the user has made their way to your cube and is impatiently tapping their foot waiting for you to magically solve there problem.  So you find their account, reset their password and everything is right with the world...Or is it?  Two minutes later they show up again because their account was locked-out before they even got back to their desk.  Now what do you do?

There are several ways to go about finding this information, some MUCH better than others.  Since we are all PowerShell people (or at least stayed at a Holiday Inn Express) that will be our method of choice.  If you want to read more click on the link below, but if you just want to get to the script you can follow this link to my downloads page.

As always make sure once you've checked us out over at to head back here to read more awesome PowerShell posts on

Find Location of Locked Out Accounts

If you have some comments, questions or advice I'm happy to hear it.  Thanks for reading and I hope everyone likes the article.



Tonight on the PowerScripting Podcast: Rick Claus and Symon Perriman talk about Build a Windows Server and System Center Environment with the PowerShell Deployment Toolkit

Join us tonight at 9:30 PM as Rick Claus and Symon Perriman talk about how to Build a Windows Server and System Center Environment with the PowerShell Deployment Toolkit.



Script for Setting Up and Demoing a DSC Pull Server

DSC Setup and Demo Scripts

I recently set up a virtual machine to use for Desired State Configuration (DSC) demos. I wanted to make the demo-ing fairly brainless, as DSC requires a number of setup steps to get a pull server running. So I took some demo scripts Microsoft offered from TechEd 2013, updated them to work with Windows Server 2012 R2 RTM, and thought I'd offer them to you.

SetupDSC.ps1 is the main script. Now, because I didn't want to use good ol' Start-Demo, there's a who crapload of kinda ugly Write-Debug statements. That way I can get an "about to do ____" message and then have the script pause before doing it. Lets me explain to the class what's about to happen. You can remove all that crud if you like.

InstallPullServerConfig.ps1 and PSWSIISEndpoint.psm1 are the updated Microsoft scripts. SetupDSC.ps1 calls these. They're intended to run locally; you'll need to be on the machine you want to make into a pull server, and it needs to be Windows Server 2012 R2 (the DSC pull server role is part of the OS, not part of Windows Management Framework v4). Setup takes a few minutes, and will install IIS. This sets up an HTTP pull server.

SampleConfig.ps1 is a sample DSC configuration, targeted to a computer named MEMBER2. It just specifies that the Windows Server Backup feature be installed. SetupDSC.ps1 actually runs this, which produces a MOF. SetupDSC.ps1 also copies the MOF to the DSC pull server configuration directory.

SampleSetPullMode.ps1 also gets run by SetupDSC.ps1. This contains a DSC Local Configuration Manager configuration, targeted to MEMBER2, that turns on pull mode and directs MEMBER2 to pull the previously-created configuration. I think I have it refreshing every 5 minutes, which is totally unrealistic for production. Again, this was made for class demos, but you can adjust the time or leave it off to default to 30min. Running this script creates the MOF and pushes it to MEMBER2. That, in turn, causes MEMBER2 to start pulling the sample config, which causes Windows Server Backup to be installed.

SetupDSC.ps1 has some additional code to show that Windows Server Backup isn't installed, and then is installed (after you give the pull time to occur).

Anyway, might need some tweaking to use in production, but hopefully it'll give you a snapshot of the whole DSC process. Much thanks to James Dawson's article on DSC, which gave me a couple of the tweaks I needed to get all this working on RTM code.


Notes for Event 6

Jun 7, 2013

When I read the instructions for event 6, I thought that here's a tough one. A lot of competitors won't have access to a test environment with Windows Server 2012 and Virtual Machines that they can actually work with. So, I expected that many of the entries wouldn't get tested and intended to forgive minor errors that would have shown up in testing.

Well, there was one thing that really surprised me. The instructions were quite clear about minimizing "Are You Sure" queries to the user, but you can count on one hand the number of entries that included -Confirm:$false. This is just an example of why it's so important to read the problem statement very carefully and extract the solution requirements. Then, after creating the solution, go back and verify that the requirements have all been met. Many of the entries called out this requirement in the comments, but then didn't account for it in the script.

I had mentioned in a previous blog entry that, particularly in the advanced entries, the author was working too hard. Sometimes this means putting more emphasis on "completeness" than in solving the problem. Here's an example of a wasted effort. A few entries used the [ValidateNotNullOrEmpty()] test for a possible alternate to the default value for "Server".  Because there is a default value for the parameter, it won't be null or empty making this test unnecessary. Here, give this a try:

function Test-NullOrEmpty { [CmdletBinding()] Param ( [ValidateNotNullOrEmpty()] $Name = "Server" ) "Got $Name" } Test-NullOrEmpty

Note that calling the function without a named parameter just assigns the default value. In order to make it fail you have to deliberately call the function with an empty value (Test-NullOrEmpty -Name), which is not going to happen in the real world.

I know that these are just nit-picking -- and if these are examples of the nits in the Event 6 entries, then CONGRATULATIONS!! y'all did a mighty fine job of solving the problem. Calling out these issues is just intended as a learning opportunity. There are lots and lots of correct ways to write PowerShell solutions, it's just that some are more efficient or take less typing than others. And learning about them is one of the important results of participating in the games.

Thanks to all of you for your efforts!

Microsoft announces PowerShell v4, DSC

Jun 4, 2013

Yesterday at TechEd North America, Jeffrey Snover and Kenneth Hansen began describing features to be delivered with PowerShell v4 in Windows Server 2012 R2 (the company has not yet announced availability dates for either).

In particular, a new feature called Desired State Configuration promises to become the foundation for some pretty serious expansion. Essentially, DSC lets administrators write a declarative "script" that describes what a computer should look like. PowerShell takes that, matches the declarative components with underlying modules, and ensures that the computer does, in fact, look like that. Nearly anything can be checked and controlled: roles, features, files, registry keys - anything, in fact, that a PowerShell module can do.

The architecture includes the notion of centrally stored declarative scripts, and the ability to dynamically deploy supporting modules on an as-needed basis to computers that are checking themselves. A System Center Virtual Machine Manager demonstration utilized the feature to dynamically spin up brand-new VM instances and have them immediately reconfigure to their desired state.

At first glance, it's easy to see "more Microsoft stuff" in this feature. After all, the company has previous given us Dynamic Systems Management (DSM), various universal "configuration languages," and even System Center Configuration Manager's somewhat primitive configuration auditing feature. But keep in mind that DSC will be a core part of the OS. That means product teams and ISVs can rely on it being there, with no other dependencies to worry about. DSC is also built around DMTF standards - like the MOF format - making it natively suitable for cross-platform management. A demo from Opscode using their Chef product showed clever use of the new DSC feature.

Hansen also mentioned that PowerShell modules will be deployable through DSC as ZIP files, helping make them more self-contained (not entirely unlike PECL packages in the Unix world).

There has been no announcement as yet on how far back PowerShell v4 will be made available, nor whether or not DSC is a PowerShell feature or a Windows Server 2012 R2 feature. If it is indeed a PowerShell feature (which I suspect it is), then it'll be available on any system with v4 installed. That will hopefully include at least Windows 7, Windows Server 2008 R2, and later.

Use the AD DS Module to Find Computers with PowerShell

Apr 22, 2013

Summary: The Scripting Wife learns about querying Active Directory Domain Services with Windows PowerShell in prep for the 2013 Scripting Games.

Microsoft Scripting Guy, Ed Wilson, is here. Well yesterday I gave my first presentation (of three) at the PowerShell Summit happening here in Redmond, Washington. I thought my talk went really well, and several tweets I saw seemed to confirm that. I was also able to see some excellent presentations during the say. The Scripting Wife ran the registration desk, and so she was able to see everyone who is out here this week.

I am still on Charlotte time, and therefore am waking up at oh dark thirty each day. Surprisingly, the Scripting Wife has also been making early morning appearances for breakfast as well. Anyway, I am in the lobby sipping a cup of English Breakfast Tea (I did not bring any lemon grass or cinnamon sticks with me) and so it not my favorite cup of tea ever – but it is ok. It is strong, and helps to breakdown the croissants.

My eyes are closed as I visualize my two presentations I am making today at the PowerShell Summit. I open my eyes, and there she is – the Scripting Wife.

“If you are that sleepy, you need to go back upstairs and get some rest,” she began.

“Not sleepy, I am thinking about my presentations today,” I said.

“Oh that. Then you are not really doing anything, and so you can help me,” she said.

“What do you need,” I asked.

“I need to know how to query Active Directory,” she said.

“Say what,” I shockingly exclaimed. “Why do you need to query AD?”

“Well I think it is going to be in the 2013 Scripting Games, and so I figure I need to know how to query AD,” she said with emphasis.

“Well all right,” I said.

Use the ActiveDirectory module to query AD

“First let me fire up a Windows Server 2012 domain controller on my Windows 8 Hyper-V,” I said.

“I will take your word for it,” she said will as little interest as possible. “Just let me know when you are ready.”

I logged onto the Windows Server 2012 domain controller, and opened the Windows PowerShell console.

“Ok. It is up,” I said.

“So what do I need to do,” she asked.

“Well to get a listing of all computers in AD use the Get-ADComputer cmdlet. Specify a wildcard for the filter,” I instructed.

The Scripting Wife slid the laptop over to her, and typed the following:


When she typed –f<tab> there was a slight pause, and the Windows PowerShell progress bar appeared as it imported the ActiveDirectory module. After that, the command proceeded quickly. The command appears here:

Get-ADComputer -Filter *

A command and the first computer from the output appears here:

PS C:\> Get-ADComputer -Filter *

DistinguishedName : CN=DC1,OU=Domain Controllers,DC=nwtraders,DC=msft

DNSHostName : dc1.nwtraders.msft

Enabled : True

Name : DC1

ObjectClass : computer

ObjectGUID : e1b57333-7155-4026-949d-82c35400a850

SamAccountName : DC1$

SID : S-1-5-21-1844339390-1396565537-2470583527-1001

UserPrincipalName :

Requesting a specific attribute

“Well that was painless. But what if I need to know the version of the operating system. How do I get that information? It does not seem to be in the output,” she asked.

“Well that is a very good observation. There are many more properties for each object in Active Directory Domain Services than are returned by a basic query. The reason for returning a subset of the attributes is for performance reasons. To request a specific property such as operatingsystem add the properties parameter. Why don’t you go ahead and try that,” I suggested.

The Scripting Wife thought for about 30 seconds and then she used the up arrow to retrieve her previous command. Next she added the –properties parameter and she added the operatingsystem attribute. This is what she typed:

<up arrow><space>-p<tab><space>operatingsystem<enter>

The command she created appears here.

Get-ADComputer -Filter * -Properties operatingsystem

The command and first output appears here.

PS C:\> Get-ADComputer -Filter * -Properties operatingsystem

DistinguishedName : CN=DC1,OU=Domain Controllers,DC=nwtraders,DC=msft

DNSHostName : dc1.nwtraders.msft

Enabled : True

Name : DC1

ObjectClass : computer

ObjectGUID : e1b57333-7155-4026-949d-82c35400a850

OperatingSystem : Windows Server 2012 Standard

SamAccountName : DC1$

SID : S-1-5-21-1844339390-1396565537-2470583527-1001

UserPrincipalName :

Using wildcards for properties

“That is pretty cool, but I do not like the output – it is rather crowded. I only want the name of the server and the name of the operating system. Can I get that,” she asked.

“But of course you can,” I said in my best Bela Lugosi imitation.

Ignoring the humorous voice, she plowed on, “So are you going to help me?”

“Well you cannot use a wildcard in the properties parameter, but when you use the Sort-Object cmdlet and the select-Object cmdlet you can use wildcards. So retrieve your previous command and pipeline it to Sort-Object and to Select-Object,” I said.

She thought for a minute, and this is what she typed:

<up arrow><space>|<space>sort<space>oper*<space>|<space>select<space>name,oper*<enter>

The command she created appears here:

Get-ADComputer -Filter * -Properties operatingsystem | sort oper* | select name, oper*

The command and the output appears here:

PS C:\> Get-ADComputer -Filter * -Properties operatingsystem | sort oper* | select name, oper*

name OperatingSystem

---- ---------------

C7 Windows 7 Ultimate

C1 Windows 8 Enterprise

C2 Windows 8 Enterprise

SQL1 Windows Server 2012 Datacenter

DC1 Windows Server 2012 Standard

“That is pretty cool. Thanks. I am outta here, I think I just saw some PowerShell Summit people come in,” she said. And with that she was gone. I figured I would see her again when I got to building 40.

Join us tomorrow as the Scripting Wife continues studying for the 2013 Scripting Games.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

Skip to toolbar