Param( [Parameter()][String]$WACNAME, [Parameter()][String]$WACPort, [Parameter()][Switch]$uninstall ) $DeviceScript = @' Param( [Parameter(Mandatory=$True, Position=0)][String]$computer ) $WACName = "WAC_NAME" $WACPort = "WAC_Port" $WACFQDN = ([System.Net.Dns]::GetHostByName(($WACName))).Hostname $producttrype = $NULL $producttrype = (Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName $computer -ErrorAction SilentlyContinue).ProductType $FQDN = ([System.Net.Dns]::GetHostByName(($computer))).Hostname if($producttrype -eq 1){$URL = "https://$($WACFQDN):$($WACPort)/computerManagement/connections/computer/$($FQDN)/tools/overview"} else{$URL = "https://$($WACFQDN):$($WACPort)/servermanager/connections/server/$($FQDN)/tools/overview"} Start-Process $URL '@ $basexmlST = @' AdminUI.UIResources.dll Microsoft.ConfigurationManagement.AdminConsole.UIResources.Properties.Resources.resources ClientCheck ContextMenu '@ $siteXMLST = @' AdminUI.UIResources.dll Microsoft.ConfigurationManagement.AdminConsole.UIResources.Properties.Resources.resources InstallClient ENTEREXEPATH ENTERPARAMETERS ContextMenu '@ $CollScript = @' Param( [Parameter(Mandatory=$True, Position=0)][String]$collid ) $WACName = "WAC_NAME" $WACPort = "WAC_Port" add-type @" using System.Net; using System.Security.Cryptography.X509Certificates; public class TrustAllCertsPolicy : ICertificatePolicy { public bool CheckValidationResult( ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) { return true; } } "@ Function Get-Params { param( [Parameter(Mandatory = $false)] [Uri] $GatewayEndpoint, [Parameter(Mandatory = $false)] [pscredential] $Credential ) if ( $GatewayEndpoint -eq $null ) { try { $GatewayEndpoint = [Uri] ( Get-ItemPropertyValue 'HKCU:\Software\Microsoft\ServerManagementGateway' 'SmeDesktopEndpoint' ) } catch { throw (New-Object System.Exception -ArgumentList 'No endpoint was specified so a local gateway was assumed and it must be run at least once.') } } $params = @{useBasicParsing = $true; userAgent = "PowerShell"} [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy $clientCertificateThumbprint = '' $IsLocal = $GatewayEndpoint.IsLoopback -or ( $GatewayEndpoint.Host -eq $Env:ComputerName ) if ( ( $GatewayEndpoint.Scheme -eq [Uri]::UriSchemeHttps ) -and $IsLocal ) { $clientCertificateThumbprint = (Get-ChildItem 'Cert:\CurrentUser\My' | Where-Object { $_.Subject -eq 'CN=Windows Admin Center Client' }).Thumbprint } if ($clientCertificateThumbprint) { $params.certificateThumbprint = "$clientCertificateThumbprint" } else { if ($Credential) { $params.credential = $Credential } else { $params.useDefaultCredentials = $True } } $params.uri = "$($GatewayEndpoint)/api/connections" return $params } Function Get-Connections { param( [Parameter(Mandatory = $false)] [Uri] $GatewayEndpoint, [Parameter(Mandatory = $false)] [pscredential] $Credential ) $params = Get-Params $GatewayEndpoint $Credential $params.method = "Get" $response = Invoke-WebRequest @params if ($response.StatusCode -ne 200 ) { throw "Failed to get the connections" } $connections = ConvertFrom-Json $response.Content return $connections } Function Remove-Connection { param( [Parameter(Mandatory = $false)] [Uri] $GatewayEndpoint, [Parameter(Mandatory = $true)] [String] $connectionId, [Parameter(Mandatory = $false)] [pscredential] $Credential ) $params = Get-Params $GatewayEndpoint $Credential $params.method = "Delete" $params.uri = $params.uri + "/" + $connectionId $response = Invoke-WebRequest @params if ($response.StatusCode -ge 300) { throw "Failed to remove the connection" } } <# .SYNOPSIS Import the connections available in a file to the Windows Admin Center Gateway. .DESCRIPTION The function import all the connections especified into a file .PARAMETER GatewayEndpoint Required. Provide the gateway name. .PARAMETER Credential Optional. If you wish to provide credentials to the Windows Admin Center gateway which are different from your credentials on the computer where you're executing the script, provide a PSCredential by using Get-Credential. You can also provide just the username for this parameter and you will be prompted to enter the corresponding password (which gets stored as a SecureString). .PARAMETER fileName Required. File name to export the results. If is not provided the result is show in console. .PARAMETER prune Optional. If it is present, the connections not included in the file will be removed. .EXAMPLE C:\PS> Import-Connection "http://localhost:4100" -fileName "lista.csv" #> Function Import-Connection { param( [Parameter(Mandatory = $false)] [Uri] $GatewayEndpoint, [Parameter(Mandatory = $false)] [pscredential] $Credential, [Parameter(Mandatory = $true)] [String] $fileName, [Parameter(Mandatory = $false)] [switch] $prune ) $connections = Import-Csv $fileName $connections | ForEach-Object { if ([string]::IsNullOrEmpty($_.type)) { $_.type = "msft.sme.connection-type.server" } $id = ($_.type + "!" + $_.name) if ($_.groupId) { $id = ($id + "!" + $_.groupId) } $_ | Add-Member "id" $id if ($_.tags) { $_.tags = $_.tags.split("|") } } $params = Get-Params $GatewayEndpoint $Credential $params.method = "Put" $params.body = ConvertTo-Json @($connections) Try { $response = Invoke-WebRequest @params } Catch { $error = ConvertFrom-Json $_ throw $error.error.message } if ($response) { if ($response.StatusCode -ne 200 ) { throw "Failed to import the connections" } $content = ConvertFrom-Json $response if ($content -and $content.errors) { Write-Host "The operation partially succeeded with errors:" Write-Warning ($content.errors | fl * | Out-String) } else { Write-Host "Import connections succeeded" } if ($prune) { $connectionsResult = Get-Connections $GatewayEndpoint $Credential $connectionsImported = $connections.id $connectionsRemove = $connectionsResult.value | Where-Object { $_.name -notin $connectionsImported} $connectionsRemove | ForEach-Object { Remove-Connection $GatewayEndpoint $_.name $Credential } } } return $connections } $WACFQDN = ([System.Net.Dns]::GetHostByName(($WAC))).Hostname $localFQDN = ([System.Net.Dns]::GetHostByName(($env:computerName))).Hostname $tempfile = "$($ENV:temp)\wac.csv" if($WACFQDN -eq $localFQDN){} if((Get-Module ConfigurationManager) -eq $null) {Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1"} $psdrive = Get-PSDrive -PSProvider CMSite $sitecode = $psdrive.SiteCode $provider = $psdrive.Connection.NamedValueDictionary["ProviderLocation"].Machine $namespace = "root\sms\site_"+$sitecode Set-Location "$(($psdrive).Name):\" Add-Content -Path $tempfile -Value '"name","type","tags","groupId"' $TargetMachines = (Get-CMDevice -CollectionId $collid | Select-Object -ExpandProperty Name) ForEach($TargetMachine in $TargetMachines){ if(test-wsman $TargetMachine -ErrorAction SilentlyContinue){ $producttrype = $NULL $PT = $NULL $producttrype = (Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName $TargetMachine -ErrorAction SilentlyContinue).ProductType $FQDN = ([System.Net.Dns]::GetHostByName(($TargetMachine))).Hostname if($producttrype -eq 1){$PT = "msft.sme.connection-type.windows-client"} elseif($producttrype -eq $NULL){} else{$PT = "msft.sme.connection-type.server"} if($PT){Add-Content -Path $tempfile -Value "`"$($FQDN)`",`"$($PT)`",`"$($collid)`""} } } Import-Connection "https://$($WACFQDN):$($WACPort)" -fileName $tempfile remove-item $tempfile Write-Host -NoNewLine 'Press any key to close...'; $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown'); '@ $baseXMLCT = @' AdminUI.UIResources.dll Microsoft.ConfigurationManagement.AdminConsole.UIResources.Properties.Resources.resources ClientCheck ContextMenu '@ $siteXMLCT = @' AdminUI.UIResources.dll Microsoft.ConfigurationManagement.AdminConsole.UIResources.Properties.Resources.resources InstallClient ENTEREXEPATH ENTERPARAMETERS ContextMenu '@ #build required strings for install/uninstall $ConsoleDir = $Env:SMS_ADMIN_UI_PATH.Substring(0,$Env:SMS_ADMIN_UI_PATH.Length-8) $ConsoleTools = $ConsoleDir + 'XmlStorage\Tools' $RCTPathST = $ConsoleTools + '\WAC_Launch.ps1' $RCTPathCT = $ConsoleTools + '\AddCollToWAC.ps1' $ConsoleActions = $ConsoleDir + 'XmlStorage\Extensions\Actions' $system1 = $ConsoleActions + '\3fd01cd1-9e01-461e-92cd-94866b8d1f39' $systemfile1 = $system1 + '\WAC_Launch.xml' $system2 = $ConsoleActions + '\0770186d-ea57-4276-a46b-7344ae081b58' $systemfile2 = $system2 + '\WAC_Launch.xml' $system3 = $ConsoleActions + '\ed9dee86-eadd-4ac8-82a1-7234a4646e62' $systemfile3 = $system3 + '\WAC_Launch.xml' $coll1 = $ConsoleActions + '\3785759b-db2c-414e-a540-e879497c6f97' $collfile1 = $coll1 + '\WAC_Launch.xml' $coll2 = $ConsoleActions + '\a92615d6-9df3-49ba-a8c9-6ecb0e8b956b' $collfile2 = $coll2 + '\WAC_Launch.xml' $PSPath = "Powershell.exe" $STXML = $basexmlST $COLLXML = $baseXMLCT $STParam = "-noexit -windowstyle hidden -executionpolicy bypass -file `"$RCTPathST`" ##SUB:Name## " $CRParam = "-executionpolicy bypass -file `"$RCTPathCT`" ##SUB:CollectionID## " $STXML = $STXML -replace '', $siteXMLST ` -Replace 'ENTEREXEPATH', $PSPath -Replace 'ENTERPARAMETERS', $STParam $COLLXML = $COLLXML -Replace '', $siteXMLCT -Replace 'ENTEREXEPATH', $PSPath -Replace 'ENTERPARAMETERS', $CRParam if($Uninstall){ #remove files if(test-path $RCTPathST){Remove-Item $RCTPathST -force} if(test-path $RCTPathCT){Remove-Item $RCTPathCT -force} if(test-path $systemfile1){Remove-Item $systemfile1 -force} if(test-path $systemfile2){Remove-Item $systemfile2 -force} if(test-path $systemfile3){Remove-Item $systemfile3 -force} if(test-path $collfile1){Remove-Item $collfile1 -force} if(test-path $collfile1){Remove-Item $collfile1 -force} } else{ #create scripts if(!(test-path $ConsoleTools)){New-item ConsoleTools -ItemType directory | out-null} if(test-path $RCTPathST){Remove-Item $RCTPathST -force} $DeviceScript -replace "WAC_NAME",$WACNAME -replace "WAC_Port",$WACPort | out-file $RCTPathST -Force if(test-path $RCTPathCT){Remove-Item $RCTPathCT -force} $CollScript -replace "WAC_NAME",$WACNAME -replace "WAC_Port",$WACPort | out-file $RCTPathCT -Force #build / populate extension directories if(!(test-path $system1)){New-item $system1 -ItemType directory | out-null} $STXML | out-file $systemfile1 if(!(test-path $system2)){New-item $system2 -ItemType directory | out-null} $STXML | out-file $systemfile2 if(!(test-path $system3)){New-item $system3 -ItemType directory | out-null} $STXML | out-file $systemfile3 if(!(test-path $coll1)){New-item $coll1 -ItemType directory | out-null} $COLLXML | out-file $collfile1 if(!(test-path $coll2)){New-item $coll2 -ItemType directory | out-null} $COLLXML | out-file $collfile2 }