param ( [Parameter(Mandatory=$true)] [string] $airline = 'ua', [Parameter(Mandatory=$true)] [ValidateSet('gate', 'checkin')] [string] $comType, [Parameter(Mandatory=$true)] [ValidateSet('query', 'import', 'delete', 'generate')] [string] $action, [Parameter(Mandatory=$false)] [ValidateSet('HKEY_LOCAL_MACHINE', 'HKEY_CURRENT_USER', 'HKLM', 'HKCU')] [string] $hive = 'HKEY_LOCAL_MACHINE', [Parameter(Mandatory=$false)] [string] $comDir, [Parameter(Mandatory=$false)] [string] $comFileName, [Parameter(Mandatory=$false)] [switch] $enableDebugging = $false ) if ($enableDebugging) { $DebugPreference = 'Continue' } else { $DebugPreference = 'SilentlyContinue' } switch ($airline) { 'as' { Write-Error "Not yet implemented for airline ""$airline""" exit 1 } '4n' { Write-Error "Not yet implemented for airline ""$airline""" exit 1 } 'nz' { Write-Error "Not yet implemented for airline ""$airline""" exit 1 } 'ua' { switch ($comType) { 'checkin' { $appName = 'uasrdev' $clsid = '35578409-F9F5-43e8-A6BD-8B77199ED854' $appId = 'C123476B-ABB6-4BCC-B557-2FDC0CDCD6A8' $classLabel = 'QSRDev Class' $interfaceId = '6B15E61A-381F-41E7-8B65-BA386473FE8C' $interfaceName = 'IQSRDev' $interfaceStubClsid = '00020424-0000-0000-C000-000000000046' $eventInterfaceId = '17DCFB07-18A9-4FFE-B34D-37B91D809C41' $eventInterfaceName = '_IQSRDevEvents' $eventInterfaceStubClsid = '00020420-0000-0000-C000-000000000046' $typeLibId='CD886C7B-B61C-49CF-B3B8-90DB303A502A' $typeLibLabel = 'QSRDevice 1.0 Type Library' $typeLibVersion = '1.0' $versionIndependentProgId = 'QSRDevice.QSRDev' } 'gate' { $appName = 'uagrdev' $clsid = '3F52625C-F66C-43F5-B538-CDF7331E0B7D' $appId = '91D04D72-DCB6-11D3-957D-00409500D5AD' $classLabel = 'QWDev Class' $interfaceId = 'D178FEAC-4969-45B4-92BF-4582EA5C6F47' $interfaceName = 'IQWDev' $interfaceStubClsid = '00020424-0000-0000-C000-000000000046' $eventInterfaceId = 'FDE206D5-EB3E-4DB1-AC3E-6CF314417443' $eventInterfaceName = '_IQWDevEvents' $eventInterfaceStubClsid = '00020420-0000-0000-C000-000000000046' $typeLibId='FB2C3447-9D8D-4AD0-9234-A163505FC3AE' $typeLibLabel = 'QWDevice 1.0 Type Library' $typeLibVersion = '1.0' $versionIndependentProgId = 'QWDevice.QWDev' } } } default { Write-Error "Unknown airline: $airline" exit 1 } } $progId = "$versionIndependentProgId.1"; switch ($action) { 'generate' { } 'delete' { } 'query' { } 'import' { if (!$comDir) { Write-Error "Missing COM server directory" exit 1 } if (!$comFileName) { Write-Error "Missing COM server file name" exit 1 } } default { Write-Error "Unknown action: $action" exit 1 } } switch ($hive) { 'HKCU' { $hiveShort = 'HKCU' $hive = 'HKEY_CURRENT_USER' } 'HKLM' { $hiveShort = 'HKLM' $hive = 'HKEY_LOCAL_MACHINE' } 'HKEY_CURRENT_USER' { $hiveShort = 'HKCU' $hive = 'HKEY_CURRENT_USER' } 'HKEY_LOCAL_MACHINE' { $hiveShort = 'HKLM' $hive = 'HKEY_LOCAL_MACHINE' } default { Write-Error "Invalid registry hive: $hive" exit 1 } } $comDir = $comDir.TrimEnd('\') $comPath = "$comDir\$comFileName" if (![System.IO.Path]::IsPathRooted($comPath)) { Write-Error "Provided COM server path is not absolute: $comPath" exit 1 } if (!(Test-Path $comPath)) { Write-Warning "COM server path does not exist: $comPath" } # COM servers use the network path in some registry keys when self-registering, so attempt to discover it. $comNetworkPath = $comPath try { $driveLetter = $comPath.Substring(0, 1) $networkPathToDrive = (Get-PSDrive | Where-Object {$_.Name -eq $driveLetter}).DisplayRoot if ($networkPathToDrive) { $rootPathWithoutDrive = $comPath.Substring(2) $comNetworkPath = "$networkPathToDrive$rootPathWithoutDrive" } } catch { Write-Error "An error occurred trying to discover network path to COM server at $comPath" } function Get-ClsidData { param( [Parameter(Mandatory=$false)] [string] $architectureNode = '\' ) return @( @{ Key = "\SOFTWARE\Classes$($architectureNode)CLSID\{$clsid}" ValueItems = @( @{ Name = '(default)' Value = $classLabel }, @{ Name = 'AppID' Value = "{$appId}" } ) }, @{ Key = "\SOFTWARE\Classes$($architectureNode)CLSID\{$clsid}\LocalServer32" ValueItems = @( @{ Name = '(default)' Value = $comPath } ) }, @{ Key = "\SOFTWARE\Classes$($architectureNode)CLSID\{$clsid}\ProgID" ValueItems = @( @{ Name = '(default)' Value = $progId } ) }, @{ Key = "\SOFTWARE\Classes$($architectureNode)CLSID\{$clsid}\Programmable" ValueItems = @() }, @{ Key = "\SOFTWARE\Classes$($architectureNode)CLSID\{$clsid}\TypeLib" ValueItems = @( @{ Name = '(default)' Value = "{$typeLibId}" } ) }, @{ Key = "\SOFTWARE\Classes$($architectureNode)CLSID\{$clsid}\VersionIndependentProgID" ValueItems = @( @{ Name = '(default)' Value = $versionIndependentProgId } ) } ) } function Get-InterfaceData { param( [Parameter(Mandatory=$false)] [string] $architectureNode = '\' ) return @( @{ Key = "\SOFTWARE\Classes$($architectureNode)Interface\{$interfaceId}" ValueItems = @( @{ Name = '(default)' Value = $interfaceName } ) }, @{ Key = "\SOFTWARE\Classes$($architectureNode)Interface\{$interfaceId}\ProxyStubClsid32" ValueItems = @( @{ Name = '(default)' Value = "{$interfaceStubClsid}" } ) }, @{ Key = "\SOFTWARE\Classes$($architectureNode)Interface\{$interfaceId}\TypeLib" ValueItems = @( @{ Name = '(default)' Value = "{$typeLibId}" }, @{ Name = 'Version' Value = $typeLibVersion } ) }, @{ Key = "\SOFTWARE\Classes$($architectureNode)Interface\{$eventInterfaceId}" ValueItems = @( @{ Name = '(default)' Value = $eventInterfaceName } ) }, @{ Key = "\SOFTWARE\Classes$($architectureNode)Interface\{$eventInterfaceId}\ProxyStubClsid32" ValueItems = @( @{ Name = '(default)' Value = "{$eventInterfaceStubClsid}" } ) }, @{ Key = "\SOFTWARE\Classes$($architectureNode)Interface\{$eventInterfaceId}\TypeLib" ValueItems = @( @{ Name = '(default)' Value = "{$typeLibId}" } @{ Name = 'Version' Value = $typeLibVersion } ) } ) } function Get-ProgIdData { return @( @{ Key = "\SOFTWARE\Classes\$versionIndependentProgId" ValueItems = @( @{ Name = '(default)' Value = $classLabel } ) }, @{ Key = "\SOFTWARE\Classes\$versionIndependentProgId\CLSID" ValueItems = @( @{ Name = '(default)' Value = "{$clsid}" } ) }, @{ Key = "\SOFTWARE\Classes\$versionIndependentProgId\CurVer" ValueItems = @( @{ Name = '(default)' Value = $progId } ) } @{ Key = "\SOFTWARE\Classes\$progId" ValueItems = @( @{ Name = '(default)' Value = $classLabel } ) }, @{ Key = "\SOFTWARE\Classes\$progId\CLSID" ValueItems = @( @{ Name = '(default)' Value = "{$clsid}" } ) } ) } function Get-TypeLibData { param( [Parameter(Mandatory=$false)] [string] $architectureNode = '\' ) return @( @{ Key = "\SOFTWARE\Classes$($architectureNode)TypeLib\{$typeLibId}" ValueItems = @() }, @{ Key = "\SOFTWARE\Classes$($architectureNode)TypeLib\{$typeLibId}\$typeLibVersion" ValueItems = @( @{ Name = '(default)' Value = $typeLibLabel } ) }, @{ Key = "\SOFTWARE\Classes$($architectureNode)TypeLib\{$typeLibId}\$typeLibVersion\0" ValueItems = @() }, @{ Key = "\SOFTWARE\Classes$($architectureNode)TypeLib\{$typeLibId}\$typeLibVersion\0\win32" ValueItems = @( @{ Name = '(default)' Value = $comNetworkPath } ) }, @{ Key = "\SOFTWARE\Classes$($architectureNode)TypeLib\{$typeLibId}\$typeLibVersion\FLAGS" ValueItems = @( @{ Name = '(default)' Value = '0' } ) }, @{ Key = "\SOFTWARE\Classes$($architectureNode)TypeLib\{$typeLibId}\$typeLibVersion\HELPDIR" ValueItems = @( @{ Name = '(default)' Value = "$comDir\" } ) } ) } function Get-Data { param( [Parameter(Mandatory=$false)] [switch] $includeWrongArchitecturePaths = $false ) if ($env:PROCESSOR_ARCHITECTURE -eq 'x86') { $wow6432Node = '\' } else { $wow6432Node = '\WOW6432Node\' } $paths = New-Object System.Collections.Generic.List[System.Object] $paths.AddRange((Get-ProgIdData)) $paths.AddRange((Get-ClsidData -architectureNode $wow6432Node)) if ($includeWrongArchitecturePaths -and $wow6432Node -ne '\') { $paths.AddRange((Get-ClsidData)) } $paths.AddRange((Get-InterfaceData -architectureNode $wow6432Node)) if ($wow6432Node -ne '\') { $paths.AddRange((Get-InterfaceData)) } $paths.AddRange((Get-TypeLibData -architectureNode $wow6432Node)) if ($wow6432Node -ne '\') { $paths.AddRange((Get-TypeLibData)) } return $paths } switch ($action) { 'delete' { $data = Get-Data -includeWrongArchitecturePaths foreach ($dataEntry in $data) { $path = "$($hiveShort):\$($dataEntry.Key)" try { Remove-Item -Path $path -Recurse -Force -ErrorAction Stop Write-Information "Deleted registry key: $path" } catch { Write-Error "Failed to find $path" continue } } } 'import' { $data = Get-Data foreach ($dataEntry in $data) { $path = "$($hiveShort):\$($dataEntry.Key)" # try { # New-Item -Path $path -Force -ErrorAction Stop # Write-Information "Imported key: $path" # } # catch { # Write-Error "Failed to import key: $path" # continue # } Write-Debug $path foreach ($valueItem in $dataEntry.ValueItems) { # try { # New-ItemProperty -Path $path -Name $valueItem.Name -Value $valueItem.Value -PropertyType 'String' -Force -ErrorAction Stop # Write-Information "Imported value: $($valueItem.Name) in $path" # } # catch { # Write-Error "Failed to create entry: $($valueItem.Name) in $path" # continue # } Write-Debug "$($valueItem.Name)=$($valueItem.Value)" } } } 'query' { $data = Get-Data -includeWrongArchitecturePaths foreach ($dataEntry in $data) { $path = "$($hiveShort):\$($dataEntry.Key)" try { $foundKey = Get-Item -Path $path -ErrorAction Stop } catch { Write-Warning "Failed to find $path" continue } $pathShort = $foundKey.PSPath -replace '^.*::', '' Write-Host Write-Host $pathShort $itemProperty = Get-ItemProperty -Path $path if (!$itemProperty) { continue } foreach ($property in $itemProperty.PSObject.Properties) { if ($property.Name.StartsWith('PS')) { continue } Write-Host "$($property.Name)=$($property.Value)" } } } 'generate' { $outFileAdd = "$appName-add.reg" $outFileDel = "$appName-del.reg" $data = Get-Data if (Test-Path $outFileAdd) { try { Remove-Item -Path $outFileAdd -ErrorAction Stop } catch { Write-Error "Failed to delete existing file: $outFileAdd" exit 1 } } Write-Output 'Windows Registry Editor Version 5.00' > $outFileAdd Write-Output 'Windows Registry Editor Version 5.00' > $outFileDel foreach ($dataEntry in $data) { $path = "$($hive)$($dataEntry.Key)" Write-Output '' >> $outFileAdd Write-Output "[$path]" >> $outFileAdd Write-Output "[-$path]" >> $outFileDel foreach ($valueItem in $dataEntry.ValueItems) { if ($valueItem.Name -eq '(default)') { $name = '@' } else { $name = """$($valueItem.Name)""" } $value = $valueItem.Value.Replace('\', '\\').Replace('"', '\"') Write-Output "$name=""$value""" >> $outFileAdd } } } default { Write-Error "Unknown action: $action" exit 1 } }