Category Archives: WMI

The CIM-ple way with PowerShell and Event Logs

I’m always on the lookout for new ways to do things. Often I’m trying to find a way to create something that is easy to use without requiring a lot of PowerShell scripting.  I also like using the final result as teaching aids so even if you don’t need the end product, I hope you’ll pick up a trick or two that you can use in your own scripting projects. The task I had in mind today is a better way to get event log information. Not the events themselves, but rather the event log file. How many entries are in it? How big is it? How much of the configured log is being used? Here’s what I came up with.

Continue reading The CIM-ple way with PowerShell and Event Logs

Memory Reporting with PowerShell

I’ve started a new project and I’m hoping a few of you will give it a spin and let me know how it works for you. I’ve created a PowerShell module called MemoryTools that uses a few WMI classes and performance counters to provide insight into memory utilization and configuration on your servers. The module has several commands including one that skips the pipeline (exception to the rule!) and uses Write-Host to display memory status in living color.

show-memoryusage

The project is up on GitHub at https://github.com/jdhitsolutions/MemoryTools if you’d like to give it a try. The Readme file should give you a overview of what to expect. Use GitHub to report any bugs or feature requests. I know I still need to add command help.

The module should work on any computer running v3 or later. Note that the Get-PhysicalMemory command, which queries the Win32_PhysicalMemory class, may not show results for some properties. There are a few new class properties that require Windows Server 2016 but I decided to include them anyway.

I look forward to hearing about your experiences.

The Power of Custom Properties

The other day fellow PowerShell MVP Adam Bertram published an article about using custom properties with Select-Object. It is a good article in that it gets you thinking about PowerShell in terms of objects and not simple text. But I want to take Adam’s article as a jumping off point and take his ideas a bit further. I’m going to use Adam’s same example as a learning tool. Don’t get distracted by other ways to get the same information. The process and techniques are what matter here.

Whenever I’m working with PowerShell, I’m always thinking about how I can use this at scale.  How can I get this same information for 10 or 100 servers? And of course,  at this point I need to make sure I include a computername in the results.  First, I’ll try something with a single computer.

image

Close but not quite. Get-CimInstance is writing multiple objects to the pipeline.  The server in question has 2  8GB sticks of memory which is what you see in the output. I need something more along Adam’s original idea to that this becomes 16GB.

What I really want is the Sum property from Measure-Object and to that I need to add a Computername property. I’ll turn things around a bit.

image

This works because I’m using the common PipelineVariable parameter introduced in PowerShell 4.  What happens is that the pipeline output from Get-CimInstance is stored in a variable, pv, which I can access later in the expression. In my case I’m defining a new property for the computername using $pv and adding it to the selected output from Measure-Object.

However, if I try this for multiple computer names, I don’t get the expected result.

image

That’s because I’m adding up the physical memory instances from all servers, which isn’t really what I want. Instead, this is a situation where I have to process each computer individually.

image

One thing to be careful of when using the ForEach enumerator is that you can’t pipe the output to another cmdlet like Export-CSV, unless you explicitly save the results to a variable.

Then you can pipe $data to other cmdlets. You can use ForEach-Object although it might be little harder to follow.

But this makes it easier if you need to pipe the output to something else.

image

To wrap this up let’s go all out and define a few more custom properties.

image

Even though I’m selecting a few properties from the output of Measure-Object, I’m defining several others which are calculated on the fly. There is so much you can do with this technique,  but if I lost you anywhere please let me know.

What Are You?

Here’s a quick way to tell whether a given machine is real or not: check the Win32_Baseboard class. You can use either Get-WmiObject or Get-CimInstance. Notice the results from a few physical machines.

Now see the result when querying a Hyper-V virtual machine:

I don’t have any VMware available so I don’t know what kind of result that would show. I also haven’t done extensive testing with items like a Microsoft Surface. I threw together this simple function you could use.

Have fun.

Creating Your Own PowerShell Command

atomic powershellLast week, I posted a PowerShell function that you could use as an accelerator to create your own PowerShell tools. My tool takes command metadata from an existing PowerShell cmdlet and gives you the structure to create your own tool wrapped around what is in essence a proxy function.

The advantage, besides saving a lot of typing, is that by using a proxy function you can take advantage of the wrapped cmdlet’s features and parameters. But perhaps it would help to see an example. With the Get-CommandMetadata function loaded into the PowerShell ISE, I run this command:

Instead of using CDXML, or writing my own function to call Get-Cimstance, I’m going to create a proxy to Get-Ciminstance that designed to retrieve operating system information. Here’s what I start with.

As with any PowerShell scripting project, you have to think about who will run your command and what expectations they might have. In my example, I simply want to be able to specify a computer name or a CIM Session and retrieve information from the Win32_Operatingsystem class. So to begin with I can delete all the parameter definitions except Computername and CIMSession. I’ll also keep the OperationTimeOut parameter just in case. As you can see in the code sample, Get-CimInstance also has a number of parameter sets. Again, I can delete references to ones I’m not going to use.

Here’s my revised parameter definition.

One change I made was to give the computername a default value for the local computer. I amd doing this so that the PSComputername property will always have a value.

But you may be wondering, what about the classname? This is where the fun begins. I am going to hard-code other parameters into the function.

When the wrapped command is executed it will use these values which is what I want. At this point, I could save the function and run it. But the output would be the same as if I had run Get-Ciminstance and I have a specific output in mind. Here’s how.

First, copy and paste a new version of the $scriptCmd line. Comment out the original line.

What I need to do is create my own script command, which must be a single pipelined expression.

I still want the wrapped Get-Ciminstance command to run but then I’m going to pipe the results to Select-Object and specify some custom properties. That is the extent of my major changes, although I also will add some additional Write-Verbose lines for tracing and troubleshooting. After updating comment based help, here’s my final command.

Now to test it out:

I can specify a computername:

Or use CIMSessions.

osreport

I didn’t have to write any code to use the CIMSessions. I let the wrapped cmdlet handle everything for me. The end result is that I now have a very complete PowerShell tool that didn’t take much time to create. I probably spent more time getting the comment-based help written than anything.

Hopefully this gives you an idea of how to take your PowerShell toolmaking to the next level.