Streamline Your Scripting: 3 MORE PowerShell Functions I Find Helpful

Earlier this year I wrote about some PowerShell functions I use with regularity. After a few more months (and being busy and not getting much written recently) I figured its time I share a few more functions I find myself reusing. As always part of this focus is on documenting it for myself so it is easier to find, and if someone else finds them useful, then great.

Also like before, I believe in solving problems once, and reusing the solutions that work. So, I document my favorite functions and remind myself how I used them last time. This way when I am searching for a solution next time, I will remember why I wrote the code the way I wrote it. If you missed that first post, check it out here.

Streamline Your Scripting: 3 PowerShell Functions I Use Every Day » See Smitty…

Otherwise, lets dig in and see what I’ve got cooked up this time.


Please understand that the content herein is for informational purposes only. This existence and contents shall not create an obligation, liability or suggest a consultancy relationship. In further, such shall be considered as is without any express or implied warranties including, but not limited to express and implied warranties of merchantability, fitness for a particular purpose and non-infringement. There is no commitment about the content within the services that the specific functions of the services or its reliability, applicability or ability to meet your needs, whether unique or standard. Please be sure to test this process fully before deploying in ANY production capacity, and ensure you understand that you are doing so at your own risk.

Table of Contents


Test-Finished Function

This is one I use quite frequently. If I am writing scripts that might be run over and over again, this is a simple PowerShell function that doesn’t require the script to end for it to be run again. For example, if I have to process terminated user accounts, I may not want to have to sign out and back in every time, so I use Test-Finished to save me the trouble.

Test-Finished.ps1 · SeeSmitty GitHub

Example Script

#Begin Example Script

function Test-Finished {
    $finished = Read-Host "Do Need to assign any more licenses? Y or N" 
    IF ($finished -like "Y") {
    ELSE {
        Write-Host "Disconnecting from Graph" -ForegroundColor Blue

function Start-AssignLicense {
    try {
        $input = Read-Host "What user do you want to assign a license to?"
        $user = Get-MgUser -ConsistencyLevel eventual -Search '"DisplayName:$input"'
        $EmsSku = Get-MgSubscribedSku -All | Where SkuPartNumber -eq 'EMSPREMIUM'
        Set-MgUserLicense -UserId $ -AddLicenses @{SkuId = $EmsSku.SkuId} -RemoveLicenses @()
        #Run the test Finished function to either quit or restart the loop
    catch {
        Write-Host $Error

#connect Graph

#begin Loop

You can see here that the script is split between 2 functions that call each other at various points. This allows the user running the script to perform an action, and then begin from the beginning if they choose to. This is a simplified example, but it should demonstrate why I find this function helpful. One other specific use case I’ve used this for is to assign employees a phone number in teams.

I’m sure you could bypass this with a CSV file, and specific inputs in each column, and just run it that way. Sometimes though, I want to just run something for a few users and instead of updating a CSV, this lets me just cycle through a few times.

ConvertFrom-Seconds Function

This is one I found I needed after I started working with certain API’s. Some API’s I’ve used will require that you convert the time from UNIX EPOCH rather than have it already calculated for you. This is probably not new to some folks, but it was for me. I decided that I needed to have a way that was easy to do since I needed to repeat it dynamically throughout my scripts. Here is how I did it.

ConvertFrom-Seconds.ps1 · SeeSmitty Github

function ConvertFrom-Seconds {
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
    process {
        $apiDate = (Get-Date -Date "01-01-1970") + ([System.TimeSpan]::FromSeconds(($Seconds)))
        $timeZoneOffset = [System.TimeSpan]::FromHours(-4)  # Eastern Daylight Time offset
        $convertedDateTime = $apiDate.Add($timeZoneOffset)
    end {
        return $convertedDateTime

I have this written specifically for Eastern Time Zone, but its an easy enough conversion if you want a different time zone. Just change the timezoneOffset from “-4” to whatever you need it to be. If you spend some time working with API’s, then this function might be useful to you.

Remove-NetworkPrinter Function

I wanted to create a function that I could use a printer name or IP Address because despite all my best efforts, printers don’t always install the way I want. So this way, I could feed it a list of printer names and IP Addresses, and it will make the decision about what is the best method to uninstall the printer based on what I gave it. As such, here is the function.

Remove-NetworkPrinter.ps1 · SeeSmitty

function Remove-NetworkPrinter {
    param (
    switch -Regex ($printer) {
        '\b(?<ipv4>\d{1,3}(?:\.\d{1,3}){3})\b' {
            if ($Matches['ipv4'] -as [IPAddress]) {
                # It's an IP address - Removing Printer by IP Address
                $printerToRemove = Get-WmiObject -Class Win32_Printer | Where-Object { $_.PortName -eq $printer }
                Write-Host "Removing Printer by IP Address"
        default {
            # This is the default case for printer name processing
            $printerToRemove = Get-WmiObject -Class Win32_Printer | Where-Object { $_.ShareName -eq $printer }
            Write-Host "Its not an IP Address - Removing by Printer Name"

    if ($printerToRemove) {
        #Removes the printer
        Write-Host "Printer removed successfully."
    else {
        Write-Host "Printer not found or removal failed."

This gives me some flexibility as well as functionality. Plus, it gave me an opportunity to start using a switch, which is something I’ve not done a lot of, nor do I have a lot of experience with. It is something I plan on expanding on in the future and rewriting some of my previous scripts as it makes sense. This is just one of the first examples.


Well, there you have it, three more scripts from my personal collection. These aren’t necessarily daily PowerShell functions, but they can come in handy when writing scripts, and hopefully it saves you time like it saved me. As I continue to find things I’ve found to be useful, I will check back in and share them here.

I’d love to hear how you were able to use one of these or how you were able to improve them. Hit me up on Twitter @SeeSmittyIT to let me know what you thought of this post. Or if you are avoiding the bird site, I’m also posted up on Mastodon @[email protected]. Thanks for reading!


Curtis Smith works in IT with a primary focus on Mobile Device Management, M365 Apps, and Azure AD. He has certifications from CompTIA and Microsoft, and writes as a hobby.

View all posts by Smitty →