Dmitry Nefedov
3 years ago
5 changed files with 0 additions and 1312 deletions
@ -1,555 +0,0 @@ |
|||
#requires -Version 2.0 |
|||
|
|||
$scriptRoot = Split-Path $MyInvocation.MyCommand.Path |
|||
. "$scriptRoot\Common.ps1" |
|||
|
|||
<# |
|||
.SYNOPSIS |
|||
Creates or modifies a value in a .pol file. |
|||
.DESCRIPTION |
|||
Creates or modifies a value in a .pol file. By default, also updates the version number in the policy's gpt.ini file. |
|||
.PARAMETER Path |
|||
Path to the .pol file that is to be modified. |
|||
.PARAMETER Key |
|||
The registry key inside the .pol file that you want to modify. |
|||
.PARAMETER ValueName |
|||
The name of the registry value. May be set to an empty string to modify the default value of a key. |
|||
.PARAMETER Data |
|||
The new value to assign to the registry key / value. Cannot be $null, but can be set to an empty string or empty array. |
|||
.PARAMETER Type |
|||
The type of registry value to set in the policy file. Cannot be set to Unknown or None, but all other values of the RegistryValueKind enum are legal. |
|||
.PARAMETER NoGptIniUpdate |
|||
When this switch is used, the command will not attempt to update the version number in the gpt.ini file |
|||
.EXAMPLE |
|||
Set-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key Software\Policies\Something -ValueName SomeValue -Data 'Hello, World!' -Type String |
|||
|
|||
Assigns a value of 'Hello, World!' to the String value Software\Policies\Something\SomeValue in the local computer Machine GPO. Updates the Machine version counter in $env:systemroot\system32\GroupPolicy\gpt.ini |
|||
.EXAMPLE |
|||
Set-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key Software\Policies\Something -ValueName SomeValue -Data 'Hello, World!' -Type String -NoGptIniUpdate |
|||
|
|||
Same as example 1, except this one does not update gpt.ini right away. This can be useful if you want to set multiple |
|||
values in the policy file and only trigger a single Group Policy refresh. |
|||
.EXAMPLE |
|||
Set-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key Software\Policies\Something -ValueName SomeValue -Data '0x12345' -Type DWord |
|||
|
|||
Example demonstrating that strings with valid numeric data (including hexadecimal strings beginning with 0x) can be assigned to the numeric types DWord, QWord and Binary. |
|||
.EXAMPLE |
|||
$entries = @( |
|||
New-Object psobject -Property @{ ValueName = 'MaxXResolution'; Data = 1680 } |
|||
New-Object psobject -Property @{ ValueName = 'MaxYResolution'; Data = 1050 } |
|||
) |
|||
|
|||
$entries | Set-PolicyFileEntry -Path $env:SystemRoot\system32\GroupPolicy\Machine\registry.pol ` |
|||
-Key 'SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' ` |
|||
-Type DWord |
|||
|
|||
Example of using pipeline input to set multiple values at once. The advantage to this approach is that the |
|||
.pol file on disk (and the GPT.ini file) will be updated if _any_ of the specified settings had to be modified, |
|||
and will be left alone if the file already contained all of the correct values. |
|||
|
|||
The Key and Type properties could have also been specified via the pipeline objects instead of on the command line, |
|||
but since both values shared the same Key and Type, this example shows that you can pass the values in either way. |
|||
.INPUTS |
|||
The Key, ValueName, Data, and Type properties may be bound via the pipeline by property name. |
|||
.OUTPUTS |
|||
None. This command does not generate output. |
|||
.NOTES |
|||
If the specified policy file already contains the correct value, the file will not be modified, and the gpt.ini file will not be updated. |
|||
.LINK |
|||
Get-PolicyFileEntry |
|||
.LINK |
|||
Remove-PolicyFileEntry |
|||
.LINK |
|||
Update-GptIniVersion |
|||
.LINK |
|||
about_RegistryValuesForAdminTemplates |
|||
#> |
|||
|
|||
function Set-PolicyFileEntry |
|||
{ |
|||
[CmdletBinding(SupportsShouldProcess = $true)] |
|||
param ( |
|||
[Parameter(Mandatory = $true, Position = 0)] |
|||
[string] $Path, |
|||
|
|||
[Parameter(Mandatory = $true, Position = 1, ValueFromPipelineByPropertyName = $true)] |
|||
[string] $Key, |
|||
|
|||
[Parameter(Mandatory = $true, Position = 2, ValueFromPipelineByPropertyName = $true)] |
|||
[AllowEmptyString()] |
|||
[string] $ValueName, |
|||
|
|||
[Parameter(Mandatory = $true, Position = 3, ValueFromPipelineByPropertyName = $true)] |
|||
[AllowEmptyString()] |
|||
[AllowEmptyCollection()] |
|||
[object] $Data, |
|||
|
|||
[Parameter(ValueFromPipelineByPropertyName = $true)] |
|||
[ValidateScript({ |
|||
if ($_ -eq [Microsoft.Win32.RegistryValueKind]::Unknown) |
|||
{ |
|||
throw 'Unknown is not a valid value for the Type parameter' |
|||
} |
|||
|
|||
if ($_ -eq [Microsoft.Win32.RegistryValueKind]::None) |
|||
{ |
|||
throw 'None is not a valid value for the Type parameter' |
|||
} |
|||
|
|||
return $true |
|||
})] |
|||
[Microsoft.Win32.RegistryValueKind] $Type = [Microsoft.Win32.RegistryValueKind]::String, |
|||
|
|||
[switch] $NoGptIniUpdate |
|||
) |
|||
|
|||
begin |
|||
{ |
|||
if (Get-Command [G]et-CallerPreference -CommandType Function -Module PreferenceVariables) |
|||
{ |
|||
Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState |
|||
} |
|||
|
|||
$dirty = $false |
|||
|
|||
try |
|||
{ |
|||
$policyFile = OpenPolicyFile -Path $Path -ErrorAction Stop |
|||
} |
|||
catch |
|||
{ |
|||
$PSCmdlet.ThrowTerminatingError($_) |
|||
} |
|||
} |
|||
|
|||
process |
|||
{ |
|||
$existingEntry = $policyFile.GetValue($Key, $ValueName) |
|||
|
|||
if ($null -ne $existingEntry -and $Type -eq (PolEntryTypeToRegistryValueKind $existingEntry.Type)) |
|||
{ |
|||
$existingData = GetEntryData -Entry $existingEntry -Type $Type |
|||
if (DataIsEqual $Data $existingData -Type $Type) |
|||
{ |
|||
Write-Verbose "Policy setting '$Key\$ValueName' is already set to '$Data' of type '$Type'." |
|||
return |
|||
} |
|||
} |
|||
|
|||
Write-Verbose "Configuring '$Key\$ValueName' to value '$Data' of type '$Type'." |
|||
|
|||
try |
|||
{ |
|||
switch ($Type) |
|||
{ |
|||
([Microsoft.Win32.RegistryValueKind]::Binary) |
|||
{ |
|||
$bytes = $Data -as [byte[]] |
|||
if ($null -eq $bytes) |
|||
{ |
|||
$errorRecord = InvalidDataTypeCombinationErrorRecord -Message 'When -Type is set to Binary, -Data must be passed a Byte[] array.' |
|||
$PSCmdlet.ThrowTerminatingError($errorRecord) |
|||
} |
|||
else |
|||
{ |
|||
$policyFile.SetBinaryValue($Key, $ValueName, $bytes) |
|||
} |
|||
|
|||
break |
|||
} |
|||
|
|||
([Microsoft.Win32.RegistryValueKind]::String) |
|||
{ |
|||
$array = @($Data) |
|||
|
|||
if ($array.Count -ne 1) |
|||
{ |
|||
$errorRecord = InvalidDataTypeCombinationErrorRecord -Message 'When -Type is set to String, -Data must be passed a scalar value or single-element array.' |
|||
$PSCmdlet.ThrowTerminatingError($errorRecord) |
|||
} |
|||
else |
|||
{ |
|||
$policyFile.SetStringValue($Key, $ValueName, $array[0].ToString()) |
|||
} |
|||
|
|||
break |
|||
} |
|||
|
|||
([Microsoft.Win32.RegistryValueKind]::ExpandString) |
|||
{ |
|||
$array = @($Data) |
|||
|
|||
if ($array.Count -ne 1) |
|||
{ |
|||
$errorRecord = InvalidDataTypeCombinationErrorRecord -Message 'When -Type is set to ExpandString, -Data must be passed a scalar value or single-element array.' |
|||
$PSCmdlet.ThrowTerminatingError($errorRecord) |
|||
} |
|||
else |
|||
{ |
|||
$policyFile.SetStringValue($Key, $ValueName, $array[0].ToString(), $true) |
|||
} |
|||
|
|||
break |
|||
} |
|||
|
|||
([Microsoft.Win32.RegistryValueKind]::DWord) |
|||
{ |
|||
$array = @($Data) |
|||
$dword = ($array | Select-Object -First 1) -as [UInt32] |
|||
if ($null -eq $dword -or $array.Count -ne 1) |
|||
{ |
|||
$errorRecord = InvalidDataTypeCombinationErrorRecord -Message 'When -Type is set to DWord, -Data must be passed a valid UInt32 value.' |
|||
$PSCmdlet.ThrowTerminatingError($errorRecord) |
|||
} |
|||
else |
|||
{ |
|||
$policyFile.SetDWORDValue($key, $ValueName, $dword) |
|||
} |
|||
|
|||
break |
|||
} |
|||
|
|||
([Microsoft.Win32.RegistryValueKind]::QWord) |
|||
{ |
|||
$array = @($Data) |
|||
$qword = ($array | Select-Object -First 1) -as [UInt64] |
|||
if ($null -eq $qword -or $array.Count -ne 1) |
|||
{ |
|||
$errorRecord = InvalidDataTypeCombinationErrorRecord -Message 'When -Type is set to QWord, -Data must be passed a valid UInt64 value.' |
|||
$PSCmdlet.ThrowTerminatingError($errorRecord) |
|||
} |
|||
else |
|||
{ |
|||
$policyFile.SetQWORDValue($key, $ValueName, $qword) |
|||
} |
|||
|
|||
break |
|||
} |
|||
|
|||
([Microsoft.Win32.RegistryValueKind]::MultiString) |
|||
{ |
|||
$strings = [string[]] @( |
|||
foreach ($item in @($Data)) |
|||
{ |
|||
$item.ToString() |
|||
} |
|||
) |
|||
|
|||
$policyFile.SetMultiStringValue($Key, $ValueName, $strings) |
|||
|
|||
break |
|||
} |
|||
|
|||
} # switch ($Type) |
|||
|
|||
$dirty = $true |
|||
} |
|||
catch |
|||
{ |
|||
throw |
|||
} |
|||
} |
|||
|
|||
end |
|||
{ |
|||
if ($dirty) |
|||
{ |
|||
$doUpdateGptIni = -not $NoGptIniUpdate |
|||
|
|||
try |
|||
{ |
|||
# SavePolicyFile contains the calls to $PSCmdlet.ShouldProcess, and will inherit our |
|||
# WhatIfPreference / ConfirmPreference values from here. |
|||
SavePolicyFile -PolicyFile $policyFile -UpdateGptIni:$doUpdateGptIni -ErrorAction Stop |
|||
} |
|||
catch |
|||
{ |
|||
$PSCmdlet.ThrowTerminatingError($_) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
<# |
|||
.SYNOPSIS |
|||
Retrieves the current setting(s) from a .pol file. |
|||
.DESCRIPTION |
|||
Retrieves the current setting(s) from a .pol file. |
|||
.PARAMETER Path |
|||
Path to the .pol file that is to be read. |
|||
.PARAMETER Key |
|||
The registry key inside the .pol file that you want to read. |
|||
.PARAMETER ValueName |
|||
The name of the registry value. May be set to an empty string to read the default value of a key. |
|||
.PARAMETER All |
|||
Switch indicating that all entries from the specified .pol file should be output, instead of searching for a specific key / ValueName pair. |
|||
.EXAMPLE |
|||
Get-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key Software\Policies\Something -ValueName SomeValue |
|||
|
|||
Reads the value of Software\Policies\Something\SomeValue from the Machine admin templates of the local GPO. |
|||
Either returns an object with the data and type of this registry value (if present), or returns nothing, if not found. |
|||
.EXAMPLE |
|||
Get-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -All |
|||
|
|||
Outputs all of the registry values from the local machine Administrative Templates |
|||
.INPUTS |
|||
None. This command does not accept pipeline input. |
|||
.OUTPUTS |
|||
If the specified registry value is found, the function outputs a PSCustomObject with the following properties: |
|||
ValueName: The same value that was passed to the -ValueName parameter |
|||
Key: The same value that was passed to the -Key parameter |
|||
Data: The current value assigned to the specified Key / ValueName in the .pol file. |
|||
Type: The RegistryValueKind type of the specified Key / ValueName in the .pol file. |
|||
If the specified registry value is not found in the .pol file, the command returns nothing. No error is produced. |
|||
.LINK |
|||
Set-PolicyFileEntry |
|||
.LINK |
|||
Remove-PolicyFileEntry |
|||
.LINK |
|||
Update-GptIniVersion |
|||
.LINK |
|||
about_RegistryValuesForAdminTemplates |
|||
#> |
|||
|
|||
function Get-PolicyFileEntry |
|||
{ |
|||
[CmdletBinding(DefaultParameterSetName = 'ByKeyAndValue')] |
|||
param ( |
|||
[Parameter(Mandatory = $true, Position = 0)] |
|||
[string] $Path, |
|||
|
|||
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = 'ByKeyAndValue')] |
|||
[string] $Key, |
|||
|
|||
[Parameter(Mandatory = $true, Position = 2, ParameterSetName = 'ByKeyAndValue')] |
|||
[string] $ValueName, |
|||
|
|||
[Parameter(Mandatory = $true, ParameterSetName = 'All')] |
|||
[switch] $All |
|||
) |
|||
|
|||
if (Get-Command [G]et-CallerPreference -CommandType Function -Module PreferenceVariables) |
|||
{ |
|||
Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState |
|||
} |
|||
|
|||
try |
|||
{ |
|||
$policyFile = OpenPolicyFile -Path $Path -ErrorAction Stop |
|||
} |
|||
catch |
|||
{ |
|||
$PSCmdlet.ThrowTerminatingError($_) |
|||
} |
|||
|
|||
if ($PSCmdlet.ParameterSetName -eq 'ByKeyAndValue') |
|||
{ |
|||
$entry = $policyFile.GetValue($Key, $ValueName) |
|||
|
|||
if ($null -ne $entry) |
|||
{ |
|||
PolEntryToPsObject -PolEntry $entry |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
foreach ($entry in $policyFile.Entries) |
|||
{ |
|||
PolEntryToPsObject -PolEntry $entry |
|||
} |
|||
} |
|||
} |
|||
|
|||
<# |
|||
.SYNOPSIS |
|||
Removes a value from a .pol file. |
|||
.DESCRIPTION |
|||
Removes a value from a .pol file. By default, also updates the version number in the policy's gpt.ini file. |
|||
.PARAMETER Path |
|||
Path to the .pol file that is to be modified. |
|||
.PARAMETER Key |
|||
The registry key inside the .pol file from which you want to remove a value. |
|||
.PARAMETER ValueName |
|||
The name of the registry value to be removed. May be set to an empty string to remove the default value of a key. |
|||
.PARAMETER NoGptIniUpdate |
|||
When this switch is used, the command will not attempt to update the version number in the gpt.ini file |
|||
.EXAMPLE |
|||
Remove-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key Software\Policies\Something -ValueName SomeValue |
|||
|
|||
Removes the value Software\Policies\Something\SomeValue from the local computer Machine GPO, if present. Updates the Machine version counter in $env:systemroot\system32\GroupPolicy\gpt.ini |
|||
.EXAMPLE |
|||
$entries = @( |
|||
New-Object psobject -Property @{ ValueName = 'MaxXResolution'; Data = 1680 } |
|||
New-Object psobject -Property @{ ValueName = 'MaxYResolution'; Data = 1050 } |
|||
) |
|||
|
|||
$entries | Remove-PolicyFileEntry -Path $env:SystemRoot\system32\GroupPolicy\Machine\registry.pol ` |
|||
-Key 'SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' |
|||
|
|||
Example of using pipeline input to remove multiple values at once. The advantage to this approach is that the |
|||
.pol file on disk (and the GPT.ini file) will be updated if _any_ of the specified settings had to be removed, |
|||
and will be left alone if the file already did not contain any of those values. |
|||
|
|||
The Key property could have also been specified via the pipeline objects instead of on the command line, but |
|||
since both values shared the same Key, this example shows that you can pass the value in either way. |
|||
|
|||
.INPUTS |
|||
The Key and ValueName properties may be bound via the pipeline by property name. |
|||
.OUTPUTS |
|||
None. This command does not generate output. |
|||
.NOTES |
|||
If the specified policy file is already not present in the .pol file, the file will not be modified, and the gpt.ini file will not be updated. |
|||
.LINK |
|||
Get-PolicyFileEntry |
|||
.LINK |
|||
Set-PolicyFileEntry |
|||
.LINK |
|||
Update-GptIniVersion |
|||
.LINK |
|||
about_RegistryValuesForAdminTemplates |
|||
#> |
|||
|
|||
function Remove-PolicyFileEntry |
|||
{ |
|||
[CmdletBinding(SupportsShouldProcess = $true)] |
|||
param ( |
|||
[Parameter(Mandatory = $true, Position = 0)] |
|||
[string] $Path, |
|||
|
|||
[Parameter(Mandatory = $true, Position = 1, ValueFromPipelineByPropertyName = $true)] |
|||
[string] $Key, |
|||
|
|||
[Parameter(Mandatory = $true, Position = 2, ValueFromPipelineByPropertyName = $true)] |
|||
[string] $ValueName, |
|||
|
|||
[switch] $NoGptIniUpdate |
|||
) |
|||
|
|||
begin |
|||
{ |
|||
if (Get-Command [G]et-CallerPreference -CommandType Function -Module PreferenceVariables) |
|||
{ |
|||
Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState |
|||
} |
|||
|
|||
$dirty = $false |
|||
|
|||
try |
|||
{ |
|||
$policyFile = OpenPolicyFile -Path $Path -ErrorAction Stop |
|||
} |
|||
catch |
|||
{ |
|||
$PSCmdlet.ThrowTerminatingError($_) |
|||
} |
|||
} |
|||
|
|||
process |
|||
{ |
|||
$entry = $policyFile.GetValue($Key, $ValueName) |
|||
|
|||
if ($null -eq $entry) |
|||
{ |
|||
Write-Verbose "Entry '$Key\$ValueName' is already not present in file '$Path'." |
|||
return |
|||
} |
|||
|
|||
Write-Verbose "Removing entry '$Key\$ValueName' from file '$Path'" |
|||
$policyFile.DeleteValue($Key, $ValueName) |
|||
$dirty = $true |
|||
} |
|||
|
|||
end |
|||
{ |
|||
if ($dirty) |
|||
{ |
|||
$doUpdateGptIni = -not $NoGptIniUpdate |
|||
|
|||
try |
|||
{ |
|||
# SavePolicyFile contains the calls to $PSCmdlet.ShouldProcess, and will inherit our |
|||
# WhatIfPreference / ConfirmPreference values from here. |
|||
SavePolicyFile -PolicyFile $policyFile -UpdateGptIni:$doUpdateGptIni -ErrorAction Stop |
|||
} |
|||
catch |
|||
{ |
|||
$PSCmdlet.ThrowTerminatingError($_) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
<# |
|||
.SYNOPSIS |
|||
Increments the version counter in a gpt.ini file. |
|||
.DESCRIPTION |
|||
Increments the version counter in a gpt.ini file. |
|||
.PARAMETER Path |
|||
Path to the gpt.ini file that is to be modified. |
|||
.PARAMETER PolicyType |
|||
Can be set to either 'Machine', 'User', or both. This affects how the value of the Version number in the ini file is changed. |
|||
.EXAMPLE |
|||
Update-GptIniVersion -Path $env:SystemRoot\system32\GroupPolicy\gpt.ini -PolicyType Machine |
|||
|
|||
Increments the Machine version counter of the local GPO. |
|||
.EXAMPLE |
|||
Update-GptIniVersion -Path $env:SystemRoot\system32\GroupPolicy\gpt.ini -PolicyType User |
|||
|
|||
Increments the User version counter of the local GPO. |
|||
.EXAMPLE |
|||
Update-GptIniVersion -Path $env:SystemRoot\system32\GroupPolicy\gpt.ini -PolicyType Machine,User |
|||
|
|||
Increments both the Machine and User version counters of the local GPO. |
|||
.INPUTS |
|||
None. This command does not accept pipeline input. |
|||
.OUTPUTS |
|||
None. This command does not generate output. |
|||
.NOTES |
|||
A gpt.ini file contains only a single Version value. However, this represents two separate counters, for machine and user versions. |
|||
The high 16 bits of the value are the User counter, and the low 16 bits are the Machine counter. For example (on PowerShell 3.0 |
|||
and later), the Version value when the Machine counter is set to 3 and the User counter is set to 5 can be found by evaluating this |
|||
expression: (5 -shl 16) -bor 3 , which will show up as decimal value 327683 in the INI file. |
|||
.LINK |
|||
Get-PolicyFileEntry |
|||
.LINK |
|||
Set-PolicyFileEntry |
|||
.LINK |
|||
Remove-PolicyFileEntry |
|||
.LINK |
|||
about_RegistryValuesForAdminTemplates |
|||
#> |
|||
|
|||
function Update-GptIniVersion |
|||
{ |
|||
[CmdletBinding(SupportsShouldProcess = $true)] |
|||
param ( |
|||
[Parameter(Mandatory = $true)] |
|||
[ValidateScript({ |
|||
if (Test-Path -LiteralPath $_ -PathType Leaf) |
|||
{ |
|||
return $true |
|||
} |
|||
|
|||
throw "Path '$_' does not exist." |
|||
})] |
|||
[string] $Path, |
|||
|
|||
[Parameter(Mandatory = $true)] |
|||
[ValidateSet('Machine', 'User')] |
|||
[string[]] $PolicyType |
|||
) |
|||
|
|||
if (Get-Command [G]et-CallerPreference -CommandType Function -Module PreferenceVariables) |
|||
{ |
|||
Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState |
|||
} |
|||
|
|||
try |
|||
{ |
|||
IncrementGptIniVersion @PSBoundParameters |
|||
} |
|||
catch |
|||
{ |
|||
$PSCmdlet.ThrowTerminatingError($_) |
|||
} |
|||
} |
@ -1,704 +0,0 @@ |
|||
#requires -Version 2.0 |
|||
|
|||
$script:MachineExtensionGuids = '[{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{D02B1F72-3407-48AE-BA88-E8213C6761F1}]' |
|||
$script:UserExtensionGuids = '[{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{D02B1F73-3407-48AE-BA88-E8213C6761F1}]' |
|||
|
|||
function OpenPolicyFile |
|||
{ |
|||
[CmdletBinding()] |
|||
param ( |
|||
[Parameter(Mandatory = $true)] |
|||
[string] $Path |
|||
) |
|||
|
|||
$policyFile = New-Object TJX.PolFileEditor.PolFile |
|||
$policyFile.FileName = $PSCmdlet.GetUnresolvedProviderPathFromPSPath($Path) |
|||
|
|||
if (Test-Path -LiteralPath $policyFile.FileName) |
|||
{ |
|||
try |
|||
{ |
|||
$policyFile.LoadFile() |
|||
} |
|||
catch [TJX.PolFileEditor.FileFormatException] |
|||
{ |
|||
$message = "File '$Path' is not a valid POL file." |
|||
$exception = New-Object System.Exception($message) |
|||
|
|||
$errorRecord = New-Object System.Management.Automation.ErrorRecord( |
|||
$exception, 'InvalidPolFileContents', [System.Management.Automation.ErrorCategory]::InvalidData, $Path |
|||
) |
|||
|
|||
throw $errorRecord |
|||
} |
|||
catch |
|||
{ |
|||
$errorRecord = $_ |
|||
$message = "Error loading policy file at path '$Path': $($errorRecord.Exception.Message)" |
|||
$exception = New-Object System.Exception($message, $errorRecord.Exception) |
|||
|
|||
$newErrorRecord = New-Object System.Management.Automation.ErrorRecord( |
|||
$exception, 'FailedToOpenPolicyFile', [System.Management.Automation.ErrorCategory]::OperationStopped, $Path |
|||
) |
|||
|
|||
throw $newErrorRecord |
|||
} |
|||
} |
|||
|
|||
return $policyFile |
|||
} |
|||
|
|||
function PolEntryToPsObject |
|||
{ |
|||
param ( |
|||
[TJX.PolFileEditor.PolEntry] $PolEntry |
|||
) |
|||
|
|||
$type = PolEntryTypeToRegistryValueKind $PolEntry.Type |
|||
$data = GetEntryData -Entry $PolEntry -Type $type |
|||
|
|||
return New-Object psobject -Property @{ |
|||
Key = $PolEntry.KeyName |
|||
ValueName = $PolEntry.ValueName |
|||
Type = $type |
|||
Data = $data |
|||
} |
|||
} |
|||
|
|||
function GetEntryData |
|||
{ |
|||
param ( |
|||
[TJX.PolFileEditor.PolEntry] $Entry, |
|||
[Microsoft.Win32.RegistryValueKind] $Type |
|||
) |
|||
|
|||
switch ($type) |
|||
{ |
|||
([Microsoft.Win32.RegistryValueKind]::Binary) |
|||
{ |
|||
return $Entry.BinaryValue |
|||
} |
|||
|
|||
([Microsoft.Win32.RegistryValueKind]::DWord) |
|||
{ |
|||
return $Entry.DWORDValue |
|||
} |
|||
|
|||
([Microsoft.Win32.RegistryValueKind]::ExpandString) |
|||
{ |
|||
return $Entry.StringValue |
|||
} |
|||
|
|||
([Microsoft.Win32.RegistryValueKind]::MultiString) |
|||
{ |
|||
return $Entry.MultiStringValue |
|||
} |
|||
|
|||
([Microsoft.Win32.RegistryValueKind]::QWord) |
|||
{ |
|||
return $Entry.QWORDValue |
|||
} |
|||
|
|||
([Microsoft.Win32.RegistryValueKind]::String) |
|||
{ |
|||
return $Entry.StringValue |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
function SavePolicyFile |
|||
{ |
|||
[CmdletBinding(SupportsShouldProcess = $true)] |
|||
param ( |
|||
[Parameter(Mandatory = $true)] |
|||
[TJX.PolFileEditor.PolFile] $PolicyFile, |
|||
|
|||
[switch] $UpdateGptIni |
|||
) |
|||
|
|||
if ($PSCmdlet.ShouldProcess($PolicyFile.FileName, 'Save new settings')) |
|||
{ |
|||
$parentPath = Split-Path $PolicyFile.FileName -Parent |
|||
if (-not (Test-Path -LiteralPath $parentPath -PathType Container)) |
|||
{ |
|||
try |
|||
{ |
|||
$null = New-Item -Path $parentPath -ItemType Directory -ErrorAction Stop -Confirm:$false -WhatIf:$false |
|||
} |
|||
catch |
|||
{ |
|||
$errorRecord = $_ |
|||
$message = "Error creating parent folder of path '$Path': $($errorRecord.Exception.Message)" |
|||
$exception = New-Object System.Exception($message, $errorRecord.Exception) |
|||
|
|||
$newErrorRecord = New-Object System.Management.Automation.ErrorRecord( |
|||
$exception, 'CreateParentFolderError', $errorRecord.CategoryInfo.Category, $Path |
|||
) |
|||
|
|||
throw $newErrorRecord |
|||
} |
|||
} |
|||
|
|||
try |
|||
{ |
|||
$PolicyFile.SaveFile() |
|||
} |
|||
catch |
|||
{ |
|||
$errorRecord = $_ |
|||
$message = "Error saving policy file to path '$($PolicyFile.FileName)': $($errorRecord.Exception.Message)" |
|||
$exception = New-Object System.Exception($message, $errorRecord.Exception) |
|||
|
|||
$newErrorRecord = New-Object System.Management.Automation.ErrorRecord( |
|||
$exception, 'FailedToSavePolicyFile', [System.Management.Automation.ErrorCategory]::OperationStopped, $PolicyFile |
|||
) |
|||
|
|||
throw $newErrorRecord |
|||
} |
|||
} |
|||
|
|||
if ($UpdateGptIni) |
|||
{ |
|||
if ($policyFile.FileName -match '^(.*)\\+([^\\]+)\\+[^\\]+$' -and |
|||
$Matches[2] -eq 'User' -or $Matches[2] -eq 'Machine') |
|||
{ |
|||
$iniPath = Join-Path $Matches[1] GPT.ini |
|||
|
|||
if (Test-Path -LiteralPath $iniPath -PathType Leaf) |
|||
{ |
|||
if ($PSCmdlet.ShouldProcess($iniPath, 'Increment version number in INI file')) |
|||
{ |
|||
IncrementGptIniVersion -Path $iniPath -PolicyType $Matches[2] -Confirm:$false -WhatIf:$false |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if ($PSCmdlet.ShouldProcess($iniPath, 'Create new gpt.ini file')) |
|||
{ |
|||
NewGptIni -Path $iniPath -PolicyType $Matches[2] |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
function NewGptIni |
|||
{ |
|||
param ( |
|||
[string] $Path, |
|||
[string[]] $PolicyType |
|||
) |
|||
|
|||
$parent = Split-Path $Path -Parent |
|||
|
|||
if (-not (Test-Path $parent -PathType Container)) |
|||
{ |
|||
$null = New-Item -Path $parent -ItemType Directory -ErrorAction Stop |
|||
} |
|||
|
|||
$version = GetNewVersionNumber -Version 0 -PolicyType $PolicyType |
|||
|
|||
Set-Content -Path $Path -Encoding Ascii -Value @" |
|||
[General] |
|||
gPCMachineExtensionNames=$script:MachineExtensionGuids |
|||
Version=$version |
|||
gPCUserExtensionNames=$script:UserExtensionGuids |
|||
"@ |
|||
} |
|||
|
|||
function IncrementGptIniVersion |
|||
{ |
|||
[CmdletBinding(SupportsShouldProcess = $true)] |
|||
param ( |
|||
[string] $Path, |
|||
[string[]] $PolicyType |
|||
) |
|||
|
|||
$foundVersionLine = $false |
|||
$section = '' |
|||
|
|||
$newContents = @( |
|||
foreach ($line in Get-Content $Path) |
|||
{ |
|||
# This might not be the most unreadable regex ever, but it's trying hard to be! |
|||
# It's looking for section lines: [SectionName] |
|||
if ($line -match '^\s*\[([^\]]+)\]\s*$') |
|||
{ |
|||
if ($section -eq 'General') |
|||
{ |
|||
if (-not $foundVersionLine) |
|||
{ |
|||
$foundVersionLine = $true |
|||
$newVersion = GetNewVersionNumber -Version 0 -PolicyType $PolicyType |
|||
|
|||
"Version=$newVersion" |
|||
} |
|||
|
|||
if (-not $foundMachineExtensionLine) |
|||
{ |
|||
$foundMachineExtensionLine = $true |
|||
"gPCMachineExtensionNames=$script:MachineExtensionGuids" |
|||
} |
|||
|
|||
if (-not $foundUserExtensionLine) |
|||
{ |
|||
$foundUserExtensionLine = $true |
|||
"gPCUserExtensionNames=$script:UserExtensionGuids" |
|||
} |
|||
} |
|||
|
|||
$section = $matches[1] |
|||
} |
|||
elseif ($section -eq 'General' -and |
|||
$line -match '^\s*Version\s*=\s*(\d+)\s*$' -and |
|||
$null -ne ($version = $matches[1] -as [uint32])) |
|||
{ |
|||
$foundVersionLine = $true |
|||
$newVersion = GetNewVersionNumber -Version $version -PolicyType $PolicyType |
|||
$line = "Version=$newVersion" |
|||
} |
|||
elseif ($section -eq 'General' -and $line -match '^\s*gPC(Machine|User)ExtensionNames\s*=') |
|||
{ |
|||
if ($matches[1] -eq 'Machine') |
|||
{ |
|||
$foundMachineExtensionLine = $true |
|||
} |
|||
else |
|||
{ |
|||
$foundUserExtensionLine = $true |
|||
} |
|||
|
|||
$line = EnsureAdminTemplateCseGuidsArePresent $line |
|||
} |
|||
|
|||
$line |
|||
} |
|||
|
|||
if ($section -eq 'General') |
|||
{ |
|||
if (-not $foundVersionLine) |
|||
{ |
|||
$foundVersionLine = $true |
|||
$newVersion = GetNewVersionNumber -Version 0 -PolicyType $PolicyType |
|||
|
|||
"Version=$newVersion" |
|||
} |
|||
|
|||
if (-not $foundMachineExtensionLine) |
|||
{ |
|||
$foundMachineExtensionLine = $true |
|||
"gPCMachineExtensionNames=$script:MachineExtensionGuids" |
|||
} |
|||
|
|||
if (-not $foundUserExtensionLine) |
|||
{ |
|||
$foundUserExtensionLine = $true |
|||
"gPCUserExtensionNames=$script:MachineExtensionGuids" |
|||
} |
|||
} |
|||
) |
|||
|
|||
if ($PSCmdlet.ShouldProcess($Path, 'Increment Version number')) |
|||
{ |
|||
Set-Content -Path $Path -Value $newContents -Encoding Ascii -Confirm:$false -WhatIf:$false |
|||
} |
|||
} |
|||
|
|||
function EnsureAdminTemplateCseGuidsArePresent |
|||
{ |
|||
param ([string] $Line) |
|||
|
|||
# These lines contain pairs of GUIDs in "registry" format (with the curly braces), separated by nothing, with |
|||
# each pair of GUIDs wrapped in square brackets. Example: |
|||
|
|||
# gPCMachineExtensionNames=[{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{D02B1F72-3407-48AE-BA88-E8213C6761F1}] |
|||
|
|||
# Per Darren Mar-Elia, these GUIDs must be in alphabetical order, or GP processing will have problems. |
|||
|
|||
if ($Line -notmatch '\s*(gPC(?:Machine|User)ExtensionNames)\s*=\s*(.*)$') |
|||
{ |
|||
throw "Malformed gpt.ini line: $Line" |
|||
} |
|||
|
|||
$valueName = $matches[1] |
|||
$guidStrings = @($matches[2] -split '(?<=\])(?=\[)') |
|||
|
|||
if ($matches[1] -eq 'gPCMachineExtensionNames') |
|||
{ |
|||
$toolExtensionGuid = $script:MachineExtensionGuids |
|||
} |
|||
else |
|||
{ |
|||
$toolExtensionGuid = $script:UserExtensionGuids |
|||
} |
|||
|
|||
$guidList = @( |
|||
$guidStrings |
|||
$toolExtensionGuid |
|||
) |
|||
|
|||
$newGuidString = ($guidList | Sort-Object -Unique) -join '' |
|||
|
|||
return "$valueName=$newGuidString" |
|||
} |
|||
|
|||
function GetNewVersionNumber |
|||
{ |
|||
param ( |
|||
[UInt32] $Version, |
|||
[string[]] $PolicyType |
|||
) |
|||
|
|||
# User version is the high 16 bits, Machine version is the low 16 bits. |
|||
# Reference: http://blogs.technet.com/b/grouppolicy/archive/2007/12/14/understanding-the-gpo-version-number.aspx |
|||
|
|||
$pair = UInt32ToUInt16Pair -UInt32 $version |
|||
|
|||
if ($PolicyType -contains 'User') |
|||
{ |
|||
$pair.HighPart++ |
|||
} |
|||
|
|||
if ($PolicyType -contains 'Machine') |
|||
{ |
|||
$pair.LowPart++ |
|||
} |
|||
|
|||
return UInt16PairToUInt32 -UInt16Pair $pair |
|||
} |
|||
|
|||
function UInt32ToUInt16Pair |
|||
{ |
|||
param ([UInt32] $UInt32) |
|||
|
|||
# Deliberately avoiding bitwise shift operators here, for PowerShell v2 compatibility. |
|||
|
|||
$lowPart = $UInt32 -band 0xFFFF |
|||
$highPart = ($UInt32 - $lowPart) / 0x10000 |
|||
|
|||
return New-Object psobject -Property @{ |
|||
LowPart = [UInt16] $lowPart |
|||
HighPart = [UInt16] $highPart |
|||
} |
|||
} |
|||
|
|||
function UInt16PairToUInt32 |
|||
{ |
|||
param ([object] $UInt16Pair) |
|||
|
|||
# Deliberately avoiding bitwise shift operators here, for PowerShell v2 compatibility. |
|||
|
|||
return ([UInt32] $UInt16Pair.HighPart) * 0x10000 + $UInt16Pair.LowPart |
|||
} |
|||
|
|||
function PolEntryTypeToRegistryValueKind |
|||
{ |
|||
param ([TJX.PolFileEditor.PolEntryType] $PolEntryType) |
|||
|
|||
switch ($PolEntryType) |
|||
{ |
|||
([TJX.PolFileEditor.PolEntryType]::REG_NONE) |
|||
{ |
|||
return [Microsoft.Win32.RegistryValueKind]::None |
|||
} |
|||
|
|||
([TJX.PolFileEditor.PolEntryType]::REG_DWORD) |
|||
{ |
|||
return [Microsoft.Win32.RegistryValueKind]::DWord |
|||
} |
|||
|
|||
([TJX.PolFileEditor.PolEntryType]::REG_DWORD_BIG_ENDIAN) |
|||
{ |
|||
return [Microsoft.Win32.RegistryValueKind]::DWord |
|||
} |
|||
|
|||
([TJX.PolFileEditor.PolEntryType]::REG_BINARY) |
|||
{ |
|||
return [Microsoft.Win32.RegistryValueKind]::Binary |
|||
} |
|||
|
|||
([TJX.PolFileEditor.PolEntryType]::REG_EXPAND_SZ) |
|||
{ |
|||
return [Microsoft.Win32.RegistryValueKind]::ExpandString |
|||
} |
|||
|
|||
([TJX.PolFileEditor.PolEntryType]::REG_MULTI_SZ) |
|||
{ |
|||
return [Microsoft.Win32.RegistryValueKind]::MultiString |
|||
} |
|||
|
|||
([TJX.PolFileEditor.PolEntryType]::REG_QWORD) |
|||
{ |
|||
return [Microsoft.Win32.RegistryValueKind]::QWord |
|||
} |
|||
|
|||
([TJX.PolFileEditor.PolEntryType]::REG_SZ) |
|||
{ |
|||
return [Microsoft.Win32.RegistryValueKind]::String |
|||
} |
|||
} |
|||
} |
|||
|
|||
function GetPolFilePath |
|||
{ |
|||
param ( |
|||
[Parameter(Mandatory = $true, ParameterSetName = 'PolicyType')] |
|||
[string] $PolicyType, |
|||
|
|||
[Parameter(Mandatory = $true, ParameterSetName = 'Account')] |
|||
[string] $Account |
|||
) |
|||
|
|||
if ($PolicyType) |
|||
{ |
|||
switch ($PolicyType) |
|||
{ |
|||
'Machine' |
|||
{ |
|||
return Join-Path $env:SystemRoot System32\GroupPolicy\Machine\registry.pol |
|||
} |
|||
|
|||
'User' |
|||
{ |
|||
return Join-Path $env:SystemRoot System32\GroupPolicy\User\registry.pol |
|||
} |
|||
|
|||
'Administrators' |
|||
{ |
|||
# BUILTIN\Administrators well-known SID |
|||
return Join-Path $env:SystemRoot System32\GroupPolicyUsers\S-1-5-32-544\User\registry.pol |
|||
} |
|||
|
|||
'NonAdministrators' |
|||
{ |
|||
# BUILTIN\Users well-known SID |
|||
return Join-Path $env:SystemRoot System32\GroupPolicyUsers\S-1-5-32-545\User\registry.pol |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
try |
|||
{ |
|||
$sid = $Account -as [System.Security.Principal.SecurityIdentifier] |
|||
|
|||
if ($null -eq $sid) |
|||
{ |
|||
$sid = GetSidForAccount $Account |
|||
} |
|||
|
|||
return Join-Path $env:SystemRoot "System32\GroupPolicyUsers\$($sid.Value)\User\registry.pol" |
|||
} |
|||
catch |
|||
{ |
|||
throw |
|||
} |
|||
} |
|||
} |
|||
|
|||
function GetSidForAccount($Account) |
|||
{ |
|||
$acc = $Account |
|||
if ($acc -notlike '*\*') { $acc = "$env:COMPUTERNAME\$acc" } |
|||
|
|||
try |
|||
{ |
|||
$ntAccount = [System.Security.Principal.NTAccount]$acc |
|||
return $ntAccount.Translate([System.Security.Principal.SecurityIdentifier]) |
|||
} |
|||
catch |
|||
{ |
|||
$message = "Could not translate account '$acc' to a security identifier." |
|||
$exception = New-Object System.Exception($message, $_.Exception) |
|||
$errorRecord = New-Object System.Management.Automation.ErrorRecord( |
|||
$exception, |
|||
'CouldNotGetSidForAccount', |
|||
[System.Management.Automation.ErrorCategory]::ObjectNotFound, |
|||
$Acc |
|||
) |
|||
|
|||
throw $errorRecord |
|||
} |
|||
} |
|||
|
|||
function DataIsEqual |
|||
{ |
|||
param ( |
|||
[object] $First, |
|||
[object] $Second, |
|||
[Microsoft.Win32.RegistryValueKind] $Type |
|||
) |
|||
|
|||
if ($Type -eq [Microsoft.Win32.RegistryValueKind]::String -or |
|||
$Type -eq [Microsoft.Win32.RegistryValueKind]::ExpandString -or |
|||
$Type -eq [Microsoft.Win32.RegistryValueKind]::DWord -or |
|||
$Type -eq [Microsoft.Win32.RegistryValueKind]::QWord) |
|||
{ |
|||
return @($First)[0] -ceq @($Second)[0] |
|||
} |
|||
|
|||
# If we get here, $Type is either MultiString or Binary, both of which need to compare arrays. |
|||
# The PolicyFileEditor module never returns type Unknown or None. |
|||
|
|||
$First = @($First) |
|||
$Second = @($Second) |
|||
|
|||
if ($First.Count -ne $Second.Count) { return $false } |
|||
|
|||
$count = $First.Count |
|||
for ($i = 0; $i -lt $count; $i++) |
|||
{ |
|||
if ($First[$i] -cne $Second[$i]) { return $false } |
|||
} |
|||
|
|||
return $true |
|||
} |
|||
|
|||
function ParseKeyValueName |
|||
{ |
|||
param ([string] $KeyValueName) |
|||
|
|||
$key = $KeyValueName -replace '^\\+|\\+$' |
|||
$valueName = '' |
|||
|
|||
if ($KeyValueName -match '^\\*(?<Key>.+?)\\+(?<ValueName>[^\\]*)$') |
|||
{ |
|||
$key = $matches['Key'] -replace '\\{2,}', '\' |
|||
$valueName = $matches['ValueName'] |
|||
} |
|||
|
|||
return $key, $valueName |
|||
} |
|||
|
|||
function GetTargetResourceCommon |
|||
{ |
|||
param ( |
|||
[string] $Path, |
|||
[string] $KeyValueName |
|||
) |
|||
|
|||
$configuration = @{ |
|||
KeyValueName = $KeyValueName |
|||
Ensure = 'Absent' |
|||
Data = $null |
|||
Type = [Microsoft.Win32.RegistryValueKind]::Unknown |
|||
} |
|||
|
|||
if (Test-Path -LiteralPath $path -PathType Leaf) |
|||
{ |
|||
$key, $valueName = ParseKeyValueName $KeyValueName |
|||
$entry = Get-PolicyFileEntry -Path $Path -Key $key -ValueName $valueName |
|||
|
|||
if ($entry) |
|||
{ |
|||
$configuration['Ensure'] = 'Present' |
|||
$configuration['Type'] = $entry.Type |
|||
$configuration['Data'] = @($entry.Data) |
|||
} |
|||
} |
|||
|
|||
return $configuration |
|||
} |
|||
|
|||
function SetTargetResourceCommon |
|||
{ |
|||
param ( |
|||
[string] $Path, |
|||
[string] $KeyValueName, |
|||
[string] $Ensure, |
|||
[string[]] $Data, |
|||
[Microsoft.Win32.RegistryValueKind] $Type |
|||
) |
|||
|
|||
if ($null -eq $Data) { $Data = @() } |
|||
|
|||
try |
|||
{ |
|||
Assert-ValidDataAndType -Data $Data -Type $Type |
|||
} |
|||
catch |
|||
{ |
|||
Write-Error -ErrorRecord $_ |
|||
return |
|||
} |
|||
|
|||
$key, $valueName = ParseKeyValueName $KeyValueName |
|||
|
|||
if ($Ensure -eq 'Present') |
|||
{ |
|||
Set-PolicyFileEntry -Path $Path -Key $key -ValueName $valueName -Data $Data -Type $Type |
|||
} |
|||
else |
|||
{ |
|||
Remove-PolicyFileEntry -Path $Path -Key $key -ValueName $valueName |
|||
} |
|||
} |
|||
|
|||
function TestTargetResourceCommon |
|||
{ |
|||
[OutputType([bool])] |
|||
param ( |
|||
[string] $Path, |
|||
[string] $KeyValueName, |
|||
[string] $Ensure, |
|||
[string[]] $Data, |
|||
[Microsoft.Win32.RegistryValueKind] $Type |
|||
) |
|||
|
|||
if ($null -eq $Data) { $Data = @() } |
|||
|
|||
try |
|||
{ |
|||
Assert-ValidDataAndType -Data $Data -Type $Type |
|||
} |
|||
catch |
|||
{ |
|||
Write-Error -ErrorRecord $_ |
|||
return $false |
|||
} |
|||
|
|||
$key, $valueName = ParseKeyValueName $KeyValueName |
|||
|
|||
$fileExists = Test-Path -LiteralPath $Path -PathType Leaf |
|||
|
|||
if ($Ensure -eq 'Present') |
|||
{ |
|||
if (-not $fileExists) { return $false } |
|||
$entry = Get-PolicyFileEntry -Path $Path -Key $key -ValueName $valueName |
|||
|
|||
return $null -ne $entry -and $Type -eq $entry.Type -and (DataIsEqual $entry.Data $Data -Type $Type) |
|||
} |
|||
else # Ensure is 'Absent' |
|||
{ |
|||
if (-not $fileExists) { return $true } |
|||
$entry = Get-PolicyFileEntry -Path $Path -Key $key -ValueName $valueName |
|||
|
|||
return $null -eq $entry |
|||
} |
|||
|
|||
} |
|||
|
|||
function Assert-ValidDataAndType |
|||
{ |
|||
param ( |
|||
[string[]] $Data, |
|||
[Microsoft.Win32.RegistryValueKind] $Type |
|||
) |
|||
|
|||
if ($Type -ne [Microsoft.Win32.RegistryValueKind]::MultiString -and |
|||
$Type -ne [Microsoft.Win32.RegistryValueKind]::Binary -and |
|||
$Data.Count -gt 1) |
|||
{ |
|||
$errorRecord = InvalidDataTypeCombinationErrorRecord -Message 'Do not pass arrays with multiple values to the -Data parameter when -Type is not set to either Binary or MultiString.' |
|||
throw $errorRecord |
|||
} |
|||
} |
|||
|
|||
function InvalidDataTypeCombinationErrorRecord($Message) |
|||
{ |
|||
$exception = New-Object System.Exception($Message) |
|||
return New-Object System.Management.Automation.ErrorRecord( |
|||
$exception, 'InvalidDataTypeCombination', [System.Management.Automation.ErrorCategory]::InvalidArgument, $null |
|||
) |
|||
} |
Binary file not shown.
@ -1,43 +0,0 @@ |
|||
@{ |
|||
ModuleToProcess = 'PolicyFileEditor.psm1' |
|||
ModuleVersion = '3.0.1' |
|||
GUID = '110a2398-3053-4ffc-89d1-1b6a38a2dc86' |
|||
Author = 'Dave Wyatt' |
|||
CompanyName = 'Home' |
|||
Copyright = '(c) 2015 Dave Wyatt. All rights reserved.' |
|||
Description = 'Commands and DSC resource for modifying Administrative Templates settings in local GPO registry.pol files.' |
|||
PowerShellVersion = '2.0' |
|||
# PowerShellHostName = '' |
|||
# PowerShellHostVersion = '' |
|||
DotNetFrameworkVersion = '2.0' |
|||
# CLRVersion = '' |
|||
# ProcessorArchitecture = '' |
|||
# RequiredModules = @() |
|||
# RequiredAssemblies = @() |
|||
# ScriptsToProcess = @() |
|||
# TypesToProcess = @() |
|||
# FormatsToProcess = @() |
|||
# NestedModules = @() |
|||
FunctionsToExport = @('Set-PolicyFileEntry', 'Remove-PolicyFileEntry', 'Get-PolicyFileEntry', 'Update-GptIniVersion') |
|||
# CmdletsToExport = '*' |
|||
# VariablesToExport = '*' |
|||
# AliasesToExport = '*' |
|||
# DscResourcesToExport = @() |
|||
# ModuleList = @() |
|||
# FileList = @() |
|||
|
|||
# HelpInfoURI = '' |
|||
|
|||
# DefaultCommandPrefix = '' |
|||
|
|||
PrivateData = @{ |
|||
PSData = @{ |
|||
# Tags = @() |
|||
LicenseUri = 'https://www.apache.org/licenses/LICENSE-2.0.html' |
|||
ProjectUri = 'https://github.com/dlwyatt/PolicyFileEditor' |
|||
# IconUri = '' |
|||
ReleaseNotes = 'Updated resource schemas to be more friendly with Invoke-DscResource.' |
|||
} |
|||
} |
|||
} |
|||
|
@ -1,10 +0,0 @@ |
|||
#requires -Version 2.0 |
|||
|
|||
$scriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent |
|||
$dllPath = Join-Path $scriptRoot PolFileEditor.dll |
|||
|
|||
Add-Type -Path $dllPath -ErrorAction Stop |
|||
|
|||
$commandsFile = Join-Path $scriptRoot Commands.ps1 |
|||
|
|||
. $commandsFile |
Loading…
Reference in new issue