franz-josef-ii
Goto Top

Windows Admin Center - Tag (VM oder Host) - Powershell

Hello

Ich möchte im WAC im Übersichtsfenster bei allen Servern einen Tag setzen (Host, VM (egal auf welchem Host) oder nix davon).

Ich habe auch noch keinen Ansatz, wie ich das am Besten lösen könnte, hat irgendwer eine Idee? So einfach wie möglich, außer händisch setzen 😊

Franz

Content-ID: 23612461200

Url: https://administrator.de/contentid/23612461200

Ausgedruckt am: 24.11.2024 um 14:11 Uhr

kreuzberger
kreuzberger 10.07.2024 um 08:48:41 Uhr
Goto Top
13676056485
13676056485 10.07.2024 aktualisiert um 09:36:42 Uhr
Goto Top
Verbindungen Eportieren, CSV anpassen und wieder importieren.
Verwenden von PowerShell zum Importieren oder Exportieren deiner Verbindungen (mit Tags)

Gruß wrk
Franz-Josef-II
Franz-Josef-II 10.07.2024 um 09:44:33 Uhr
Goto Top
Danke

@kreuzberger: My english is not the yellow from the egg, but it goes 😂 Ich werde mich durchkämpfen.

@13676056485: Beim Ex- bzw Import muß man ja auch zuerst den Tag angeben, eine automatische Befüllung ist da (leider) nicht.


Wenn man im WAC in die Übersicht eines Servers geht, dann ist dort das Modell angegeben. Z.B. Dell Poweredge oder eben Virtual Machine. Wenn ich diese Info als Tag in die Gesamtübersicht hineinbringen würde, wäre es das Gewünschte oder gleich die Spalte "Modell"?

Hmmm, die Richtung habe ich,
13676056485
13676056485 10.07.2024 aktualisiert um 10:02:17 Uhr
Goto Top
Zitat von @Franz-Josef-II:
@13676056485: Beim Ex- bzw Import muß man ja auch zuerst den Tag angeben, eine automatische Befüllung ist da (leider) nicht.
Nein musst du nicht. Du musst die Tags nur in der CSV ergänzen und wieder importieren, das kann auch direkt per Powershell erfolgen wenn du nicht von Hand in Excel oder Texteditor bearbeiten willst , z.B.

# csv pfad
$csvpath = ".\wac-connections.csv"  
# wac url 
$url = "https://wac.domain.tld"  
# Modul importieren
Import-Module "$env:ProgramFiles\windows admin center\PowerShell\Modules\ConnectionTools"  
# Connections exportieren
Export-Connection $url -fileName $csvpath
# csv laden
$csv = Import-CSV -LiteralPath $csvpath -Delimiter ","  
# und bearbeiten (hier jeder Connection bestimmte Tags zuweisen, dass kannst du via Where-Object filtern wie du willst)
$csv | %{
    $_.tags = 'server|vm|testing'  
}
# CSV exportieren
$csv | Export-CSV -LiteralPath $csvpath -Delimiter "," -NoType  -Encoding UTF8  
# ... und wieder importieren
Import-Connection $url -fileName $csvpath -prune

screenshot
13676056485
13676056485 10.07.2024 aktualisiert um 10:47:55 Uhr
Goto Top
Du kannst es auch ohne den Umweg über die CSV machen wenn du willst, im oben eingebundenen PS Modul findest du alles was du brauchst, das Update läuft dann über simple get und put Web-API Requests des Admin-Centers

# admin center url
$url = 'https://wac.domain.tld'  

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
}

# get connections
$params = Get-Params $url
$params.Method = 'Get'  
$params.ContentType = 'application/json'  
$connections = (Invoke-RestMethod @params).value.properties | select id,type,name,tags,groupId

# edit connections
$connections | %{
    # assign unique id for upload
    $_.id = $_.type + "!" + $_.name  
    if($groupId){
        $_.Id = $id + "!" + $_.groupId  
    }
    # assign tags
    $_.tags = 'server','vm','testing'  
}

# upload changes
$params.Method = 'Put'  
$params.ContentType = 'application/json'  
$params.Body = $connections | ConvertTo-JSON -Depth 100
Invoke-RestMethod @params
Franz-Josef-II
Franz-Josef-II 10.07.2024 um 17:03:02 Uhr
Goto Top
Hello

Das Script erzeugt 3 Tags (Server, VM und Testing) und weist sie allen Servern zu. Ich hätte das Ganze aber gerne automatisch.

Mit diesem schlanken Einzeiler
Get-ADComputer -Filter 'operatingsystem -like "*Windows server*" -and enabled -eq "true"' | Select-Object Name | Foreach-Object {Get-CimInstance Win32_ComputerSystem -ComputerName $_.Name -ErrorAction SilentlyContinue | Select-Object PSComputerName,Model} | Export-Csv -path .\wac.csv -NoTypeInformation  
bekomme ich eine CSV mit Servernamen und der Modellbezeichnung.

Jetzt sollte ich diese CSV mit dem WAC verheiraten, also Zeile 2
Server01 ..... gibt es den im WAC? ..... wenn nein-> anlegen (mit dem FQDN?), wenn ja hat er den in der Spalte 2 genannten Tag? Die Möglichkeiten in der Spalte 2 sind: Poweredge R730 oder HP irgendwas oder eben Virtual Machine. Kommt ein neues Servermodel, dann soll das Modell als Tag angelegt werden.

An dem scheitere ich jetzt noch.
13676056485
Lösung 13676056485 10.07.2024 aktualisiert um 17:56:04 Uhr
Goto Top
Ich gehe hier von der Verwendung von DNSHostNamen (FQDNs) der Computer aus ...

# admin center url
$url = 'https://wac.domain.tld'    
$computers = Get-ADComputer -Filter 'operatingsystem -like "*Windows server*" -and enabled -eq "true"' | select Name,DnsHostName,@{n='Model';e={(Get-CimInstance Win32_ComputerSystem -Computername $_.Name -Property Model  -EA SilentlyContinue).Model}}  

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"}  
    $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
}

# get connections
$params = Get-Params $url
$params.Method = 'Get'    
$params.ContentType = 'application/json'    
[array]$connections = (Invoke-RestMethod @params).value.properties | select id,type,name,tags,groupId

# add missing computers to connections
$computers | ? DNSHostName -NotIn $connections.name | %{
    $connections += [pscustomobject]@{
        id = ''  
        type = 'msft.sme.connection-type.server'  
        name = $_.DnsHostName
        tags = $_.Model
        groupId = ''  
    }
}

# edit connections
$connections | %{
    # assign unique id for upload
    $_.id = $_.type + "!" + $_.name    
    if($groupId){
        $_.Id = $id + "!" + $_.groupId    
    }
    # assign corresponding tags from the computer array
    [string[]]$_.tags = $_.tags + ($computers | ? DnsHostname -eq $_.name | % Model) | select -Unique
}

# upload changes
$params.Method = 'Put'    
$params.ContentType = 'application/json'    
$params.Body = $connections | ConvertTo-JSON -Depth 100
Invoke-RestMethod @params

So das war jetzt genug Silbertablett from my side ...

Good luck.

Haken dran bitte nicht vergessen.

🖖 WRK
Franz-Josef-II
Franz-Josef-II 12.07.2024 um 07:40:34 Uhr
Goto Top
Guten Morgen

Es funktioniert ..... großteils.

Der DC bekommt 3x den Tag "Virtual Machine", die physischen Server zu 100% und von 12 VMs habens 8, wobei das an den VMs liegen dürfte, Verbindungsfehler aus unbekannter Ursache.

Recht herzlichen Dank