Repository navigation
Expand file tree
/
Copy pathpair-moonlight.ps1
More file actions
106 lines (90 loc) · 3.67 KB
/
Copy pathpair-moonlight.ps1
File metadata and controls
106 lines (90 loc) · 3.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
$ErrorActionPreference = "Stop"; $scriptArgs = $args
function ArgValue($name) {
for ($i = 0; $i -lt $scriptArgs.Count; $i++) {
if ($scriptArgs[$i] -in @("-$name", "--$name")) { return $scriptArgs[$i + 1] }
}
return ""
}
function FullPath($path) {
$path = [Environment]::ExpandEnvironmentVariables([string]$path)
if ($path -match '^~[\\/](.*)$') { return (Join-Path $HOME $Matches[1]) }
if ([IO.Path]::IsPathRooted($path)) { return $path }
return (Join-Path $PSScriptRoot $path)
}
function Default($cfg, $name, $value) {
if ($null -eq $cfg.$name) { $cfg | Add-Member -Force NoteProperty $name $value }
}
function ChildConfig($cfg, $name) {
if ($null -eq $cfg.$name) {
$cfg | Add-Member -Force NoteProperty $name ([pscustomobject]@{})
}
return $cfg.$name
}
function Credentials($cfg) {
$baseDir = FullPath $cfg.baseDir
$file = Join-Path $baseDir "credentials.txt"
if (-not (Test-Path -LiteralPath $file)) { throw "Missing credentials file: $file" }
$values = @{}
Get-Content -LiteralPath $file | ForEach-Object {
$parts = $_ -split ":", 2
if ($parts.Count -eq 2) { $values[$parts[0].Trim()] = $parts[1].Trim() }
}
return $values
}
function VmIPv4Addresses($vmName) {
@(Get-VMNetworkAdapter -VMName $vmName |
Select-Object -ExpandProperty IPAddresses |
Where-Object { $_ -match '^\d+\.\d+\.\d+\.\d+$' -and $_ -notlike '169.254.*' -and $_ -ne '0.0.0.0' })
}
$configPath = ArgValue "config"
$pin = ArgValue "pin"
$clientName = ArgValue "name"
$hostAddress = ArgValue "host"
if ([string]::IsNullOrWhiteSpace($configPath) -or [string]::IsNullOrWhiteSpace($pin)) {
throw "Usage: .\pair-moonlight.ps1 --config config\windows.json --pin <moonlight-pin> [--name <client-name>] [--host <vm-ip>]"
}
if ([string]::IsNullOrWhiteSpace($clientName)) { $clientName = $env:COMPUTERNAME }
$cfg = Get-Content -Raw (FullPath $configPath) | ConvertFrom-Json
@{
vmName = "WorkstationW11"
baseDir = "~/VMs/WorkstationW11"
}.GetEnumerator() | ForEach-Object { Default $cfg $_.Key $_.Value }
$streaming = ChildConfig $cfg "remoteStreaming"
Default $streaming "port" 47989
$credentials = Credentials $cfg
if (-not $credentials.ContainsKey("SunshineUser") -or -not $credentials.ContainsKey("SunshinePassword")) {
throw "credentials.txt does not contain SunshineUser and SunshinePassword."
}
if ([string]::IsNullOrWhiteSpace($hostAddress)) {
$hostAddress = VmIPv4Addresses $cfg.vmName | Select-Object -First 1
}
if ([string]::IsNullOrWhiteSpace($hostAddress)) { throw "No usable VM IPv4 address found." }
$webPort = [int]$streaming.port + 1
$pairUrl = "https://$($hostAddress):$webPort/api/pin"
$authText = "$($credentials["SunshineUser"]):$($credentials["SunshinePassword"])"
$headers = @{
Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($authText))
}
$body = @{
pin = [string]$pin
name = [string]$clientName
} | ConvertTo-Json
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$oldCallback = [Net.ServicePointManager]::ServerCertificateValidationCallback
[Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
try {
$request = @{
Uri = $pairUrl
Method = "Post"
Headers = $headers
Body = $body
ContentType = "application/json"
}
if ((Get-Command Invoke-RestMethod).Parameters.ContainsKey("SkipCertificateCheck")) {
$request.SkipCertificateCheck = $true
}
Invoke-RestMethod @request | Out-Null
} finally {
[Net.ServicePointManager]::ServerCertificateValidationCallback = $oldCallback
}
Write-Host "Moonlight pair request sent to $pairUrl for '$clientName'."