Archive for Oktober 2016

Laufwerk unter Windows auf mögliche Probleme prüfen

31 Oktober 2016

Wann gibt das Laufwerk seinen Geist auf? Sei es eine herkömmliche Festplatte, SSD oder NVME alle sprechen Sie das sogenannte S.M.A.R.T-Protokoll. Damit können Probleme und mögliche Laufwerksausfälle frühzeitig erkannt werden.

Seither müsste man dazu immer irgendwelche Tools laden oder im UEFI/BIOS nachschauen. Wenn man Glück hatte, hat einen der Rechner beim Booten auf etwaige anstehende Probleme aufmerksam gemacht.

Cool ist, dass Windows, mal wieder mittels WMI eine ganz einfache Abfragemöglichkeit mitbringt:

$Para=@{Namespace="root\wmi"
Class="MSStorageDriver_FailurePredictStatus"
ErrorAction="Silentlycontinue"}

Get-WmiObject @Para | Select InstanceName, PredictFailure,
Reason | Format-Table –Autosize

Ausgegeben wird dann sowas:

InstanceName   : SCSI\Disk&Ven_Samsung&Prod_SSD_840_EVO_750G\4&15828421&0&000000_0

PredictFailure : False

Reason         : 0

InstanceName   : SCSI\Disk&Ven_Samsung&Prod_SSD_840_EVO_750G\4&15828421&0&010000_0

PredictFailure : False

Reason         : 0

InstanceName   : SCSI\Disk&Ven_&Prod_ST95005620AS\4&15828421&0&020000_0

PredictFailure : False

Reason         : 0

Solange bei PredictFailure False dran steht, ist alles ok.

Weitere Infos findet man hier: https://blogs.msdn.microsoft.com/san/2011/08/11/have-you-ever-wanted-to-know-if-your-disk-is-going-to-fail-before-it-does/

Advertisements

Postscript direkt an Drucker unter Windows senden

28 Oktober 2016

Im Reigen mit dem direkten Drucken von Daten an Drucker unter Windows steht als nächstes dass direkte Drucken von Postscript auf dem Programm. Durch die hier https://newyear2006.wordpress.com/2016/10/17/direkte-kommunikation-mit-druckern-unter-windows-von-powershell-aus/ vorgestellte Methode um Druckern direkt Daten unterjubeln zu können und die hier https://newyear2006.wordpress.com/2016/10/27/direktes-drucken-von-pdf-dateien-unter-windows-und-wie-man-die-farbprofiluntersttzung-eines-druckers-testen-kann/ vorgestellte Methode um direkt PDF-Dateien zu drucken, wollen wir uns nun Postscript zuwenden. Man kann davon ausgehen, dass ein Drucker welcher bereits die PDF-Ausgabe beherrscht auch die Ausgabe von Postscript kann.

Zunächst, wie beim Artikel beim Druck der PDF-Dateien beschrieben (siehe dort für mehr Details), muss die Printer Language gesetzt werden, diesmal aber anstatt PDF auf Postscript:

# {ESC}%-12345X
$kb=@(27,37,45,49,50, 51, 52, 53, 88)
# Zeilenumbruch
$lfb=@(13, 10)
# Sprache einstellen:
$lb=[System.Text.Encoding]::ASCII.GetBytes("@PJL ENTER LANGUAGE = Postscript")

So jetzt brauchen wir auch etwas Postscript:

$pss=@"
/Times-Roman findfont
32 scalefont
setfont
100 200 translate
45 rotate
2 1 scale
newpath
0 0 moveto
(Testausdruck) true charpath
0.5 setlinewidth
0.4 setgray
stroke
showpage
"@

Die Erklärung zu diesem Meisterwerk findet man hier unter Text (Example4): http://paulbourke.net/dataformats/postscript/.

Dieses Postscript muss nun noch in ein Bytearray umgewandelt werden und schon kann es an den Drucker gesendet werden:

$ps=[System.Text.Encoding]::ascii.GetBytes($pss)
$out = $kb + $lb + $lfb + $ps + $kb

$p=Get-Printer|Out-GridView -PassThru -Title "Bitte Postscript Drucker wählen"
Out-RawPrinter -Printer $p -ByteArray $out -DocTitle "Postscript Direktdruck!"

Da Postscript im Prinzip eine vollständige Programmiersprache ist, kann man auch rekursive Programme ausführen um z. B. Fraktale zu generieren:

$pss=@"

%!PS-Adobe-1.0
%%Title:Random Fern
%%Creator:Eric Wicklund
% Last modified: MLO 02 Jan 1993 11:24:14
% Changed: 'save' and 'restore' statements (incorrect grammar);
% length added, and set to 0.001 (0 does not work with Post 1.7).
/m1 [ 0.00 0.00 0.00 0.16 0.00 0.00 ] def
/m2 [ 0.85 -0.04 0.04 0.85 0.00 1.60 ] def
/m3 [ 0.20 0.23 -0.26 0.22 0.00 1.60 ] def
/m4 [ -0.15 0.26 0.28 0.24 0.00 0.44 ] def
/point 72 def
%/length 0 def
/length 0.001 def
%%EndProlog
%%Page: 1 1
/zzz save def
% will draw inside a 8 inch square centered on 8.5 by 11 inch page
4.25 point mul 1.5 point mul translate
0.8 point mul dup scale
% x coordinate ranges from -5 to 5
% y coordinate ranges from 0 to 10
1 setlinecap
0.005 setlinewidth
% First point at origin
0 0
150000 {
% Pick a transformation matrix probabilistically
   /r rand 100 mod def
   r 1 lt { /m m1 def }
 { r 86 lt { /m m2 def }
 { r 93 lt { /m m3 def }
           { /m m4 def } ifelse } ifelse } ifelse
% Make a linear transformation, then
% plot a point at current location
   m transform 2 copy moveto
   length length rlineto
   stroke
} repeat
showpage
zzz restore
%%Trailer

"@
Das Script für den Baum stammt von hier: 
http://www.pvv.ntnu.no/~andersr/fractal/PostScript.html
Wer sich beim Thema Postscript und Fraktale vertiefen möchte, dem sei 
dieses Dokument “Julia fractals in PostScript” von Kees van der Laan
empfohlen: https://www.ntg.nl/maps/45/03.pdf.
Mhh, da kommt mir eine Idee. Wenn es Grafikkarten gibt, die für 
Berechnungen herangezogen werden, warum dann nicht auch Drucker?

Direktes Drucken von PDF-Dateien unter Windows und wie man die Farbprofilunterstützung eines Druckers testen kann

27 Oktober 2016

Es gibt viele Möglichkeiten Dateien unter Windows auszudrucken. Das witzige ist, dass oft Dateien mehrfach aufbereitet werden, bis sie überhaupt am Ende beim Drucker landen. Wäre es nicht toll, wenn man z. B. eine PDF-Datei zum Drucken hätte, wenn man diese unter Umgehung des Druckertreibers direkt an den Drucker senden könnte?

Wie man RAW-Dateien direkt an einen Drucker unter Windows senden kann, wurde bereits hier beschrieben: https://newyear2006.wordpress.com/2016/10/17/direkte-kommunikation-mit-druckern-unter-windows-von-powershell-aus/. Diese Variante kann man nun ausbauen, um eben auch PDF-Dateien ohne weitere Zwischenbearbeitung drucken zu können. Natürlich funktioniert diese Methode nur, wenn der Zieldrucker auch PDF-Dateien direkt verarbeiten kann! Im Zweifel gilt probieren über studieren.

Wir brauchen also die Funktion Out-RAWPrinter aus dem oben verlinkten Blogartikel. Dann müssen wir die PDF-Datei laden:

$pdf = Get-Content –Path C:\Temp\Test.PDF –Encoding Byte

$pdf enthält nun ein Bytearray. Leider lässt sich dies noch nicht direkt an Out-RawPrinter übergeben, denn dem Drucker muss noch mitgeteilt werden, welche Sprache bzw. Dateiformat da kommt. Dies ist aber ganz einfach über die Printer Job Language PJL möglich. Hier die Referenz dazu: http://h20565.www2.hp.com/hpsc/doc/public/display?docId=emr_na-bpl13208. Erfunden wurde die PJL von HP, wird aber mittlerweile auch von anderen Druckerherstellern verwendet bzw. verstanden.

In unserem Fall soll die Sprache auf PDF gestellt werden. Dies erreicht man, indem man @PJL ENTER LANGUAGE = PDF an den Drucker sendet. Damit der Drucker aber auch darauf achtet und reagiert muss noch seine Aufmerksamkeit durch einen spezielle Zeichenfolge erregt werden, indem man {ESC}%-12345X vorab und hinterher sendet. In Kombination sieht das dann so aus:

# {ESC}%-12345X
$kb=@(27,37,45,49,50, 51, 52, 53, 88)
# Zeilenumbruch
$lfb=@(13, 10)
# Sprache einstellen:
$lb=[System.Text.Encoding]::ASCII.GetBytes("@PJL ENTER LANGUAGE = PDF")
# alles Zusammensetzen
$out = $kb + $lb + $lfb + $pdf + $kb

In $out steht nun das komplette Bytearray. Das sieht dann z. B. so aus:

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

1B 25 2D 31 32 33 34 35 58 40 50 4A 4C 20 45 4E  .%-12345X@PJL EN
54 45 52 20 4C 41 4E 47 55 41 47 45 20 3D 20 50
  TER LANGUAGE = P
44 46
0D 0A
25 50 44 46 2D 31 2E 34 0D 0A 25 E2  DF..%PDF-1.4..%â
E3 CF D3 0D 0A 25 0D 0A 25 77 50 44 46 33 20 62  ãÏÓ..%..%wPDF3 b
79 20 57 50 43 75 62 65 64 20 47 6D 62 48 20 56  y WPCubed GmbH V
33 2E 36 35 5B 34 30 32 36 35 33 32 31 36 5D 20  3.65[402653216]

am Ende so:

65 65 30 63 31 32 32 62 64 32 66 38 63 34 3E 5D  ee0c122bd2f8c4>]
0D 0A 2F 49 6E 66 6F 20 32 20 30 20 52 0D 0A 3E  ../Info 2 0 R..>
3E 0D 0A 73 74 61 72 74 78 72 65 66 0D 0A 31 39  >..startxref..19
37 32 35 31 0D 0A 25 25 45 4F 46 0D 0A 1B 25 2D  7251..%%EOF...%-
31 32 33 34 35 58
                                12345X

Und jetzt noch alles an den Drucker:

$p=Get-Printer|Out-GridView -PassThru -Title "Bitte Drucker wählen"
Out-RawPrinter -Printer $p -ByteArray $out -DocTitle "PDF Direktdruck!"

Verwendet man diese Methode, muss man aber damit rechnen, dass der Ausdruck manchmal anders aussieht, als erwartet. Denn PDF ist nicht immer gleich PDF, bzw. PDF kann je nach Gerät unterschiedlich interpretiert werden.

Was kann man damit anstellen? Ja man könnte sein Gerät z. B. auf direkte Kompatibilität von ICC v4 Profil Farbraumunterstützung testen http://www.color.org/version4pdf.pdf.

$iccv4=(Invoke-WebRequest -Uri http://www.color.org/version4pdf.pdf).Content
$out = $kb+$lb+$lfb+$iccv4$x+$kb
$p=Get-Printer|Out-GridView -PassThru -Title "Bitte Drucker wählen"
Out-RawPrinter -Printer $p -ByteArray $out -DocTitle "PDF Direktdruck!"

Spannend so eine Sache!

Probleme mit Exchange, IMAP, POP3, SMTP, Outlook, Office365 usw. mit dem Microsoft Remote Connectivity Analyzer aufspühren

26 Oktober 2016

Mittels diesem Link kann man bei Microsoft verschiedene Dienste testen, ob diese generell funktionieren. Man muss zwar sein Zugangsdaten eingeben, aber was macht man nicht alles in verzweifelten Situationen, wenn gar nichts mehr geht.

https://testconnectivity.microsoft.com/

Windows Server Script zum Abschalten von unsicheren SSL und TLS Verbindungen

23 Oktober 2016

Gerade bin ich über ein schönes Powershellscript gestolpert um einen Windows Server die anfälligen SSL und TLS Protokolle und unsicheren Ciphers abzuschalten.

https://www.hass.de/content/setup-your-iis-ssl-perfect-forward-secrecy-and-tls-12

Wird schön gepflegt und auf dem aktuellen Stand gehalten. Das einzige was mich daran stört: Es wäre schön zu sehen, welcher Wert geändert wurde, damit man bei Problemen schneller nachvollziehen kann, welches Protokoll bzw. welche Cipher doch noch benötigt wird.

Probleme mit Installation von Microsoft Azure Powershell

21 Oktober 2016

Nachdem nach der Ignite Version 3.0.0 der Microsoft Azure Powershell Module erschienen ist https://azure.microsoft.com/en-us/blog/azure-powershell-300/, dachte ich ich versuche nochmal zwei Rechner auf diese Version zu aktualisieren, die davor sich verweigert haben. Doch leider wie seither ohne Erfolg. Ich hätte hier jetzt die Meldungen aufgezeigt, doch dank Windows 10 unermüdlichen Neustarts sind diese verloren gegangen. Deshalb hier nur der Verweis auf die Lösung.

Zunächst wurde versucht die betreffenden Module wie hier beschrieben zu installieren: https://github.com/PowerShell/PowerShell/issues/1874#issuecomment-241170545. Klappte jedoch leider nicht. Danach weitergesucht und am Ende sagte hier jemand was von Verzeichnissen löschen: https://powershell.org/forums/topic/unable-to-install-module-azurerm/.

Tatsächlich, nachdem in den Verzeichnissen

%ProgramFiles%\WindowsPowerShell\Modules folder
%ProgramFiles(x86)%\Microsoft SDKs\Azure\PowerShell

alles gelöscht wurde, was nach Azure roch, funktionierte danach endlich das Install-Module AzureRM.

Source auf Github: https://github.com/Azure/azure-powershell

Direkte Kommunikation mit Druckern unter Windows von Powershell aus

17 Oktober 2016

Manchmal ist es hilfreich, wenn man unter Windows direkt etwas ausdrucken kann. Direkt in diesem Fall bedeutet aber nicht über die üblichen Wege einen Druckertreiber anzusprechen, sondern, dass man direkt Steuerzeichen an einen Drucker senden kann. Man hat z. B. einen Druck in eine Datei umgeleitet und möchte nun diese Datei später an den Drucker senden. Dies ist mit den üblichen unter Powershell zur Verfügung stehenden Cmdlets wie Out-Printer nicht möglich.

Aber wie immer kann man das .Net Framework zu Hilfe nehmen. Grundlage für diesen Artikel ist der Knowledge Base Artikel https://support.microsoft.com/en-us/kb/322091. Dieser beschreibt die direkte Kommunikation mit Druckern unter C#. Hier hat sich nun jemand bereits die Mühe gemacht die Grundlage des Artikels an Powershell anzupassen: http://panchosoft.blogspot.de/2013/07/imprimir-en-impresora-de-etiquetas-sato.html. Das interessante an dieser Methode ist, dass es keine Rolle spielt, ob der Drucker per LPT- oder USB-Schnittstelle mit dem Rechner verbunden ist, noch ob mittels Netzwerk über TCP/IP oder WSD-Diensten mit ihm kommuniziert wird.

Die Daten finden mittels dieser Methode immer in Reinform ihren Weg zum Drucker, unabhängig vom Anschluss bzw. Übertragungsweg. Die generelle Druckvorgehensweise unter Windows ist hier beschrieben: https://msdn.microsoft.com/en-us/library/windows/desktop/dd145115%28v=vs.110%29.aspx.

Ein Aspekt ist noch wichtig. Es gibt sogenannte Typ 3 und Typ 4 Druckertreiber, dazu ein anderes Mal mehr. Typ 4 kommen verstärkt seit Windows 8 und nachfolgend zum Einsatz. Damit der Ansatz mit dem direkten senden von Daten an den Drucker klappt, muss dies berücksichtigt werden: https://msdn.microsoft.com/en-us/library/windows/desktop/ff686812(v=vs.110).aspx.

Hier zunächst das gesamte Script:

# Powershell RAW Print

$src = @‘
using System;
using System.Runtime.InteropServices;

public class RawPrinterHelper
{
// Structure and API declarions:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class DOCINFOA
{
  [MarshalAs(UnmanagedType.LPStr)]
  public string pDocName;
  [MarshalAs(UnmanagedType.LPStr)]
  public string pOutputFile;
  [MarshalAs(UnmanagedType.LPStr)]
  public string pDataType;
}

  [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
  public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);

  [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
  public static extern bool ClosePrinter(IntPtr hPrinter);

  [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
  public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);

  [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
  public static extern bool EndDocPrinter(IntPtr hPrinter);

  [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
  public static extern bool StartPagePrinter(IntPtr hPrinter);

  [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
  public static extern bool EndPagePrinter(IntPtr hPrinter);

  [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
  public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);

}

‚@

Add-Type -TypeDefinition $src -Language CSharpVersion3

function Out-RawPrinter {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory=$True, ParameterSetName="Printer", Position=0)]
        [PSTypeName(‚Microsoft.Management.Infrastructure.CimInstance#ROOT/StandardCimv2/MSFT_Printer‘)]
        [ciminstance]
        $Printer,
        [Parameter(Mandatory=$True, ParameterSetName="PrinterName", Position=0)]
        [String]$PrinterName,

        [String]$Output,
        [Byte[]]$ByteArray,
        [String]$DocTitle = "Powershell RAW print",
        [String]$DataType
    )

    If ($PSCmdlet.ParameterSetName -eq "PrinterName") {
        $Printer = Get-Printer $PrinterName
    }

    #
    If (((-Not ($Output)) -and (-Not ($ByteArray)))) {
        throw "Need some data, either by providing -Output or -ByteArray"
    }

    If ($Output) {
        $ByteArray = [System.Text.Encoding]::ASCII.GetBytes($Output)
        Write-Verbose "converted Output via ASCII-Encoding into ByteArray"
    }

    # DOCInfo Struktur erzeugen
    $di=New-Object RawPrinterHelper+DOCINFOA

    If (-Not ($DataType)) {
        # https://support.microsoft.com/en-us/kb/2779300 defines XPS_PASS
        If ((Get-PrinterDriver -Name $Printer.DriverName).MajorVersion -eq 4) {
            $di.pDataType = "XPS_PASS"
        } else {
            $di.pDataType = "RAW"
        }
    } else {
        $di.pDataType = $DataType
    }
    Write-Verbose "Type: $($di.pDataType)"
    $di.pDocName= $DocTitle

    # benötigte Variablen
    $hPrinter=[IntPtr]::Zero
    $dwWritten=0
    $result = $false

    If ([RawPrinterHelper]::OpenPrinter($Printer.Name.Normalize(), [ref] $hPrinter, [intptr]::Zero)) {
        If ([RawPrinterHelper]::StartDocPrinter($hPrinter, 1, $di)) {
            #$result = [RawPrinterHelper]::StartPagePrinter($hPrinter)
            $pa=[System.Runtime.InteropServices.GCHandle]::Alloc($ByteArray, [System.Runtime.InteropServices.GCHandleType]::Pinned)
            $result = [RawPrinterHelper]::WritePrinter($hPrinter, $pa.AddrOfPinnedObject(), $ByteArray.Length, [ref] $dwWritten);$Win32Error =  [ComponentModel.Win32Exception][System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
            # Win32Error, see http://www.exploit-monday.com/2016/01/properly-retrieving-win32-api-error.html
            Write-Verbose "$dwwritten Bytes sent to Printer ‚$($Printer.Name)‘, expected: $($ByteArray.Length)"
            $pa.Free()
            #$result = [RawPrinterHelper]::EndPagePrinter($hPrinter)
            $result = [RawPrinterHelper]::EndDocPrinter($hPrinter)
        }
        $result = [RawPrinterHelper]::ClosePrinter($hPrinter)
    }

}

Wie immer ist das Script nicht schön in dieser Darstellung aber es funktioniert per Copy&Paste.

Zunächst braucht man einen Druckernamen:

PS > Get-Printer| select Name

Name
—-
HP Officejet Pro X576 MFP PCL6
HP LaserJet A4/Letter PS Class Driver
HP Universal Printing PCL 6 (v6.3.0)
Microsoft XPS Document Writer
Microsoft Print to PDF
Fax
An OneNote 2013 senden

Nun wählt man am besten einen aus, in diesem Fall den ersten:

PS > $p=(get-printer)[0]
PS > $p

Name                           ComputerName    Type         DriverName
—-                           ————    —-         ———-
HP Officejet Pro X576 MFP PCL6                 Local        HP Officejet Pro X576

Nun kann man diesem Drucker Daten zukommen lassen:

$Schachttest ="$([char]27)&l4HSchacht1$([char]12)"+"$([char]27)&l1HSchacht2$([char]12)"

Out-RawPrinter –Printer $p –Output $Schachttest

Der etwas verkünstelte String druckt bei einem HP-Drucker zwei Seiten, eine vom Schacht1 (manueller) und eine vom Schacht2. Würde man in diesem Fall Out-Printer benutzen, dann würden die Steuerzeichen nicht interpretiert und als Text oder nichtdarstellbare Zeichen gedruckt.

Da die Umwandlung des Strings bei Out-RawPrinter mittels ASCII-Encoding stattfindet, stößt man auch schnell an eine Grenze, wenn man bestimmte Umlaute drucken möchte. Deshalb gibt es noch den Paramter –ByteArray anstatt –Output, somit kann man eine eigene Umwandlung durchführen und die Daten übergeben.

Dies kann man sich auch zunutze machen, wenn man einen Ausdruck in einer Datei umgelenkt hat und diese Datei dann später drucken möchte. Hier exemplarisch, wie man vorgeht:

$DruckDaten = Get-Content DruckDatei.PRN –Encoding Byte
Out-RawPrinter –Printer $p –ByteArray $DruckDaten

Neben diesen Möglichkeiten zur Kommunikation mit Druckern, möchte ich noch auf SNMP hinweisen, welches auch unter Windows 10 immer noch funktioniert, wie hier beschrieben: https://newyear2006.wordpress.com/2016/07/10/hp-netzwerkdrucker-per-remote-und-reboot-txt-neu-starten-nix-klappt-aber-snmp-bringt-die-lsung/.

Große Dateien mit Powershell splitten und wieder zusammenbauen

8 Oktober 2016

Aufgrund eines aktuellen Falles, wo große Dateien mittels Teamviewer übertragen werden mussten, die Verbindung aber mehr als instabil war, musste eine alternative Lösung her. Ein anderes Programm für die Datenübertragung zu installieren war aber nicht möglich.

Da bei jedem Abbruch des Teamviewers die Datenübertragung der großen Dateien nochmal von neuem gestartet werden musste, mussten die großen Dateien in möglichst kleine Einheiten umgepackt werden, damit diese, solange die Verbindung stabil war, erfolgreich übertragen werden konnten. Dabei gilt natürlich je kleiner die Pakete desto höher die Wahrscheinlichkeit der erfolgreichen Übertragung vor dem nächsten Abbruch.

Hier eine Funktion, welche den Part mit dem in kleinere Einheiten verpacken übernimmt:

Function Split-File{
    [CmdletBinding()]
    Param(
        [String]$File, 
        [String]$Prefix,
        [Int32] $ChunkSize
    )

    $inFile = Resolve-Path -Path $File -ErrorAction SilentlyContinue
    If (-Not $inFile) {
        throw "Unable to locate $File"
    }

    If (Test-Path $Prefix -IsValid) {
        If (Split-Path $Prefix) {
            $Prefix = Join-Path -Path (Resolve-Path (Split-Path $Prefix -Parent)) -ChildPath (Split-Path $Prefix -Leaf)
        }
    }
    Write-Verbose "InFile $inFile"
    Write-Verbose "OutPrefix $Prefix"

    # calculate amount of chunks
    $chunks = ([Math]::Round((dir $inFile).Length / $ChunkSize))
    $chunkLength = ([string]$chunks).length
    $chunkFormat = "{0,$($chunkLength):$(‚0‘ * $chunkLength )}"
    Write-Verbose "Chunks $chunks"
    Write-Verbose "Chunkformat $chunkFormat"

    $inStream = [System.IO.File]::OpenRead($inFile)
    $chunkNum = 1
    $bytes = [Byte[]] 0*$ChunkSize

    While ( $bytesRead = $inStream.Read($bytes,0,$ChunkSize)) {
       
        $outFile = "$Prefix$chunkFormat" -f $chunkNum
        $outStream = [System.IO.File]::OpenWrite($outFile)
        $outStream.Write($bytes,0,$bytesRead);
        $outStream.Close();
        Write-Verbose "ChunkFile $outFile"
        $chunkNum += 1
    }

    $inStream.Close()
}

Gegeben sei eine große Datei mit Namen GroßeDatei.ZIP mit 1,28GB, diese soll in kleine Einheiten a 100MB umgepackt werden.

Damit kann man z. B. diesen Aufruf durchführen:

Split-File -File .\GroßeDatei.ZIP -Prefix .\KleineDatei -ChunkSize 100MB –Verbose

als Ausgabe erscheint:

AUSFÜHRLICH: InFile C:\temp\GroßeDatei.ZIP
AUSFÜHRLICH: OutPrefix C:\temp\KleineDatei
AUSFÜHRLICH: ChunkFile C:\temp\KleineDatei01
AUSFÜHRLICH: ChunkFile C:\temp\KleineDatei02
AUSFÜHRLICH: ChunkFile C:\temp\KleineDatei03
AUSFÜHRLICH: ChunkFile C:\temp\KleineDatei04
AUSFÜHRLICH: ChunkFile C:\temp\KleineDatei05
AUSFÜHRLICH: ChunkFile C:\temp\KleineDatei06
AUSFÜHRLICH: ChunkFile C:\temp\KleineDatei07
AUSFÜHRLICH: ChunkFile C:\temp\KleineDatei08
AUSFÜHRLICH: ChunkFile C:\temp\KleineDatei09
AUSFÜHRLICH: ChunkFile C:\temp\KleineDatei10
AUSFÜHRLICH: ChunkFile C:\temp\KleineDatei11
AUSFÜHRLICH: ChunkFile C:\temp\KleineDatei12
AUSFÜHRLICH: ChunkFile C:\temp\KleineDatei13
AUSFÜHRLICH: ChunkFile C:\temp\KleineDatei14

Diese 100MB Pakete lassen sich nun wesentlich einfacher Übertragen und wenn doch eine Übertragung nicht klappt, muss nur das betreffende Paket nochmal übertragen werden.

Soweit so gut. Hat man nun alle Pakete auf der anderen Seite, dann muss man die Ursprungsdatei aber auch wieder zusammenbauen.

Dies geht ausnahmsweise ohne Powershell und direkt in der Eingabeaufforderung mittels COPY-Befehl:

Copy /B .\KleineDatei01 + .\KleineDatei02 TestDatei
Copy-Item : Es wurde kein Positionsparameter gefunden, der das Argument "+" akzeptiert.
In Zeile:1 Zeichen:1
+ copy /B .\KleineDatei01 + .\KleineDatei02 TestDatei
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Copy-Item], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.CopyItemCommand

Ups oder doch nicht? Die Erklärung ist ganz einfach, Powershell hat einen COPY-Alias (Get-Alias Copy) welcher auf Copy-Item verweist und Copy-Item ist eben nicht Syntaxkompatibel zum reinen Eingabeaufforderung COPY-Befehl. Aber man kann die zugehörige Shell explizit starten:

cmd.exe /C copy /B .\KleineDatei01 + .\KleineDatei02 + …  GroßeDatei.ZIP
.\KleineDatei01
.\KleineDatei02

        1 Datei(en) kopiert.

Damit ist wieder alles so wie es ursprünglich auf der anderen Seite war. Es gibt noch alternative Methoden die Dateien zusammenzubauen aber da spielt auch die Performancefrage eine Rolle: http://stackoverflow.com/questions/1783554/fast-and-simple-binary-concatenate-files-in-powershell.

Wenn man aber bei der einfachen Shell-Copy-Methode bleibt, dann kann es ziemlich mühsam werden, wenn man mehr als 5 Dateien zusammenbauen muss. Deshalb hier noch eine kleine Hilfe mittels Powershell:

(dir kleinedate*).name -join ‚ + .\‘

# Unter Powershell 2.0 verwendet man
(dir kleinedate* | select -ExpandProperty Name) -Join ‚+ .\‘

erzeugt:

KleineDatei01 + .\KleineDatei02 + .\KleineDatei03 + .\KleineDatei04 + .\KleineDatei05 + .\KleineDatei06 + .\KleineDatei07 + .\KleineDatei08 + .\KleineDatei09 + .\KleineDatei10 + .\KleineDatei11 + .\KleineDatei12 + .\KleineDatei13 + .\KleineDatei14

Damit kann man dann ganz einfach

cmd.exe /C COPY /B KleineDatei01 + .\KleineDatei02 + .\KleineDatei03 + .\KleineDatei04 + .\KleineDatei05 + .\KleineDatei06 + .\KleineDatei07 + .\KleineDatei08 + .\KleineDatei09 + .\KleineDatei10 + .\KleineDatei11 + .\KleineDatei12 + .\KleineDatei13 + .\KleineDatei14 GroßeDatei.ZIP

Damit ist die Sache fast perfekt. Man kann noch eine Sicherung einbauen, um zu bestätigen, dass die Daten korrekt übertragen wurden, indem man einen Hash Wert der Daten berechnet. Damit wird gewährleistet, dass das Zusammenbauen der Blöcke auch in der korrekten Reihenfolge erfolgte.

Dazu verwendet man Get-FileHash, falls man Powershell 2.0 einsetzt, findet man hier eine Lösung: https://newyear2006.wordpress.com/2011/07/25/md5-und-sha1-datei-checksummen-mittels-powershell-errechnen-ein-ersatz-fr-fciv/.

Windows 10 Device Guard

2 Oktober 2016

Ein sinnvolles Feature um einen Windows Rechner sicherer zu machen aber leider nur bei Enterprise Versionen verfügbar. Damit kann man mittels Credential Guard seine Passwörter und Tickets absichern.

Aber da ich davon ausgehe, dass in künftigen Versionen noch mehr Features von Device Guard in alle Windowsversionen Einzug halten, hier ein paar Dinge, die wichtig sind.

Wie immer hier die Einleitung zum Thema: https://technet.microsoft.com/en-us/itpro/windows/keep-secure/credential-guard.

Wie kann man per Powershell feststellen, ob Device Guard verfügbar ist bzw. Credential Guard läuft? Am einfachsten mittels WMI:

PS> Get-CimInstance -Namespace root/Microsoft/Windows/DeviceGuard -ClassName Win32_DeviceGuard

AvailableSecurityProperties                  : {0}
CodeIntegrityPolicyEnforcementStatus         : 0
InstanceIdentifier                           : 4ff40742-2649-41b8-bdd1-e80fad1cce80
RequiredSecurityProperties                   : {0}
SecurityServicesConfigured                   : {0}
SecurityServicesRunning                      : {0}
UsermodeCodeIntegrityPolicyEnforcementStatus : 0
Version                                      : 1.0
VirtualizationBasedSecurityStatus            : 0
PSComputerName                               :

Obiges Beispiel ist von einem älteren Rechner (BIOS), welcher Windows 10 Pro v1607 (32-Bit) installiert hat und keine Virtualisierungsfeatures aktiviert hat.

Hier ein etwas neuerer Rechner (UEFI) ebenfalls v1607 Pro (64-Bit) aber mit lokalem aktiviertem Hypervisor:

PS> get-ciminstance -Namespace root/Microsoft/Windows/DeviceGuard -ClassName Win32_DeviceGuard

AvailableSecurityProperties                  : {1, 3}
CodeIntegrityPolicyEnforcementStatus         : 0
InstanceIdentifier                           : 4ff40742-2649-41b8-bdd1-e80fad1cce80
RequiredSecurityProperties                   : {0}
SecurityServicesConfigured                   : {0}
SecurityServicesRunning                      : {0}
UsermodeCodeIntegrityPolicyEnforcementStatus : 0
Version                                      : 1.0
VirtualizationBasedSecurityStatus            : 2
PSComputerName                               :

Für die Ausgangsfrage ist, wie weiß man, dass Device Guard mit Credential Guard eingerichtet ist? Dazu fragt man SecurityServicesConfigured ab, wenn dieser Wert 1 oder höher enthält, dann ist er aktiv. Eine Beschreibung zu SecurityServicesConfigured gibt es unter https://technet.microsoft.com/de-de/itpro/windows/keep-secure/deploy-device-guard-enable-virtualization-based-security.

Wenn man wissen möchte, ob der Dienst auch läuft schaut man bei SecurityServicesRunning nach:

$DevGuard = Get-CimInstance –ClassName Win32_DeviceGuard 
–Namespace root\Microsoft\Windows\DeviceGuard;

If ($DevGuard.SecurityServicesConfigured -contains 1)
{"Credential Guard configured"};
If ($DevGuard.SecurityServicesRunning -contains 1)
{"Credential Guard running"}
https://blogs.technet.microsoft.com/poshchap/2016/09/23/
security-focus-check-credential-guard-status-with-powershell/
Übrigens auf einem Windows 10 Pro v1511 gibt es den Namespace root/
Microsoft/Windows/DeviceGuard gar nicht erst:

PS> Get-CimClass -Namespace root/Microsoft/Windows/DeviceGuard

Get-CimClass : Ungültiger Namespace

In Zeile:1 Zeichen:1

+ Get-CimClass -Namespace root/Microsoft/Windows/DeviceGuard

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : MetadataError: (:) [Get-CimClass], CimException

    + FullyQualifiedErrorId : HRESULT 0x8004100e,Microsoft.Management.Infrastructure.CimCmdlets.GetCimClassCommand

Self Encrypting Drives (SED) und Probleme mit gelöschten Bitlocker Partitionen

1 Oktober 2016

Wenn man eine SSD mit Hardwareverschlüsselung hat, z. B. eine Samsung 850 Pro mit  AES 256-bit Verschlüsselung (Class 0), TCG/Opal, IEEE1667 (Encrypted drive), dann kann es passieren, dass man diese SSD nicht mehr in ein Raid aufnehmen kann. Beim Versuch die SSD in einen dynamischen Datenträger zu konvertieren erhält man die Meldung:

"Der Datenträger konnte nicht konvertiert werden, da die Sicherheit auf mindestens einer Partition aktiviert ist."

Man hat davor schon ein Clean mittels Diskpart ausgeführt und dann so was? Man hat eine leere SSD und kann sie nicht nutzen. Das abschalten von Bitlocker ist jetzt auch nicht mehr möglich, da die Bitlockerpartition durch Clean ja gelöscht wurde.

Zum Glück gibt es ein Tool, welches die Wiederherstellung, zumindest der Funktion aber nicht der Daten, erlaubt. Bei Samsung läuft es unter dem Begriff “PSID revert”, welches man im Internet und nach Anfrage beim Samsung Support erhalten kann. Bei SanDisk heißt es “Crypto Erase”.

Hier noch Infos unter Windows 10 Anforderungen für verschlüsselte Laufwerke: https://technet.microsoft.com/en-us/itpro/windows/keep-secure/encrypted-hard-drive, hier ein ausführliches Beispiel wie man die Funktion einrichtet und wie man PSID anwendet: https://forums.anandtech.com/threads/secure-erasing-840-evo-e-drive-can-it-be-done.2366848/, hier nochmal zusätzlich eine weitere Anleitung: http://www.mcbsys.com/blog/2014/07/set-up-a-lenovo-ts140-with-an-edrive/.

Wer sich nun nicht auf dubiose Quellen im Internet einlassen möchte, der verwendet den Sourcecode für eine “PSID revert” Alternative namens sedutil-cli: https://github.com/Drive-Trust-Alliance/sedutil, sedutil ist für alle wichtigen Plattformen verfügbar: https://github.com/Drive-Trust-Alliance/sedutil/wiki/Executable-Distributions. Hier ist die Anwendung von seduti-cli beschrieben: https://github.com/Drive-Trust-Alliance/sedutil/wiki/PSID-Revert. Hier noch eine FAQ, wo auch wichtige Verhaltensweisen und Begriffe kurz angesprochen werden: https://github.com/Drive-Trust-Alliance/sedutil/wiki/FAQ.

Übrigens TCG steht für Trusted Computing Group, das sind die auch mit den TPM-Spezifikationen, diese hat hier einige Infos zu OPAL: http://www.trustedcomputinggroup.org/resource-directory/?search_query=opal&tax_category=76&tax_post_tag=&order=DESC&subbtn=Go

Hier noch Infos zur Opal Storage Specification: https://en.wikipedia.org/wiki/Opal_Storage_Specification. Unterschied zwischen Opal 1.0 und Opal 2.0: https://www.winmagic.com/blog/2013/06/03/opal-1-0-vs-opal-2-0-self-encrypting-drives-seds-faq/.

Da ich jetzt ewig gesucht habe, wo der Begriff OPAL herkommt, hier eine Erläuterung:

Full-disk encryption (FDE) used to be a software-only proprietary solution. But over the past couple of years, a hardware based hard drive standard has emerged in the form of Opal Security Subsystem Class, or just Opal for short.
http://www.esecurityplanet.com/network-security/The-Pros-and-Cons-of-Opal-Compliant-Drives-3939016.htm