Autoren-Archiv Evgenij

15 | 03 | 2019

VMware Advanced deploy exam – Erster Versuch

Geschrieben von um 13:55 Uhr

Heute wollte ich – nach ordentlicher Vorbereitung, versteht sich – meine zweite VCAP-DCV Prüfung ablegen, und zwar die Deployment-Prüfung. Diese findet im Labor statt und wird anschließend bewertet. Die bisherige Erfahrung ist wie folgt:

  • Die Labor-Umgebung wird offenbar punkt zum Prüfungsbeginn bereitgestellt. Ich war mit dem Auto da, und da mir heute die Traffic-Götter gnädig waren, kam ich fast eine halbe Stunde zu früh. Bei Multiple-Choice-Exams bisher nie ein Problem, hat dieser Umstand hier zu einer gewissen Konfusion im Test Center geführt. Learning: Nicht zu früh kommen.
  • Das Test-Center hatte 15″ 4:3-Monitore. Die Umgebung basiert auf derselben Engine wie die Hands-On-Labs.Wer schon mal ein Labor gemacht hat, kann sich vorstellen, wie praktikabel das ist. Learning: Ein Test Center suchen, das im 21. Jahrhundert angekommen ist.
  • Punkt 10 Uhr haben wir dann einen zweiten Versuch gestartet. Die HOL-Umgebung lud tatsächlich und war auch auf den ersten Blick performant genug. Allerdings blieb das rechte Fenster, wo die Prüfungsfragen erscheinen sollten, für fast 20 Minuten im Status „Loading…“. Danach brachen wir die Prüfung ab. Learning: Die alte Labor-Umgebung war einfach nur scheiße, die neue ist auf eine andere Art scheiße…
  • Nach 20 Minuten haben wir dann die Prüfung abgebrochen und ich durfte das Test Center unverrichteter Dinge verlassen. Das Test Center hatte mir gesagt, die können nichts weiter für mich tun und ich soll ein Ticket per Pearson aufmachen. Dort wurde mir folgendes empfohlen:
    Gesagt, getan. Nach ein paar Sekunden hatte ich eine Chat-Session mit Steven, der leider das Problem auch nach zweifacher Erläuterung nicht begriffen hat. Learning: Das mit dem Chat noch mal ausprobieren… in 10 Jahren oder so.
  • Das gute alte Telefon bemüht. Die kostenlose Deutschland-Nummer 0800-1810696 führt ohne Umwege zur internationalen Hotline, wo – fast schon nicht mehr überraschend – ein Steven auf mich wartete. War aber ein anderer Steven, vielleicht heißen sie dort alle so…
  • Dieser konnte das Problem nun erfassen und kannte es sogar bereits. Seine erste Reaktion war, das Test Center hätte eigentlich das Ticket aufmachen sollen. Learning: Ein Test Center suchen, das weiß, was es tut.
  • Nun habe ich eine Case ID und die Zusicherung, dass ich binnen drei Werktage von denen höre. Wir werden sehen…

Ein schönes Wochenende und Happy Testing!

Tags » , , , , «

+

09 | 03 | 2019

Windows Server User Group Berlin: Die Agenda für 21.03. steht fest

Geschrieben von um 11:43 Uhr

Die Agenda des anstehenden User Group-Treffens am 21. März steht nun fest. Alle Details und Anmeldung wie immer auf Meetup. Es sind noch Plätze frei!

Tags » , , , , , , «

+

03 | 03 | 2019

Exchange User Group Berlin trifft sich am 03. April

Geschrieben von um 22:55 Uhr

Das erste Treffen der EXUSG in diesem Jahr findet nicht mehr in Q1 statt – dafür gleich zu Beginn des April, am 03.04.2019 bei der ITACS in Mitte. Achtung! Es gibt zwei Abweichungen von der üblichen Routine:

  • Das Treffen findet an einem Mittwoch statt
  • Der Beginn ist bereits um 17 Uhr

Alle Details und Anmeldung siehe https://www.meetup.com/de-DE/EXUSG-DE/events/259304818/

Tags » , , , , , «

+

23 | 02 | 2019

Windows Server User Group Berlin trifft sich am 21. März

Geschrieben von um 13:27 Uhr

Das erste Treffen des Jahres 2019 findet am 21. März bei der COMPAREX AG in Berlin-Adlershof statt. Agenda steht noch nicht fest und wird in den nächsten Tagen aktualisiert. Vorträge, kurz oder lang, können noch eingereicht werden.
Alle Details und Anmeldung: https://www.meetup.com/de-DE/Windows-Server-User-Group-Berlin/events/259153636/

Tags » , , , , «

+

22 | 12 | 2018

Ich werde auf der PSConf.EU 2019 sprechen

Geschrieben von um 22:15 Uhr

Als ob die Vorweihnachtszeit nicht aufregend genug wäre: Gerade wurde die Speaker-Liste der europäischen PowerShell-Konferenz 2019 (http://www.psconf.eu/) auf Twitter veröffentlicht, und ich bin dabei!

Tags » , , «

+

29 | 11 | 2018

PSConf.EU 2019 – Registrierung ist eröffnet!

Geschrieben von um 9:44 Uhr

Das Traditions-Event geht in die vierte Runde: Hannover, im HCC, 4.-7. Juni 2019, alle Details und Anmeldung unter https://www.psconf.eu/

Die Registrierung ist ab sofort offen, also: schnell anmelden und ein halbes Jahr Vorfreude geniessen!

Tags » , , «

+

24 | 11 | 2018

Das neue Buch von William Hertling ist erschienen

Geschrieben von um 21:44 Uhr

Ich bin schon sehr gespannt: https://www.amazon.de/Kill-Switch-Chain-Book-English-ebook/dp/B07JLL5CP9

Tags » , , «

+

19 | 09 | 2018

PSConf.EU 2019 – Call for Papers ist offen!

Geschrieben von um 9:46 Uhr

Ab heute (und bis zum 09.12.2018) können Vorträge für die PowerShell Konferenz 2019 in Hannover eingereicht werden: HIER.

Also los, Community – reicht eure Themen ein, Hannover wartet!

Tags » , , , , «

+

10 | 09 | 2018

PowerShell Quirks: Values aus der Pipeline, Object Edition

Geschrieben von um 17:51 Uhr

Heute gab es mal wieder eine interessante Frage im TechNet-Forum. Das wollte ich mal näher untersuchen. Es ging darum, dass beim Pipen eines Objektes nach New-Item der Inhalt des erstellten Items das gesamte Objekt, aufgedröselt als Hashtable, enthielt. Im Thread war es eine Datei, aber mit dem Registry-Provider funktionierte es genau so. Das interessante am Value-Parameter ist, dass er Argumente nicht nur nach Namen, sondern auch nach dem Wert bindet:

Doch ist es nur eine Eigenart von New-Item oder ist das Verhalten generell so? Schreiben wir mal eine kleine Funktion, die ihre Argumente, falls sie aus der Pipeline angeflogen kommen, ganz regulär nach Namen bindet:

function Get-MyArgs {
    [CmdletBinding()]
    Param(
        [Parameter(ValueFromPipelineByPropertyName=$true)][string]$MyInput,
        [Parameter(ValueFromPipelineByPropertyName=$true)][string]$MyOtherParm
    )
    Write-Host "Value of MyOtherParm:"
    $MyOtherParm
    Write-Host "Value of MyInput:"
    $MyInput
}

Wenn wir der Funktion jetzt ein Objekt verfüttern, das die gewünschten Properties enthält, werden sie auch ordnungsgemäß gebunden:

$x = New-Object PSCustomObject -Property @{
    MyInput="MyInputValue";
    MyOtherParm="MyOtherParmValue";
    ForeignParm="ShouldNotSeeMe"
}
$x | Get-MyArgs

liefert

Value of MyOtherParm:
MyOtherParmValue
Value of MyInput:
MyInputValue

Akzeptieren wir nur die gleichen Parameter, aber nach dem Wert, wartet eine kleine Überraschung auf uns:

function Get-MyArgs {
    [CmdletBinding()]
    Param(
        [Parameter(ValueFromPipeline=$true)][string]$MyInput,
        [Parameter(ValueFromPipeline=$true)][string]$MyOtherParm
    )
    Write-Host "Value of MyOtherParm:"
    $MyOtherParm
    Write-Host "Value of MyInput:"
    $MyInput
}
$x = New-Object PSCustomObject -Property @{
    MyInput="MyInputValue";
    MyOtherParm="MyOtherParmValue";
    ForeignParm="ShouldNotSeeMe"
}
$x | Get-MyArgs

liefert uns

Value of MyOtherParm:
@{MyInput=MyInputValue; MyOtherParm=MyOtherParmValue; ForeignParm=ShouldNotSeeMe}
Value of MyInput:
@{MyInput=MyInputValue; MyOtherParm=MyOtherParmValue; ForeignParm=ShouldNotSeeMe}

Und jetzt kommt der Quirk:

Was passiert aber, wenn wir, wie bei Value in New-Item, beide Bindungen zulassen? Also

function Get-MyArgs {
    [CmdletBinding()]
    Param(
        [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)][string]$MyInput,
        [Parameter(ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true)][string]$MyOtherParm
    )
    Write-Host "Value of MyOtherParm:"
    $MyOtherParm
    Write-Host "Value of MyInput:"
    $MyInput
}
$x = New-Object PSCustomObject -Property @{
    MyInput="MyInputValue";
    MyOtherParm="MyOtherParmValue";
    ForeignParm="ShouldNotSeeMe"
}
$x | Get-MyArgs

Anders als bei New-Item, erhalten wir nur die String-Werte der beiden benannten Parameter!
Eine Untersuchung mit

Trace-Command -Name ParameterBinding -Expression {$x | Get-MyArgs} -PSHost

fördert die folgenden Schritte zu Tage:

BIND PIPELINE object to parameters: [Get-MyArgs]
    PIPELINE object TYPE = [System.Management.Automation.PSCustomObject]
    RESTORING pipeline parameter's original values
    Parameter [MyOtherParm] PIPELINE INPUT ValueFromPipeline NO COERCION
    BIND arg [@{MyInput=MyInputValue; MyOtherParm=MyOtherParmValue; ForeignParm=ShouldNotSeeMe}] to parameter [MyOtherParm]
        Executing DATA GENERATION metadata: [System.Management.Automation.ArgumentTypeConverterAttribute]
            result returned from DATA GENERATION: @{MyInput=MyInputValue; MyOtherParm=MyOtherParmValue; ForeignParm=ShouldNotSeeMe}
        BIND arg [@{MyInput=MyInputValue; MyOtherParm=MyOtherParmValue; ForeignParm=ShouldNotSeeMe}] to param [MyOtherParm] SKIPPED
    Parameter [MyInput] PIPELINE INPUT ValueFromPipeline NO COERCION
    BIND arg [@{MyInput=MyInputValue; MyOtherParm=MyOtherParmValue; ForeignParm=ShouldNotSeeMe}] to parameter [MyInput]
        Executing DATA GENERATION metadata: [System.Management.Automation.ArgumentTypeConverterAttribute]
            result returned from DATA GENERATION: @{MyInput=MyInputValue; MyOtherParm=MyOtherParmValue; ForeignParm=ShouldNotSeeMe}
        BIND arg [@{MyInput=MyInputValue; MyOtherParm=MyOtherParmValue; ForeignParm=ShouldNotSeeMe}] to param [MyInput] SKIPPED
    Parameter [MyOtherParm] PIPELINE INPUT ValueFromPipelineByPropertyName NO COERCION
    BIND arg [MyOtherParmValue] to parameter [MyOtherParm]
        Executing DATA GENERATION metadata: [System.Management.Automation.ArgumentTypeConverterAttribute]
            result returned from DATA GENERATION: MyOtherParmValue
        BIND arg [MyOtherParmValue] to param [MyOtherParm] SUCCESSFUL
    Parameter [MyInput] PIPELINE INPUT ValueFromPipelineByPropertyName NO COERCION
    BIND arg [MyInputValue] to parameter [MyInput]
        Executing DATA GENERATION metadata: [System.Management.Automation.ArgumentTypeConverterAttribute]
            result returned from DATA GENERATION: MyInputValue
        BIND arg [MyInputValue] to param [MyInput] SUCCESSFUL
MANDATORY PARAMETER CHECK on cmdlet [Get-MyArgs]

Bei New-Item ist das Value-Argument allerdings kein [string], sondern ein [object[]] (danke an Martin Binder für den Hinweis, dass dieser Test noch aussteht!). Ändert man das im obigen Beispiel, dann ist das Verhalten so wie bei New-Item auch, und zwar unabhängig davon, ob ein einzelnes [object] oder ein Array davon erwartet wird – es wird in beiden Fällen das ganze Objekt gebunden, sobald ValueFromPipeline=$true auftaucht.
Happy argument-passing!

Tags » , , , «

+

07 | 09 | 2018

HTML5-Client für RDS – große Freude mit kleinen Tücken

Geschrieben von um 20:16 Uhr

Anfang des Jahres hat Microsoft ohne viel Trara einen HTML5-Client für RDS herausgebracht. Ich habe mir das Ding angeschaut und war vom ersten Test ziemlich begeistert. Besonderheiten der neuen Komponente in Kürze:

  • einsetzbar nur für eine komplette RDS-Bereitstellung, nicht für den Zugriff auf einzelne Server
  • ist fest verheiratet mit RDWeb (und ersetzt ihn, wenn man den Webclient produktiv veröffentlicht)
  • erfordert zwingend den RD Gateway (und somit SSL-Zertifikate, denen ohne Wenn und Aber vertraut wird)
  • Drucker- und Zwischenablagenumleitung werden unterstützt, Laufwerke und SmartCard (noch) nicht, von anderer Peripherie ganz zu schweigen
  • Die RDS-Infrastruktur – Broker, RDWeb und Gateway – muss auf Server 2016 oder 2019 laufen (Worker können aus der 2012R2-Generation sein)
  • RDSCALs müssen per User vergeben werden (Device CALs würden sonst sehr schnell verbraucht werden)
  • Nach der offiziellen Guidance (https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/remote-desktop-web-client-admin) muss jeder RDWeb-Server zum Zeitpunkt der Installation Zugang zum Internet, d.h. zur PowerShell Gallery, haben.

Da ich kein großer Freund von Previews bin, habe ich die Testumgebung mit Server 2016 aufgebaut. Deshalb muss ich auf meinem RDWeb-Server zunächst einmal das NuGet-Modul updaten:

Install-Module -Name PowerShellGet -Force

Danach muss die PowerShell geschlossen und neu gestartet werden. So auf die neueste NuGet-Version gebracht, kann das Management-Modul für den Web Client installiert werden:

Install-Module -Name RDWebClientManagement

Das Modul exportiert 12 Cmdlets mit vielversprechender Funktionalität:

Uninstall-RDWebClient
Get-RDWebClientBrokerCert
Import-RDWebClientBrokerCert
Remove-RDWebClientBrokerCert
Get-RDWebClientDeploymentSetting
Set-RDWebClientDeploymentSetting
Find-RDWebClientPackage
Get-RDWebClientPackage
Install-RDWebClientPackage
Publish-RDWebClientPackage
Uninstall-RDWebClientPackage
Unpublish-RDWebClientPackage

Schauen wir mal, was Find-RDWebClientPackage so findet… Das sieht vielversprechend aus:

packageId                       : rd-html5
version                         : 1.0.0
author                          : Microsoft
summary                         : The Remote Desktop Web Client
minRDWebClientManagementVersion : 1.0.0
url                             : https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RE2mzyl
_baseVersion                    : 1.0.0

Doch was ist das? Bereits durch dieses „Finden“ wurde der Ordner „C:\Program Files\RemoteDesktopWeb“ erzeugt, mit einem Ordner „Internal“, auf den ich gar keine Rechte habe! OK, „Deny Everyone Read“ ist ein bisschen plump, aber Internal ist Internal. Drin sind drei Ordner: „Clients“, „Config“ und „Temp“. Alle drei sind noch leer bis auf die „Config\deploymentSettings.js“, die folgenden Inhalt hat:

var DeploymentSettings = {
    "deploymentType":  "rdWeb",
    "suppressTelemetry":  false
}

Echt jetzt? Es wird also früh vorgesorgt, dass die Telemetrie schön an ist. Weiter im Text. Sowohl Get-RDWebClientPackage als auch Install-RDWebClientPackage haben keinen Parameter, mit dem man einen lokalen Speicherort angeben kann, meine RDWeb-Server brauchen also wirklich Zugang zum Internet, damit ich den Web Client installiert bekomme. Im Moment hat mein RDWeb-Server Internet, also installiere ich:

Install-RDWebClientPackage

(das ausgepackte Archiv aus dem Internet liegt nun unter „C:\Program Files\RemoteDesktopWeb\Internal\Clients\4csqnmex.0iv“…)

Import-RDWebClientBrokerCert C:\temp\RDWeb.cer

(das Zertifikat wurde nach „C:\Program Files\RemoteDesktopWeb\Internal\Config\brokercert.cer“ kopiert…)

Publish-RDWebClientPackage -Type Test -Latest

Das war’s! Bereits im IE11 bekomme ich unter https://F.Q.D.N/RDWeb/webclient-test eine moderne Oberfläche angezeigt, verbunden mit dem Hinweis, dass Audio nicht geht: OK, IE11 ist nicht gerade ein HTML5-fähiger Browser…
In Chrome sieht es schon ganz anders aus:

Soweit, so gut. Sieht richtig gut aus, und die Performance haben die RDSGURUS ja auch positiv getestet. Schauen wir mal, was man so einstellen kann, denn oben rechts ist ja ein Zahnrad:

Na, da hat es sich ja richtig gelohnt, einen Dialog dafür zu basteln.
Freunde, diese Telemetrie-Einstellung ist gar nicht so harmlos wie sie aussieht. Wenn ich nämlich die Telemetrie anlasse und der Testumgebung den Internet-Zugang wegnehme, so startet der Web-Client gar nicht erst!

Hmm, das ist nicht schön. Zum Glück betrifft das den Rechner, von dem aus man den Browser öffnet, und nicht die gesamte Bereitstellung. Macht ja auch irgendwie Sinn, dass die am Frontend Telemetrie-Daten sammeln. Könnte diese Zeile sein:

Nicht umsonst hat Microsoft dem PowerShell-Modul das Cmdlet Set-RDWebClientDeploymentSetting mitgegeben, damit kann man nämlich auch ohne Internet-Zugang die Telemetrie ausschalten:

Set-RDWebClientDeploymentSetting -Name SuppressTelemetry -Value $true

Und falls sich jemand die Frage gestellt hat, ob das Ganze auch auf anderen Betriebssystemen geht (z.B. weil er MacOS-User ist und von den ewigen Troubles mit dem RDP Client die Nase voll hat)…

Happy RDSing!

Tags » , , , , , , «

+