Installation¶
HGPM is a PowerShell module. It needs PowerShell 7.4 or later on every platform; what else it needs depends on what you do with it and where.
The module¶
Install it from the PowerShell Gallery, or build it from the repository (the branch master):
With PSResourceGet, the module of PowerShell 7.4 and later that replaces PowerShellGet
(Install-Module):
Since 0.2.0, HGPM has releases: no -Prerelease. An alpha version installed before (0.1.x-alpha,
with -Prerelease) goes to the release with Update-PSResource -Name HGPM, which also installs
the newer versions later (updates).
The Avalonia runtime¶
The window runs on Avalonia 11. Its assemblies are not shipped with the module: the first time a
window opens, the console downloads the 21 NuGet packages of Resources/AvaloniaPackages.json
for the runtime of the computer (win-x64, win-arm64, linux-x64, linux-arm64, osx),
checks each one against its pinned SHA-512 (the hash of the nuget.org catalog) before extracting
anything, then each file of the runtime against its pinned SHA-256, and puts them in place at
once. The console checks these files again each time it loads them, and refuses a library added
next to them.
- They go into the module folder when it can be written to, else into the data folder of the user.
PSGPOTOOLS_AVALONIA_NO_DOWNLOAD=1forbids the download (offline computers: the offline archives of each release have the runtime).PSGPOTOOLS_NUGET_SOURCEtakes them from an internal NuGet feed, or a folder of.nupkgfiles, instead of nuget.org; the pinned hashes apply all the same (offline installation). A download is tried three times, two minutes each.Avalonia/Get-AvaloniaBinaries.ps1installs them beforehand, or for another computer. It loads the module: from the repository, build it first (CI/03_Build.ps1).
The commands that do not open a window (backups, drift, approval...) never need Avalonia.
The ADMX files¶
The module does not ship ADMX files: the console reads those of the central store of the domain
(\domain\SYSVOL\domain\Policies\PolicyDefinitions), of Windows (%windir%\PolicyDefinitions)
or of the SYSVOL of a Samba domain controller, else asks for a folder. As GPMC, it takes the
central store of the domain it shows when it holds ADMX files, unless another folder was chosen
in its window, which proposes the central store first; Initialize-PSGPOAdmx without -Path
takes the central store too. The files of a folder are parsed once, then read
from a cache of the user while they keep their names, sizes and dates (%LOCALAPPDATA%\PSGPOTools\Admx
on Windows; $XDG_CACHE_HOME/PSGPOTools/Admx, else ~/.cache/PSGPOTools/Admx elsewhere;
-NoCache parses them). Where there are none (a
Linux computer, a domain without a central store), Install-PSGPOAdmx installs those of Windows
from the package of Microsoft, Administrative Templates (.admx) for Windows 11 (an .msi of
download.microsoft.com: 236 .admx files, their .adml files in 22 languages). HGPM neither ships
nor redistributes them: they are the files of Microsoft, under its terms. The command extracts the
package without installing it (msiexec /a on Windows; on Linux and macOS msiextract, of the
package msitools: sudo apt install msitools, sudo dnf install msitools,
brew install msitools). The module pins the package (its size and SHA-256) and each set of its
files (the .admx files, each language): a package or files that differ are refused before
anything is written.
Install-PSGPOAdmx # en-US and the language of the session, next to the module
Install-PSGPOAdmx -UICulture en-US, fr-FR # the languages chosen
Install-PSGPOAdmx -AllLanguages -Path ~/PolicyDefinitions
Install-PSGPOAdmx -CentralStore -Server dc.hardenbox.labo -UICulture en-US, fr-FR # the central store of the domain
Install-PSGPOAdmx -MsiPath './Administrative Templates (.admx) for Windows 11 Sep 2026 Update.msi' # without internet
Without -Path, the files go next to the module when it can be written to, else into the data
folder of the user (PSGPOTools/PolicyDefinitions): the console finds them there. With
-CentralStore, they go into SYSVOL\<domain>\Policies\PolicyDefinitions of the domain
controller (an account allowed to write SYSVOL: a domain administrator), as for GPMC: every
console of the domain then reads them. The ADMX files already there are kept, those of the same
name replaced; with files already there, give -Force. A computer without internet: download the
package on another one (the page of Microsoft is in the error of a failed download) and give it
with -MsiPath; it is checked as a download is.
The cache of the ADMX files¶
Parsing a PolicyDefinitions folder takes a few seconds, and each console of the launcher opens in
a process of its own: what a load reads is kept in a cache of the user, one file for each folder
and language (%LOCALAPPDATA%\PSGPOTools\Admx on Windows; $XDG_CACHE_HOME/PSGPOTools/Admx, else
~/.cache/PSGPOTools/Admx elsewhere).
- When it is written: the first time a folder is loaded in a language, by whatever loads it:
the GPO console the first time it needs the policies (the editor, the Settings and
History tabs, a report; never for the links, the delegation or the approval), or before it
opens with
-PolicyDefinitions; the editor alone (-NoDirectory) and Policy Analyzer when they start; Load in the ADMX window;Initialize-PSGPOAdmx. It is written aside, then renamed: a console opening meanwhile reads the former file or the new one, never half of one. - When it is read: while the
.admxfiles, and the.admlfiles of the language and of en-US, keep their names, sizes and dates, with the same version of HGPM. A file added, changed or removed (a new template in the central store), or an update of HGPM, and the next load parses the files again and writes the cache again: a few seconds once more. - When it is not written: with
-NoCache, after an error, or when a file was left out for a reason that may pass (the network, the rights): the next load parses the files again rather than keep a load that misses some of them. A cache that cannot be written only makes the next load slower. - Clearing it: delete its folder, nothing else is lost; the next load writes it again.
Remove-Item -Recurse -Force "$env:LOCALAPPDATA\PSGPOTools\Admx" # Windows
Remove-Item -Recurse -Force ~/.cache/PSGPOTools/Admx # Linux, without XDG_CACHE_HOME
Windows¶
| Need | Why | How |
|---|---|---|
| A domain account | the console reads the domain with the identity of the session (Kerberos) | log on with it, or -Credential with -UseSsl |
| RSAT Group Policy Management tools | create and delete GPOs (New-GPO, Remove-GPO) |
Add-WindowsCapability -Online -Name 'Rsat.GroupPolicy.Management.Tools~~~~0.0.1.0' (Windows 10/11), Install-WindowsFeature GPMC (Server) |
| RSAT Active Directory tools | optional: only the test scripts use them | Add-WindowsCapability -Online -Name 'Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0' |
The GroupPolicy module is a Windows PowerShell module: PowerShell 7 hides it from
Get-Module -ListAvailable and loads it through its Windows PowerShell compatibility. The
console finds it with -SkipEditionCheck.
SYSVOL is read and written through its UNC path (\\dc\SYSVOL\domain\Policies\{GUID}), with the
identity of the session.
A session opened by SSH with a key
An OpenSSH session opened with a key has no network credentials (S4U logon): LDAP binds fail and SYSVOL cannot be reached. Run the console in an interactive session, or over SSH with a password.
Linux¶
| Need | Why | Debian / Ubuntu | RHEL / Fedora |
|---|---|---|---|
| OpenLDAP client library | LDAP from .NET | apt install libldap2 |
dnf install openldap |
| SASL GSSAPI module | Kerberos over LDAP | apt install libsasl2-modules-gssapi-mit |
dnf install cyrus-sasl-gssapi |
| Kerberos client | the ticket the console uses | apt install krb5-user |
dnf install krb5-workstation |
smbclient |
read and write SYSVOL | apt install smbclient |
dnf install samba-client |
samba-tool, Samba Python bindings |
create and delete GPOs, SYSVOL permissions | apt install python3-samba samba-common-bin |
dnf install samba-tools python3-samba |
| A graphical session | the window (X11 or Wayland with XWayland) |
The console authenticates with Kerberos: get a ticket first, and give the domain controller by its DNS name (Kerberos needs the name, not the IP address).
A password is never given to samba-tool or smbclient, and never sent over plain LDAP: with
-Credential, use -UseSsl (LDAPS), and the changes still need a Kerberos ticket.
-Credential on Windows
On Windows, a domain read with -Credential (and -UseSsl) is changed with that account in
the directory and in SYSVOL: the console opens an SMB connection to \\<dc>\SYSVOL with
it, as net use \\<dc>\SYSVOL /user:... does. Windows has one account per server in a
session: if the session already reaches that server with another account, the console says so
(net use \\<dc>\* /delete closes those connections). Creating and deleting a GPO use RSAT,
which only knows the identity of the session: they are refused with -Credential.
Check the installation¶
Import-Module HGPM
Get-Command -Module HGPM # the public commands
Get-PSGPODirectory -Server dc.hardenbox.labo | Select-Object DomainName, Account, Source
The status bar of the window also says what the console found: this computer, its domain, the domain controller and its directory service.
Updates¶
The import of the module says its version, and the command that installs a newer one when the PowerShell Gallery has it:
PS> Import-Module HGPM
HGPM 0.2.0
HGPM 0.2.1 is available on the PowerShell Gallery: Update-PSResource -Name HGPM, then open a new PowerShell session.
The import reads the Gallery at most once a day (UpdateCheck.json in the local data folder of
the user, PSGPOTools), and waits 8 seconds at most: without network, it gives the version only, and does not try again for an hour.
It does not read it in a CI, in a session started with -NonInteractive, nor with
PSGPOTOOLS_SKIP_UPDATE_CHECK=1. The new version is used by a new PowerShell session: the one
running keeps the module it imported.
Test-PSGPOUpdate tells whether a newer version of HGPM is published on the PowerShell Gallery,
and gives the command that installs it. It compares the version loaded with the latest of the
Gallery as semantic versions: 0.1.4-alpha comes before 0.1.4-beta, itself before 0.1.4. The
prereleases count when the version loaded is one (or with -Prerelease).
Test-PSGPOUpdate
# Name : HGPM
# InstalledVersion : 0.2.0
# LatestVersion : 0.2.1
# UpdateAvailable : True
# UpdateCommand : Update-PSResource -Name HGPM
if (Test-PSGPOUpdate -Quiet) { Update-PSResource -Name HGPM }
Update HGPM¶
- Close the consoles (
Show-GPOManagerAvalonia,Show-PSOManagerAvalonia) and the PowerShell sessions that imported HGPM: a session keeps the module it imported. -
Install the new version, as the module was installed:
The new version goes beside the old one (a folder per version in
Modules/HGPM). A module installed for all users (-Scope AllUsers) is updated as an administrator, with-Scope AllUsers(sudo pwshon Linux). Installed with PowerShellGet (Install-Module):Update-Module -Name HGPM. -
Check in a new PowerShell session: the import gives the new version, without the line
is available, and the dot of the status bar of the consoles is green. -
Optionally, remove an old version:
Uninstall-PSResource -Name HGPM -Version <version>.
The changes of each version are in the changelog.