PowerShell Beginner’s Guide – Looping through objects

In this post we will be going through the different types of loops in PowerShell.

There are a few different types of loops and we will go through each and showing examples on how to use them. Loops are very useful and will be required in most scripts.

The first we will go through is a ForEach-Object loop, this is one of the main loops I use and can be used a few different ways.

Foreach Objects

First way is to get a list of objects and then pipe to our foreach-object to go through each.

Below example will get all services, loop through the results and return each name.

Get-Service | ForEach-Object { $_.Name}
Foreach-Object

Another method for using foreach-object is to use a variable with a set of object or a command that will retrieve objects and loop through each object in the variable.

There are two short hand commands for foreach-object, % and foreach.

In the below I am getting all folders under the directory and adding them to a $folders variable and looping through each.

$folders = Get-ChildItem C:\temp\ -Directory
foreach ($folder in $folders){$folder | Select-Object Name,CreationTime}

We can also use the foreach method on the variable to loop through the objects.

I mostly use foreach in my scripts as I find it the easiest to read when I have to go back over my own scripts.

While Loops

The other type of loops is a while loop.

Do while basically mean that while a condition is true the script will then keep looping.

This can be useful if we want to run a script for a certain period of time or while a process is running.

Below will loop through till the number in the variable $i is 10 then it will run the second write host.

$i = 1;
Do {
    Write-host "is $i less then 10" -ForegroundColor Red
    $i++;
}
While ($i -lt 10)
Write-Host "is 10 or greater" -ForegroundColor Green

Next we will go through do until, the different between do while and do until is that while uses true and until uses false condition.

This could be used if we wanted to check if a certain number of files or in an install script we could wait for certain process to finish before completing the next part.

Below example I am using a do until on a folder to check how many logs are there and using a do while to create the logs.

Check logs count.

Do {

    $logs = Get-ChildItem -Path C:\temp\Logs
    Start-Sleep 5
    Write-Host "Less than 10 logs found" -ForegroundColor Green
}
Until ($logs.count -gt "10" )
Write-Host "More than 10 logs found" -ForegroundColor Red

Create logs files.

$i = 1;
Do {
    New-Item "C:\temp\Logs\Log$i.log"
    $i++;
}
While ($i -lt 10)

This has been overview of some of the different types of loops and how to use them. There are pros and cons to using each and the right one to use will really depend on what the script is being used for.

Using Group Managed Services Account with Scheduled Tasks

In this post we will be going through the steps required to create and use group managed services account (gMSA) with a scheduled task.

gMSA are a managed domain account that provides automatic password management. These accounts provide a single identity to use on multiple servers.

By using a gMSA account, we can configure services / scheduled tasks with the gMSA principal and Active Directory handles the password management.

gMSAs where introduced since Windows Server 2012.

There are pre-requests to use gMSA that most domain should already meet, this is AD Schema of 52 (2012) and at least one 2012 DC.

Once we meet the minimum scheme the second part is that we have to create the Key Distribution Services Root Key.

This involves running a command in PowerShell, we can the below command to confirm that a kds root key doesn’t exist already.

Get-KdsRootKey
Get KDS Root Key

To create the KDS run

Add-KdsRootKey –EffectiveImmediately
Adding root key

Now when we check KDS again we can see the root key.

Get KDS Root Key

Now that we have the KDS root key we can create the gMSA

We can add the host either individually or using a security group, we will be using a group in this post as it will be easier to mange and just need to add any additional servers to the group to allow access.

I have create a group called tskgmsa_access to use and added some server computer accounts.

The below command is used to create the gMSA account (The DNS is required by the command but not needed for running scheduled task so you can use whatever name as it doesn’t need to be resolvable)

New-ADServiceAccount -name gMSAName -DNSHostName DNSName -PrincipalsAllowedToRetrieveManagedPassword "Group or Hosts"
Create gMSA Account

The accounts are create under the Managed Services Accounts OU.

Managed Accounts OU

We can add the account to a security group to give more rights, this could be used if the account needs admin right to do a specific tasks.

The Microsoft documentation says that you need to install RSAT tools and run Install-ADServiceAccount but I didn’t have to do this for scheduled task to run.

To allow the account to run a script we need to add the account to the logon as a batch job under user rights assignment. This can either be done using group policy or using secpol.msc.

I used secpol as i only have two servers to configure.

To test we will create a scheduled task that will out put text to a log file.

Below is the script file that will be run.

Test Script

To use the gMSA account we have to create the task using PowerShell as the GUI can’t find the account.

Below is the command I used.

$arg = "-ExecutionPolicy Bypass -NoProfile -File C:\scriptpath\script.ps1"

$ta = New-ScheduledTaskAction -Execute C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe  -Argument $arg

$tt = New-ScheduledTaskTrigger -At "Time to Run"

$ap = New-ScheduledTaskPrincipal -UserID Domain\gMSA_AccountName -LogonType Password

Register-ScheduledTask gMSA_Test_Task –Action $ta –Trigger $tt –Principal $ap

If you get incorrect users or password and only recently added the computer account to the security group, the server will need a reboot to pickup the membership.

Scheduled Task Error
Create Scheduled Task
Scheduled Task

Next we need to run the task and confirm data is written to the log. From the task events we can see the account used is gmsa_tsksch$.

Scheduled Task Event

We can also see the authentication on the domain controller.

Logon Event

When we check the logs folders we can see the text files are created.

Test Log

This has been a overview of creating and using a Group Managed Service Account for running scheduled tasks.

PowerShell Beginner’s Guide – Filtering Objects

In this post we will be going over filtering in PowerShell and different methods available.

Filtering should be done as close to the source command as possible, this will speed up the time it takes for the command to complete and return the data.

Depending on the command used there can be a filter parameters available, if there is no filtering we would use where-object.

Where-Object can be used to filter objects based on any property that is returned from the command.

If we need help with example or the right syntax to run the command we can use

Get-Help Where-Object

Get-Help Where-Object -Examples
Where-object help

Where-object can be used with lots of filtering parameters to return objects like Contains, eg (equal to), gt (greater than), lt (less than), like…….

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/where-object?view=powershell-7.4#parameters

Once we have the syntax worked out we can start to filter the data to returned. In the below command we will return any file that has .pdf extension and just select the name to make the results easier to read.

Get-ChildItem -Path 'C:\Program Files\' -Recurse -File | Where-Object {$_.Name -like "*.pdf"} | Select-Object Name
where-object results

Get-ChildItem has a filter parameter, this allow us to test and show the speed difference when we can.

Below is the time when running the command using where-object.

Where-object command time

When we use the -filter with Get-ChildItem we can see that the time to run went from 6 second to 2 seconds.

Get-ChildItem Filter command time

This was only a small subset of data but if we where running against thousand or hundred of thousand of files this can add up and save minutes to hours of time for data to returned.