This is a base runbook template developed by CT Global.

This version was first presented at Experts Live EU 2017.


.VERSION 1.0.0

.GUID d5033d8e-237f-42dc-84b7-6d2d20605e9f

.AUTHOR Jakob Gottlieb Svendsen & Andreas Sobczyk , CTGlobal.










Change Log:
1.0.0 - Initial Version
        Awesome template for Azure Automation / SMA.
 Completed script and errors are logged to 1 or more eventlog events in Application Eventlog
Event IDs (Application Log):
1000: Information - Successfully completed
1001: Error - General Error
1002: Error - Error in Toolkit - script continues
1003: Warning - List of machines which is active in SP but not active in SCCM
1004: Error - Server has issue, skipped to next server 

[OutputType([Object])] #Set to specific object type if possible (fx. if script gets a ADUser, set output type to ADUser)
    [Parameter (Mandatory = $true)]
    [String] $ResourceGroupName

    $ErrorActionPreference = "stop"
    $VerbosePreference = "silentlycontinue"

    #//  Global constant and variable declarations
    #//  Shared Resource retrieval (Assets)
    $Prefix = "CT-"
    $Credential = Get-AutomationCredential -Name "Admin"

    #//  Procedures (Logging etc.)
    #region Procedures
    Function Add-Tracelog {
    Adds a tracelog message to tracelog 
    Uses a script scope tracelog variable to have alle scopes write to a sinlg etracelog.
    Outputs each message to the Verbose stream.
    param($Message, $TraceLog)

        $Message = "$(get-date) - $Message`n"
        Write-Verbose $Message
        if ([String]::IsNullOrEmpty($TraceLog)) {
            $TraceLog = $Message
        else {
            $TraceLog += $Message
    Function ConvertTo-IndexedTable {
    Converts an array of objects to a array of hashtables for performance
    Converts an array of objects to a hashtable of hashtables for performance
    The hashtable has takes one field as index, for example name 
    and the index field can be used to filter/sort much quicker than and array of objects. 
    (see example for details)
    Get-CMDevice -CollectionName "All Systems" -Fast | ConvertTo-IndexedTable Name

    Name                           Value
    ----                           -----
    Object                         ...
    Name                           NCOP-CCMP-CCM01

    the index field is available directly, while the complete object is available in the object key of the hash table.
            [Parameter(Mandatory = $true,
                ValueFromPipelineByPropertyName = $false,
                Position = 0)]
            [Parameter(Mandatory = $true,
                ValueFromPipelineByPropertyName = $true,
                ValueFromPipeline = $true,
                Position = 1)]

        #begin { $ReturnArray = @() } #New-Object System.Collections.ArrayList }
        process {
                $IndexFieldName = $Object.$IndexFieldName
                Object          = $Object
        #end { $ReturnArray }

    #//  Main routines

    Try { #Main Catch
        $script:TraceLog = $null #when testing in ISE, tracelog is not reset
        $StartTime = get-date
        Add-Tracelog -TraceLog $TraceLog -Message "Job Started at $StartTime"
        Add-Tracelog -TraceLog $TraceLog -Message "Running on: $env:computername"

        $OutputData = @{}

        #region Main Code
        #Import Modules
        Add-Tracelog -TraceLog $TraceLog -Message "Import SCCM Module"
        Import-Module AzureRM

        #Redirect all outputs to $null
        $null = . {

        $EndTime = Get-date
        Add-Tracelog -TraceLog $TraceLog -Message "Finished at: $EndTime"
        Add-Tracelog -TraceLog $TraceLog -Message "Total Runtime: $($Endtime - $StartTime)"

        $OutputData.Add("TraceLog", $TraceLog)
        $OutputData.Add("Status", "Success")
        Write-Output $OutputData

        Write-Verbose $TraceLog
    Catch {
        $ErrorMessage = $_.Exception.Message + "`nAt Line number: $($_.InvocationInfo.ScriptLineNumber)"
        Write-Error -Message $ErrorMessage
        $OutputData.Add("ErrorMessage", $ErrorMessage)
        $OutputData.Add("Status", "Failed")
        Write-Output $OutputData
    #//  End Script