One of those most common tasks help desk technicians and system administrators find themselves doing is provisioning user resources. Depending on the services the business has, those tasks may include creating Active Directory user accounts, creating home folders, provisioning new Office 365 mailboxes, setting up a VoIP extension in the phone system and all kinds of other tasks.

If you're not automating this process to some degree, you're wasting your precious time!

Document Onboarding Tasks

When sitting down to automate this process, it's essential to define all of the tasks that have to happen. At a minimum, many companies have a document that outlines all of the steps IT must take to onboard a new employee. Use that as your starting point. Document things like:

  • Creating an Active Directory user account
  • Creating a user folder on a file share somewhere
  • Assigning a mobile device

When building a PowerShell script to automate this process, first research and figure out which processes can be automated with PowerShell. For example, perhaps the system you're using to assign a mobile device doesn't have an API. This can't be completely automated.

Instead of ignoring it, you can still account for this in your script by sending an email to the appropriate person. Its sorta automating this process because the responsible person will be notified, but it's better than nothing!

For all of the other tasks that can be automated with PowerShell, you'll need to start scaffolding out some code.

Open up your favorite PowerShell code editor and let's get started!

Prerequisites

Before you get too far, you'll need to ensure the machine you're running the code on in this post has some prereqs:

  • Windows 10 Build 1809 or higher (although may work with earlier builds)
  • ActiveDirectory module. Install via Add-WindowsCapability –online –Name “Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0”
  • Logged into an Active Directory-joined computer with a user with permissions to create user accounts

Code Scaffolding

First, build out some essential functions that will encapsulate each task. Below I've shown you an example of functions you could build for each of the tasks we're working with.

param(
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$CsvFilePath
)

function New-CompanyAdUser {
    [CmdletBinding()]
    param
    (
        
    )
    
}

function New-CompanyUserFolder {
    [CmdletBinding()]
    param
    (
        
    )

}

function Register-CompanyMobileDevice {
    [CmdletBinding()]
    param
    (
        
    )

}

function Read-Employee {
    [CmdletBinding()]
    param
    (
        
    )

}
New-Employee.ps1

We're not working with "real" code at this time. At this point, we're mostly brainstorming with code.

Receiving Input

Notice the param block at the top and the Read-Employee function. This function will receive input of whatever kind you expect. Will you be providing the script a CSV? Database? Regardless, when we have a function created, we can easily add or replace code at will if that method ever changes.

For now, you're using a CSV file making the Read-Employee script look like below. The below function will take the CSV file path given when running the script by default.

function Read-Employee {
    [CmdletBinding()]
    param
    (
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$CsvFilePath = $CsvFilePath
    )

    Import-Csv -Path $CsvFilePath

}

We have a CSV that we get from HR that looks like this:

FirstName,LastName,Department
Adam,Bertram,Accounting
Joe,Jones,HR

We can then call the script (I'll call mine New-Employee.ps1) with the CsvFilePath parameter.

PS> ./New-Employee.ps1 -CsvFilePath './Employees.csv'

Building the Functions

We'll now fill in each of the other functions. I'm skipping over a lot of this because it could potentially be different for your organization. This is just an example but should give you a good idea of how your code could be built. For more information on how the New-CompanyAdUser function is made, check out the blog post Automating Employee Onboarding in Active Directory.

param(
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$CsvFilePath
)

function New-CompanyAdUser {
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [pscustomobject]$EmployeeRecord
    )
    
    Add-Type -AssemblyName 'System.Web'
    ## Generate a random password
    $password = [System.Web.Security.Membership]::GeneratePassword((Get-Random -Minimum 20 -Maximum 32), 3)
    $secPw = ConvertTo-SecureString -String $password -AsPlainText -Force

    ## Generate a first initial/last name username
    $userName = "$($EmployeeRecord.FirstName.Substring(0,1))$($EmployeeRecord.LastName))"

    ## Create the user
    $NewUserParameters = @{
        GivenName       = $EmployeeRecord.FirstName
        Surname         = $EmployeeRecord.LastName
        Name            = $userName
        AccountPassword = $secPw
    }
    New-AdUser @NewUserParameters

    ## Add the user to the department group
    Add-AdGroupMember -Identity $EmployeeRecord.Department -Members $userName
}

function New-CompanyUserFolder {
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [pscustomobject]$EmployeeRecord
    )

    $fileServer = 'FS1'

    $null = New-Item -Path "\\$fileServer\Users\$($EmployeeRecord.FirstName)$($EmployeeRecord.LastName)" -ItemType Directory

}

function Register-CompanyMobileDevice {
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [pscustomobject]$EmployeeRecord
    )

    ## Send an email for now. If we ever can automate this, we'll do it here.
    $sendMailParams = @{
        'From'       = '[email protected]'
        'To'         = '[email protected]'
        'Subject'    = 'A new mobile device needs to be registered'
        'Body'       = "Employee: $($EmployeeRecord.FirstName) $($EmployeeRecord.LastName)"
        'SMTPServer' = 'smtpserver.something.local'
        'SMTPPort'   = '587'
    }
    
    Send-MailMessage @sendMailParams

}

function Read-Employee {
    [CmdletBinding()]
    param
    (
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$CsvFilePath = $CsvFilePath
    )

    Import-Csv -Path $CsvFilePath

}

Read-Employee

Calling the Functions

Once all of the functions have been built, you'll then need to pass each of the employee records returned from Read-Employee to each function, as shown below.

$functions = 'New-CompanyAdUser','New-CompanyUserFolder','Register-CompanyMobileDevice'
foreach ($employee in (Read-Employee)) {
    foreach ($function in $functions) {
        & $function -EmployeeRecord $employee
    }
}

You can see that since I've standardized all of the function parameters to have a single parameter EmployeeRecord which coincides to a row in the CSV file, I can define the functions I want to call in an array an loop over each of them.

Summary

Every company's employee, provisioning script, is going to be a little different. However, using the PowerShell coding skills you've learned in this article along with the examples we covered should provide you with a high starting point at finally automating all of that tedious onboarding work!

Download the code we wrote in this article on GitHub.

Further Reading

Join the Jar Tippers on Patreon

It takes a lot of time to write detailed blog posts like this one. In a single-income family, this blog is one way I depend on to keep the lights on. I'd be eternally grateful if you could become a Patreon patron today!

Become a Patron!