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
}