Windows PowerShell (Legacy) Archives - i Love PowerShell https://ilovepowershell.com/category/windows-powershell-legacy/ I came. I saw. I automated. Fri, 17 Mar 2023 15:50:45 +0000 en-US hourly 1 https://wordpress.org/?v=6.6.2 https://ilovepowershell.com/wp-content/uploads/2020/09/SiteLogo-150x150.png Windows PowerShell (Legacy) Archives - i Love PowerShell https://ilovepowershell.com/category/windows-powershell-legacy/ 32 32 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
Awesome and Simple Way to Generate Random Passwords with PowerShell https://ilovepowershell.com/windows-powershell-legacy/awesome-and-simple-way-to-generate-random-passwords-with-powershell/ Mon, 28 May 2018 21:34:52 +0000 https://ilovepowershell.com/?p=2621 I get tired of thinking up unique and strong passwords. So anymore, for the most part, I don’t do it. I will use random generated passwords, then save them into an Azure KeyVault. It is a good way to use strong passwords that are practically impossible to remember but then keep them usable and within […]

The post Awesome and Simple Way to Generate Random Passwords with PowerShell appeared first on i Love PowerShell.

]]>

I get tired of thinking up unique and strong passwords.

So anymore, for the most part, I don’t do it.

I will use random generated passwords, then save them into an Azure KeyVault.

It is a good way to use strong passwords that are practically impossible to remember but then keep them usable and within reach.

I’m also a big fan of randomly generating a password for service accounts.

By using PowerShell to create the service accounts, it’s even better because I never even know the passwords of the service accounts. I can have PowerShell:

  • generate a random password
  • save the password to the Key Vault, then
  • use that password for the service accounts.

It works like a dream!!!

But how do I generate the passwords?

It’s so simple that you’ll never use a homegrown, one-character-at-a-time randomizer again.

Hey…

This article was written before PowerShell Core came along and took away the [System.Web.Security.Membership] class.

This article still works if you’re on Windows PowerShell (through version 5) but if you’re on later PowerShell versions (like you should be)…

Here’s how to Make a Random Password in PowerShell 7

I use the built in .Net Framework GeneratePassword() method.

# GeneratePassword can be called as a static method
# You don't need to instantiate the class first. It works just fine like this:

[System.Web.Security.Membership]::GeneratePassword(24,5)
# It just takes two arguments: "How long is the password" and "How many special characters"?
The generated password is a string, and that's find for reading but not useful for creating a credential object. So you'll usually need to convert the password into a SecureString.

# Same as above, just a different password length and complexity
$PW = [System.Web.Security.Membership]::GeneratePassword(30,10)

# The password as it is now:
$PW

# Converted to SecureString
$SecurePass = $PW | ConvertTo-SecureString -AsPlainText -Force

# The SecureString object
$SecurePass

So that’s all there is to it! If you’ve got questions or comments, I’d love to hear them.

How did this work for you and what else have you tried?

The post Awesome and Simple Way to Generate Random Passwords with PowerShell appeared first on i Love PowerShell.

]]>
2621
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
Get a Folder Size with PowerShell https://ilovepowershell.com/windows-powershell-legacy/get-a-folder-size-with-powershell/ Fri, 11 Sep 2015 04:20:01 +0000 https://ilovepowershell.com/?p=2413 It’s really easy to get the size of a folder with PowerShell. Even though the directory does not actually have a property for size, you just need to get the size of all of the files inside the folder. function Get-FolderSize { [CmdletBinding()] Param ( [Parameter(Mandatory=$true,ValueFromPipeline=$true)] $Path, [ValidateSet("KB","MB","GB")] $Units = "MB" )   if ( […]

The post Get a Folder Size with PowerShell appeared first on i Love PowerShell.

]]>
It’s really easy to get the size of a folder with PowerShell.

Even though the directory does not actually have a property for size, you just need to get the size of all of the files inside the folder.

function Get-FolderSize {
[CmdletBinding()]
Param (
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
$Path,
[ValidateSet("KB","MB","GB")]
$Units = "MB"
)
  if ( (Test-Path $Path) -and (Get-Item $Path).PSIsContainer ) {
    $Measure = Get-ChildItem $Path -Recurse -Force -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum
    $Sum = $Measure.Sum / "1$Units"
    [PSCustomObject]@{
      "Path" = $Path
      "Size($Units)" = $Sum
    }
  }
}

One of my favorite things about this script is the ability to choose to get the folder size in KB, MB or GB.

This won’t include any results from items that you don’t have read access to, so be aware of that. Otherwise, it’s a fast and easy way to get the folder size from PowerShell!

The post Get a Folder Size with PowerShell appeared first on i Love PowerShell.

]]>
2413
How to Check if a Server Needs a Reboot https://ilovepowershell.com/windows-powershell-legacy/how-to-check-if-a-server-needs-a-reboot/ https://ilovepowershell.com/windows-powershell-legacy/how-to-check-if-a-server-needs-a-reboot/#respond Thu, 10 Sep 2015 23:26:15 +0000 https://ilovepowershell.com/?p=2407 If you’re trying to determine which of your servers require reboots, you’ll love this PowerShell script to check the status. It turns out that a simple way to identify servers that are pending reboot is to check the registry. This information is stored in the HKeyLocalMachine hive of the registry. PowerShell is perfect for working […]

The post How to Check if a Server Needs a Reboot appeared first on i Love PowerShell.

]]>
If you’re trying to determine which of your servers require reboots, you’ll love this PowerShell script to check the status.

It turns out that a simple way to identify servers that are pending reboot is to check the registry.

This information is stored in the HKeyLocalMachine hive of the registry.

PowerShell is perfect for working with the registry.

Registry is one of the built-in PowerShell providers!

There’s even already a PSDrive connected to that registry hive!

You can’t ask for anything more… except to maybe be able to map a new PSDrive to a different part of the Registry — which is ALSO super easy to do!

You can browse around the registry just like you do with the filesystem.

#Change to the registry drive. 
#Set-Location can also be invoked through its aliases - CD and SL
#Get-ChildItem can also be invoked through its aliases - Dir and LS

Set-Location HKLM:
Get-ChildItem

Wow! Super easy, right?

Now you just need to know where the “pending reboot” location is. There are a couple of places to check.

  • HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired

Is where patches installed through automatic updates register the need to reboot.

  • HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending

Is another place where pending reboots can be identified.

  • HKLM\SYSTEM\CurrentControlSet\Control\Session Manager

Is yet another. Finally, there is Configuration Manager which, if present, can be queried via WMI.

I found a function that I really like to check all four locations.

I’ll need to wrap it up with some parameters to check remote computers, but in general it was a great start.

I’ve adapted the function to return $true on the first condition that satisfies, since I only care about whether the computer is pending a reboot, and not where the source of the reboot is coming from.

#Adapted from https://gist.github.com/altrive/5329377
#Based on <https://gallery.technet.microsoft.com/scriptcenter/Get-PendingReboot-Query-bdb79542>
function Test-PendingReboot
{
 if (Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending" -EA Ignore) { return $true }
 if (Get-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired" -EA Ignore) { return $true }
 if (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name PendingFileRenameOperations -EA Ignore) { return $true }
 try { 
   $util = [wmiclass]"\\.\root\ccm\clientsdk:CCM_ClientUtilities"
   $status = $util.DetermineIfRebootPending()
   if(($status -ne $null) -and $status.RebootPending){
     return $true
   }
 }catch{}

 return $false
}

The post How to Check if a Server Needs a Reboot appeared first on i Love PowerShell.

]]>
https://ilovepowershell.com/windows-powershell-legacy/how-to-check-if-a-server-needs-a-reboot/feed/ 0 2407
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
Looking at Installed Certificates with PowerShell https://ilovepowershell.com/windows-powershell-legacy/looking-at-installed-certificates-with-powershell/ Sat, 21 Mar 2015 04:00:26 +0000 https://www.ilovepowershell.com/?p=324 Q. How can I see what certificates are installed on a Windows computer with PowerShell? A. Using PowerShell to view certificates is easy. PowerShell has a provider that exposes the certificates store which is part of the pki and security modules, which are loaded automatically as long as you’re on version 3 or greater. You do not need to […]

The post Looking at Installed Certificates with PowerShell appeared first on i Love PowerShell.

]]>
Q. How can I see what certificates are installed on a Windows computer with PowerShell?

A. Using PowerShell to view certificates is easy. PowerShell has a provider that exposes the certificates store which is part of the pki and security modules, which are loaded automatically as long as you’re on version 3 or greater. You do not need to manually load the modules, they auto-load from PowerShell v3 and above.

To view the certificates in the local users personal certificate store I would use the following:

#Change to the location of the personal certificates
Set-Location Cert:\CurrentUser\My

#Change to the location of the local machine certificates
Set-Location Cert:\LocalMachine\My

#Get the installed certificates in that location
Get-ChildItem | Format-Table Subject, FriendlyName, Thumbprint -AutoSize

#Get the installed certificates from a remote machine
$Srv = "SERVER-HOSTNAME"
$Certs = Invoke-Command -Computername $Srv -Scriptblock {Get-ChildItem "Cert:\LocalMachine\My"}




There is also a cmdlet called Get-Certificate, but don’t be fooled – it’s for requesting and installing certificates, not listing the certificates already installed.

H/T: http://windowsitpro.com/powershell/browse-certificate-store-using-powershell

The post Looking at Installed Certificates with PowerShell appeared first on i Love PowerShell.

]]>
324
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
Overview of the SMBShare Module for PowerShell 3 https://ilovepowershell.com/windows-powershell-legacy/overview-smbshare-module-powershell-3/ Mon, 25 Mar 2013 19:07:59 +0000 https://www.ilovepowershell.com/?p=180 The SMBShare Module that comes with PowerShell 3 lets you administer network shares directly from within PowerShell. The cmdlets are easy to use, and it is my new favorite way to work with network shares. It’s the Quickest Way to Create a Network Share with PowerShell It’s very easy to create network shares with PowerShell […]

The post Overview of the SMBShare Module for PowerShell 3 appeared first on i Love PowerShell.

]]>
The SMBShare Module that comes with PowerShell 3 lets you administer network shares directly from within PowerShell. The cmdlets are easy to use, and it is my new favorite way to work with network shares.

It’s the Quickest Way to Create a Network Share with PowerShell

It’s very easy to create network shares with PowerShell by using the SMBShare module that comes in PowerShell version 3.

How to Install the SMBShare Module for PowerShell 3

If you’ve already got PowerShell v.3, then you’re already all set.  You don’t even have to add a pssnapin or import a module.  One of my favorite PowerShell 3 features is the ability to load modules on demand when one of the commands in the module is called.

So if you want to load the SMBShare module, just run one of the commands I’m getting ready to tell you about!

The SMBShare “Get-” Commands

The SMBShare module includes 11 different Get commands, for finding out the current state of affairs with your SMB shares and your SMB client configuration.

Get-SmbClientConfiguration:  This will tell you how a computer, either locally or remote through WMI connection, is configured.  It returns items such as how long to stay connected (KeepConn) and how soon to consider a dropped session a timeout (SessionTimeout).

Get-SmbClientNetworkInterface: All of the Network Interfaces, including wired, wireless, and logical, are all displayed.  this makes:

#Get all of the IP addresses for all network interfaces
$AllIPs  = Get-SMBClientNetworkInterfaces | Select-Object -ExpandProperty  IPAddresses

Get-SmbConnection:  This lists active SMB connections and even includes Bytes Sent and Received.  Administrative PowerShell session  required.

Hey, have you seen the cool trick I use to color my administrative shells with a red background?  It’s really easy.

Read: How to Change Background Color on Administrative PowerShell Session

Get-SmbMapping  gives you a list of mapped drives, and returns properties such as LocalDrive (the drive letter the mapped drive is assigned) and the RemotePath, which is the mapped network share.  It also displays the status.

Here’s hoping that I can finally and easily remove old sessions to servers to I can connect to an administrative share without getting the stupid “Cannot connect with more than one user name to a server” error.  BTW, in case you didn’t know about it, there’s a sneaky trick to get a second set of credentials mapped to a server share

Get-SmbMultichannelConnection  If you’re using SMB Multichannel, then this is your tool of choice for getting that connection information.  I’m not using it, so I’ll leave it open.  If you’ve got some information about this, please send a note in the comments and I’ll update with your facts and give you credit.

Get-SmbOpenFile I love this one!  Gets all of the files that are currently open.  This was available in the Server properties through the GUI, but this is an administrative function that was a hassle to script in WMI and it’s so much easier now.

Get-SmbServerConfiguration Similar to the first command we mentioned, but this is the server settings instead of the client settings

Get-SmbShare All shares, including administrative and hidden shares, are included with this simple command.    You can quickly see at a glance which of your shares are temporary, permanent, using shadow copy, and its status.  Another one that makes an admins job much easier.

Get-SmbShareAccess  You were probably already asking the question:  ”Does Get-SMBShare tell you who has access?”   But no, it doesn’t.  Instead, you use the Get-SMBShare command, then pipe it into Get-SMBShareAccess

#Get a list of any users that write to any shares that are not online

$Shares = Get-SMBShare

$Offline = $Shares | Where-Object {$_.ShareState -eq “Offline”}

$Users = $Offline  | Get-SMBShareAccess | Where-Object {$_.AccessRight -le “Change”}

That’s just the Get Commands, but I think you can tell a lot from the Get commands, because that’s what’s going to feed into the Set commands.

Still, I bet you’d like to know which of the nouns you’ll be able to modify using the SMBShare module.

Set, New, and Remove – the rest of the SMBShare module cmdlets.

By the nouns, that is, the objects that you’re able to administer, here is what you can do to the different SMBShare objects.

SMBClientConfiguration: In addition to Get-, you can also use Set-SMBClientConfiguration.

SMBShare: You can also use New-SMBShare, Remove-SMBShare, and Set-SMBShare.

SMBMultichannelConnection: Update-SMBMultichannelConnection is the only additional cmdlet for working with the Multi-channel SMB connections.

SMBServerConfiguration: Like client configuration, you also get Set-SMBServerConfiguration.

SMBOpenFile: If you were excited to see the Get-SMBOpenFile, you were probably eagerly hoping that this command was included.  Yes, you also get Close-SMBOpenFile.

SMBShareAccess: Also available for administering share permissions is Block-SMBShareAccess, Grant-SMBShareAccess, Revoke-SMBShareAccess, and Unblock-SMShareAccess.

SMBMapping: New-SMBMapping and Remove-SMBMapping are also available, so you can now actually map real drives from within PowerShell, not just PSDrives that exist only in the PowerShell session.

SMBSession: When you’re ready to end a session, you can do it with style using the Close-SMBSession cmdlet.

In Ending

Well, it’s been a great journey, and this exercise was as good for me to learn as it was for you to learn.  While I had already been using some of the SMBShare commands, actually taking the time to try the different cmdlets and seeing which ones are available is really beneficial.

My favorite two that I’ll use the most:

Grant-SMBShareAccess

New-SMBMapping

What about you?  What’s your favorite from this module?  Let me know if you liked this article by connecting in the comments below, and please subscribe.

The post Overview of the SMBShare Module for PowerShell 3 appeared first on i Love PowerShell.

]]>
180