Friday, June 13, 2014

Script to inventory logon / logoff / startup / shutdown scripts in GPO environment

I was looking for a way on how to access programmatically GPO information about different type of GPO logon, etc. scripts.
Unfortunately standard GPO cmdlets don't cover this part of GPO configurations. So after a bit of looking around on MSDN GPO Documentation, I confirmed my assumptions that it's stored in scripts.ini files on Sysvol. So for any given GPO you need to look in these 2 places:
- User part: \\domain\SYSVOL\domain\Policies\GPO_GUID\User\Scripts\scripts.ini
- Computer part: \\domain\SYSVOL\domain\Policies\GPO_GUID\Machine\Scripts\scripts.ini

Following this I've created a script that goes through all GPOs in AD & inventories the information about all scripts referenced there.
InventoryLogonScriptsInGPOs.ps1
# Inventory script to gather the information about logon / logoff / startup / shutdown scripts in your environment
# It's scanning all GPOs in your environment & checking Sysvol for scripts.ini files
# that contain references about these scripts
# support maximum 10 scripts per GPO part (user or machine)
# Author: Michael Sedenkov (PMI)

clear
#please define here your domain name
$DomainName = "domain"
#please define here the path to your Policies folder on Sysvol
$SysvolPath = "\\domain\SYSVOL\domain\Policies"


Function ParseScriptsINI ($FileToParse, $GPOpart) {
    #Initialize variables
    $LogonScriptsList = "no", "no", "no", "no", "no", "no", "no", "no", "no", "no"
    $LogonScriptsParameters = "no", "no", "no", "no", "no", "no", "no", "no", "no", "no"
    $LogoffScriptsList = "no", "no", "no", "no", "no", "no", "no", "no", "no", "no"
    $LogoffScriptsParameters = "no", "no", "no", "no", "no", "no", "no", "no", "no", "no"
    $StartupScriptsList = "no", "no", "no", "no", "no", "no", "no", "no", "no", "no"
    $StartupScriptsParameters = "no", "no", "no", "no", "no", "no", "no", "no", "no", "no"
    $ShutdownScriptsList = "no", "no", "no", "no", "no", "no", "no", "no", "no", "no"
    $ShutdownScriptsParameters = "no", "no", "no", "no", "no", "no", "no", "no", "no", "no"
    $LogonScriptCounter = 0
    $LogoffScriptCounter = 0
    $StartupScriptCounter = 0
    $ShutdownScriptCounter = 0
    $section = ""

    #read file content
    $AllLines = Get-Content -Path $FileToParse

    #if the file is too short - escaping
    if ($AllLines.Count -le 1) { Write-Debug "File is too short, doing nothing"; return }

    #parse line by line
    foreach ($line in $AllLines) {
        switch ($line.Trim())
        {
            #defining in what part of the file we are
            "" {Write-Debug "empty line"}
            "[Logon]" { Write-debug "found logon scripts section"; $section = "logon"}
            "[Logoff]" { Write-debug "found logoff scripts section"; $section = "logoff"}
            "[Startup]" { Write-debug "found logoff scripts section"; $section = "startup"}
            "[Shutdown]" { Write-debug "found logoff scripts section"; $section = "shutdown"}
            "[ScriptConfig]" { Write-debug "found configuration section"; $section = "config"}
         default {
                #trying to split the script line
                $data = $line.Split("=")
                if ($data[0].Trim() -eq "") { exit }
                #reading logon section
                if ($section -eq "logon") {
                        #increasing the counter
                        $LogonScriptCounter = [int]($data[0].Chars(0)).tostring() + 1
                        #populating the scripts array
                        if ($data[0].Contains("CmdLine")) {$LogonScriptsList[[int]($data[0].Chars(0)).tostring()] = $data[1]}
                        #populating the parameters array
                        if ($data[0].Contains("Parameters")) {$LogonScriptsParameters[[int]($data[0].Chars(0)).tostring()] = $data[1]}
                    }
                if ($section -eq "logoff") {
                        $LogoffScriptCounter = [int]($data[0].Chars(0)).tostring() + 1
                        if ($data[0].Contains("CmdLine")) {$LogoffScriptsList[[int]($data[0].Chars(0)).tostring()] = $data[1]}
                        if ($data[0].Contains("Parameters")) {$LogoffScriptsParameters[[int]($data[0].Chars(0)).tostring()] = $data[1]}
                    }
                if ($section -eq "startup") {
                        $StartupScriptCounter = [int]($data[0].Chars(0)).tostring() + 1
                        if ($data[0].Contains("CmdLine")) {$StartupScriptsList[[int]($data[0].Chars(0)).tostring()] = $data[1]}
                        if ($data[0].Contains("Parameters")) {$StartupScriptsParameters[[int]($data[0].Chars(0)).tostring()] = $data[1]}
                    }
                if ($section -eq "shutdown") {
                        $ShutdownScriptCounter = [int]($data[0].Chars(0)).tostring() + 1
                        if ($data[0].Contains("CmdLine")) {$ShutdownScriptsList[[int]($data[0].Chars(0)).tostring()] = $data[1]}
                        if ($data[0].Contains("Parameters")) {$ShutdownScriptsParameters[[int]($data[0].Chars(0)).tostring()] = $data[1]}
                    }
                }
                
         }
    }

    #in case something is found - printing it out
    if ( ($GPOpart -eq "User") -and (($LogonScriptCounter -ne 0) -or ($LogoffScriptCounter -ne 0))) {
        Write-Host "Parsing the GPO (User part):" $targetGPO.DisplayName "; GUID:{"$targetGPO.ID"}"
        if ($LogonScriptCounter -ne 0) { Write-Host "   Total number of logon  scripts: " $LogonScriptCounter}
        while ($LogonScriptCounter -ne 0) {
            Write-Host "   "$LogonScriptsList[$LogonScriptCounter - 1] "params:" $LogonScriptsParameters[$LogonScriptCounter - 1]
            $LogonScriptCounter = $LogonScriptCounter - 1
        }
        if ($LogoffScriptCounter -ne 0) { Write-Host "   Total number of logoff scripts: " $LogoffScriptCounter}
        while ($LogoffScriptCounter -ne 0) {
            Write-Host "   "$LogoffScriptsList[$LogoffScriptCounter - 1] "params:" $LogoffScriptsParameters[$LogoffScriptCounter - 1]
            $LogoffScriptCounter = $LogoffScriptCounter - 1
        }
    }

    if ( ($GPOpart -eq "Machine") -and (($StartupScriptCounter -ne 0) -or ($ShutdownScriptCounter -ne 0))) {
        Write-Host "Parsing the GPO (Machine part):" $targetGPO.DisplayName "; GUID:{"$targetGPO.ID"}"
        if ($StartupScriptCounter -ne 0) { Write-Host "   Total number of startup scripts: " $StartupScriptCounter}
        while ($StartupScriptCounter -ne 0) {
            Write-Host "   "$StartupScriptsList[$StartupScriptCounter - 1] "params:" $StartupScriptsParameters[$StartupScriptCounter - 1]
            $StartupScriptCounter = $StartupScriptCounter - 1
        }
        if ($ShutdownScriptCounter -ne 0) { Write-Host "   Total number of shutdown scripts: " $ShutdownScriptCounter}
        while ($ShutdownScriptCounter -ne 0) {
            Write-Host "   "$ShutdownScriptsList[$ShutdownScriptCounter - 1] "params:" $ShutdownScriptsParameters[$ShutdownScriptCounter - 1]
            $ShutdownScriptCounter = $ShutdownScriptCounter - 1
        }
    }
}

#look at all GPOs in the domain environment
$AllDomainGPOs = (Get-GPO -All -Domain $DomainName | sort DisplayName)

#for each GPO we check if there are any logon / logoff / startup / shutdown scripts
foreach ($targetGPO in $AllDomainGPOs) {

    #construct path to User part scripts
    $InputFileUser = $SysvolPath + "\{$($targetGPO.ID)}\User\Scripts\scripts.ini"
    
    #if scripts.ini file exists - then we try to parse it
    if ((Test-Path $InputFileUser) -eq $true) { ParseScriptsINI $InputFileUser User }
    
    #construct path to Machine part scripts
    $InputFileMachine = $SysvolPath + "\{$($targetGPO.ID)}\Machine\Scripts\scripts.ini"
    
    #if scripts.ini file exists - then we try to parse it
    if ((Test-Path $InputFileMachine) -eq $true) { ParseScriptsINI $InputFileMachine Machine }
}

No comments:

Post a Comment