first commit
This commit is contained in:
229
scripts/install-mpv-handler.ps1
Normal file
229
scripts/install-mpv-handler.ps1
Normal file
@@ -0,0 +1,229 @@
|
||||
#Requires -Version 5.1
|
||||
#Requires -RunAsAdministrator
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$InstallRoot,
|
||||
[string]$IconPath,
|
||||
[switch]$KeepExistingProtocolKeys
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
function Resolve-ExistingFile {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$BasePath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$FileName
|
||||
)
|
||||
|
||||
$resolvedPath = Join-Path -Path $BasePath -ChildPath $FileName
|
||||
if (-not (Test-Path -LiteralPath $resolvedPath -PathType Leaf)) {
|
||||
throw "Required file not found: $resolvedPath`nInstallRoot must point at the extracted mpv-handler folder that contains config.toml, mpv-handler.exe, and mpv-handler-debug.exe."
|
||||
}
|
||||
|
||||
return (Resolve-Path -LiteralPath $resolvedPath).Path
|
||||
}
|
||||
|
||||
function Get-UsageExample {
|
||||
return @"
|
||||
Example usage:
|
||||
powershell -ExecutionPolicy Bypass -File .\scripts\install-mpv-handler.ps1 -InstallRoot 'C:\path\to\mpv-handler'
|
||||
|
||||
Or from an elevated PowerShell session:
|
||||
& 'C:\Forgejo\API-MediaPlayer\scripts\install-mpv-handler.ps1' -InstallRoot 'C:\path\to\mpv-handler'
|
||||
|
||||
If config.toml, mpv-handler.exe, and mpv-handler-debug.exe are in the same folder as this script,
|
||||
you can run it without -InstallRoot.
|
||||
"@
|
||||
}
|
||||
|
||||
function Test-InstallRootContents {
|
||||
param(
|
||||
[string]$CandidatePath
|
||||
)
|
||||
|
||||
if (-not $CandidatePath) {
|
||||
return $false
|
||||
}
|
||||
|
||||
if (-not (Test-Path -LiteralPath $CandidatePath -PathType Container)) {
|
||||
return $false
|
||||
}
|
||||
|
||||
return (
|
||||
(Test-Path -LiteralPath (Join-Path -Path $CandidatePath -ChildPath 'config.toml') -PathType Leaf) -and
|
||||
(Test-Path -LiteralPath (Join-Path -Path $CandidatePath -ChildPath 'mpv-handler.exe') -PathType Leaf) -and
|
||||
(Test-Path -LiteralPath (Join-Path -Path $CandidatePath -ChildPath 'mpv-handler-debug.exe') -PathType Leaf)
|
||||
)
|
||||
}
|
||||
|
||||
function Get-DefaultInstallRoot {
|
||||
if (Test-InstallRootContents -CandidatePath $PSScriptRoot) {
|
||||
return (Resolve-Path -LiteralPath $PSScriptRoot).Path
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
function Assert-InstallRoot {
|
||||
param(
|
||||
[string]$CandidatePath
|
||||
)
|
||||
|
||||
if (-not $CandidatePath) {
|
||||
$defaultInstallRoot = Get-DefaultInstallRoot
|
||||
if ($defaultInstallRoot) {
|
||||
return $defaultInstallRoot
|
||||
}
|
||||
|
||||
throw "InstallRoot is required.`n$(Get-UsageExample)"
|
||||
}
|
||||
|
||||
if (-not (Test-Path -LiteralPath $CandidatePath -PathType Container)) {
|
||||
throw "InstallRoot does not exist or is not a folder: $CandidatePath`n$(Get-UsageExample)"
|
||||
}
|
||||
|
||||
$resolved = (Resolve-Path -LiteralPath $CandidatePath).Path
|
||||
|
||||
if (Test-Path -LiteralPath (Join-Path -Path $resolved -ChildPath 'package.json') -PathType Leaf) {
|
||||
throw "InstallRoot appears to be this repo, not the extracted mpv-handler folder: $resolved`n$(Get-UsageExample)"
|
||||
}
|
||||
|
||||
return $resolved
|
||||
}
|
||||
|
||||
function Get-MpvPathFromConfig {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$ConfigPath
|
||||
)
|
||||
|
||||
if (-not (Test-Path -LiteralPath $ConfigPath -PathType Leaf)) {
|
||||
return $null
|
||||
}
|
||||
|
||||
$raw = Get-Content -LiteralPath $ConfigPath -Raw
|
||||
$match = [regex]::Match($raw, '(?m)^\s*mpv\s*=\s*"(?<path>[^"]+)"\s*$')
|
||||
if (-not $match.Success) {
|
||||
return $null
|
||||
}
|
||||
|
||||
$candidate = $match.Groups['path'].Value.Trim()
|
||||
if (-not $candidate) {
|
||||
return $null
|
||||
}
|
||||
|
||||
if ([System.IO.Path]::IsPathRooted($candidate) -and (Test-Path -LiteralPath $candidate -PathType Leaf)) {
|
||||
return (Resolve-Path -LiteralPath $candidate).Path
|
||||
}
|
||||
|
||||
try {
|
||||
$command = Get-Command -Name $candidate -ErrorAction Stop
|
||||
return $command.Source
|
||||
} catch {
|
||||
return $null
|
||||
}
|
||||
}
|
||||
|
||||
function Remove-ProtocolKey {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$SchemeName
|
||||
)
|
||||
|
||||
$classesRoot = [Microsoft.Win32.Registry]::ClassesRoot
|
||||
try {
|
||||
$classesRoot.DeleteSubKeyTree($SchemeName, $false)
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
|
||||
function Register-Protocol {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$SchemeName,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Description,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$ContentType,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$HandlerExecutable,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$EffectiveIconPath
|
||||
)
|
||||
|
||||
$classesRoot = [Microsoft.Win32.Registry]::ClassesRoot
|
||||
$schemeKey = $classesRoot.CreateSubKey($SchemeName)
|
||||
if (-not $schemeKey) {
|
||||
throw "Failed to create registry key for $SchemeName"
|
||||
}
|
||||
|
||||
try {
|
||||
$schemeKey.SetValue('', $Description, [Microsoft.Win32.RegistryValueKind]::String)
|
||||
$schemeKey.SetValue('Content Type', $ContentType, [Microsoft.Win32.RegistryValueKind]::String)
|
||||
$schemeKey.SetValue('URL Protocol', '', [Microsoft.Win32.RegistryValueKind]::String)
|
||||
|
||||
$defaultIconKey = $schemeKey.CreateSubKey('DefaultIcon')
|
||||
try {
|
||||
$defaultIconKey.SetValue('', ('"{0}",1' -f $EffectiveIconPath), [Microsoft.Win32.RegistryValueKind]::String)
|
||||
} finally {
|
||||
$defaultIconKey.Dispose()
|
||||
}
|
||||
|
||||
$commandKey = $schemeKey.CreateSubKey('shell\open\command')
|
||||
try {
|
||||
$commandKey.SetValue('', ('"{0}" "%1"' -f $HandlerExecutable), [Microsoft.Win32.RegistryValueKind]::String)
|
||||
} finally {
|
||||
$commandKey.Dispose()
|
||||
}
|
||||
} finally {
|
||||
$schemeKey.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
if ([System.Environment]::OSVersion.Platform -ne [System.PlatformID]::Win32NT) {
|
||||
throw 'This installer is only for Windows.'
|
||||
}
|
||||
|
||||
$installRootPath = Assert-InstallRoot -CandidatePath $InstallRoot
|
||||
$configPath = Resolve-ExistingFile -BasePath $installRootPath -FileName 'config.toml'
|
||||
$handlerPath = Resolve-ExistingFile -BasePath $installRootPath -FileName 'mpv-handler.exe'
|
||||
$handlerDebugPath = Resolve-ExistingFile -BasePath $installRootPath -FileName 'mpv-handler-debug.exe'
|
||||
|
||||
$effectiveIconPath = if ($IconPath) {
|
||||
if (-not (Test-Path -LiteralPath $IconPath -PathType Leaf)) {
|
||||
throw "IconPath does not exist: $IconPath"
|
||||
}
|
||||
(Resolve-Path -LiteralPath $IconPath).Path
|
||||
} else {
|
||||
Get-MpvPathFromConfig -ConfigPath $configPath
|
||||
}
|
||||
|
||||
if (-not $effectiveIconPath) {
|
||||
$effectiveIconPath = $handlerPath
|
||||
}
|
||||
|
||||
if (-not $KeepExistingProtocolKeys) {
|
||||
Remove-ProtocolKey -SchemeName 'mpv'
|
||||
Remove-ProtocolKey -SchemeName 'mpv-debug'
|
||||
Remove-ProtocolKey -SchemeName 'mpv-handler'
|
||||
Remove-ProtocolKey -SchemeName 'mpv-handler-debug'
|
||||
}
|
||||
|
||||
Register-Protocol -SchemeName 'mpv-handler' -Description 'URL:MPV Handler' -ContentType 'application/x-mpv-handler' -HandlerExecutable $handlerPath -EffectiveIconPath $effectiveIconPath
|
||||
Register-Protocol -SchemeName 'mpv-handler-debug' -Description 'URL:MPV Handler Debug' -ContentType 'application/x-mpv-handler-debug' -HandlerExecutable $handlerDebugPath -EffectiveIconPath $effectiveIconPath
|
||||
|
||||
Write-Host 'Successfully installed mpv-handler protocol registration.' -ForegroundColor Green
|
||||
Write-Host ('InstallRoot: {0}' -f $installRootPath)
|
||||
Write-Host ('Handler: {0}' -f $handlerPath)
|
||||
Write-Host ('Debug Handler: {0}' -f $handlerDebugPath)
|
||||
Write-Host ('Icon: {0}' -f $effectiveIconPath)
|
||||
Write-Host 'You can now test an mpv-handler:// URL from the browser.'
|
||||
Reference in New Issue
Block a user