Skip to content

manuel-alcocer/powershell-sysutils

Repository files navigation

powershell-sysutils

PowerShell sysadmin tools for Windows. The flagship is the SysUtils module on the PowerShell Gallery (currently exporting Get-DllInfo). The other three tools — process monitor and two registry browsers — still ship as standalone .ps1 scripts in this repo and will move into the module in subsequent releases.

Built and tested against Windows PowerShell 5.1 on Windows 10 / Server 2016 and newer. No external dependencies.

Quick start

# From any Windows machine with PowerShell 5.1+:
Install-Module SysUtils -Force
Get-DllInfo C:\Windows\System32\scrrun.dll | ConvertTo-Json -Depth 12

That's it — PSGallery is registered by default, no Register-PSRepository needed.

First-time bootstrap on Windows Server 2019 / older

Pristine Windows 10 1809 / Server 2019 boxes ship with a stock PowerShellGet 1.0.0.1 that does not pull TLS 1.2 by default and lacks the NuGet provider. Install-Module fails with NuGet provider is required until you run this once per box:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted   # optional, skips the per-install confirmation

After that, Install-Module SysUtils -Force works as documented above. Newer Windows builds (Server 2022, Win10 21H2+, Win11) already have the NuGet provider preinstalled.

Tools

Get-DllInfo (module: SysUtils) — Read-only PE/COM/.NET inspector

Inspects DLL, OCX, EXE and SYS files without loading them into the process (no LoadLibrary, no DllMain execution). Works cross-bitness — a 32-bit DLL in SysWOW64 can be inspected from a 64-bit PowerShell session and vice versa.

Layered output, all opt-in via switches; emits a single PSCustomObject suitable for ConvertTo-Json (Ansible-friendly):

Switch What it adds
(default) PE header (architecture, subsystem, characteristics, sections, timestamp), version info, COM and .NET detection
-IncludeImports IDT walk: per-module function lists, including import-by-ordinal
-IncludeExports Full export table with forwarder detection (e.g. kernel32 -> NTDLL.Rtl*)
-IncludeResources Recursive 3-level walk of the resource tree
-IncludeTypeLib TypeLib reader via oleaut32!LoadTypeLibEx (REGKIND_NONE) — CoClasses, interfaces, methods, parameters, enums, aliases, IIDs/CLSIDs
-IncludeDotNetTypes Assembly.ReflectionOnlyLoadFrom[ComVisible] / [Guid] / [ProgId] per type, full type listing
-IncludeSignature Authenticode signature info
-IncludeHash SHA-256 of the file
-Detailed Convenience: enables every Include* switch above

For managed assemblies, the cheap path also reports a PEKind field that disambiguates AnyCPU from real x86 / x64 / AnyCPUPrefer32 / ManagedMixed (which the raw Machine field cannot do alone).

# One DLL, full report as JSON
Get-DllInfo C:\Windows\System32\scrrun.dll -Detailed | ConvertTo-Json -Depth 12

# Find every COM-registrable DLL under a directory
Get-ChildItem C:\Legacy -Include *.dll,*.ocx -Recurse |
    Get-DllInfo |
    Where-Object { $_.Com.IsComServer } |
    Select-Object Path, @{n='HasTLB';e={$_.Com.HasTypeLib}},
                  @{n='Arch';e={$_.PE.Architecture}}

# Audit which DLLs import a given API
Get-ChildItem C:\App -Filter *.dll |
    Get-DllInfo -IncludeImports |
    Where-Object { $_.Imports.Functions.Name -contains 'CreateRemoteThread' } |
    Select-Object Path

Dll-Inspector.ps1 at the repo root is a thin wrapper that imports the module and forwards every parameter to Get-DllInfo, so users who git clone the repo can keep running .\Dll-Inspector.ps1 unchanged.

Process-Monitor.ps1 — Procmon-lite for the console (standalone, not yet in module)

Live activity monitor for a binary (by name or PID). Subscribes to WMI process creation/termination events and polls each tracked PID for loaded modules and network connections. If Sysmon is installed on the target, also tails its file/registry/DNS/image-load events. Follows child processes automatically. Works locally or remotely via WinRM.

# Follow every notepad.exe on the local machine
.\Process-Monitor.ps1 -Target notepad.exe

# Follow PID 1234 on a remote host
$c = Import-Clixml .\admin.xml
.\Process-Monitor.ps1 -Target 1234 -ComputerName host.example -Credential $c

Registry-Navigator.ps1 — Interactive registry REPL (standalone)

Lightweight REPL to browse registry keys and values. Local mode talks to the local registry directly; remote mode dispatches each command via a persistent PSSession over WinRM.

# Local
.\Registry-Navigator.ps1

# Remote
$cred = Get-Credential administrator
.\Registry-Navigator.ps1 -ComputerName host.example -Credential $cred

Registry-TUI.ps1 — Full-screen registry browser (standalone)

Two-pane TUI (subkeys | values) using the Windows console API. Arrow-key navigation, Enter to descend, Backspace to go up. Same remote WinRM mode as Registry-Navigator.ps1.

.\Registry-TUI.ps1
.\Registry-TUI.ps1 -ComputerName host.example -Credential (Get-Credential)

Help

Every script ships full comment-based help:

Get-Help .\Dll-Inspector.ps1 -Full
Get-Help .\Process-Monitor.ps1 -Examples

Installation

Option A — PowerShell Gallery (recommended)

Get-DllInfo lives in the SysUtils module. The PSGallery repository is registered by default on every Windows with PowerShellGet, so a single command on each server is enough:

Install-Module SysUtils -Force
Get-DllInfo C:\Windows\System32\scrrun.dll

For the standalone scripts that haven't moved into the module yet (Process-Monitor.ps1, Registry-Navigator.ps1, Registry-TUI.ps1), fall back to git clone (Option B) or direct download (Option C).

Option B — git clone on each server

The simplest path if git is installed on the targets. Includes both the module and the standalone scripts. git pull to update.

git clone https://github.com/manuel-alcocer/powershell-sysutils.git C:\Tools\powershell-sysutils
cd C:\Tools\powershell-sysutils

# Run a standalone script directly:
.\Dll-Inspector.ps1 -Path .\anything.dll

# Or import the module from the cloned tree (no Install-Module):
Import-Module .\SysUtils\SysUtils.psd1 -Force
Get-DllInfo .\anything.dll

Option C — Direct download (no git on the target)

Pull individual scripts from raw.githubusercontent.com. Useful for one-off runs or for bootstrapping.

$base = 'https://raw.githubusercontent.com/manuel-alcocer/powershell-sysutils/main'
foreach ($s in 'Dll-Inspector.ps1','Process-Monitor.ps1','Registry-Navigator.ps1','Registry-TUI.ps1') {
    Invoke-WebRequest "$base/$s" -OutFile "C:\Tools\$s" -UseBasicParsing
}

Option D — Ansible

Three patterns from a control node. Pick whichever fits your playbook.

win_psmodule — installs the module from PowerShell Gallery. Cleanest:

- hosts: windows
  tasks:
    - name: Install SysUtils module
      community.windows.win_psmodule:
        name: SysUtils
        state: present
        accept_license: yes

win_get_url — pulls individual scripts over HTTP, no git required on the target. Use this for the standalone scripts not yet in the module:

- hosts: windows
  vars:
    repo_base: https://raw.githubusercontent.com/manuel-alcocer/powershell-sysutils/main
    install_dir: C:\Tools\powershell-sysutils
    scripts:
      - Dll-Inspector.ps1
      - Process-Monitor.ps1
      - Registry-Navigator.ps1
      - Registry-TUI.ps1
  tasks:
    - name: Ensure install dir exists
      ansible.windows.win_file:
        path: "{{ install_dir }}"
        state: directory

    - name: Download scripts
      ansible.windows.win_get_url:
        url: "{{ repo_base }}/{{ item }}"
        dest: "{{ install_dir }}\\{{ item }}"
        force: yes
      loop: "{{ scripts }}"

win_command — clone the repo if you have git for Windows on the targets and want a versioned working tree:

- name: Clone powershell-sysutils
  ansible.windows.win_command:
    cmd: git clone --depth 1 https://github.com/manuel-alcocer/powershell-sysutils.git C:\Tools\powershell-sysutils
    creates: C:\Tools\powershell-sysutils\.git

To call any script from a playbook and consume its output as structured data, run it through ConvertTo-Json and parse on the control node:

- name: Inspect a DLL
  ansible.windows.win_powershell:
    script: |
      C:\Tools\powershell-sysutils\Dll-Inspector.ps1 `
        -Path C:\Windows\System32\scrrun.dll -Detailed |
        ConvertTo-Json -Depth 12 -Compress
  register: dll_info

Execution policy

If your servers refuse to run scripts because of ExecutionPolicy, run them with the Bypass flag — it does not persist beyond the call:

powershell -NoProfile -ExecutionPolicy Bypass -File .\Dll-Inspector.ps1 -Path foo.dll

Publishing (maintainer notes)

Releases are tag-driven via GitHub Actions:

Workflow Trigger What it does
.github/workflows/ci.yml every push / PR Test-ModuleManifest + import + smoke test of Get-DllInfo against kernel32.dll, scrrun.dll (with -IncludeTypeLib) and a managed assembly. Catches regressions before tagging.
.github/workflows/publish.yml push of tag v*.*.* (or manual workflow_dispatch) Asserts the tag version matches ModuleVersion in SysUtils.psd1, re-runs the smoke tests, then Publish-Module to PowerShell Gallery and creates a GitHub Release.

One-time setup: create the repository secret PSGALLERY_API_KEY under Settings → Secrets and variables → Actions → New repository secret, with a key obtained from powershellgallery.com → My Account → API Keys.

Cutting a release:

# 1. Bump ModuleVersion in SysUtils/SysUtils.psd1
# 2. Update ReleaseNotes in the same file
git commit -am 'Release v1.0.1'
git push

# 3. Tag and push — Actions does the rest
git tag v1.0.1
git push --tags

Versions on the Gallery are immutable — once 1.0.0 is published, that exact .nupkg cannot be replaced. Bump for any fix.

Build-Module.ps1 at the repo root is kept for local validation only (.\Build-Module.ps1 -WhatIfOnly is handy before tagging) and as an emergency manual publish path. The CI flow is the canonical one.

License

MIT — see LICENSE.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors