PowerShell (Modern) Archives - i Love PowerShell https://ilovepowershell.com/category/powershell-modern/ I came. I saw. I automated. Tue, 02 May 2023 10:19:23 +0000 en-US hourly 1 https://wordpress.org/?v=6.7.1 https://ilovepowershell.com/wp-content/uploads/2020/09/SiteLogo-150x150.png PowerShell (Modern) Archives - i Love PowerShell https://ilovepowershell.com/category/powershell-modern/ 32 32 The Random Password Generator for PowerShell Core 6 and 7 https://ilovepowershell.com/powershell-modern/the-random-password-generator-for-powershell-core-6-and-7/ Fri, 20 Aug 2021 03:56:02 +0000 https://ilovepowershell.com/?p=3114 What works for Windows Powershell, doesn't always work for .NET 5, which is what modern versions of PowerShell like PowerShell 7 use.

Well, thankfully it's pretty easy to write a simple random password generator in PowerShell 7

It follows a simple pattern, and I'll show you how to do it.

The post The Random Password Generator for PowerShell Core 6 and 7 appeared first on i Love PowerShell.

]]>
I’ve mentioned previously about How to Create a Random Password using the .NET Framework.

That works for Windows Powershell, but it doesn’t work for .NET 5, which is what modern versions of PowerShell use.

So what can you do?

Well, thankfully it’s pretty easy to write a simple random password generator in PowerShell 7. It follows a simple pattern, and I’ll show you how to do it.

  • Make a list of characters
  • Decide how long the password is going to be
  • Use a For-Loop to add characters to an array

Make your list of characters

You have a few options here. You could do something like this:

# Take a string of acceptable characters and change it into an array of individual characters
 [char[]]"abcdefABCDEF1234567890"

You could also use the RANGE selector (..) to help you

'a'..'z'

If you want to use multiple RANGES, you can do that too. Ranges can be added together to form a bigger list:

'a'..'z' + 'A'..'Z' + '0'..'9'

I actually wanted to include some special characters in my list, but I didn’t want to have any special characters that might cause problems when used in a SQL Server password.

Showing the list of ASCII characters

There are 255 ASCII characters. Some of them (like ♣ or ?) would not be useful to me for a password.

But a quick list like this would help me to find the ranges that I want to include for my password generator.

0..255 | Foreach-Object {"$_ : $([char]$_)"}
#In English, this is:
#  Give me a list of numbers from 0 to 255.
#  Then for each of those numbers,  write this to the screen:
#   The Number, a colon, and the ASCII character equivalent for that number  

After seeing the characters in a list, and checking to make sure I wasn’t going to use any special characters that would cause me problems later, this is what I ended up with.

$charlist = [char]94..[char]126 + [char]65..[char]90 +  [char]47..[char]57
# All uppercase and lowercase letters, all numbers and some special characters. 

No matter which way you create your list, you should end up with a variable to hold your characters. It should be a variable that is a character array.

$charList.GetType()

Should confirm that you have an array, not a string.

Got it so far? The rest is easy!

Decide how long you want your password to be

I’m not going to ever try to remember this password.

It’s mostly going to be:

  1. Generated
  2. Saved in an Azure KeyVault
  3. Looked up later when I need it

So I don’t really care what it is as long as it’s complex, long and impossible to guess.

But I don’t want it to even have the same number of characters each time.

I’ll have a range of password lengths. I want passwords to be at least 20 characters long, but it doesn’t need to be longer than 32.

There are a few logical ways to do that.

  1. A random number between 0 and 12, plus 20
  2. A random number between 20 and 32
light bulb

When I first wrote this, my brain was still thinking about “ranges” from character selection.

But there was a better way…

All of these lines do the same thing: They give me a random number between 20 and 32.

# Option 1:  Randomize the variation
$PwdLength = ([0..12] | Get-Random) + 20

# Option 2:  Randomization from the whole range
$PwdLength = [20..32] | Get-Random

#Option 3:  Built in parameters from a native PowerShell cmdlet.
$PwdLength = Get-Random -Minimum 20 -Maximum 32

Option 3 is best. It’s the easiest one to read.

Now make your random password from the list of characters

#Create a new empty array to store the list of random characters 
$pwdList = @()

# Use a FOR loop to pick a character from the list one time for each count of the password length
For ($i = 0; $i -lt $pwlength; $i++) {
  $pwdList += $charList | Get-Random
}

# Join all the individual characters together into one string using the -JOIN operator
$pass = -join $pwdList

The whole thing put all together

$charlist = [char]94..[char]126 + [char]65..[char]90 +  [char]47..[char]57
$pwLength = (1..10 | Get-Random) + 24  
$pwdList = @()
For ($i = 0; $i -lt $pwlength; $i++) {
   $pwdList += $charList | Get-Random
}
$pass = -join $pwdList

The post The Random Password Generator for PowerShell Core 6 and 7 appeared first on i Love PowerShell.

]]>
3114
Ultimate Guide to Using PowerShell Add-Member Cmdlet https://ilovepowershell.com/powershell-modern/ultimate-guide-to-using-powershell-add-member-cmdlet/ Tue, 19 Nov 2019 01:29:56 +0000 https://ilovepowershell.com/?p=2790 Is Add-Member the most underrated and underappreciated cmdlet in PowerShell? PowerShell is so vast and can manage so many platforms and technologies. It’s easy to get deep in one module or topic. But the core features and language of PowerShell is so often where the real power is. I want to encourage you readers to […]

The post Ultimate Guide to Using PowerShell Add-Member Cmdlet appeared first on i Love PowerShell.

]]>
Is Add-Member the most underrated and underappreciated cmdlet in PowerShell?

PowerShell is so vast and can manage so many platforms and technologies. It’s easy to get deep in one module or topic. But the core features and language of PowerShell is so often where the real power is. I want to encourage you readers to (re)familiarize yourself with how to use add-member cmdlet in PowerShell.

Consider this:

  1. PowerShell is the most flexible and amazing programming language for performing system administration and cross-platform scripting
  2. PowerShell is built using the .NET language where everything is represented as objects
  3. Add-Member is a core cmdlet of the PowerShell language – it’s been there from the beginning, and it’s THE way to ADD a property to an object
  4. It gets far less attention than other cmdlets that perform getting, sorting, filtering and formatting.

You have to agree… the poor, lowly “Add-Member” command has to be the most underrated and underappreciated cmdlet!

But after working with PowerShell and mastering some basic skills, you’re going to want to start doing more with your objects than just taking bulk operations on them, or sending them through the pipeline to be filtered, sorted and formatted.

You will want to keep your object AND modify it by adding a property to it.  That’s exactly what Add-Member can do for you!

Parameters, Descriptions and Definitions

I’m going to give you some great use cases and examples of how to use the Add-Member cmdlet in PowerShell to extend an existing object with a new property.  But just in case we need a little help in understanding the basics of properties, members, methods, and objects

Object

In PowerShell, the “things” we work with are all objects.

  • Files
  • Services
  • Websites
  • Office365 Users
  • Active Directory Domains
  • Virtual Machines

No matter whether you’re dealing with something large or small, each “thing” you use in PowerShell is an object.  PowerShell provides more details about objects in the Microsoft PowerShell documentation or from the help files, so I won’t go DEEP into objects…

Just enough to say that OBJECTS end up being the NOUNS that we work with in PowerShell, and those OBJECTS have members that give us ways to work with the objects

Member

So the object is the THING that we’re working with…  and OBJECTS have MEMBERS.

Members are either:

  1. Properties that describe them, or
  2. Methods that define the actions they can take.

Membertype

There are two main types of members: 

  1. methods, which are the actions that an object can perform, and
  2. properties, which describe some part of the object.

In addition to these 2 “main” types of members, there are several member types which all fall under the category of “property”. 

Here’s the list of PS MemberTypes as of version 6.2; It doesn’t change much between versions, but it could have a new PSMemberType show up as PowerShell continues to grow.

What’s important to note in the context of ADD-MEMBER is that these are the only member types we can add:

  • NoteProperty
  • AliasProperty
  • ScriptProperty
  • CodeProperty
  • ScriptMethod
  • CopyMethod

Property

Property members are great at describing the object. 

“How large is a file?” – the answer is stored in the LENGTH property of the file object.

“What is the username?”, “Is the VM powered on?”, “Is the user account disabled?” – the answers to all of these questions are answered in the PROPERTIES of the OBJECTS.

So…

“What is the difference between a property and a noteproperty and all these other kinds of properties?”

“Property”, by itself, is the most generic form. It’s defined by type definitions, which are usually well documented parts of the language or the module you’re working with.

For any properties that you add to an object, you will NOT be adding generic “property” members.  Instead, you’ll be adding a specific property type.

NoteProperty:  A simple property, can be used for just about anything. Integers, Booleans, Null values, Strings, Decimals, and even complex objects can be attached to objects with noteproperty members.

AliasProperty: Gives you a way to add a “nickname” or alternate name for a property. It becomes a pointer to the original property, so changing either one will change both.

$file = Get-ChildItem .\FileName   
$pic | Add-Member -NotePropertyName "Owner" -NotePropertyValue "Michael"
$pic.Owner
$pic | Add-Member -MemberType AliasProperty -Name "Boss" -Value "Owner"
$pic.Boss
$pic.Owner = "Michael Simmons"
$pic.Boss
ScriptProperty: A property that is calculated by processing a script.

ScriptProperty: A property that is called by processing a script.

ScriptMethod: Add a method to your object that processes a scriptblock when called.

CodeProperty: Code properties get their values by referencing a method of a .NET object.

CodeMethod: Add a method to your object that references a method of a .NET object.

Between these few property and method membertypes, you’re able to add members to your object to suit your specific needs.

Parameter and Options

Learning how to use the add-member cmdlet in PowerShell is going to take some practice. But keep trying to make it part of your arsenal! It’s too valuable to ignore!

Now that we have a full understanding of object members, we can explore the parameters an options of the Add-Member cmdlet.

InputObject

InputObject is the object that you’re adding a member to.

This parameter is mandatory!

InputObject also accepts pipeline input. So if you’ve got an object stored in $a…

$a = New-Object -TypeName "PSCustomObject"
#These next two lines do the same thing
$a | Add-Member -MemberType NoteProperty `
  -Name "FirstName" -Value "Michael"
Add-Member -InputObject $a -MemberType NoteProperty `
  -Name "FirstName" -Value "Michael"

Name

This parameter is mandatory in most parameter sets

Name is the name of the member, whether it’s a method or property. Methods on objects are called by using the parenthesis () to invoke the method, and any arguments that you pass into the method are contained inside the parenthesis. But for the purposes of Add-Member, you won’t include parenthesis in the name of your member, even for methods.

Value

Value is what the member is set to. In the case of a NoteProperty, it could be anything from a simple object, like a STRING or an INTEGER, or it could be a complex object like a hashtable or even another .NET object.

SecondValue

SecondValue is an interesting parameter. At first glance it looks like a way to provide 2 values to the same property. But it takes on a slightly different form depending on the member type that is added.

SecondValue is only available for AliasProperty, ScriptProperty, CodeProperty and CodeMethod.

How SecondValue is used (by Membertype)
AliasProperty Used to cast the property as a specific type (integer or string, for example)
ScriptProperty A scriptblock that sets the value  
CodeProperty A reference to a method on a .NET object that sets the value of the property
CodeMethod A reference to a method on a .NET object that calls a “Set” method


NotePropertyName

NoteProperty is so widely used, it started to become synonymous with Add-Member. In fact, as Jeffrey Snover wrote in “Hate Add-Member?”,

“I love that Add-Member lets me do a zillion things but in reality, 95% of the time, I just want to add a bunch of NOTEPROPERTIES to an object and Add-Member feels way to heavy to accomplish that.”

-Jeffrey Snover,
PowerShell Chief Architect

NotePropertyName is a response to this interaction with Add-Member. Since NoteProperty was the biggest use case for Add-Member, it only makes sense to make that easier.

When using the NotePropertyName, you don’t need to specify the MemberType by parameter. It’s already taken care of for you.

NotePropertyValue

When using the NotePropertyName parameter, you don’t have to use the -MemberType parameter, but you still need to specify a value for your property.  NotePropertyValue is the right parameter to use for that.

$a = New-Object PSCustomObject
Add-Member -InputObject $a -NotePropertyName "Size" -NotePropertyValue 14 

NotePropertyMembers

I love this parameter!

It’s similar to creating a PSCustomObject through a hashtable. But in this case, it’s a fast, simple way to add a bunch of properties to an object.

$a = New-Object PSCustomObject
Add-Member -InputObject $a -NotePropertyMembers @{
Size = 14
First = "Michael"
Last = "Simmons"
}

TypeName

TypeName sets the name of the object type. If you use the GetType() method of an object, you can see the name of the type that the object is. It could be system.string or int32 or system.processinfo.

Or, you could include the -TypeName parameter and your object is no longer a PSCustomType object but a type named “MySuperObject”.

What does FORCE do on Add-Member?

Force creates the member on the object even if it already exists, overwriting any previous values of the member.

Notice in the above examples for NotePropertyValue and NotePropertyMembers, both add a “Size” NoteProperty to the object stored in the $a variable. Without the -force, the second command would give an error that the Size member already exists on the object.  If you include the -Force option, there is no error message and the Size member is re-added to the object!

Parameter Sets

Parameter Sets are different ways to utilize a command, and with the examples we just gave about NotePropertyName and NotePropertyValue, it’s easy to understand.

If you use the NotePropertyName parameter, there’s no need to use the MemberType parameter to specify you’re adding a NoteProperty.  The NotePropertyName and NotePropertyValue are used in one ParameterSet. Once you specify the MemberType by using the MemberType parameter, you are now using the “MemberSet” parameter set and the NotePropertyName parameter is not available to you.

Parameter Set Notes about it
MemberSet Have to specify the member type that you’re adding
TypeNameSet Can be used without adding other members to the object, just setting the object type nameTypeName can also be included with any other parameter set
NotePropertySingleMemberSet Uses NotePropertyName and NotePropertyValueSince NoteProperty has no use for the SecondValue, that parameter is not available in this set
NotePropertyMultiMemberSet Uses NotePropertyMembersSince NoteProperty has no use for the SecondValue, that parameter is not available in this set

So… That’s all the details about Add-Member that you could ever want to know…

How about some examples in code?

How to Use Add-Member Cmdlet in PowerShell

Using Add-Member used to be so cumbersome! Especially for creating custom objects – it was this tedious process of creating the object with one line of code, then going though and calling Add-Member over and over, once per line until your object has all it’s properties. 

Creating Custom Object

We can still use several variations of this, and the advances in Add-Member make it less painful.  We can use the NoteProperty parameter sets to simplify the language, and make bulk changes in NoteProperty members with a hashtable.

$a = New-Object -TypeName PSCustomObject
$a | Add-Member -NotePropertyMembers @{
Name = "Michael"
Language = "PowerShell"
OS = "Windows"
}

Using Casting as an Alternative to Add-Member

Thankfully, we can also use casting as an alternative. This means that our object can start with a set of properties. Here’s how that looks:

$a = [PSCustomObject]@{
Name = "Michael"
Language = "PowerShell"
OS = "Windows"
}

This doesn’t stop us from using Add-Member, it just gives us a great starting point with a custom object. If you have more members to add later in your script, you’ve still got Add-Member to get you what you need!

How to use the add-member cmdlet in a PowerShell Loop

There are several ways to use Add-Member in a loop!

Let’s look at a few. The looping options in PowerShell are:

  • For loops
  • Do loops (Do/While and Do/Until)
  • While loops

For Loops are especially good at processing items sequentially or operating on each item in an array.

I am having a little trouble coming up with a use case for adding members in a for loop. Here’s how the code looks, but my mind keeps coming back to using the counter to get the index of an item in an array.

Alright… so without any great reason I can think of for using Add-Member in a For loop… Here it is anyway:

$a = New-Object -TypeName "PSCustomObject"
For ($i = 0; $i -lt 3; $i++) {
  Add-Member -InputObject $a `
    -NotePropertyName "Index$($i)" -NotePropertyValue $i
}

Output:

PS C:\WINDOWS\system32> $a
Index0 Index1 Index2
------ ------ ------
0      1      2

Then, there’ creating a collection of objects, and storing them in an array, then performing Add-Member operations on each item in the collection.

Foreach is a mechanism for that.

Using Foreach 

Foreach is a more intuitive use for Add-Member. 

Here’s an example of using Foreach as a way to perform operations on each item in a collection, and referencing those items to perform lookups on a 2nd collection.

$Services = Get-Service
$Services | Where Status -eq "Running"
$CimServices = Get-CimInstance -ClassName Win32_Service
$Services | Foreach {
$ProcessId = $CimServices | Where Name -eq $_.Name | `
  Select-Object -ExpandProperty ProcessId
Add-Member -InputObject $_ `
   -NotePropertyName "ProcessId" -NotePropertyValue $ProcessId
}
$Services | select Name, ProcessId

In a Pipeline

The Foreach is great when you want to perform individual operations, or different property values,  on each item in a collection.

But if you want to put the SAME property on each member of a collection, there’s a better way.

By using the pipeline you can use the objects in an array as the inputs to the Add-Member cmdlet.

$Today = Get-Date
$Services | Add-Member -MemberType NoteProperty `
  -Name "CollectionDate" -Value $Today
$Services | Select-Object Name, CollectionDate

If it Doesn’t Exist

There can be a time when you want to add a member, but ONLY if that member doesn’t exist.

For this, using the -FORCE parameter wouldn’t help since it would overwrite in cases where the member already exists.  Instead, you need to do one of these:

  • Use and IF/THEN Statement that checks for the existence of the property.
Foreach ($item in $list) {
if (-not ($item | Get-Member -Name "AProperty")) {
Add-Member `
  -InputObject $item `
  -NotePropertyName "AProperty" `
  -NotePropertyValue "A Value"
 }
}
  • Use and ErrorAction parameter to silently continue on even though the Add-Member spits out an error when it tries to add an already existing member.
Foreach ($item in $list) {
  $item | Add-Member `
    -NotePropertyName "AProperty" `
    -NotePropertyValue "A Value" `
    -ErrorAction "SilentlyContinue"
}

What if it Already Exists?

On the other hand, if you want to switch your thinking and have a use case to set the value of a property only if it already exists then you don’t want to use Add-Member.  

Just use an assignment operator (like ‘=’ or ‘+=’) to set the value of the property that already exists.

Saving your work

It’s a shame to go through all of this effort to learn how to use add-member cmdlet in PowerShell scripts and start customizing your list of objects, just to shut down your terminal and lose your work. Don’t do that!

Instead, save your newly updated list of objects! You have several great options for saving object sets in all versions of PowerShell, including the latest PowerShell Core versions that run on Mac, Linux or Windows.

Exporting and Importing as XML

Exporting as an XML file is pretty easy, and is not hard to read as a file either. It’s not my favorite but it gets the job done.

$list | Export-Clixml -Depth 2 -Encoding UTF8 -Path C:\Exports\MyList.xml  

Use the -DEPTH parameter to help break up complex objects that are stored as a property, otherwise you’ll end up with a property described in your XML file that just lists the name of the object type that is stored in the property.

JSON

I love the readability of a JSON file, so this is my preferred export.  The “DEPTH” parameter is used the same was as exporting an XML

$list | ConvertTo-Json -Depth 2 -Compress | Out-File C:\Exports\MyList.json

The JSON cmdlet doesn’t automatically write to a file.

You may want to have the JSON object returned to the pipeline so it can be used as the body of an API call. So just pipe the JSON object to a file using Out-File to create your object export in JSON format.  

Note the -COMPRESS parameter, which doesn’t ZIP your JSON object. It just removes all the white-space.

Compressing your JSON makes it harder to read but if it’s just going to be read by a computer, an API, or another script you write later, then you don’t need the white space anyway.

CSV

If you’ve got a flat object, with not a lot of complex properties, then you may also really like the CSV option to export your list of PowerShell objects.

$list | Export-CSV -Path C:\Exports\MyList.csv

The upside is that it’s easy to read, especially for multi-line objects, and can even be opened in Excel. Then just save it as an Excel Workbook and share your work with your boss.

Recapping How to Use the Add-Member Cmdlet in PowerShell

Since I started looking closer at Add-Member, I’ve increased my overall proficiency with it. Where before it would be kind of an afterthought, I now am quick to add what I want to my list of objects. How to use add-member cmdlet in PowerShellSince I started looking closer at Add-Member, I’ve increased my overall proficiency with it. Where before it would be kind of an afterthought, I now am quick to add what I want to my list of objects.

VMs suddenly have a more direct PowerState property on them while I’m working on them.

Properties of cloud resources that are nested 3 levels deep in a complex object are surfaced and presented as full-on properties of the root object.

If Add-Member was the most underrated cmdlet in PowerShell before, for me it will stop being underappreciated.

It’s a GREAT cmdlet and so useful in so many ways! My scripting is better because of it!

The post Ultimate Guide to Using PowerShell Add-Member Cmdlet appeared first on i Love PowerShell.

]]>
2790
How To Open A Directory Chooser Window With PowerShell https://ilovepowershell.com/powershell-modern/how-to-open-a-directory-chooser-window-with-powershell/ Wed, 08 Mar 2017 21:42:58 +0000 https://ilovepowershell.com/?p=2448 I’m sure that you’ve seen plenty of scripts that set a path like “C:\temp” for logs, files, and other outputs.  But did you know that it’s actually very easy to add a pop up directory UI in PowerShell that gives a choice of where to save those output files? It’s true! And the amazing thing […]

The post How To Open A Directory Chooser Window With PowerShell appeared first on i Love PowerShell.

]]>
I’m sure that you’ve seen plenty of scripts that set a path like “C:\temp” for logs, files, and other outputs. 

But did you know that it’s actually very easy to add a pop up directory UI in PowerShell that gives a choice of where to save those output files? It’s true! And the amazing thing is that it really doesn’t take much time to write, it’s not even a lot of lines of code.

For this I’ll use any example.  Let’s use a script I shared previously on how to find which process is using the most CPU with PowerShell. First, to include this function in this script I will dot-source it from my calling script.

. C:\scripts\get-iLPHighCPUProcess.ps1

This doesn’t run the command, because I’m dot-sourcing it. This is a way of making the function in that second script available in this script that I’m writing now.

Next, we can call the function from our script, and save the output to any location:

Get-iLPHighCPUProcess | Out-File C:\temp\HighCPU_Processes.txt

But this will error out if there is no C:\temp folder created.  Yes, there are ways around that. You could use Test-Path to find out if the folder is there, and issue a warning if it isn’t. Or, you could force the creation of the file first by including something like this:

If (-Not (Test-Path C:\temp)) {New-Item -Itemtype directory -Path C:\temp -Force}

How to Add a “Save File As…” Dialog Window to Your PowerShell Scripts

Though both of those solutions are fine, they are NOT the point of this post!  This is about how to let the users choose where to save the file in PowerShell. So let’s take a look at that.

Here I will add one extra line to the same script. The purpose is to create the dialog that shows the user a directory window where they will choose their own location where they want the file saved. Even better, this let’s the user name their saved output with whatever file name they want.

$SaveChooser = New-Object -Typename System.Windows.Forms.SaveFileDialog
$SaveChooser.ShowDialog()

Look at that! The way to have a nice UI popup where the user can choose their own place to save a file is really easy. You can use the built-in .NET Framework object for working with files, folders and Windows Forms objects to get it done!

You can see it yourself by running just those two lines from the PowerShell console.  Notice that it has all of the functionality that you need. You can browse the folder structure, create or rename folders, and choose the file name to save to.

Nice! A quick and easy way to choose a file to save output to!

When the “Save” button is pressed, the dialog is complete. After the dialog closes, control passes back to the PowerShell script. From there, you still have the SaveDialog object saved as a variable. But now, the variable has some important information stored in its properties!

To access the file and folder path where the file should be saved you can use the FileName property.

Get-iLPHighCPUProcess | Out-File $SaveChooser.Filename

How the Save File Dialog box looks in PowerShell

Put it all together, and the code looks like this:

. C:\Users\micha\OneDrive\scripts\Get-iLPHighCPUProcess.ps1
$SaveChooser = New-Object -TypeName System.Windows.Forms.SaveFileDialog
$SaveChooser.ShowDialog()
Get-iLPHighCPUProcess | Out-File $SaveChooser.Filename

That’s a whole lot of nice functionality for such a small amount of code, it’s definitely worth it to give some choice to the script operator. So use the SaveFileDialog object from .NET to improve your PowerShell scripts.

The post How To Open A Directory Chooser Window With PowerShell appeared first on i Love PowerShell.

]]>
2448
Find the processes using the most CPU on a computer with PowerShell https://ilovepowershell.com/powershell-modern/find-the-processes-using-the-most-cpu-on-a-computer-with-powershell/ https://ilovepowershell.com/powershell-modern/find-the-processes-using-the-most-cpu-on-a-computer-with-powershell/#respond Sat, 06 Jun 2015 05:20:56 +0000 https://ilovepowershell.com/?p=2396 Have a complaint from a user that a server is sluggish? Maybe you’re just curious if the problem you’re seeing on a server is related to a process consuming a lot of CPU, or you know the CPU is pegged and you want to identify which process is the culprit. I had a similar situation, and […]

The post Find the processes using the most CPU on a computer with PowerShell appeared first on i Love PowerShell.

]]>
Have a complaint from a user that a server is sluggish? Maybe you’re just curious if the problem you’re seeing on a server is related to a process consuming a lot of CPU, or you know the CPU is pegged and you want to identify which process is the culprit.

I had a similar situation, and so I wrapped it up into a nice little package that I’ll share with you here. This uses WMI to find processes running high CPU with PowerShell.

It can run in one of two ways – by reporting all processes using more than a certain percentage of the CPU or by reporting a the top CPU hogging processes. I use parameter sets for those different options, so it’s one or the other. I considered making it possible to list “top 3 processes consuming more than 10%,” which could have been done very easily, but decided I preferred it this way.

Function Get-iLPHighCPUProcess {
<#
.SYNOPSIS
    Retrieve processes that are utilizing the CPU on local or remote systems.

.DESCRIPTION
    Uses WMI to retrieve process information from remote or local machines. You can specify to return X number of the top CPU consuming processes
    or to return all processes using more than a certain percentage of the CPU.

.EXAMPLE
    Get-HighCPUProcess

    Returns the 3 highest CPU consuming processes on the local system.

.EXAMPLE
    Get-HighCPUProcess -Count 1 -Computername AppServer01

    Returns the 1 highest CPU consuming processes on the remote system AppServer01.


.EXAMPLE
    Get-HighCPUProcess -MinPercent 15 -Computername "WebServer15","WebServer16"

    Returns all processes that are consuming more that 15% of the CPU process on the hosts webserver15 and webserver160
#>

[Cmdletbinding(DefaultParameterSetName="ByCount")]
Param(
    [Parameter(ValueFromPipelineByPropertyName)]
    [Alias("PSComputername")]
    [string[]]$Computername = "localhost",
    
    [Parameter(ParameterSetName="ByPercent")]
    [ValidateRange(1,100)]
    [int]$MinPercent,

    [Parameter(ParameterSetName="ByCount")]
    [int]$Count = 3
)


Process {
    Foreach ($computer in $Computername){
    
        Write-Verbose "Retrieving processes from $computer"
        $wmiProcs = Get-WmiObject Win32_PerfFormattedData_PerfProc_Process -Filter "idProcess != 0" -ComputerName $Computername
    
        if ($PSCmdlet.ParameterSetName -eq "ByCount") {
            $wmiObjects = $wmiProcs | Sort PercentProcessorTime -Descending | Select -First $Count
        } elseif ($psCmdlet.ParameterSetName -eq "ByPercent") {
            $wmiObjects = $wmiProcs | Where {$_.PercentProcessorTime -ge $MinPercent} 
        } #end IF

        $wmiObjects | Foreach {
            $outObject = [PSCustomObject]@{
                Computername = $computer
                ProcessName = $_.name
                Percent = $_.PercentProcessorTime
                ID = $_.idProcess
            }
            $outObject
        } #End ForeachObject
    } #End ForeachComputer
}

}

Things I like about this function are:

  • Concise output: Computername, ProcessName, Percent (of CPU), and ID (Process ID)
  • Accepts pipeline input by property value of “ComputerName” or “PSComputerName”
  • Easy to use against multiple computers
  • Flexible: I like the option to find the 3 highest CPU processes or all processes above 5 percent (or any percent)
  • Accepts multiple computers through parameter (as an array) or through the pipeline

Questions? Comments? Whether it’s a different approach or just saying “Thanks” I really appreciate the feedback.

The post Find the processes using the most CPU on a computer with PowerShell appeared first on i Love PowerShell.

]]>
https://ilovepowershell.com/powershell-modern/find-the-processes-using-the-most-cpu-on-a-computer-with-powershell/feed/ 0 2396
Using -match and the $matches variable in PowerShell https://ilovepowershell.com/powershell-modern/using-match-and-the-matches-variable-in-powershell/ https://ilovepowershell.com/powershell-modern/using-match-and-the-matches-variable-in-powershell/#respond Thu, 28 May 2015 13:30:52 +0000 https://ilovepowershell.com/?p=2383 I’ve been rereading the Windows PowerShell Cookbook and I came across a variable I hadn’t noticed before… It turns out to be related to the -match comparison operator. -Match performs a regular expression comparison. A simple way of thinking about regular expressions is that they “describe” the patterns of characters. Another way of thinking of regular […]

The post Using -match and the $matches variable in PowerShell appeared first on i Love PowerShell.

]]>
I’ve been rereading the Windows PowerShell Cookbook and I came across a variable I hadn’t noticed before…

It turns out to be related to the -match comparison operator. -Match performs a regular expression comparison. A simple way of thinking about regular expressions is that they “describe” the patterns of characters. Another way of thinking of regular expressions is “Wildcards on steroids.”

For these examples, I’m going to keep things very simple as far as regular expressions go:

.   <– means “anything”
*  <– means “zero or more of it”
so
.* <– means “zero or more of anything”

<#####################
 -Match and $Matches 
#####################> 

<# Like -eq, -match will evaluate True/False 
   when compared against one object #>
"One" -eq "One"
"One" -match ".*"

<# Also like -eq, -match passes objects that evaluate to 
  TRUE through the pipeline when compared against multiple objects#>
"One","Two","Three" -eq "Two"
"One","Two","Three" -match "T.*"

An interesting thing about using the -match comparison operator is that when matches are evaluated, the result is stored in a unique variable, $matches.

The $matches variable takes a little getting used to.

#1 - $Matches doesn't work with -eq
"One", "Two", "Three" -eq "One" | Foreach {$Matches[0]}
<# Surprised? If you've dropped these 
  examples into the ISE, it looks like it works. #>

#2 - $Matches really doesn't work with -eq
"One", "Two", "Three" -eq "Two" | Foreach {$Matches[0]}
<# See? I tricked you! The reason it looked like it worked on #1 was because
   it was still set from the last time -match was used. #>

#3 - $Matches isn't set when evaluating multiple objects 
"One" -match ".*"
"One", "Two", "Three" -match "T.*"
$Matches

#4 - $Matches CAN be used with multiple items, but evaluate each item individually
"One" -match ".*"
"One","Two","Three" | Where-Object {$_ -match "T.*"} | Foreach {$Matches[0]}
$Matches
<#Notice how $matches now equals "Three"? What happened to "Two"? 
  Since I used the pipeline to break the list into three items, 
  the -match comparison in the Where cmdlet does update the 
  $Matches variable. But immediately after evaluating TRUE for "Two", 
  it updates with "Three" and Two returns to the ether. #>

#5 - Don't be fooled by trying to -match on multiples
"One","Two","Three" -match "T.*" | Foreach {$Matches[0]}
<#See? It's tricky.#>

Finally, you’ll just want to notice that I keep switching between $Matches and $Matches[0]. $Matches is a variable that contains a hashtable. The hashtable (a key-pair) has a key and a value. The key is the index and the value is “what was returned as the match.” Since there is only one value in the $Matches variable, you can get to the value of the match by referencing the key-pair by its name.

Alright, so you’ve seen how $Matches works. But why use it?

In the examples that I’ve shown here, you probably aren’t that impressed. I promise I kept it simple so it wouldn’t be too intimidating with the crazy looking regular expressions. Regex can look really nuts.

Let’s use another example that is equally as useless but at least serves as a better example of why we might like $Matches.

#Let's make a little list of words
$words = "The quick brown fox jumped over the lazy dog".Split()

#Now show only words that start with a letter between "a" and "l" and also have an "o" somewhere in the word.
$Words | Where {$_ -match "[A-L,a-l].*o.*"} | Foreach {$Matches[0]}


That really can’t be done with using a -like comparison operator and normal wildcards. Still not sure if you’d have a use case for having the matches of a regular expression displayed? Here’s when you want to use it.

Grab a list of strings. Pipe them into a Where-Object or Select-String to perform a -match against them. If what you want is the whole string when it has the match, then you just use the standard output. But if what you want is only the resulting match, then you can pipe it to Foreach-Object {$matches[0]}

The post Using -match and the $matches variable in PowerShell appeared first on i Love PowerShell.

]]>
https://ilovepowershell.com/powershell-modern/using-match-and-the-matches-variable-in-powershell/feed/ 0 2383
Easiest way to Shuffle an Array with PowerShell https://ilovepowershell.com/powershell-modern/easiest-way-shuffle-array-powershell/ Sun, 25 Jan 2015 01:23:51 +0000 https://www.ilovepowershell.com/?p=315 I was going nuts trying to sort an array into a random order. I was hoping for something in PowerShell that would be along the lines of Shuffle() in PHP or Ruby. Thankfully I figured out the easiest way ever to do it!

The post Easiest way to Shuffle an Array with PowerShell appeared first on i Love PowerShell.

]]>
I was going nuts trying to sort an array into a random order. I was hoping for something in PowerShell that would be along the lines of Shuffle() in PHP or Ruby.

In fact, after looking at it I was a little surprised at all of the things that an array can’t do in PowerShell.

But that’s ok – it turns out to be really easy and if you’re thinking that you need to learn a different language to shuffle an array in PowerShell you’re dead wrong.

It’s super easy to randomize the order of an array in PowerShell – you just have to simplify and think about it in a different way.

#Give me a list - any list will do. Here's 26 numbers.
$MyList = 0..25

#Shuffle your array content but keep them in the same array

$MyList = $MyList | Sort-Object {Get-Random}

#Randomize the contents of your array and save them into a new array

$MyShuffledList = $MyList | Sort-Object {Get-Random}

This is so easy it defies belief. Why does it work?

Since the Sort-Object can accept pipeline input, it’s often used to organize the contents of a list based on one property or another. You’ve probably used it for sorting by names, or for sorting files by their size. But a magical thing happens when you tell it to not sort by a specific property but instead pass it a scriptblock.

For each object that is passed into Sort-Object through the pipeline the scriptblock is called. And since Get-Random evaluates to a rather large random number – the objects in the array are sorted based on all of those random integers.

I know this was an eye-opener for me, and I really like doing it this way. Before coming across the sort method I tried going through each item in the array and adding a noteproperty to it.  Which worked since I was using an array of objects anyway but was way clunkier than doing it this way.

Leave any questions or feedback in the comments and do me a favor and hit the like button on my facebook page for me, ok? Thanks!

The post Easiest way to Shuffle an Array with PowerShell appeared first on i Love PowerShell.

]]>
315
How to Find Enum Values in PowerShell https://ilovepowershell.com/powershell-modern/find-enum-values-in-powershell/ Mon, 25 Mar 2013 19:39:06 +0000 https://www.ilovepowershell.com/?p=183   There are a couple of very easy ways to get a find enum values in PowerShell.  Enums are often used when choosing an option as a parameter in a PowerShell command.  This article shows you exactly how to get those values for any enumerated list type (called “enum”). The easiest way to find enum […]

The post How to Find Enum Values in PowerShell appeared first on i Love PowerShell.

]]>
WindowsPowerShellCookbook

Windows PowerShell Cookbook Volume 3 by Lee Holmes

 

There are a couple of very easy ways to get a find enum values in PowerShell.  Enums are often used when choosing an option as a parameter in a PowerShell command.  This article shows you exactly how to get those values for any enumerated list type (called “enum”).

The easiest way to find enum values in PowerShell is to use Get-Help, but that doesn’t always work

The easiest way is by using the Get-Help command on a PowerShell cmdlet or function.  All of the built in PowerShell cmdlets have great help that is painstakingly created and maintained. Some of the functions that are included with PowerShell modules or a PSSnapin will also have documented parameters.

So the number one most simple way to check out the possible accepted values for an enum is to check with the get-help documentation.

It looks like this:


Get-Help Set-ExecutionPolicy –full

usingGetHelp_thumb

In the results, you can see in the values displayed inline with the parameter that accepts the type

 

Start by using Get-Help to try finding enum values. It is very fast, and the enum values are often in the help documentation.

That’s pretty good.  Unfortunately, the help for a function that was developed in house does not usually include such great documentation.

The best way to find enum values with PowerShell is to use a static method.

I’ll continue to use the Set-ExecutionPolicy cmdlet as my example, but these will work for any class that is an enum.

There are two approaches to this, and each one does the same thing.

First, you can use a static method from the base enum class, [system.enum].  Secondly, you can use a static method of the class (the enum) that you’re trying to identify the values for.

And before you can do either one, you need to identify the type that the enum represents.

How to find out the type of an enum

Consider the “Set-ExecutionPolicy” cmdlet, which uses a parameter “ExecutionPolicyScope” to specify at what level you want to apply the execution policy that you’re setting.

So if you want to know what options can go in

Set-ExecutionPolicy –ExecutionPolicy RemoteSigned –Scope  ???

You can find out what class the “Scope” parameter accepts by using Get-Help to interrogate the parameter.

Get-Help Set-ExecutionPolicy –Parameter Scope

Which returns just the information about the “Scope” parameter.

usingGetHelp-FindParameterType_thumb

 

This shows that what you put into the Scope parameter is an object of type ExecutionPolicyScope.

That’s half the battle.  Actually, it’s way more than half the battle:  you’re almost done.

Finding out the names in an enumerated list (enum) when you know the type.

So now that we know the type, we need to be able to reference it.

To do this, I’m going to use a static method from the Enumeration class, SYSTEM.ENUM, called GetNames().  Use it like this:

[Enum]::GetNames(“Microsoft.PowerShell.ExecutionPolicyScope”)

ListEnum_thumb

And you will get all of the possible options for your enumerated list.  It might look like I took some liberties with the class name, because when it was listed in the Get-Help –Parameter output from above it was listed as “ExecutionPolicyScope” but when I entered it into the GetNames static method I used “Microsoft.PowerShell.ExecutionPolicy”.  When I first tried it with just “ExecutionPolicyScope” it returned an error.  So I made a guess that it was part of the standard PowerShell namespace, and it turned out to be correct.

By the way, the default PowerShell namespace is Microsoft.PowerShell and many PowerShell objects that are listed as only a class name actually belong to it, so it can be worth a try.

Many other enums listed as types in parameters for a command will list out the full namespace with the object.

Ok – so you’ve read the article.  I hope that you’ve gotten something great out of it.  I love helping people get more out of PowerShell, because I know PowerShell can help people do more work, faster, and with fewer mistakes than ever.

I’m committed to sharing great PowerShell advice and tips, so how’s about subscribing or spreading the word by sharing this article with a fellow that would benefit from it.

The post How to Find Enum Values in PowerShell appeared first on i Love PowerShell.

]]>
183