Repository navigation
Home
A collection of reusable PowerShell and T-SQL scripts for enterprise Active Directory, SQL Server, and infrastructure management.
- Clone or download the repository.
- Navigate to the folder of the script you need.
- Read the accompanying
.mdfile for full prerequisites, parameters, and examples. - Run from an elevated PowerShell session where required (noted per script).
All PowerShell scripts require PowerShell 5.1 or PowerShell 7+ unless stated otherwise. T-SQL scripts require SQL Server 2016 or later.
Version 2.0.0 | PowerShell | Requires local administrator | CIS hardening
Assigns NT Service\<ServiceName> virtual accounts for SQL Server named instance
services (engine, agent, SSIS) to the local security groups that correspond to the
Windows User Rights Assignments required by CIS hardening guidelines.
| What it does | Detail |
|---|---|
| Discovers services |
Get-Service (SQL engine / agent) + Get-CimInstance Win32_Service (SSIS / all NT Service accounts) |
| Creates groups | Missing local security groups are created automatically |
| Verifies LSA rights | Exports effective policy via secedit /export and logs any gaps between group membership and User Rights Assignment |
| Safe to re-run | Idempotent — already-present members are skipped |
| Dry run | Full -WhatIf support; log is still written |
| Exit code |
1 when any operation fails; 0 on full success |
| Requirement | Detail |
|---|---|
| PowerShell | 5.1 or 7+ (64-bit only — LocalAccounts module unavailable in 32-bit PS on 64-bit OS) |
| Privileges | Local administrator / SYSTEM (GPO startup script) |
| Modules |
Microsoft.PowerShell.LocalAccounts (built-in) |
| Parameter | Default | Description |
|---|---|---|
-LogDirectory |
C:\Temp |
Directory for timestamped log files |
-WhatIf |
— | Dry-run mode |
-Confirm |
— | Prompt before each change |
When deploying via GPO, ensure the Script Name resolves to the 64-bit PowerShell executable:
%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe
Not %SystemRoot%\SysWOW64\… — the LocalAccounts module will fail silently in 32-bit mode.
Version 1.4.0 | PowerShell | Domain read access
Inventories Group Policy Objects in an Active Directory domain and reports two categories of potentially unused policies:
- Unlinked GPOs — GPOs with no link to any OU, site, or domain container.
-
No Apply ACE — GPOs where no security principal has an
Allow — Apply Group PolicyACE, meaning no one can actually apply the policy.
Output is a two-worksheet Excel workbook (or two CSV files when ImportExcel is unavailable).
The script uses Get-GPPermission -All and checks for the GPPermissionType enum value
GpoApply. This approach is locale-independent — earlier XML-parsing methods compared
localised strings ("Apply Group Policy" / Dutch: "Groepsbeleid toepassen") which caused
false positives on non-English systems.
| Requirement | Detail |
|---|---|
| PowerShell | 5.1 or 7+ |
| RSAT — Group Policy |
GroupPolicy module — install via Add-WindowsCapability -Online -Name 'Rsat.GroupPolicy.Management.Tools~~~~0.0.1.0'
|
| RSAT — Active Directory |
ActiveDirectory module — install via Add-WindowsCapability -Online -Name 'Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0'
|
| ImportExcel | Optional — dfinke/ImportExcel; falls back to CSV |
| Permissions | Domain read + Group Policy Read on all GPOs |
Note:
Add-WindowsCapabilityrequires Windows Update connectivity (or an internal WSUS/MEM source configured for Features on Demand). It cannot use WSUS for FOD packages on Windows 10 1809+.
| Parameter | Default | Description |
|---|---|---|
-Domain |
$env:USERDNSDOMAIN |
FQDN of the AD domain to query |
-OutputPath |
Script directory | Where the report is written |
| Column | Description |
|---|---|
GPOName |
Display name |
GPOId |
GUID in {…} notation |
GpoStatus |
AllSettingsEnabled / Disabled / UserSettingsDisabled / ComputerSettingsDisabled |
CreationTime |
When the GPO was created |
ModificationTime |
When the GPO was last modified |
LinkedTo |
Semicolon-separated list of container DNs (blank = unlinked) |
IsUnlinked |
True when the GPO has no links |
HasApplyAce |
False when no GpoApply ACE exists |
Version 1.6.0 | PowerShell | Domain read access
Reports every GPO linked to each Organizational Unit and the domain root, including full WMI filter details, to enable side-by-side comparison of policies applied to the same container.
Output is a two-worksheet Excel workbook (GPOsByOU detail + Summary) or two CSV files when ImportExcel is unavailable.
- Link properties — link order (precedence), link enabled state, link enforced (No Override) flag.
- GPO properties — status (enabled/disabled per Computer/User half), creation and modification time, description.
-
WMI filter — display name, description, and full WQL query read directly from the
domain's
CN=SOM,CN=WMIPolicy,CN=Systemcontainer (msWMI-Parm2attribute).
| Requirement | Detail |
|---|---|
| PowerShell | 5.1 or 7+ |
| RSAT — Group Policy |
GroupPolicy module — install via Add-WindowsCapability -Online -Name 'Rsat.GroupPolicy.Management.Tools~~~~0.0.1.0'
|
| RSAT — Active Directory |
ActiveDirectory module — install via Add-WindowsCapability -Online -Name 'Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0'
|
| ImportExcel | Optional — dfinke/ImportExcel; falls back to CSV |
| Permissions | Domain read + Group Policy Read on all GPOs + Read on CN=SOM,CN=WMIPolicy,CN=System,<DomainDN>
|
| Parameter | Default | Description |
|---|---|---|
-Domain |
$env:USERDNSDOMAIN |
FQDN of the AD domain to query |
-OutputPath |
Script directory | Where the report is written |
-IncludeAll |
— | Also include containers with no linked GPOs in the Summary sheet |
| Column | Description |
|---|---|
ContainerName / ContainerDN
|
OU friendly name and full DN |
LinkOrder |
GPO precedence (1 = highest) |
LinkEnabled / LinkEnforced
|
Link state flags |
GPOName / GPOId
|
Display name and GUID |
GPOStatus |
AllSettingsEnabled / ComputerSettingsDisabled / UserSettingsDisabled / AllSettingsDisabled |
WMIFilterName |
Attached WMI filter display name (blank = none) |
WMIFilterQuery |
Full WQL query including namespace (root\CIMv2;SELECT …) |
Version 2.1.0 | PowerShell | AD read access
Generates Remote Desktop Connection Manager (.rdg) configuration files for one or
more Active Directory domains. For each domain, all enabled Windows Server computer
objects are queried and organised into nested groups that mirror the OU/canonical-path
structure.
| Feature | Detail |
|---|---|
| Multi-domain | Pass multiple FQDNs via -DomainNames
|
| Credentials | Interactive per-domain prompt, or -UseCurrentCredentials for unattended use |
| Overwrite protection | Existing .rdg files are skipped unless -Force is specified |
| Dry run |
-WhatIf support |
| XPath safety | OU names with embedded quotes are safely escaped via concat()
|
| Requirement | Detail |
|---|---|
| PowerShell | 5.1 or 7+ |
| RSAT — Active Directory |
ActiveDirectory module |
| RDCMan | Version 2.93+ to open generated .rdg files |
| Parameter | Mandatory | Description |
|---|---|---|
-RDCManPath |
Yes | Directory where .rdg files are saved (must exist) |
-DomainNames |
Yes | One or more domain FQDNs |
-UseCurrentCredentials |
No | Skip per-domain credential prompt |
-Force |
No | Overwrite existing .rdg files |
Version 1.1.0 | PowerShell | Domain read access
Reports every configured setting in every GPO in a domain, regardless of where — or
whether — each GPO is linked. Unlike Compare-GPOsByOU (which reports settings per OU
link), this script is scoped purely to GPOs: orphaned/unlinked GPOs are included, and
each configured setting appears exactly once per GPO regardless of how many containers
link it.
Output is a single-worksheet Excel workbook (or one CSV file when ImportExcel is unavailable).
| Requirement | Detail |
|---|---|
| PowerShell | 5.1 or 7+ |
| RSAT — Group Policy |
GroupPolicy module — install via Add-WindowsCapability -Online -Name 'Rsat.GroupPolicy.Management.Tools~~~~0.0.1.0'
|
| ImportExcel | Optional — dfinke/ImportExcel; falls back to CSV |
| Permissions | Group Policy Read on all GPOs |
| Parameter | Default | Description |
|---|---|---|
-Domain |
$env:USERDNSDOMAIN |
FQDN of the AD domain to query |
-DomainController |
— (Windows selects) | Pins all GPO queries to a specific DC |
-OutputPath |
Script directory | Where the report is written |
-PassThru |
— | Also return the collected settings to the pipeline |
| Column | Description |
|---|---|
GPOName / GPOId
|
Display name and GUID |
GPOStatus |
AllSettingsEnabled / UserSettingsDisabled / ComputerSettingsDisabled / AllSettingsDisabled |
WMIFilterName |
Attached WMI filter (blank = none) |
ExtensionType |
Administrative Templates, Security Settings, Scripts, or Windows Firewall |
SettingName / SettingState / SettingValue
|
Configured setting and its value |
Version 1.8 | PowerShell | AD read + remote WMI/WinRM access
Scans all enabled Windows Server objects in Active Directory for non-standard accounts
used by Windows services and scheduled tasks. Built-in accounts (LocalSystem,
NT AUTHORITY\*, NT SERVICE\*) are excluded automatically.
Output per server:
-
<ServerName>_Services.csv— services with non-standard accounts -
<ServerName>_ScheduledTasks.csv— scheduled tasks with non-standard accounts
Combined output:
-
<timestamp>_ServiceAccounts.xlsx— two-sheet workbook (Services + ScheduledTasks) -
<timestamp>_FailedServers.txt— offline/error servers for retry (if any)
| Requirement | Detail |
|---|---|
| PowerShell |
7+ (uses Test-Connection -TimeoutSeconds, a PS 6.1+ parameter) |
| RSAT — Active Directory |
ActiveDirectory module |
| ImportExcel | Required for Excel output — dfinke/ImportExcel |
| Network | WMI/CIM access to all target servers; WinRM for scheduled task enumeration |
Tip: Use the generated
_FailedServers.txtas input to-ComputerListon subsequent runs to retry only offline hosts.
| Parameter | Default | Description |
|---|---|---|
-SearchBase |
Entire domain | DN of the OU to search |
-ComputerList |
— | Path to a text file (one server per line) to scan instead of AD |
-OutputFolder |
.\Output |
Where per-server CSV files are written |
-LogFolder |
.\Log |
Where the timestamped log file is written |
-PingCount |
1 |
ICMP echo requests per host (range 1–5) |
Version 1.1.0 | PowerShell module | No direct invocation
Shared/PublicScripts.psm1 is an internal module that provides the logging,
module-import, and GPO XML report parsing infrastructure shared by PowerShell scripts
in this repository. Scripts import it relative to their own location — there is no
need to install or publish it separately.
| Function | Purpose |
|---|---|
Initialize-ScriptLog |
Creates the log directory, builds the timestamped filename, returns the log path |
Write-ScriptLog |
Appends a [yyyy-MM-dd HH:mm:ss] [LEVEL] Message entry (UTF-8 NoBOM) and routes to the matching PS stream |
Remove-OldLog |
Deletes log files matching a wildcard filter that are older than a retention threshold |
Import-RequiredModule |
Imports one or more modules if not already loaded, logging each import via Write-ScriptLog
|
Get-XmlInnerText |
Returns the InnerText of a named child XML node, or $null when absent |
Get-GpoSetting |
Parses a GPO XML report (Get-GPOReport) into a flat list of configured settings; safe to call from ForEach-Object -Parallel runspaces |
Log filename format: yyyyMMdd_HHmmss[_Tag]_ScriptName.log
Scripts that tag logs with a domain name produce filenames such as
20260713_143022_contoso.com_Compare-GPOsByOU.log.
Version 1.0 | T-SQL | SQL Server
securityadminorsysadmin
Provisions a Windows-authenticated SQL Server login and database user for the local
machine account <MachineName>\servicenow, used by ServiceNow discovery and integration.
The machine name is derived dynamically from SERVERPROPERTY('MachineName') — no manual
substitution required.
Accounts are created in two databases:
| Database | Purpose |
|---|---|
master |
Server-level login + user for general connectivity |
msdb |
User for SQL Agent / maintenance plan visibility |
- The local Windows account
<MachineName>\servicenowmust exist before running the script. - Executing account requires
securityadmin+db_accessadmininmasterandmsdb, orsysadmin.
sqlcmd -S SERVER\INSTANCE -E -i Create-ServiceNow-User.sql
Run once per SQL Server instance. Named instances have independent login stores.
# Group Policy Management
Add-WindowsCapability -Online -Name 'Rsat.GroupPolicy.Management.Tools~~~~0.0.1.0'
# Active Directory Domain Services
Add-WindowsCapability -Online -Name 'Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0'Requires Windows Update connectivity. WSUS cannot serve Features on Demand packages on Windows 10 1809 or later.
Install-Module -Name ImportExcel -Scope CurrentUser| Pattern | Meaning |
|---|---|
YYYY-MM-dd_<name>.xlsx |
Date-prefixed Excel workbook |
<ServerName>_Services.csv |
Per-server service account export |
<timestamp>_FailedServers.txt |
Servers that could not be reached (retry input) |
Log\YYYYMMDD_HHmmss_<name>.log |
Timestamped script log |
Log entries follow the format:
[yyyy-MM-dd HH:mm:ss] [LEVEL] Message
Levels: INFO, WARN, ERROR.
- Fork the repository and create a feature branch.
- Follow the script structure conventions in
.github/copilot-instructions.md. - Run
Invoke-ScriptAnalyzerand resolve all warnings/errors before submitting. - Keep the accompanying
.mdfile andREADME.mdversion table in sync with any changes. - Open a pull request with a clear description of what changed and why.