Archive for the ‘Powershell’ Category

Windows Drucker will nicht mehr und beim Versuch eine Testseite auszudrucken erscheint Fehlernummer 0×00000006

23 Juli 2014

Ein Kunde meldet sich und meint, sein Drucker druckt nicht mehr. Jetzt kann dies wie immer viele Ursachen haben aber diese ist mal wieder typisch Microsoft. Der Kunde hat ein kleines Netzwerk und somit eine Domäne. Der Drucker wird vom Server verwaltet und ist per Netzwerk dem Client zugeordnet.

Wie gesagt druckt der jetzt nicht mehr. Also die übliche Prozedur mit zunächst Windows-Testseite drucken, um rauszufinden, ob es ein Windows bzw. Treiberproblem ist oder von der Anwendung herrührt.

Mmhh. Windows-Testseite drucken meldet:

[Window Title]

Druckereigenschaften

 

[Main Instruction]

Die Testseite konnte nicht gedruckt werden. Soll die Druckproblembehandlung angezeigt werden? Der Vorgang konnte nicht abgeschlossen werden (Fehler 0×00000006).

 

[Ja] [Nein]

Dasselbe nochmal als Admin probiert half auch nichts. Nett wie Windows ist, bietet es einem die Druckproblembehandlung an. Aber alles was die fabriziert ist: Der Drucker ist nicht der Standarddrucker, soll dies geändert werden? Was hat dies mit dem Fehler zu tun? Nichts! Also wie immer ignorieren und selber den Fehler ausfindig machen.

Zunächst war der Gedanke, vielleicht liegt es am Druckertreiber, also Druckerwarteschlange neu gestartet aber wieder nichts. OK, vielleicht der Treiber selber, Rechner neu gestartet, brachte auch nichts. OK, dann vielleicht mal direkt am Server eine Testseite ausdrucken. Klappt!

Na toll. Der Drucker druckt vom Server aber nicht von der betreffenden Station. Also Netzwerkproblem aber welches?

Also mal Powershell aufgerufen und Test-ComputerSecureChannel probiert:

PS C:\Windows\system32> Test-ComputerSecureChannel

Test-ComputerSecureChannel : Der lokale Computer ist keiner Domäne beigetreten,

 oder die Domäne kann nicht kontaktiert werden.

Bei Zeile:1 Zeichen:27

+ Test-ComputerSecureChannel <<<<

    + CategoryInfo          : NotSpecified: (:) [Test-ComputerSecureChannel],

   ActiveDirectoryObjectNotFoundException

    + FullyQualifiedErrorId : System.DirectoryServices.ActiveDirectory.ActiveD

   irectoryObjectNotFoundException,Microsoft.PowerShell.Commands.TestComputer

  SecureChannelCommand

 

Aha, also ein Problem mit der Domänenkommunikation. Zur Bestätigung noch ein w32tm /monitor abgesetzt:

GetDcList ist fehlgeschlagen mit Fehlercode: 0x8007054B.
Beendet mit Fehler 0x8007054B

 

OK.

 

Übrigens ist das Cmdlet Test-ComputerSecureChannel die optimale Hilfe um Probleme mit der Vertrauensstellung zur Domäne (trust relationship) herauszufinden. Nichts mehr wie früher mit NETDOM, wo man zuerst immer schauen musste, wo man es herbekommt. Test-ComputerSecureChannel ist ab PS 2.0 enthalten, also quasi überall. http://technet.microsoft.com/en-us/library/hh849757.aspx.

 

Grund

Ein Vergleich der Uhrzeit zwischen Server und Client offenbarte dann auch schnell den Grund. Der Client hinkte 7 Minuten hinterm Server her!

Ja dann ist ja die Lösung einfach. Zeit gesetzt und Rechner gebootet, neu angemeldet und immer noch der Fehler. Mist.

Wieder Powershell angeworfen und Reset-ComputerMachinePassword probiert:

PS C:\Windows\system32> Reset-ComputerMachinePassword -Server server
Reset-ComputerMachinePassword : Der lokale Computer ist keiner Domäne beigetret

en, oder die Domäne kann nicht kontaktiert werden.

Bei Zeile:1 Zeichen:30

+ Reset-ComputerMachinePassword <<<<  -Server server

    + CategoryInfo          : NotSpecified: (:) [Reset-ComputerMachinePassword

   ], ActiveDirectoryObjectNotFoundException

    + FullyQualifiedErrorId : System.DirectoryServices.ActiveDirectory.ActiveD

   irectoryObjectNotFoundException,Microsoft.PowerShell.Commands.ResetCompute

  rMachinePasswordCommand

Komisch immer diese Fehlermeldungen. In einem anderen Fall hatte dies problemlos zum Erfolg geführt, warum hier nicht? Auf dem anderen Rechner war allerdings Powershell 3.0, in diesem Fall war nur 2.0 installiert.

Lösung:
Also noch Powershell 4.0 von http://www.microsoft.com/de-de/download/details.aspx?id=40855 installiert. Danach war alles gleich viel freundlicher:

PS C:\Windows\system32> Test-ComputerSecureChannel
False
PS C:\Windows\system32> Reset-ComputerMachinePassword -Server server –Credential (Get-Credential)
Cmdlet Get-Credential an der Befehlspipelineposition 1
Geben Sie Werte für die folgenden Parameter an:
Credential
PS C:\Windows\system32> Test-ComputerSecureChannel
False

So jetzt nochmal einen Neustart und alles war gut:

PS C:\Windows\system32> Test-ComputerSecureChannel
True
PS C:\Windows\system32> w32tm /monitor
SERVER.thiel.local *** PDC ***[192.168.16.1:123]:

    ICMP: 0ms Verzögerung

    NTP: +0.0000000s Offset von SERVER.thiel.local

        RefID: (unbekannt) [0xCE383741]

        Stratum: 3

[Warnung]

Die Reversenamenauflösung ist die beste Möglichkeit. Sie ist ggf. nicht

korrekt, da sich das Ref-ID-Feld in Zeitpaketen im Bereich von

NTP-Implementierungen unterscheidet und ggf. keine IP-Adressen verwendet.

PS C:\Windows\system32>

Fazit: Es ist halt immer wieder dasselbe Spiel, sobald Zeitdifferenzen größer 5 Minuten passieren, dann geht das Vertrauen verloren und es kommen die verrücktesten Fehlermeldungen zustande.

Noch ein paar Links mit weiteren Hinweisen:

http://www.techiesweb.com/repair-broken-windows-trust-relationship-between-domain-controller-and-client-machine/

http://www.implbits.com/about/blog/tabid/78/post/don-t-rejoin-to-fix-the-trust-relationship-between-this-workstation-and-the-primary-domain-failed/default.aspx

http://blog.joeware.net/2012/06/05/2508/

http://www.cievo.sk/2012/02/21/reset-computer-accounts-in-active-directory-domain/

Gruppierung bei Windows Druckern aufheben

9 Juli 2014

Wenn man unter Windows 7 oder 8 die “Geräte und Drucker” anzeigen lässt, dann stellt Windows Geräte, die denselben Treiber und denselben Port verwenden aber unterschiedliche Namen haben, alle gruppiert in einem Objekt dar.

Bei Problemen kann dies aber hinderlich sein. Mittels dieser Powershell Zeilen wird im Temp-Verzeichnis, welches auch angelegt wird, falls es nicht vorhanden sein sollte ein Symbol mit Drucker angelegt, welches dann den Zugang zu den Druckern erlaubt:

New-Item -ItemType Directory -Name "C:\Temp\Drucker.{2227A280-3AEA-1069-A2DE-08002B30309D}"
Invoke-Item C:\Temp

OK, vielleicht etwas übers Ziel rausgeschossen. Es geht auch einfacher, man gibt in der oberen Adresszeile eines Windows Explorers dies ein und erhält dann auch die Darstellung der Drucker.

shell:::{2227A280-3AEA-1069-A2DE-08002B30309D}

Oder einfach direkt von der Eingabeaufforderung:

start "" "shell:::{2227A280-3AEA-1069-A2DE-08002B30309D}"

stellt eine sogannte ClassID dar, von der es noch mehrere gibt, z. B. stellt diese ClassID die Systemsteuerung dar:

shell:::{21ec2020-3aea-1069-a2dd-08002b30309d}

Eine Auflistung der möglichen Werte findet man hier: https://code.google.com/p/libfwsi/wiki/ShellFolderIdentifiers

In diesem Zusammenhang auch noch interessant: http://newyear2006.wordpress.com/2013/01/19/windows-8-godmode/ 

Der genaue Hintergrund wird hier beleuchtet: http://msdn.microsoft.com/en-us/library/cc144096(VS.85).aspx#virtual

Windows OEM Key aus BIOS/UEFI bzw. ACPI per Powershell auslesen oder wo kommt der Windowskey für die Aktivierung her?

30 Juni 2014

Letzthin war ich doch etwas geschockt, als es darum ging, einem neuen Rechner Windows 8.1 Update 1 beizubringen. Nicht dass jetzt die Installation unmöglich gewesen wäre aber ein paar Details haben mich etwas stutzig gemacht.

Zunächst muss ich sagen, es handelt sich um einen fertigen ASUS-Tower. Dieser wird mit Windows 7 vorinstalliert ausgeliefert. Da aber Windows 8 drauf sollte und dabei gleich die neueste Fassung mit 8.1 Update 1, wollte ich über die übliche Methode diese Version installieren: http://newyear2006.wordpress.com/2013/09/13/windows-8-1-mit-product-key-von-windows-8-installieren/ indem ich die Installation über einen Microsoft-Demokey vornehmen wollte. Bei der Vorbereitung machte ich mich dann auf die Suche nach dem Windows 8 Key. Aber was soll ich sagen? Es gab keinen! Weder auf dem Tower aufgeklebt noch auf den DVDs oder sonstwo.

OK, es gibt ja die Möglichkeit den Key auf die DVD zu verpacken. Also DVD untersucht und die WIM-Dateien mittels 7zip angeschaut aber nix. Keine Datei mit einem Key. Was geht hier ab?

Ich gebs zu, ich hab dann doch von der Original-DVD Windows 8 installiert. Aber nur um zu sehen, ob später ein Key eingetragen ist. Siehe da, die Installation flutscht durch, ohne nach dem Key zu fragen und führt bei Internetverbindung gleich noch die Aktivierung durch. Das nenn ich ja mal Service! Aber genau diesen Service möchte ich am allerwenigsten.

Die Herausforderung
Jetzt wird es aber interessant. Also auf der DVD ist kein Key zu finden. Aber Windows ist nach der Installation aktiviert. Wie geht das? Wo kommt der Key für die Aktivierung her? Hat es Microsoft etwa eingesehen, dass dieses ganze Zwangsaktivierungsgedöns langfristig deren Untergang ist und aktiviert einfach so? Oder ist die Sache irgendwie an das ASUS-Bios bzw. ASUS UEFI Umgebung gebunden?

Mit der letzten Vermutung kommen wir der Sache näher aber zu meiner Überraschung ganz anders, als ich ursprünglich gedacht hatte. Es hat tatsächlich etwas mit UEFI zu tun aber es wird nicht einfach ein Hersteller ermittelt und dieser freigeschaltet, sondern jeder Rechner bringt seinen eigenen Key im ACPI mit! Dies ist auch keine Besonderheit von ASUS sondern alle Hersteller LENOVO, ACER, DELL usw. alle scheinen diese Variante mittlerweile zu praktizieren!

Die verfügbaren Tools
Hier der erste Artikel bei dem ich über die Sache gestolpert bin: http://www.zdnet.com/will-bios-embedded-windows-8-product-keys-cause-reinstall-troubles-7000008226/. Dieser bestätigte also schon mal, dass es tatsächlich so ist, dass der OEM-Key im BIOS hinterlegt ist. Dann ging es weiter: Wenn der da hinterlegt wird, dann kann man den ja irgendwie auslesen: http://www.nextofwindows.com/how-to-retrieve-windows-8-oem-product-key-from-bios/. Hier kommt neben den üblichen Verdächtigen wie Nirsoft auch RWEverything (http://rweverything.com/download/) zur Sprache, welches ich bisher noch nicht kannte. Der Link bei nextofwindows hat auch ein Python-Script parat. In diesem Script kommen interessante Win32-Funktionen zum Einsatz um den OEM-Key auszulesen! Hier das Script auf Github: https://github.com/christian-korneck/get_win8key#files. Python ist gut aber Powershell wäre besser! http://www.eightforums.com/installation-setup/35444-laptop-encrypted-key-uefi-bios-how-obtain-iso-2.html hat einen Powershellfetzen und spricht mittels WMI den SoftwareLicensingService an, welcher mittels OA3xOriginalProductKey den Key anscheinend auslesen kann. Nur leider klappte dies bei mir nie!

Die Hintergründe
Microsoft hat scheinbar schon lange die Möglichkeit vorgesehen, Daten aus dem BIOS bzw. aus dem Firmwarebereich auszulesen. So gibt es z. B. die Win32-Funktion EnumSystemFirmwareTables bereits seit Windows XP mit 64-Bit und generell seit Windows Vista. Macht auch Sinn, da ja ab Windows Vista durch die Umstellungen der Systemsicherheit vieles abgeschottet und umgebaut wurde. http://msdn.microsoft.com/en-us/library/windows/desktop/ms724259(v=vs.85).aspx. Mittels EnumSystemFirmwareTables und GetSystemFirmwareTable kann man nun die nötigen Daten aus der Firmware auslesen. http://msdn.microsoft.com/en-us/library/windows/desktop/ms724379(v=vs.85).aspx. Diese Funktionen nutzt auch das Pythonskript um den Key auszulesen.

Dazu gibt es auch eine offizielle Beschreibung der Speicherstruktur: http://msdn.microsoft.com/en-us/library/windows/hardware/dn653305(v=vs.85).aspx. Microsoft nennt es Microsoft Software Licensing Tables, welche im ACPI-Bereich unter den Systembeschreibungstabellen zu finden ist. Das Dokument spezifiziert davon zwei, einmal SLIC-Table und einmal MSDM-Table. Obwohl das Tabellenformat identisch ist, ist der Unterschied, dass SLIC für VolumeLicenseKeys und MSDM für individuelle Keys gedacht ist.

Bei Tests hat sich herausgestellt, dass Lenovo wie Asus und wahrscheinlich die meisten Hardwarehersteller MSDM benutzen. Dies zeigen auch die vielen Scripte, die es zum Auslesen gibt, welche sich ausschließlich immer auf MSDM beziehen. Interessant dabei ist natürlich, dass bei der Herstellung der Rechner jeder einzelne mit seinem individuellen Key versehen wird! Okay, früher waren es die individualisierten Keyaufkleber aber durch diese Methode können ja im Prinzip viel mehr Dinge auf dem Rechner aktiviert oder individualisiert werden. Denken wir jetzt an nichts Böses, sondern einfach mal an die bei der Bestellung hochgeladene, individuelle Startgrafik.

Powershell Fassung
Auf der weiteren Suche nach einer Fassung in Powershell, bin ich über diese Variante gestolpert: http://winaero.com/blog/how-to-get-the-windows-product-key-without-using-third-party-software/. Auf den ersten Blick genau was ich wollte aber leider wird nur wieder der Key aus der Registrierung ausgelesen, wie man es früher gemacht hat.

Diese Variante war auch ganz hilfreich und enthält noch mehr Infos zu verschiedenen Gegebenheiten und verschiedene Sourcecodes und Scripte: http://forums.mydigitallife.info/threads/43788-C-C-VB-NET-Read-MSDM-license-information-from-BIOS-ACPI-tables/page3.

Aber am Ende war keine Powershellfassung dabei. Also selber machen! Warum eigentlich Powershell? Ja warum? Weil Powershell wird solange da sein, wie sich Microsoft über Wasser halten kann und es ist bei jedem neuen Rechner von Haus aus mit an Bord! Sogar Windows RT bringt es mit. In der reinen Lehre gibt es also nichts anderes.

Also hier der Code:

$SFTCode = @"

 

[DllImport("kernel32")] public static extern uint EnumSystemFirmwareTables (uint FirmwareTableProviderSignature, IntPtr pFirmwareTableBuffer, uint BufferSize);

[DllImport("kernel32")] public static extern uint GetSystemFirmwareTable   (uint FirmwareTableProviderSignature, uint FimrwareTableID, IntPtr pFirmwareTableBuffer, uint BufferSize);

 

"@

 

$SFT = Add-Type -MemberDefinition $SFTCode -Name "SFTKlasse" -Language CSharp -UsingNamespace "System.Reflection", "System.Diagnostics", "System.Collections.Generic" -PassThru

 

# 0×41435049=ACPI ? https://github.com/michaelforney/coreboot/blob/master/src/include/cbmem.h

$firmwareTableProviderSignature = 0×41435049

$StructSize = $SFT::EnumSystemFirmwareTables($firmwareTableProviderSignature, [IntPtr]::Zero, 0)

try

{

    $StructPtr = [Runtime.InteropServices.Marshal]::AllocHGlobal($StructSize)

}

catch [OutOfMemoryException]

{

    throw Error[0]

}

 

$buffer = New-Object Byte[]($StructSize)

$SFT::EnumSystemFirmwareTables($firmwareTableProviderSignature, $StructPtr, $StructSize)

[Runtime.InteropServices.Marshal]::Copy($StructPtr, $buffer, 0, $StructSize)

[Runtime.InteropServices.Marshal]::FreeHGlobal($StructPtr)

 

if (([System.Text.Encoding]::ASCII).GetString($buffer).Contains("MSDM"))

{

    $firmwareTableMSDMID = 0x4d44534d

 

    $StructSize = $SFT::GetSystemFirmwareTable($firmwareTableProviderSignature, $firmwareTableMSDMID, [IntPtr]::Zero, 0)

    try

    {

        $StructPtr = [Runtime.InteropServices.Marshal]::AllocHGlobal($StructSize)

    }

    catch [OutOfMemoryException]

    {

        throw Error[0]

    }

 

    $buffer = New-Object Byte[]($StructSize)

    $SFT::GetSystemFirmwareTable($firmwareTableProviderSignature, $firmwareTableMSDMID, $StructPtr, $StructSize)

    [Runtime.InteropServices.Marshal]::Copy($StructPtr, $buffer, 0, $StructSize)

    [Runtime.InteropServices.Marshal]::FreeHGlobal($StructPtr)

 

    $encoding = [System.Text.Encoding]::GetEncoding(0x4e4)

 

    $key = $encoding.GetString($buffer, 56, 29)

}

$key

Wie immer gilt, von der Formatierung nicht abschrecken lassen, sondern einfach Copy&Paste und loslegen. Übrigens es werden keine Admin-Rechte benötigt! Da einiges durcheinander geht, hier noch der Gist-Verweis: https://gist.github.com/newyear2006/5578386bf4793a334f85#file-getacpi-oemkey-ps1

Würde mich freuen, wenn der eine oder andere seine Erfahrungen im Kommentarbereich verewigen könnte, um ein Gefühl dafür zu bekommen, welche Hersteller die Variante unterstützen.

Zusätzlich interessiert mich besonders:

PS > ([System.Text.Encoding]::ASCII).GetString($buffer)

Dies gibt einen String aus, mit den auf dem Rechner verfügbaren Firmwaretabellen.

Noch ein Hinweis:
Falls es nach dem Copy&Paste zu einem Fehler wie diesem hier kommt:

0×41435049 : Die Benennung "0×41435049" wurde nicht als Name eines Cmdlet, einer Funktion, einer Skriptdatei oder eines ausführbaren Programms erkannt. Überprüfen

Sie die Schreibweise des Namens, oder ob der Pfad korrekt ist (sofern enthalten), und wiederholen Sie den Vorgang.

In Zeile:12 Zeichen:35

+ $firmwareTableProviderSignature = 0×41435049

+ ~~~~~~~~~~

+ CategoryInfo : ObjectNotFound: (0×41435049:String) [], CommandNotFoundException

+ FullyQualifiedErrorId : CommandNotFoundException

dann bitte das x bei 0×41434049 löschen und nochmal eingeben. Scheint eine nette Anomalie von WordPress zu sein.

Powershell Cmdlets nach Verben und Substantiven (Nouns) sortiert ausgeben

21 Mai 2014

Wenn man Powershell Cmdlets schreibt, steht man das eine oder andere Mal vor der Frage, mit welchem Verb man sein Cmdlet bezeichnen sollte.

Zur Inspiration kann man sich ja einfach mal die bestehenden ausgeben lassen:

get-command -CommandType Cmdlet | Group-Object -Property Verb | Sort-Object -Property Count –Descending

Wenn man dann schon dabei ist, kann man sich ja gleich auch noch die aktuellen Substantive (Nouns) ausgeben lassen:

get-command -CommandType Cmdlet | Group-Object -Property Noun  | Sort-Object -Property Count -Descending

Ach und wer seine Cmdlets Professional aussehen lassen will, der verwendet in der Powershell ISE im Editor die Combination STRG+J zur Auswahl von Cmdlet-Codesnippets also Codeschnipsel! Leider erst ab PS 3.0 aufwärts verfügbar.

Windows Server 2012 (R2) Server Manager um eigene Powershell Skripte erweitern

19 Mai 2014

Seit Windows Server 2012 hat Microsoft bei den GUI-Verwaltungen der alten MMC den Kampf angesagt. Alle neuen Tools werden immer weiter in den neuen Server-Manager integriert. Führt man über das Toolsmenü einen Befehl aus, läuft im Hintergrund ein Powershell-Skript ab.

Das Toolsmenü kann man um eigene Powershell-Skripte erweitern, dazu muss man nur das Powershell-Skript in das Verzeichnis

%PROGRAMDATA%\Microsoft\Windows\Start Menu\Programs\Administrative Tools

verlinken. Dabei kann man auf alle im Dashboard bekannten Server zurückgreifen, indem man diese Datei ausliest:

%APPDATA%\Microsoft\Windows\ServerManager\ServerList.XML

Näheres beschreibt dieser Artikel: http://blogs.technet.com/b/keithmayer/archive/2013/11/20/step-by-step-extending-server-manager-in-windows-server-2012-and-2012-r2.aspx

Powershell Enumeration zu unbekannten Typ ermitteln

18 Mai 2014

Wenn man beim Durchstöbern von verschiedenen Daten aus Powershellobjekten auf einmal an einem Enumerationstyp landet, wie z. B. diesen hier:

IsPublic IsSerial Name             BaseType
——– ——– —-             ——–
True     True     ImageHealthState System.Enum

Dann fragt man sich, was könnten die anderen Werte noch sein? Wie kommt an die anderen Werte, wenn Google nichts brauchbares liefert und die Werte scheinbar nirgends offiziell dokumentiert sind?

In so einem Fall hilft die ausführliche Ausgabe mittels Format-List:

PS C:\> $h.ImageHealthState.GetType()| fl *

Module                : Microsoft.Dism.PowerShell.dll
Assembly              : Microsoft.Dism.PowerShell, Version=6.3.0.0,Culture=neutral, PublicKeyToken=null
TypeHandle            : System.RuntimeTypeHandle
DeclaringMethod       :
BaseType              : System.Enum
UnderlyingSystemType  : Microsoft.Dism.Commands.ImageHealthState
FullName              : Microsoft.Dism.Commands.ImageHealthState
AssemblyQualifiedName : Microsoft.Dism.Commands.ImageHealthState,                            Microsoft.Dism.PowerShell, Version=6.3.0.0,                            Culture=neutral, PublicKeyToken=null
Namespace              : Microsoft.Dism.Commands
GUID                   : eea8dbef-fb34-3b75-8b86-c80dcd47dd53
IsEnum                     : True
GenericParameterAttributes :
IsSecurityCritical         : True
IsSecuritySafeCritical     : False
IsSecurityTransparent      : False
IsGenericTypeDefinition    : False
IsGenericParameter         : False
GenericParameterPosition   :
IsGenericType              : False
IsConstructedGenericType   : False
ContainsGenericParameters  : False
StructLayoutAttribute      : System.Runtime.InteropServices.StructLayoutAttribu
                             te
Name                       : ImageHealthState
MemberType                 : TypeInfo
DeclaringType              :
ReflectedType              :
MetadataToken              : 33554456
GenericTypeParameters      : {}
DeclaredConstructors       : {}
DeclaredEvents             : {}
DeclaredFields             : {value__, Healthy, Repairable, NonRepairable}
DeclaredMembers            : {value__, Healthy, Repairable, NonRepairable}
DeclaredMethods            : {}
DeclaredNestedTypes        : {}
DeclaredProperties         : {}
ImplementedInterfaces      : {System.IComparable, System.IFormattable,
                             System.IConvertible}
TypeInitializer            :
IsNested                   : False
Attributes                 : AutoLayout, AnsiClass, Class, Public, Sealed
IsVisible                  : True
IsNotPublic                : False
IsPublic                   : True
IsNestedPublic             : False
IsNestedPrivate            : False
IsNestedFamily             : False
IsNestedAssembly           : False
IsNestedFamANDAssem        : False
IsNestedFamORAssem         : False
IsAutoLayout               : True
IsLayoutSequential         : False
IsExplicitLayout           : False
IsClass                    : False
IsInterface                : False
IsValueType                : True
IsAbstract                 : False
IsSealed                   : True
IsSpecialName              : False
IsImport                   : False
IsSerializable             : True
IsAnsiClass                : True
IsUnicodeClass             : False
IsAutoClass                : False
IsArray                    : False
IsByRef                    : False
IsPointer                  : False
IsPrimitive                : False
IsCOMObject                : False
HasElementType             : False
IsContextful               : False
IsMarshalByRef             : False
GenericTypeArguments       : {}

Bei obiger Auflistung taucht der Fullname auf. Kürzer gehts mit

($h.ImageHealthState.GetType()).Fullname

Diesen Namen kann man verwenden, um die anderen Enumerationsnamen auflisten zu lassen:

PS C:\>
[Microsoft.Dism.Commands.ImageHealthState].GetEnumNames()
Healthy
Repairable
NonRepairable

Auf virtuelle Maschinen eines Microsoft Hyper-V Server 2012 R2 mittels FreeRDP zugreifen

8 Januar 2014

Mit der aktuellen, umsonst verfügbaren Version des Microsoft Hyper-V Server 2012 R2 kann man mittels Powershell per Commandline mittlerweile fast jeden Bereich administrieren. Das einzig störende ist, wenn man Netzwerkkartenprobleme hat oder Schwierigkeiten hat einen Windows 8.1 Client für die Remoteadministration anzubinden. Powershell ist zwar mächtig, allerdings ist es manchmal hilfreich, wenn man direkt auf eine virtuelle Maschine zugreifen und diese direkt steuern kann.

Es gab zwar schon länger käufliche Lösungen, wie den 5Nine Manager, aber es gibt noch eine bessere Lösung: FreeRDP! Dank der Offenlegung des RPD-Protokolls seitens Microsoft, gibt es keine großen Geheimnisse mehr zur Implementierung. Hier das Projekt: http://www.freerdp.com/ und alles steht feinsäuberlich im Source auf Github. Es gibt sogar Unterstützung für Mac, Linux, Android sowie iOS. Was will man mehr.

Am einfachsten um FreeRDP unter Hyper-V nutzen zu können, verwendet man die 3MB-Variante von cloudbase.it http://www.cloudbase.it/using-freerdp-to-connect-to-the-hyper-v-console/, dort findet man unten diesen Downloadlink: http://www.cloudbase.it/downloads/FreeRDP_powershell.zip. Die Version ist explizit für die 2012 R2 Version freigegeben.

Von der FreeRDP-Geschichte abgesehen, gilt es auch die anderen Dinge von Cloudbase in Richtung OpenStack an sich zu beachten!

SSL/TLS Fehler in Powershell, bzw. wie man Zertifikatsprobleme unter Windows analysieren kann

4 Januar 2014

Beim Herumspielen mit Chocolatey, dazu ein anderes Mal mehr, gab es Probleme auf einem Windows XP-Rechner. Der Windows XP Rechner war für Chocolatey noch nicht vorbereitet, d. h. er hatte zwar .Net 1, 2 und 3.5 bereits aber noch kein .Net Framework 4. Powershell 2 war bereits installiert.

Ausgangslage
Der Aufruf von

@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString(‘https://chocolatey.org/install.ps1&#8242;))" && SET PATH=%PATH%;%systemdrive%\chocolatey\bin

für die Installation, führte zu folgender Fehlermeldung:

Exception calling "DownloadString" with "1" argument(s): "The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."
At line:1 char:47
+ iex ((new-object net.webclient).DownloadString <<<< (‘https://chocolatey.org/
install.ps1′))
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

Der entscheidende Punkt ist oben rot markiert. Aber was macht man jetzt? Die Meldung ist leider doch zu allgemein.

Erster Versuch mehr Infos zum Fehler zu bekommen
Powershell kennt das $error Objekt. In diesem ist immer der letzte Fehler enthalten. Aber gleichzeitig sind bestimmte Randbedingungen und tiefergehende Infos zum Fehler abrufbar. Wichtig: Wenn man beim Rumspielen einen neuen Fehler verursacht, dann gehts schnell durcheinander und man untersucht nicht den eigentlichen Fehler, sondern einen nachfolgenden! Also geht man zuerst her und sichert den Fehler:

$myE = $error[0]

Damit kann nun nichts schiefgehen und mittels verschiedenen Abfragen kommt man dann irgendwann dazu:

((($myE).Exception).InnerException).Innerexception
The remote certificate is invalid according to the validation procedure.

Aha, wir haben also ein Zertifikatsproblem.

Prüfung mittels Browser
Aber welches Zertifikat macht nun die Probleme? Wie kann man dies überprüfen? Ein einfacher Versuch ist mittels Browser, in diesem gibt man einfach im aktuellen Fall https://chocolatey.org ein und schaut was passiert. Wer jetzt Chrome benutzt, der ist fein raus und bleibt verdutzt zurück, wer es aber mit dem Internet Explorer probiert, welcher den gleichen Weg einschlägt wie eben Powershell, bekommt diese Meldung:

Es besteht ein Problem mit dem Sicherheitszertifikat der Website.

Das Sicherheitszertifikat dieser Website wurde für eine andere Adresse der Website ausgestellt.

Die Sicherheitszertifikatprobleme deuten eventuell auf den Versuch hin, Sie auszutricksen bzw. Daten die Sie an den Server gesendet haben abzufangen.

Es wird empfohlen, dass Sie die Webseite schließen und nicht zu dieser Website wechseln.

Klicken Sie hier, um diese Webseite zu schließen.

Laden dieser Website fortsetzen (nicht empfohlen).

Weitere Informationen

Ja das kennen wir schon. Wenn man aber “Laden dieser Website fortsetzen (nicht empfohlen)” anklickt, bekommt man den bekannten roten Balken des IE mit dem Zertifikatsfehler. Dort kann man nun auf Zertifikatsfehler klicken und sich die Sache etwas genauer anschauen. Blöd nur das, dass es nicht offensichtlich ist, wo das Problem wieder genau liegt. Auf jeden Fall bekommt man raus, dass es sich in diesem Fall um Geotrust-Zertfikate handelt. Übrigens bekommt man diese Info auch von Chrome geliefert, wenn man auf das Schloss in der Adresszeile klickt und das Register Verbindung auswählt. Aber Hallo! Hier wird ein Go Daddy Zertifikat für chocolatey.org genannt! Ja was denn nun? GeoTrust oder Go Daddy? Des Rätsel Lösung nennt sich SNI und wird am Ende aufgelöst.

Tiefergehende Suche mittels Powershell
Wie kann man die Geschichte aber mittels Powershell besser in Griff bekommen? Da zu unterst immer irgendwo eine TCP-Verbindung aufgebaut werden muss, kann nur der direkte Aufruf über TCPClient etwas bringen.

Die einfachste Variante wäre nun:

$host = "chocolatey.org"
$port = 443
$conn = New-Object System.Net.Sockets.TcpClient ($host, $port)
$stream = New-Object System.Net.Security.SslStream($conn.GetStream())
$result=$stream.AuthenticateAsClient($host)
$conn.Close()

aber hier kommt nur wieder die Fehlermeldung wie oben bei der doppelten InnerException. Also was tun?

Der Konstruktor von SslStream kennt noch weitere Parameter. Unter anderem den RemoteCertificateValidationCallback Delegaten. http://msdn.microsoft.com/en-us/library/system.net.security.remotecertificatevalidationcallback(v=vs.110).aspx. Dieser wird üblicherweise benutzt, um bestimmte Fehlermeldungen in Verbindung mit Zertifikaten zu unterdrücken. Ab Powershell 2.0 ist dies ohne weiteres möglich, wie dieser Artikel hier schön beschreibt: http://www.nivot.org/blog/post/2009/07/18/PowerShell20RCWorking
WithNETCallbacksPart1Synchronous
. Der Callback kennt aber alle relevanten Informationen, so dass man diesen nun so nutzen kann:

$conn = New-Object System.Net.Sockets.TcpClient($host,$port)
$stream = New-Object System.Net.Security.SslStream($conn.GetStream(), $null, {
                    Write-Host "Sender: $($args[0])";
                    Write-Host "Certificate: $(($args[1]).gettype())";
                    Write-Host "CertificateChain: $($args[2])";
                    Write-Host "PolicyErrors: $($args[3])"; 
         })
$result = $stream.AuthenticateAsClient($host)
$conn.Close()

nun bekommt man als Ergebnis dies geliefert:

Sender: System.Net.Security.SslStream
Certificate: System.Security.Cryptography.X509Certificates.X509Certificate2
CertificateChain: System.Security.Cryptography.X509Certificates.X509Chain
PolicyErrors: RemoteCertificateNameMismatch

Also genau was auf MSDN als Parameter dokumentiert steht. Vor allem interessant ist nun die Aussage mit RemoteCertificateNameMismatch. Jetzt wird die Sache schon etwas klarer. Sollte chocolatey.org nicht im Zertifikat genannt sein?

Hier nun das Script welches die richtigen Infos ausgibt:

$conn = New-Object system.net.sockets.tcpclient($host, $port)
$stream = New-Object system.net.security.sslstream($conn.getstream(), $null, {
                    Write-Host $args[2].ChainElements[0].Certificate.Subject;
                    Write-Host "PolicyErrors: $($args[3])";
         })
$result = $stream.authenticateasclient("chocolatey.org")
$conn.Close()

Als Ausgabe erhält man:

CN=*.apphb.com, O=AppHarbor Inc, L=San Francisco, S=California, C=US, SERIALNUMBER=MyGg//QgdanmdPPqqfNR5JjsvbrKA/uJ
PolicyErrors: RemoteCertificateNameMismatch

Aha, nun wird es klarer. Wir wollen auf die Seite chocolatey.org bekommen aber ein Zertifikat vom Server für AppHarbor. Findet hier eine Attacke statt? Oh Gott, alle Schotten dicht!

Zusammenfassung
Ich wollte nur mal schnell Chocolatey installieren und bin dann wegen den Sicherheitsanforderungen von Chocolatey bei einer Attacke gelandet, wo mir irgendjemand falsche Zertifikate unterjubeln möchte. Oder ist doch alles ganz anders?

Aufklärung
Die Lösung des Dilemmas lautet SNI “Server Name Indication”. Ein schöner Artikel dazu findet man auf der deutschen Wikipedia unter http://de.wikipedia.org/wiki/Server_Name_Indication. Dort wird im Zusammenhang von SNI darauf hingewiesen, dass Windows XP kein Server Name Indication unterstützt. Warum ist dies wichtig? Weil Powershell mittels der Systembibliotheken von Windows XP seine HTTPS Verbindung aufbauen möchte und ebenso wie der IE8 Probleme bekommt. Hintergrund dafür ist, dass chocolatey.org bei HTTPS-Verbindungen auf SNI angewiesen ist, wie dieser Test zeigt: https://www.ssllabs.com/ssltest/analyze.html?d=chocolatey.org.

Dort ist dann zu lesen:

This site works only in browsers with SNI support.

Dies erklärt nun auch die unterschiedlichen Zertifikate. Denn IE8 auf Windows XP kann kein SNI, Chrome jedoch kann es, obwohl Windows XP zum Einsatz kommt. Der Grund dafür ist, dass Chrome seine eigene Crypto-Library mitbringt.

Beim Versuch also die Verbindung ohne SNI aufzubauen, landet man nicht auf dem gewünschten Server sondern bekommt ein allgemeineres Zertifikat des Hosters zurück. Dies erklärt nun den Punkt mit den unterschiedlichen Zertifikaten von GeoTrust und Go Daddy.

Man kann die Sache sehr schön nachverfolgen, wenn man Fiddler einsetzt. http://fiddler2.com/. Damit kann man, wenn der HTTPS-Mitschnitt aktiviert ist, sehr schön sehen, dass Powershell 2.0 diesen Aufruf generiert:

Version: 3.1 (TLS/1.0)

Extensions:
renegotiation_info 00
Ciphers:
[0004] SSL_RSA_WITH_RC4_128_MD5
[0005] SSL_RSA_WITH_RC4_128_SHA
[000A] SSL_RSA_WITH_3DES_EDE_SHA
[0009] SSL_RSA_WITH_DES_SHA
[0064] TLS_RSA_EXPORT1024_WITH_RC4_56_SHA
[0062] TLS_RSA_EXPORT1024_WITH_DES_SHA
[0003] SSL_RSA_EXPORT_WITH_RC4_40_MD5
[0006] SSL_RSA_EXPORT_WITH_RC2_40_MD5
[0013] SSL_DHE_DSS_WITH_3DES_EDE_SHA
[0012] SSL_DHE_DSS_WITH_DES_SHA
[0063] TLS_DHE_DSS_EXPORT1024_WITH_DES_SHA

Compression:
[00] NO_COMPRESSION

Während Chrome dies zustande bringt:

Version: 3.1 (TLS/1.0)

Extensions:
 server_name chocolatey.org
renegotiation_info 00
elliptic_curves secp256r1 [0x17], secp384r1 [0x18], secp521r1 [0x19]
ec_point_formats uncompressed [0x0]
SessionTicket TLS empty
NextProtocolNegotiation empty
ALPN  spdy/2; spdy/3; spdy/3.1; http/1.1;
channel_id empty
status_request 01 00 00 00 00
Ciphers:
[C02F] TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
[009E] TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
[009C] TLS_RSA_WITH_AES_128_GCM_SHA256
[C014] TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA
[0039] TLS_DHE_RSA_WITH_AES_256_SHA
[0035] TLS_RSA_AES_256_SHA
[C011] TLS_ECDHE_RSA_WITH_RC4_128_SHA
[C013] TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA
[0033] TLS_DHE_RSA_WITH_AES_128_SHA
[0032] TLS_DHE_DSS_WITH_AES_128_SHA
[0005] SSL_RSA_WITH_RC4_128_SHA
[0004] SSL_RSA_WITH_RC4_128_MD5
[002F] TLS_RSA_AES_128_SHA
[000A] SSL_RSA_WITH_3DES_EDE_SHA

Compression:
[00] NO_COMPRESSION

Der Extensions-Eintrag server_name chocolatey.org ist genau der Punkt, welcher beim Powershell-Aufruf fehlt und die Sache zum Scheitern bringt. Gleichwohl auch Chrome innerhalb von Fiddler Probleme mit dem Aufruf bekommt, denn Fiddler2 basiert auf .Net Framework 2.0 und damit ist der weitere Fortgang zum Scheitern verurteilt und man bekommt am Ende nicht das Go Daddy Zertifikat sondern wieder das falsche GeoTrust Zertifikat.

Übrigens geht genau dieser Artikel auf das aktuelle Problem ein und bestätigt nochmal alles: https://groups.google.com/forum/#!searchin/chocolatey/geotrust$20/chocolatey/r9EdhJdPjWM/FavaGm07VtoJ

Zu guter Letzt noch die Bestätigung, dass Powershell 4.0 unter Windows 8.1 problemlos damit umgehen kann:

A SSLv3-compatible ClientHello handshake was found. Fiddler extracted the parameters below.

Version: 3.1 (TLS/1.0)

Extensions:
renegotiation_info 00
 server_name chocolatey.org
elliptic_curves secp256r1 [0x17], secp384r1 [0x18]
ec_point_formats uncompressed [0x0]
SessionTicket TLS empty
Ciphers:
[002F] TLS_RSA_AES_128_SHA
[0035] TLS_RSA_AES_256_SHA
[0005] SSL_RSA_WITH_RC4_128_SHA
[000A] SSL_RSA_WITH_3DES_EDE_SHA
[C013] TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA
[C014] TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA
[C009] TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
[C00A] TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
[0032] TLS_DHE_DSS_WITH_AES_128_SHA
[0038] TLS_DHE_DSS_WITH_AES_256_SHA
[0013] SSL_DHE_DSS_WITH_3DES_EDE_SHA
[0004] SSL_RSA_WITH_RC4_128_MD5

Compression:
[00] NO_COMPRESSION

Also alles halb so wild, wenn man weiß, wie es zusammenhängt!

Zugriff auf WWAN Profile unter Windows 8 per Powershell

26 November 2013

Mit Windows 8.1 sind zwar nochmals einige Powershell Cmdlets hinzugekommen allerdings für WWAN, also Breitbandverbindungen wie LTE, HSDPA, UMTS und GSM war noch nichts dabei. Hier ist also Handarbeit angesagt.

Da die Windows Runtime von Windows 8 auch unter Powershell nutzbar ist, kann dort auf alle verfügbaren APIs zugegriffen werden, die für “desktop apps” gekennzeichnet sind, wie z. B. NetworkInformation: http://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.connectivity.
networkinformation.aspx

Dabei sorgt der Aufruf von

[void][Windows.Networking.Connectivity.NetworkInformation,Windows, ContentType=WindowsRuntime]

dass die betreffende Assembly geladen wird, worauf dann dieser Aufruf möglich ist:

[Windows.Networking.Connectivity.NetworkInformation]:: GetConnectionProfiles()

Anstatt GetConnectionProfiles kann man auch GetInternetConnectionProfile() aufrufen, welches dann das aktuelle Internetverbindungsobjekt zurück gibt. Dieses kann man nun mittels GetConnectionCost zum NetworkCostType befragen. Die möglichen Werte sind dann hier beschrieben: http://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.connectivity.networkcosttype.aspx.

Weitere Infos zu den Möglichkeiten stehen hier:

http://blogs.technet.com/b/heyscriptingguy/archive/2013/08/02/more-messing-around-with-wireless-settings-with-powershell.aspx

Wenn es Probleme genereller Natur gibt, helfen evtl. die Loggingmöglichkeiten weiter: http://msdn.microsoft.com/en-us/library/windows/hardware/dn423925(v=vs.85).aspx

Für WinRT mit Asnyc-Aufrufen und Powershell, gilt es dies zu beachten: http://rkeithhill.wordpress.com/2013/09/30/calling-winrt-async-methods-from-windows-powershell/

Alles zusammenkombiniert kann man mittels GetNetworkUsageAsync() auch herausfinden, wie viel MB pro Tag, pro Stunde, pro Minute oder insgesamt die letzten 60 Tage über die Leitung gingen!

http://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.connectivity.
connectionprofile.getnetworkusageasync.aspx

Exchange 2010 Verteilergruppe auch extern erreichbar machen

8 Juni 2013

Um eine allgemeine Adresse mail@domain.de mehreren Benutzern zugänglich zu machen, kann man eine Verteilergruppe im Exchange einrichten. Diese bekommt einfach den passenden Aias mail.

Damit diese Adresse auch von extern erreichbar ist, muss man allerdings noch bei den Nachrichtenübermittlungseinstellungen der Verteilergruppe bei “Einschränkungen für die Nachrichtenübermittlung” den Punkt “Authentifizierung aller Absender anfordern” ausschalten.

Per Powershell gehts mittels

set-DistributionGroup –identity "mail"
-RequireSenderAuthenticationEnabled $false


Folgen

Erhalte jeden neuen Beitrag in deinen Posteingang.