Category Archives: PowerShell

Active Directory provisioning script

When writing PowerShell scripts for use in our Active Directory environment, I noticed that I use the same variables and information in every script. That’s all fine, but when something changes I had to update each and every script seperately. And you always forget to update 1 or 2 scripts which is annoying.
At one of my previous employers, they developed something they refered to as a provisioning script. This script not only contained these variables and information, but also a lot of commonly used functions. Among others, this script contained functions to create new user accounts and service accounts. Other scripts, outside of the provisioning script, could then ‘import’ the provisioning script using a technique called dot sourcing and be able to use the variables declared in the provisioning script as well as the functions from the provisioning script.
So when information changes, I only have to update 1 location.

In our environment we have created an Active Directory administration OU (see one of my previous posts) which contain the admin accounts and service accounts.
The provisioning script declares all of the OU locations for items like admin accounts, service accounts, profile groups, role groups, etc. Function GetDomainConfig is used to declare these variables.

Below you can find a basic version of the provisioning script.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<###
.SYNOPSIS
    <Synopsis>

.DESCRIPTION
    <Description>

.NOTES
    File Name      : ICT-Provisioning.ps1
    Author         : Dennis Kool
    Prerequisites  : PowerShell V3, PSModule ActiveDirectory
#>


# ---------------------------------------------------------------------------------------------------------------

#Region 0 - Global PowerShell settings

$ErrorActionPreference = 'Stop'

#EndRegion 0 -  Global PowerShell settings

# ---------------------------------------------------------------------------------------------------------------

#Region 1 - Generic functions

Function MyLogger {
    Param(
        [Parameter(Mandatory = $True)]
        [String] $Message
    )

    $TimeStamp = Get-Date -Format "dd-MMM-yyyy HH:mm:ss"

    Write-Host -NoNewline -ForegroundColor White "[$timestamp]"
    Write-Host -ForegroundColor Green " $message"
}

Function MyLoggerError {
    Param(
        [Parameter(Mandatory = $True)] [String] $Message
    )

    $TimeStamp = Get-Date -Format "dd-MMM-yyyy HH:mm:ss"

    Write-Host -NoNewline -ForegroundColor White "[$timestamp]"
    Write-Host -ForegroundColor Red -BackgroundColor Yellow " $message"
}

#EndRegion 1 - Generic functions

# ---------------------------------------------------------------------------------------------------------------

#Region 2 - ActiveDirectory related functions
Function GetDomainConfig {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $True)]
        [ValidateSet(
            '<FQDN of AD domain 1>',
            '<FQDN of AD domain 2>',
            '<FQDN of AD domain 3>'
        )]
        [String] $Domain
    )

    BEGIN { } # Begin

    PROCESS {
        If (-not (Get-Module -Name 'ActiveDirectory' -ErrorAction SilentlyContinue)) {
            Import-Module ActiveDirectory
        }

        # Clear variables in case GetDomainConfig has been used before in the same PowerShell session
        $Global:DomainData = $null
        $Global:DomainDistinguishedName = $null
        $Global:DomainDNSRoot = $null
        $Global:DomainDC = $null
        $Global:DomainNetBIOSName = $null
        $Global:DomainNetlogonDir = $null
        $Global:AdminAccountsOU = $null
        $Global:DisabledAdminAccountsOU = $null
        $Global:ServiceAccountsOU = $null


        # Standard RBAC OU structure
        $Global:DomainData = Get-ADDomain -Server $Domain
        $Global:DomainDistinguishedName = $Global:DomainData.DistinguishedName
        $Global:DomainDNSRoot = $Global:DomainData.DNSRoot
        $Global:DomainDC = $Global:DomainData.PDCEmulator
        $Global:DomainNetBIOSName = $Global:DomainData.NetBIOSName
        $Global:DomainNetlogonDir = "\" + $Global:DomainDNSRoot + "\NetLogon"
        $Global:AdminAccountsOU = "OU=Admin accounts,OU=Accounts,OU=ICT-Administration," + $Global:DomainDistinguishedName
        $Global:DisabledAdminAccountsOU = "OU=_Disabled," + $Global:AdminAccountsOU
        $Global:ServiceAccountsOU = "OU=Service Accounts," + $Global:DomainDistinguishedName


        # Exceptions to standard RBAC OU structure for e.g. a specific AD domain
        #If ($Domain -eq 'FQDN of AD domain') {
        #$Global:AdminAccountsOU = "OU=Admin accounts,OU=Accounts,OU=ICT-Administration," + $Global:DomainDistinguishedName
        #}


        Clear-Host
        Write-Host -ForegroundColor Green  '$DomainAdminAccountsOU              =' $AdminAccountsOU
        Write-Host -ForegroundColor Green  '$DomainDisabledAdminAccountsOU      =' $DisabledAdminAccountsOU
        Write-Host -ForegroundColor Green  '$DomainDC                           =' $DomainDC
        Write-Host -ForegroundColor Green  '$DomainDistinghuishedName           =' $DomainDistinguishedName
        Write-Host -ForegroundColor Green  '$DomainDNSRoot                      =' $DomainDNSRoot
        Write-Host -ForegroundColor Green  '$DomainNetBIOSName                  =' $DomainNetBIOSName
        Write-Host -ForegroundColor Green  '$DomainNetlogonDir                  =' $DomainNetlogonDir
        Write-Host -ForegroundColor Green  '$LeveranciersAccountsOU             =' $LeveranciersAccountsOU
        Write-Host -ForegroundColor Green  '$DomainServiceAccountsOU            =' $ServiceAccountsOU

    } # Process

    END { } # End
} # Function GetDomainConfig


#EndRegion 2 - Active Directory related functions

# ---------------------------------------------------------------------------------------------------------------

To use the provisioning script, all you have to do is dotsource it from either a PowerShell window or from a script. Notice the dot (.) at the beginning of the line. This is very important but easily overlooked !!

[cc lang=”powershell”]
. :\Folder\ICT-Provisioning.ps1
. \\


You can now run command GetDomainConfig to show you which variables are now available and what their values are. In my next post I will share with you the function I have written to create new admin accounts, which uses the information provided by function GetDomainConfig.

I hope it’s clear what a provisioning script can do for you and how to use it. If not, please leave a comment and I will try to make this post more clear.
As always, please keep in mind this script is tailored to my environment, but can be used as a template for your environment. I do not pretend to be a PowerShell guru and as such my script may not be perfect. I am open to suggestions  🙂
If you found this script useful, I’d appreciate it if you leave a comment.

Monitor AD group changes

Ever wanted to monitor group changes in AD? This is a script I came up with to do just that. It will collect the security log events from the last hour on all your domain controllers.

In order to use this script, just create a new scheduled task on a machine with the Active Directory module for Windows PowerShell installed and run this script every hour (or whatever you changed $time to). !! Note that the scheduled task needs to be run with an account which has domain admin privileges to be able to read from the security logs of all your domain controllers !!>

The script needs some customization to your environment:

Continue reading Monitor AD group changes

Inventory VMware virtual machines

For reporting purposes, I maintain an Excel sheet containing information on my server base. I update this sheet on a weekly basis. Part of the information displayed in this sheet comes from a PowerShell script I have created to extract the required data from our vCenters.

This script pulls the following information for every VM running the vCenter environment: VM Name, Hardware version, VMware tools status, guest OS, number of vCPU’s, amount of assigned RAM, the host the VM runs on, the cluster the VM is assigned to, the folder it lives in, the power status, number of NICs, the NIC types and the vCenter it runs on (in case you have more than 1). Continue reading Inventory VMware virtual machines

Fix Windows Update error code 0x80244022, 0x8024401C and 0x80072EE2

WSUS is a great product from Microsoft to keep your servers up to date. In the past years, I have often used it at the companies I worked for. But it has it downsides as well. Sometimes the Windows Update client just won’t work. You’ll get errors like 0x80244022, 0x8024401C and 0x80072EE2 and just haven’t got a clue what is going on.

I have collected a number of solutions to fix these errors and put them in a PowerShell script. This script contains all the tricks I had to pull to get the Windows Update client running again.
Continue reading Fix Windows Update error code 0x80244022, 0x8024401C and 0x80072EE2