Streamline Your Scripting: 3 PowerShell Functions I Use Every Day

3 powershell functions I use daily

As I have spent more time learning and growing in PowerShell, I’ve finding more and more that there are things that I tend to reuse across my scripts. There are PowerShell functions that find their way more and more of my scripts as I go on because of their versatility or usability. I’ve started sanitizing a few of them and making them more general in the hope that others may be able to find value in them. Whether you change them to suit your needs or grab them as is, I think you’ll agree that they offer value to many tasks you may find yourself performing.

I’ve heard in the past that you shouldn’t save your functions, and that you should write them each time so you remember how they work, and how you made them. I find that the value of an efficient and clean function outweighs any amount of knowledge I am losing because I didn’t write it on the fly. I’m a bigger fan of solving problems once, and saving them or tweaking them to match whatever new problems come up. To support this, I just try to document them well enough to recall what each step does.

So these are 3 of my favorite functions that I use all the time, and I wanted to share. I hope you find as much value in them as I do. Let’s take a look.

DISCLAIMER

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

PowerShell Function #1: Get-RandomPassword
PowerShell Function #2: Remove-CloudGroups
PowerShell Function #3: Send-GraphMailMessage
Conclusion


PowerShell Function #1: Get-RandomPassword

The idea behind the first of these 3 PowerShell functions is to generate a random string of characters that could be used as a password. This function in its basic form will choose a random number between the default values of (min) 25 and (max) 32. It will then generate this random string of characters based on whatever random number it picks. Randomizing the number of characters from run to run ensure that the the number of possible password options is greatly increased from a brute force perspective.

However, in some cases you may have specific parameters you need to meet for password creation. Whether this is included as part of a user termination script or it is used with managing system passwords, the built in options give flexibility for whatever you are trying to use it for.

Get-RandomPassword

The full description and most up to date function can be found on GitHub here.

function Get-RandomPassword {
    [CmdletBinding()]
    Param (
    [String]$characters = "abcdefghiklmnoprstuvwxyzABCDEFGHKLMNOPRSTUVWXYZ1234567890!$%&/()=?}][{@#*+",
    [Int32]$minChar = 25,
    [Int32]$maxChar = 32
    )
    if ($minChar -le $maxChar) {
        $length = Get-Random -Count 1 -InputObject ($minChar..$maxChar)
        $random = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length }
        $private:ofs=""
        Write-Host "Password is $length characters long"
        return [String]$characters[$random] 
    }else {
        Write-Host "Your Minimum $minChar is greater than your maximum $maxChar, please adjust your values and try again" -ForegroundColor Red
    }
       
}

PowerShell Function #2: Remove-CloudGroups

Another of my PowerShell functions I get regular use out of is the Remove-CloudGroups function. This one is useful because it leverages Microsoft Graph to remove user group membership. This means there are no modules that need to be installed or maintained to make it work. You can use an App Registration you already have in place if it has the right permissions.

This function in particular works well because it checks to see where the group lives (On-prem or in Azure) and will let you know what action to take if it cannot handle there removal. Handy for Hybrid Azure AD environments. This function can also be modified to leverage it as a tool to reconcile the membership of group as well, and I may post that modification as that is also pretty useful.

Update 1/21/2023

I Converted this to use a switch instead of cascading If statements so it would be faster and more efficient. I also expanded the groups covered as I found that I had more missed originally than I thought. I attempted to convert everything over to use the Microsoft Graph PowerShell SDK, but unfortunately, I found that several parts of it did not work with PowerShell 5.1. I ultimately decided that it was better to stick with the Invoke-WebRequest for those Unified groups, and it works well. I also not have it skipping Dynamic Membership groups in addition to On-premises groups as I completely overlooked that the first time around.

Remove-CloudGroups

The full description and most up to date function can be found on GitHub here.

#Updated 1/21/2023
function Remove-CloudGroups {
    param (
        [Parameter(Mandatory)][string]$username
    )
    #gather details about the user in question
    [string]$usrUri = 'https://graph.microsoft.com/v1.0/users?$filter' + ("=startswith(mail, '$userName')")
    $User = (Invoke-RestMethod -Method Get -Uri $usrUri -Headers $headers).value
    $userId = $user.id

    #collect information about what groups the user is a part of
    [string]$allGrpUri = "https://graph.microsoft.com/v1.0/users/$userId/transitiveMemberOf/microsoft.graph.group"
    $groups = (Invoke-RestMethod -Method Get -Uri $allGrpUri -Headers $headers).value

    foreach ($grp in $groups) {
        switch ($true) {
        ($grp.mailEnabled -eq $true -and $grp.groupTypes -ne 'Unified') { 
                #This will remove the member from any Distribution List 
                Remove-DistributionGroupMember -Identity $grp.Mail -Member $user.displayName -Confirm:$false
                Write-Host "Removed from" $grp.displayName "Distribution Group" -ForegroundColor DarkCyan
            }
        ($grp.GroupType -eq 'Universal, SecurityEnabled' -and $grp.groupTypes -ne 'Unified') {
                #This will remove the member from any Mail-Enabled Security Group
                Remove-DistributionGroupMember -Identity $grp.displayName -Member $user.displayName -Confirm:$false
                Write-Host "Removed from" $grp.displayName "Mail-Enabled Security Group" -ForegroundColor DarkGreen
            }
        ($grp.MailEnabled -eq $true -and $grp.SecurityEnabled -eq $false -and $grp.groupTypes -ne 'Unified') {
                #This will attempt to remove the member from any 
                Remove-DistributionGroupMember -Identity $grp.Mail -Member $user.displayName -Confirm:$false 
                Write-Host "Removed from" $grp.displayName "Group" -ForegroundColor DarkCyan
            }
        ($grp.onPremisesSyncEnabled -eq $true) {
                #Skip on-prem groups that are sycned - they were removed in the AD section
                Write-Host $grp.displayName "is on-prem synced - not removed" -ForegroundColor DarkYellow
            }
        ($null -ne $grp.MembershipRule) {
                #Skip Dynamic Groups as they will be removed when conditions are no longer met
                Write-Host $grp.displayName "is Dynamic - not removed" -ForegroundColor DarkYellow
            }
            Default {
                #Remove user from All Azure AD groups, and M365 Groups
                $id = $grp.id
                #You must have the /$ref included at the end of this URI or it will delete the user instead of the reference
                [string]$DelUri = "https://graph.microsoft.com/v1.0/groups/$id/members/$userId" + '/$ref' 
                Invoke-RestMethod -Method Delete -Uri $DelUri -Headers $headers -ErrorAction SilentlyContinue
                Write-host "Removed from" $grp.displayName -ForegroundColor Green
            }
        }
    } 
}

PowerShell Function #3: Send-GraphMailMessage

This function has become a regular staple in my arsenal of scripts. The main reason for this is that like the function above, it does not require a particular module to be loaded, installed or updated. It adds a lot of flexibility, and enables me to include email notifications in most all of my automation scripts. Whether the notification is to me or someone else, I use this one ALL THE TIME!

Again, you need to use Microsoft Graph with this, but it works as an excellent alternative to Send-MgMailMessage. I like using it this way because in some of my scripts, I have an HTML template directly in the the script. In others I have it build the HTML message as the script runs, and sends me the final message as the summary. It’s not all that different from the Send-MgMailMessage function, but I find it to be more reliable and more flexible if I’m not already connected to Graph PowerShell SDK module.

function Send-GraphMailMessage {
    [CmdletBinding()]
    Param (
        [string]$from = "[email protected]",   
        [Parameter(Mandatory)][string]$subject,
        [Parameter(Mandatory)][string]$recipient, #person who has delegate access
        [Parameter(Mandatory)]$content
    )
    begin {
        $headers = @{
            "Authorization" = "Bearer $token"
            "Content-Type" = "application/json"
        }
        $data = @{
            message = @{
                subject = $subject
                body = @{
                    ContentType = "HTML"
                    Content = $content
                }
                toRecipients = @(
                    @{
                        EmailAddress = @{
                            Address = $recipient
                        }
                    }
                )
            }          
        }
        $apiUrl = "https://graph.microsoft.com/v1.0/users/$from/sendMail"
    }
    process {
        $json = $data | ConvertTo-Json -Depth 4
        Invoke-RestMethod -Uri $apiURL -Headers $headers -Method POST -Body $json
    }
}

Conclusion

There you have it, my top 3 PowerShell functions I get regular usage out of. I plan to include more of these later, and you can always find a complete and up to date list on my GitHub. This post was short and sweet compared to some of my other longer winded ones, but I wanted to get this out there to start sharing some of these ones I use so frequently. I’m also working on something larger that will take much more time, and I didn’t want to have too long of a gap between posts.

I hope you can also find some usefulness in these functions. Each of them could be easily modified and even improved to add more functionality. 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!

Smitty

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 →