Skip to content

Instantly share code, notes, and snippets.

View joshooaj's full-sized avatar

Josh Hendricks joshooaj

View GitHub Profile
@joshooaj
joshooaj / install-pwsh.sh
Last active July 3, 2025 00:09
Install PowerShell on linux
#!/bin/bash
# This script is a slightly modified version of the install script shared by
# by Mike F. Robbins on September 26th, 2024.
# Url: https://mikefrobbins.com/2024/09/26/how-to-install-powershell-7-and-essential-tools-on-linux/
# Determine the system architecture
ARCH=$(dpkg --print-architecture)
# Downloads use x64 instead of amd64 now
@joshooaj
joshooaj / DevicePermissions.psm1
Last active July 1, 2025 23:51
Export and import XProtect VMS device permissions
#requires -Module MilestonePSTools
function Export-DevicePermissions {
<#
.SYNOPSIS
Export all device permissions for a given role to a JSON file.
.DESCRIPTION
Export all device permissions for a given role to a JSON file. Note that
this does not include the Overall Security permissions or other settings.
@joshooaj
joshooaj / Get-AlarmHistory.ps1
Last active June 21, 2025 16:31
Get the alarm update history for an alarm by ID
#requires -Module MilestonePSTools
<#
.SYNOPSIS
Get the update history for an XProtect VMS alarm by ID
.DESCRIPTION
This function retrieves the update history for a specific alarm on an
XProtect VMS based on the provided alarm ID. The alarm ID is the number
shown in the ID column in XProtect Smart Client.
@joshooaj
joshooaj / Get-LineEnding.ps1
Last active May 29, 2025 21:16
Find files with specific line endings or mixed line endings
function Get-LineEnding {
<#
.SYNOPSIS
Returns the line ending found in a given file.
.DESCRIPTION
Returns a [PSCustomObject] with a `LineEnding` property with the value
'CRLF', 'LF', or 'MIXED' depending on the line endings found in the file.
.EXAMPLE
@joshooaj
joshooaj / Get-DevicePack.ps1
Created May 27, 2025 18:21
Retrieve Milestone Supported Hardware List data
function Get-DevicePack {
<#
.SYNOPSIS
Get the device pack from Milestone's online supported hardware list.
.DESCRIPTION
This command retrieves the device pack data from Milestone's support
hardware list available at https://www.milestonesys.com/support/software/supported-devices/xprotect/.
The data does not include the detailed information available when clicking
@joshooaj
joshooaj / README.md
Last active May 22, 2025 18:13
Traefik reverse-proxy configuration example for XProtect VMS

Running XProtect behind Traefik

Observations

  • The DNS names used by clients to access XProtect must match the DNS names XProtect is configured to use. If the client cannot resolve the DNS names seen in Management Client, things will not work regardless of what DNS name you use to login to XProtect. This is because after a successful login, the client receives a configuration from the server with a list of recording server URLs, registered service URLs, and more.

  • Because of the DNS thing explained above, you'll have to come up with your own strategy for handling DNS resolution on the proxy server(s) and/or clients. Essentially, you need to do split-horizon DNS resolution where clients resolve to the address of the reverse-proxy while the reverse-proxy resolves the same DNS names to the actual Milestone server(s).

  • So far I am still having trouble logging in with Smart Client using a Windows user through Traefik. The IDP component on the Management Server logs an error. But I can login using a basi

@joshooaj
joshooaj / watch-diskfreespace.ps1
Last active March 18, 2025 19:08
Call the GetDiskFreeSpaceExW function from PowerShell using p/invoke
<#
.SYNOPSIS
Gets the free space on a disk and waits 500ms or for a specified delay before checking again.
.DESCRIPTION
This function uses p/invoke to call the GetDiskFreeSpaceEx function from the kernel32.dll library to get the free
space on a disk based on the path provided. It will keep checking the free space at the specified interval, or 500ms
by default, until an error occurs.
When an error occurs, the function will include the output of GetLastError and the string-formatted
@joshooaj
joshooaj / convert.ps1
Last active January 22, 2025 23:08
Convert all video in one or more XProtect database to mkv files
#require -Modules MilestonePSTools, MilestoneSystems.PowerShell.MediaDB
param(
# Specifies the path to a folder containing one or more XProtect media database folders.
[Parameter()]
[string]
$Source,
# Specifies the path to a folder where MKV files will be saved.
[Parameter()]
[string]
@joshooaj
joshooaj / parallel-exports.ps1
Created January 13, 2025 20:35
Export recording sequences in parallel
#requires -Modules Microsoft.PowerShell.ThreadJob
<#
This is an example of how you could parallelize exports. You _probably_ wouldn't do this specific thing in practice
but it was an easy proof of concept on a small system.
The following script will get all enabled cameras, and then get all recording sequences for todays date, and then
using the Start-ThreadJob command, it will run each export in a separate job, saving each recording sequence found
on each enabled camera to it's own MKV file in the C:\temp directory.
#>
@joshooaj
joshooaj / New-RandomPass.ps1
Last active December 10, 2024 23:31 — forked from steviecoaster/New-RandomPass.ps1
Cross platform password generator
function New-RandomPass {
<#
.Synopsis
Generates and returns a suitably secure password
.EXAMPLE
New-RandomPass
Returns a random password as a SecureString object
.EXAMPLE