DSCResources/LogonScript/LogonScript.schema.psm1
Configuration LogonScript { param ( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $ScriptPath, [Parameter()] [ValidateSet('Logon', 'Logoff', 'Startup', 'Shutdown')] [string] $RunAt = 'Logon', [Parameter()] [ValidateSet('Command', 'PowerShell')] [string] $ScriptType = 'Command', [Parameter()] [ValidateRange(0, 99)] [int] $Index = 0, [Parameter()] [ValidateNotNull()] [AllowEmptyString()] [string] $Parameters = '' ) # ============================================================ # Import dependency modules # ============================================================ Import-DscResource -ModuleName 'PSDesiredStateConfiguration' Import-DscResource -ModuleName 'DSCR_FileContent' # ============================================================ # Constant variables # ============================================================ $GroupPolicyPath = 'C:\Windows\System32\GroupPolicy' $GptIniPath = Join-Path -Path $GroupPolicyPath -ChildPath 'gpt.ini' $UserScriptsFolder = Join-Path -Path $GroupPolicyPath -ChildPath '\User\Scripts' $MachineScriptsFolder = Join-Path -Path $GroupPolicyPath -ChildPath '\Machine\Scripts' $UserScriptsIniFile = Join-Path -Path $UserScriptsFolder -ChildPath ('{0}scripts.ini' -f $(if ($ScriptType -eq 'PowerShell') { 'ps' })) $MachineScriptsIniFile = Join-Path -Path $MachineScriptsFolder -ChildPath ('{0}scripts.ini' -f $(if ($ScriptType -eq 'PowerShell') { 'ps' })) $UserScriptCSE = '{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{40B66650-4972-11D1-A7CA-0000F87571E3}' $MachineScriptCSE = '{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{40B6664F-4972-11D1-A7CA-0000F87571E3}' switch ($RunAt) { 'Logon' { $Target = 'User' $TargetScriptsIniFile = $UserScriptsIniFile $TargetScriptCSE = $UserScriptCSE $TargetExtensionsName = 'gPCUserExtensionNames' } 'Logoff' { $Target = 'User' $TargetScriptsIniFile = $UserScriptsIniFile $TargetScriptCSE = $UserScriptCSE $TargetExtensionsName = 'gPCUserExtensionNames' } 'Startup' { $Target = 'Computer' $TargetScriptsIniFile = $MachineScriptsIniFile $TargetScriptCSE = $MachineScriptCSE $TargetExtensionsName = 'gPCMachineExtensionNames' } 'Shutdown' { $Target = 'Computer' $TargetScriptsIniFile = $MachineScriptsIniFile $TargetScriptCSE = $MachineScriptCSE $TargetExtensionsName = 'gPCMachineExtensionNames' } } # ============================================================ # Rise a warning if the script path does not exist. # ============================================================ Script TestPath { SetScript = { $null = $TestScript } TestScript = { $local:ErrorActionPreference = 'Stop' if (-not (Test-Path -LiteralPath $using:ScriptPath -PathType Leaf)) { Write-Warning ('"{0}" is not exist.' -f $using:ScriptPath) } return $true } GetScript = { return @{ Result = $TestScript } } } # ============================================================ # Increment version numbers in the gpt.ini # ============================================================ Script IncrementGptIniVersion { SetScript = { $local:ErrorActionPreference = 'Stop' $local:GptIniPath = $using:GptIniPath $local:TargetScriptCSE = $using:TargetScriptCSE $local:TargetExtensionsName = $using:TargetExtensionsName if (-not (Test-Path -LiteralPath $GptIniPath -PathType Leaf)) { # Create gpt.ini if not exist. ('[General]', "$TargetExtensionsName=[$TargetScriptCSE]", 'Version=65537') |` Out-File -FilePath $GptIniPath -Encoding ascii } else { $GptIniContent = Get-Content -LiteralPath $GptIniPath $ExtensionsMatchInfo = $GptIniContent | Select-String -Pattern "$TargetExtensionsName=.*" if ($null -eq $ExtensionsMatchInfo) { $GptIniContent += "$TargetExtensionsName=[$TargetScriptCSE]" } else { $CSEMatchInfo = $GptIniContent | Select-String -Pattern "$TargetExtensionsName=.*\[$TargetScriptCSE\].*" if ($null -eq $CSEMatchInfo) { $private:Index = $ExtensionsMatchInfo.LineNumber - 1 $GptIniContent[$private:Index] = [string]($GptIniContent[$private:Index] + "[$TargetScriptCSE]") } } $VersionMatchInfo = $GptIniContent | Select-String -Pattern 'Version=(.+)' if ($VersionMatchInfo.Matches.Groups -and $VersionMatchInfo.Matches.Groups[1].Success) { [int]$CurrentVersionValue = [int]::Parse($VersionMatchInfo.Matches.Groups[1].Value) if ($TargetExtensionsName -eq 'gPCUserExtensionNames') { [int]$NewVersionValue = $CurrentVersionValue + 65536 } else { [int]$NewVersionValue = $CurrentVersionValue + 1 } $private:Index = $VersionMatchInfo.LineNumber - 1 $GptIniContent[$private:Index] = ('Version={0}' -f $NewVersionValue) } $GptIniContent | Set-Content -Path $GptIniPath -Encoding ascii -Force } } TestScript = { $local:ErrorActionPreference = 'Stop' Import-Module -Name DSCR_FileContent -Force -Verbose:$false if (-not (Test-Path -LiteralPath $using:GptIniPath -PathType Leaf)) { return $false } $ret = Select-String -LiteralPath $using:GptIniPath -Pattern "$using:TargetExtensionsName=.*\[$using:TargetScriptCSE\].*" -Quiet if ($false -eq $ret) { return $false } if (-not (Test-Path -LiteralPath $using:TargetScriptsIniFile -PathType Leaf)) { return $false } $scriptsIni = Get-IniFile -Path $using:TargetScriptsIniFile if ($using:Index -ge 1) { for ($i = 0; $i -lt $using:Index; $i++) { if ($null -eq $scriptsIni.$using:RunAt.('{0}CmdLine' -f $i)) { #Get ordinals for number $ordinalIndex = switch ($i % 10) { 1 { '{0}st' -f $i } 2 { '{0}nd' -f $i } 3 { '{0}rd' -f $i } Default { '{0}th' -f $i } } Write-Error ('The {0} entry of the {1} script is not exist. The Value of the Index ({2}) may invalid.' -f $ordinalIndex, $using:RunAt, $using:Index) } } } if ($scriptsIni.$using:RunAt.('{0}CmdLine' -f $using:Index) -ne $using:ScriptPath) { return $false } if ($scriptsIni.$using:RunAt.('{0}Parameters' -f $using:Index) -ne $using:Parameters) { return $false } return $true } GetScript = { return @{ Result = $TestScript } } DependsOn = '[Script]TestPath' } # ============================================================ # Create a file that defines the logon scripts. # ============================================================ IniFile CmdLine { Ensure = 'Present' Path = $TargetScriptsIniFile Section = $RunAt Key = ('{0}CmdLine' -f $Index) Value = $ScriptPath Encoding = 'unicode' DependsOn = '[Script]IncrementGptIniVersion' } IniFile Parameters { Ensure = 'Present' Path = $TargetScriptsIniFile Section = $RunAt Key = ('{0}Parameters' -f $Index) Value = $Parameters Encoding = 'unicode' DependsOn = '[Script]IncrementGptIniVersion' } # ============================================================ # Create necessary folders # ============================================================ if ($Target -eq 'Computer') { $Folder1 = Join-Path -Path $MachineScriptsFolder -ChildPath 'Startup' $Folder2 = Join-Path -Path $MachineScriptsFolder -ChildPath 'Shutdown' } else { $Folder1 = Join-Path -Path $UserScriptsFolder -ChildPath 'Logon' $Folder2 = Join-Path -Path $UserScriptsFolder -ChildPath 'Logoff' } File Folder1 { Ensure = 'Present' DestinationPath = $Folder1 Type = 'Directory' } File Folder2 { Ensure = 'Present' DestinationPath = $Folder2 Type = 'Directory' } # ============================================================ # Update policy # ============================================================ # Script GpUpdate { # SetScript = { } # TestScript = { # $private:out = & gpupdate.exe /Force /Target:$using:Target # $private:out | Where-Object { ![string]::IsNullOrWhiteSpace($_) } | Write-Verbose # $true # } # GetScript = { # return @{ # Result = $TestScript # } # } # DependsOn = '[IniFile]CmdLine', '[IniFile]Parameters' # } } |