Archiv für die Kategorie » Microsoft «

21 | 06 | 2017

PowerShell: Ein schneller Versuch, ADMX zu parsen

Geschrieben von um 19:45 Uhr

Hier ein bißchen Code, um alle Einstellungen aus ADMXen inklusive Registry-Pfad und -Typ zu exportieren. Ein paar Typen könnten noch fehlen …

Achtung! In Zeilen 10 und 11 frißt der Syntax Highlighter den Typ (quadratische Klammer auf)xml(quadratische Klammer zu) unmittelbar vor der runden Klammer. Noch weiß ich nicht, wie ich ihn überredet bekomme, das anzuzeigen. Bis dahin hier der Quelltext zum Download: admx_parser

$language = "de-DE"
$root = "C:\Windows\PolicyDefinitions"
$output = @()

$admx_files = Get-ChildItem $root -Filter "*.admx"
foreach ($admx in $admx_files) {
    $admx_file = Split-Path $admx -Leaf
    $adml = "C:\Windows\PolicyDefinitions\$($language)\$($admx_file.TrimEnd('x'))l"
    if (Test-Path $adml) {
        $admx_data = (Get-Content $admx.FullName)
        $adml_data = (Get-Content $adml -Encoding UTF8)
        $adml_strings = $adml_data.policyDefinitionResources.resources.stringTable.GetEnumerator()
        $policies = $admx_data.policyDefinitions.policies
        foreach ($pol in $policies.policy) {
            $dn_string = $pol.displayName.Substring(9, ($pol.displayName.Length - 10))
            $et_string = $pol.explainText.Substring(9, ($pol.explainText.Length - 10))
            $policy_name = ($adml_strings.Where({$_.id -eq $dn_string})).'#text'
            $adml_strings.Reset()
            $policy_desc = ($adml_strings.Where({$_.id -eq $et_string})).'#text'
            $adml_strings.Reset()
            if ($pol.elements.HasChildNodes) {
                $els = $pol.elements.GetEnumerator()
                foreach ($el in $els) {
                    $reg_value = "$($pol.Key)\$($el.valueName)"
                    switch ($el.Name) {
                        'boolean' { $reg_type = 'REG_DWORD (1)' }
                        'decimal' { $reg_type = 'REG_DWORD' }
                        'text' {
                            if ($el.expandable) {
                                $reg_type = 'REG_EXPAND_SZ'
                            } else {
                                $reg_type = 'REG_SZ'
                            }
                        }
                        'enum' {
                            $ex = $el.FirstChild.FirstChild.FirstChild.Name
                            switch ($ex) {
                                'decimal' { $reg_type = 'REG_DWORD' }
                                'text' {
                                    if ($el.expandable) {
                                        $reg_type = 'REG_EXPAND_SZ'
                                    } else {
                                        $reg_type = 'REG_SZ'
                                    }
                                }
                            }
                        }
                        'list' {
                            $reg_type = 'REG_SZ (list)'
                            $reg_value = $el.Key
                        }
                        default { 
                            Write-Host $el.Name -ForegroundColor Cyan
                            $reg_type = $el.Name
                            $reg_value = $el.Key
                        }
                    }
                    $out_item = New-Object PSObject -Property @{'RegPath' = $reg_value; 'RegType' = $reg_type; 'PolicyTitle' = $policy_name; 'PolicyDescription' = $policy_desc; 'ADMXFile' = $admx_file}
                    $output += $out_item
                }
            } else {
                $reg_value = "$($pol.Key)\$($pol.valueName)"
                $reg_type = 'REG_DWORD (1)'
                $out_item = New-Object PSObject -Property @{'RegPath' = $reg_value; 'RegType' = $reg_type; 'PolicyTitle' = $policy_name; 'PolicyDescription' = $policy_desc; 'ADMXFile' = $admx_file }
                $output += $out_item
            }
        }
    } else {
        Write-Host "ADML in $language not found: $adml" -ForegroundColor Yellow
    }
}
$output | Export-CSV c:\temp\admx.csv -Encoding UTF8

Enjoy!

Tags » , , «

2

07 | 05 | 2017

PSConfEU 2017: Das war schön

Geschrieben von um 23:08 Uhr

Drei unvergessliche Tage in Hannover, Inspiration für das ganze Jahr, tolle Gespräche, neue und alte Freunde:

Danke an @TobiasPSP, das Orga-Team, die Speaker!

Tags » , , , «

+

04 | 03 | 2017

PowerShell als Malware-Engine war gestern, jetzt ist Group Policy dran…

Geschrieben von um 20:22 Uhr

Interessante und extrem beunruhigende Beobachtung (leider schon im Feld) von Darren Mar-Elia: https://sdmsoftware.com/group-policy-blog/security-related/group-policy-malware-delivery-system/

Aber letztendlich gilt auch hier, was wir schon immer gepredigt haben: Nicht darauf verlassen, dass der Hersteller es besser weiß, sondern den Zugriff nach Möglichkeit explizit steuern.

Tags » , , «

+

24 | 01 | 2017

USB, Plug’n’Play und das seltsame Startup- und Shutdown-Verhalten

Geschrieben von um 13:22 Uhr

Hatte heute ein seltsames Verhalten eines Windows 7 Embedded Thin Clients (HP T520) erlebt:

  • Client fährt mit eingestecktem USB-Stick hoch (kein Boot-Stick, nur Daten) und sieht ihn beim Hochfahren (Dateien vom Stick werden im Maschinen-Kontext auf den RAMDrive des Thin Clients kopiert, daher weiß man, dass der Stick gelesen wurde)
  • Nach dem Boot wird der User „User“ automatisch angemeldet. Er sieht den Stick im Explorer nicht (das ist normal)
  • Meldet man „User“ ab und den „Administrator“ an, sieht er den Stick auch nicht – weder im Explorer noch im Geräte-Manager!
  • Zieht man den Stick und steckt ihn wieder, erscheint er sofort im Explorer und im Geräte-Manager
  • Solange der Stick steckt, fährt der Thin Client nicht herunter (bleibt im Status „Herunterfahren…“ stecken). Zieht man den Stick, ist der Thin Client binnen weniger Sekunden aus.
  • Mit einem anderen Stick funktioniert alles wie es soll.

Die Ursache war USB3.0 („der andere Stick“ war noch USB2.0). Die Einstellung im BIOS „Force USB2.0“ heilte das Verhalten. Interessanterweise wurde dieses Verhalten mit einer früheren Tranche von T520ern (aus 2014) nicht beobachtet. Go figure.

Tags » , , , «

+

14 | 01 | 2017

Der netdom-Befehl und die Sprachverwirrung

Geschrieben von um 11:19 Uhr

In einem aktuellen Projekt schon wieder erlebt und, da man es bis zum nächsten Mal garantiert wieder vergisst, hier zur Erinnerung:

Auf einem deutschen Domain Controller heißt es nicht etwa so wie in der Dokumentation

netdom trust DOMAIN1 /domain:DOMAIN2 /EnableSidHistory:YES

, sondern vielmehr

netdom trust DOMAIN1 /domain:DOMAIN2 /EnableSidHistory:JA

Also, Eselsbrücke: Bei AD-Migrationen gilt das Törtchen-Motto: „Sag‘ JA zu YES“. Happy migrating!

Tags » «

+

16 | 12 | 2016

Quest Migration Manager for Exchange: Nun auch nach Exchange 2010 mit MAgE!

Geschrieben von um 19:36 Uhr

Still und heimlich hat Quest, noch unter der Marke „DELL Software“, ein Update-Paket für den Migration Manager 8.13 rausgebracht. Neben den üblichen Bugfixes gibt es eine tolle Neuerung: Der „neue“ Migration Agent fpr Exchhange (MAgE) kann nun auch nach Exchange 2010 migrieren. Das ermöglicht gleich zwei Dinge, die bis dato nicht gingen:

  • Migration von Exchange 2013 nach 2010 (der „alte“ Mail Source Agent konnte und kann nicht mit Exchange 2013 sprechen)
  • Migration in bestehende Postfächer (rettet mit gerade ziemlich den Abend, der alte Agent musste sie selber neu anlegen, bevor er bereit war, per MAPI da hinein zu schreiben)

Drei Dinge sind beim Einsatz des MAgE zu beachten:

  • Die SQL-Datenbank wird richtig groß (1.036 Bytes pro synchronisiertes Element) – das ist generell so bei MAgE, nicht nur mit Exchange 2010
  • Wenn die Synchronisierung eines Postfachs mit dem alten MSA/MTA begonnen wurde, kann man nicht auf MAgE umstellen, ohne dass es massenhaft Dubletten gibt
  • Man muss zwingend CPUU ab 5.6.4 einsetzen, um Profile zu migrieren.

Danke Quest, das war lange fällig! Und ja, es wird noch nach Exchange 2010 migriert 🙂

Tags » , , , , «

+

16 | 12 | 2016

Erstes Treffen der EXUSG Berlin – das war schön :-)

Geschrieben von um 19:25 Uhr

Gestern haben wir uns bei der dama.go am Spittelmarkt zum ersten Mal getroffen. Der Abend war ein voller erfolg – geballtes Know-How in einem Raum, inspirierende Vorträge, tolle Gespräche und auch ein bißchen Nostalgie 🙂

Mein Vorschlag, Termine für die Treffen in 2017 bereits jetzt festzulegen, wurde zumindest nicht abgelehnt. Die Termine stehen unter http://exusg.de/veranstaltungen/terminplanung-2017/ zur Abstimmung nach dem Motto „wer was dagegen hat, möge sich jetzt äußern oder für immer schweigen“.

Ich freue mich schon auf das nächste Treffen, voraussichtlich im Februar.

Tags » , , , , , , «

+

07 | 12 | 2016

PowerShell Quirks: String-Array als verbindliches Argument

Geschrieben von um 18:04 Uhr

Nicht wirklich schwierig, aber gut zu wissen: Nehmen wir mal eine Funktion, die irgendwas mit einem Array aus Strings machen soll. Und weil wir sie nicht umsonst aufrufen wollen, deklarieren wir diesen Parameter als verbindlich:

function Do-Something {
    [CmdletBinding()]
    Param(
        [Parameter (Mandatory=$true)][string[]]$in_content
    )
    foreach ($x in $in_content) {
        $col = Get-Random @('Red','Yellow','Green')
        Write-Host $x -ForegroundColor $col
    }
}

Wenn wir also Do-Something ‚blahblahblah‘ oder Do-Something @(‚blah‘,’suelz‘,’foo‘,’bar‘) aufrufen, bekommen wir das erwartete Ergebnis. Die Funktion sollte aber in meinem Fall Inhalte von Textdateien verarbeiten:

Do-Something (Get-Content 'c:\temp\textfile01.txt')

Und siehe da, prompt bekam man den Fehler „Do-Something : Cannot bind argument to parameter ‚in_content‘ because it is an empty string.„. Offensichtlich enthält die Textdatei eine leere Zeile, und diese wird durch den Mandatory-Dekorator geblockt.

Um dies zu umgehen, kann man den Parameter wie folgt definieren:

[Parameter (Mandatory=$true)][AllowEmptyString()][string[]]$in_content

Ganz ohne Argument kann man die Funktion danach immer noch nicht aufrufen. Happy scripting!

Tags » , , , , «

+

14 | 11 | 2016

Happy 10th Birthday PowerShell!

Geschrieben von um 0:34 Uhr

14.11.2016: PowerShell feiert den ersten runden Geburtstag – wer den ganzen Tag Zeit hat, kann die ultimative Tech-Party auf Channel9 live verfolgen: https://channel9.msdn.com/Events/PowerShell-Team/PowerShell-10-Year-Anniversary

PowerShell hat unser Verständnis von Systemadministration grundlegend verändert. Ich bin gespannt auf die nächsten 10 Jahre 🙂

Tags » , , «

+

12 | 11 | 2016

RDExSessionInfo – neue Version 1.1.0.0

Geschrieben von um 13:36 Uhr

Ich hatte gerade etwas Zeit und habe das RDExSessionInfo-Modul aktualisiert. Nun kann auch ein Server remote abgefragt werden. Außerdem liefern Datums-/Zeitwerte, die keinen sinnvollen Wert haben, ab sofort NULL zurück und nicht 01.01.1601 🙂

Alle Infos und Download wie immer unter http://www.it-pro-berlin.de/rdexsessioninfo-de, Download aus der PSGallery unter https://www.powershellgallery.com/packages/RDExSessionInfo/1.1.0.0 und aus der TechNetGallery unter https://gallery.technet.microsoft.com/RDExSessionInfo-a-79a18fac .

Happy automating!

Tags » , , , , «

+