Archive for Juli 2016

Binärtyp einer EXE-Datei unter Windows ermitteln, ob 32- oder 64-Bit–man spricht auch von Bitness

27 Juli 2016

Möchte man unter Windows bei einer ausführbaren Datei wissen, ob diese eine 32-Bit oder 64-Bit Version ist, dann kennt die Win32-API die Funktion GetBinaryType. Mittels Powershell kann man diese Funktion wie folgt nutzen:

$MethodDefinition = @‘

// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364819(v=vs.85).aspx
[DllImport("kernel32.dll")]
public static extern bool GetBinaryType(string lpApplicationName, out uint lpBinaryType);

‚@

$Kernel32 = Add-Type -MemberDefinition $MethodDefinition -Name ‚Kernel32‘ -Namespace ‚Win32‘ -PassThru

# Funktioniert aber nur, wenn man sich in einem 64-Bit Prozess befindet, also: [System.IntPtr]::Size -eq 8
$type=0
$Kernel32::GetBinaryType("c:\windows\system32\cmd.exe", [ref] $type)  # unter 64-Bit sollte es 6 sein
$type
$Kernel32::GetBinaryType("c:\windows\syswow64\cmd.exe", [ref] $type)  # unter 64-Bit sollte es 0 sein
$type

# mögliche Werte für $type:
# SCS_32BIT_BINARY = 0, // A 32-bit Windows-based application
# SCS_64BIT_BINARY = 6, // A 64-bit Windows-based application.
# SCS_DOS_BINARY = 1,   // An MS-DOS – based application
# SCS_OS216_BINARY = 5, // A 16-bit OS/2-based application
# SCS_PIF_BINARY = 3,   // A PIF file that executes an MS-DOS – based application
# SCS_POSIX_BINARY = 4, // A POSIX – based application
# SCS_WOW_BINARY = 2    // A 16-bit Windows-based application

Dabei ist zu beachten, wenn man den Test macht, dass IntPtr 8 liefern sollte, sonst befindet man sich in einem simulierten WOW64-32Bit-Prozess und bekommt verwunderliche Ergebnisse zurück.

HP Netzwerkdrucker per Remote und Reboot.TXT neu starten – nix klappt aber SNMP bringt die Lösung

10 Juli 2016

Beim Rumspielen mit verschiedenen HP-Druckereigenschaften kommen einem manchmal Zweifel, ob alles noch korrekt reagiert. Aus diesem Grund sollte man den betreffenden Drucker von Zeit zu Zeit neu starten um nach einem Neustart die betreffenden Reaktionen zu testen. Im konkreten Fall handelt es sich um einen “HP LaserJet MFP M426fdw”, also ein recht aktuelles Modell.

Blöd nur, dass Varianten mittels einer reboot.txt, wie hier https://community.spiceworks.com/how_to/122155-how-to-reboot-an-hp-printer-remotely oder hier http://dxpetti.com/blog/?p=706 beschrieben nicht funktionieren. Übrigens, FTP-Druck wurde explizit aktiviert, sonst kann man den Drucker per FTP nicht anfahren. Die kompliziertere Variante für Reboot.TXT sieht übrigens so aus:

%-12345X@PJL COMMENT
@PJL DMINFO ASCIIHEX="040006020501010301040105"
%-12345X

Allerdings muss man wissen, dass vor % noch ein ein ASCII-Zeichen mit Code 27 steht. Man kann die passende Datei mittels Powershell ganz einfach so erzeugen:

# {ESC}%-12345X
$k=[System.Text.Encoding]::ASCII.GetString(@(27,37,45,49,50, 51, 52, 53, 88))
$lf=[System.Text.Encoding]::ASCII.GetString(@(13, 10))
$i=’@PJL COMMENT‘
$c=’@PJL DMINFO ASCIIHEX="040006020501010301040105"‘
#$c=’@PJL DMCMD ASCIIHEX="040006020501010301040105"‘

$k + $i + $lf + $c + $lf + $k | set-content -Encoding Ascii -Path "$($env:USERPROFILE)\Reboot.txt"

Aber auch mit der korrekten Escape-Sequenz am Anfang klappte es nicht!

Auch hier wird wieder die ganz einfache reboot.txt Variante beschrieben: https://www.experts-exchange.com/questions/24432791/Rebooting-HP-Jetdirect-remotley.html. Klappt natürlich nicht, aber es war etwas von einem Reboot mittels SNMP beschrieben. Hier soll set OID .1.3.6.1.2.1.43.5.1.1.3.1 with Integer "4" gesetzt werden.

Aha, SNMP das uralte Protokoll. Selbst HP geht darauf aber noch ein und verwendet es für bestimmte Aufgaben, hier ein aktuelles Dokument aus April 2016: http://h20564.www2.hp.com/hpsc/doc/public/display?docId=c01840676.

Tatsächlich findet man bei der Suche nach der OID und Powershell Scripte, wie hier: http://forum.support.xerox.com/t5/Copying-Faxing-Scanning/Schedule-printer-reboot/m-p/176844#M5393. Das Script ist zwar nicht 1:1 übertragbar aber damit wird der Weg klar.

Selbst in Windows 10 gibt es eine OLE SNMP-Klasse https://msdn.microsoft.com/en-us/library/windows/hardware/ff554433(v=vs.85).aspx, welche man mittels Powershell ganz einfach für diesen Zweck einsetzen kann:

$PrinterIP = "192.168.1.87" # hier die tatsächliche IP des Druckers setzen
$SNMP = New-Object -ComObject olePrn.OleSNMP
$SNMP.Open($PrinterIP, "public")
$SNMP.Set(".1.3.6.1.2.1.43.5.1.1.3.1",4)
$SNMP.Close()

Sofort nach absetzen des Set-Befehls startet der Drucker neu! Und was dabei noch interessant ist, es klappt auch mit anderen Druckerfabrikaten.

Vorsicht mit Get-NetFirewallRule bzw. WMI MSFT_NetFirewallRule-Klasse bei Abfrage der Enabled-Eigenschaft – gilt allgemein bei $True und $False in Powershell

10 Juli 2016

Ein Script welches Windows Firewall Regel-Eigenschaften abfragte funktionierte nicht wie erwartet. Es wurde immer die Enabled Eigenschaft abgefragt aber es kam nicht das erwartete Ergebnis, wurde die Abfrage aber negiert, kam das erwartete Ergebnis heraus! Am Ende stellte es sich heraus, dass die Enabled-Eigenschaften kein klassisches Bool sondern einen String zurückgibt, hier die Story:

Fragen wir zunächst die aktuelle Anzahl von Regeln ab, hier bei einem aktuellen Windows 10:

$r=Get-NetFirewallRule
$r.length
413

Es gibt also 413 Regeln. Nun sollen alle Regeln ermitteln werden, die aktiviert sind:

($r | where enabled -eq $true).length
184

Jetzt sollen alle Regeln ermittelt werden, die nicht aktiviert sind:

($r | where enabled -eq $false).length
0

Die 0 ist jetzt nicht das erwartete Ergebnis, wenn man davon ausgeht, dass es 413 Regeln gibt, davon sind 184 aktiv, dann sollten mehr als 0 inaktiv sein.

Wo liegt das Problem? Das Problem ist, dass bei $True oder $False in Powershell immer True oder False am Bildschirm ausgegeben wird. Man interpretiert einen solchen Wert schnell als Boolean. Aber in diesem Fall hat man es nicht mit einem Boolean zu tun:

$r[0].enabled.pstypenames
Microsoft.PowerShell.Cmdletization.GeneratedTypes.NetSecurity.Enabled
System.Enum
System.ValueType
System.Object

Es ist also ein Aufzählungstyp!

($r | where enabled -eq "True").length
184
($r | where enabled -eq "False").length
229

So macht die Sache mehr Sinn!

Oder man macht die Abfrage über den passenden Typ:

($r| where enabled -eq ([Microsoft.PowerShell.Cmdletization.GeneratedTypes.NetSecurity.Enabled]:
:True)).length
184
($r| where enabled -eq ([Microsoft.PowerShell.Cmdletization.GeneratedTypes.NetSecurity.Enabled]:
:False)).length
229

Übrigens: $true –eq "True" ergibt immer True, auch wenn man $true –eq "irgendwas" setzt! Und $False –eq "False" ergibt immer False, egal mit was verglichen wird, außer $false!