Die Schattenkopie-Funktion von Windows ist das Mittel der Wahl um geöffnete Dateien Kopieren oder Sichern zu können. Mit Hilfe diverses Kommandozeilen-Tools kann man manuell oder mittels Skript eine Schattenkopie erstellen, darauf zugreifen und diese letztlich wieder zu entfernen. Ideal sind diese beispielsweise für automatisierte Aufgaben wie Datensicherungen.
Das Bordmittel “vssadmin”
Seit Windows Server 2003 bietet der Onboard-Befehl vssadmin zusammen mit dem Parameter create shadow eine Möglichkeit Schattenkopien zu erstellen. Dessen Nutzung im Zusammenhang mit Skripten ist allerdings aufgrund der relativ aufwendigen Ermittlung der notwendigen Schattenkopie-Kennung, dem Einhängen der Schattenkopie sowie letztlich deren Entfernung recht umständlich. Ein Beispiel findet sich in diesem Beitrag:
Windows: Robocopy mit VSS (Schattenkopie)
Einfacher geht es mit den folgenden Werkzeugen.
VShadow aus dem SDK
Das wohl bekannteste Tool in Sachen Schattenkopien dürfte vshadow.exe aus dem Windows SDK sein. Bereits seit Windows XP gibt es dieses Werkzeug, welches im Windows 10 SDK zu finden ist. Um an dieses zu gelangen muss das SDK heruntergeladen und installiert werden.
Tipp: Am besten das SDK mittels der ISO installieren, dies geht schneller und zuverlässiger.
Die Datei für verschiedene Plattformen findet sich letztlich an verschiedenen Stellen:
C:\Program Files (x86)\Windows Kits\10\bin>dir vshadow.exe /s Datenträger in Laufwerk C: ist OS Volumeseriennummer: 1234-5678 Verzeichnis von C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\arm64 02.12.2020 05:26 375.784 vshadow.exe 1 Datei(en), 375.784 Bytes Verzeichnis von C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64 02.12.2020 05:30 356.832 vshadow.exe 1 Datei(en), 356.832 Bytes Verzeichnis von C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x86 02.12.2020 04:59 256.992 vshadow.exe 1 Datei(en), 256.992 Bytes
Je nach installierte Version können die Pfade variieren, daher ist der oben gezeigte “dir…”-Befehl oder eine Suche mittels Explorer hilfreich.
Im Gegensatz zu “vssadmin create shadow” liegt eine wesentliche Erleichterung durch die “vshadow.exe” darin, das mittels des Parameters “-script=” eine Batch-Datei erzeugt wird, mit deren Hilfe die notwendige Variablen gesetzt werden, die man für die weitere Verwendung benötigt.
Ein Beispiel-Befehl kann wie folgt aussehen:
vshadow.exe -nw -script=vars.cmd -exec=backup.cmd C:
Damit man die so erstellte Schattenkopie nutzen kann, muss im unter “-exec=” angegebenen Skript zuerst das durch “vshadow.exe” erstellte Skript “vars.cmd” ausgeführt werden.
Inhalt von “Backup.cmd”:
@echo off rem VSS-Variablen laden call vars.cmd rem Die Schattenkopie zur Verfuegung stellen (mounten) mklink /d C:\VSS\ %shadow_device_1%\ rem Die auszufuehrenden Befehle fuer diese Schattenkopie rem Hier koennte z.B. robocopy verwendet werden. rem Die Bereitstellung aufheben und die Schattenkopie entfernen rmdir C:\VSS\ rem Die "vars.cmd" entfernen del vars.cmd /q
Der Inhalt einer “vars.cmd” kann so aussehen:
@echo. @echo [This script is generated by VSHADOW.EXE for the shadow set {ea5f29e0-cb08-433e-9dcd-b24777e7af26}] @echo. SET SHADOW_SET_ID={ea5f29e0-cb08-433e-9dcd-b24777e7af26} SET SHADOW_ID_1={16238672-865e-4e6b-9251-cd88febab273} SET SHADOW_DEVICE_1=\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy22
Die Ausgabe des vshadow-Befehls samt “backup.cmd” (in diesem Beispiel für Laufwerk E: und nur ein “dir” der Schattenkopie) kann so dargestellt werden:
VSHADOW.EXE 3.0 - Volume Shadow Copy sample client. Copyright (C) 2005 Microsoft Corporation. All rights reserved. (Option: No-writers option detected) (Option: Generate SETVAR script 'vars.cmd') (Option: Execute binary/script after shadow creation 'backup.cmd') (Option: Create shadow copy set) - Setting the VSS context to: 0x00000010 Creating shadow set {ea5f29e0-cb08-433e-9dcd-b24777e7af26} ... - Adding volume \\?\Volume{65eded96-880a-465e-8e8e-b1f4d9b707b6}\ [E:\] to the shadow set... Creating the shadow (DoSnapshotSet) ... (Waiting for the asynchronous operation to finish...) Shadow copy set succesfully created. List of created shadow copies: Querying all shadow copies with the SnapshotSetID {ea5f29e0-cb08-433e-9dcd-b24777e7af26} ... * SNAPSHOT ID = {16238672-865e-4e6b-9251-cd88febab273} ... - Shadow copy Set: {ea5f29e0-cb08-433e-9dcd-b24777e7af26} - Original count of shadow copies = 1 - Original Volume name: \\?\Volume{65eded96-880a-465e-8e8e-b1f4d9b707b6}\ [E:\] - Creation Time: 21.09.2021 23:16:01 - Shadow copy device name: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy22 - Originating machine: hv02 - Service machine: hv02 - Not Exposed - Provider id: {b5946137-7b9f-4925-af80-51abd60b20d5} - Attributes: Auto_Release No_Writers Differential Generating the SETVAR script (vars.cmd) ... - Executing command 'backup.cmd' ... ----------------------------------------------------- [This script is generated by VSHADOW.EXE for the shadow set {ea5f29e0-cb08-433e-9dcd-b24777e7af26}] symbolische Verknüpfung erstellt für E:\VSS\ <<===>> \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy22\ Datenträger in Laufwerk E: ist Hyper-V - 180GD SSD Volumeseriennummer: F03D-2A3E Verzeichnis von E:\VSS 20.09.2021 16:50 <DIR> Hyper-V 0 Datei(en), 0 Bytes 1 Verzeichnis(se), 59.027.152.896 Bytes frei ----------------------------------------------------- Snapshot creation done.
ShadowRun
Mit ShadowRun steht wohl das am einfachsten zu verwendende Tool zur Verfügung. Auf Basis des Quellcodes der “vshadow.exe” hat Albertony eine erweiterte Version erstellt.
Wenn man nur einen Befehl ausführen möchte, besteht die Möglichkeit alles in einer Zeile unter zu bekommen:
shadowrun.exe -env -mount -wait -drive=V: -exec=C:\Windows\System32\cmd.exe E: -- /C dir %SHADOW_DRIVE_1%
Möchte man zunächst nur eine Schattenkopie erstellen und dann mit anderen Anwendungen auf diese Zugreifen, kann man einfach
shadowrun.exe -env -mount -wait -drive=V: E:
ausführen. Die Schattenkopie wird als Laufwerk V: zur Verfügung gestellt und ShadowRun wartet auf die “ENTER”-Taste. Die nachfolgende Variante öffnet eine Eingabeaufforderung, die auf die eingehängte Schattenkopie Zugriff hat:
shadowrun.exe -env -mount -wait -drive=V: -exec=C:\Windows\System32\cmd.exe E:
Diese Eingabeaufforderung kann mit “exit” verlassen werden.
Geht es um das Ausführen eines Skripts, nachdem die Schattenkopie erstellt wurde, geht dies am einfachsten so:
shadowrun.exe -env -mount -drive=V: -exec=backup.cmd E:
Neben der direkten Nutzung der Umgebungsvariablen und dem damit einhergehenden Verzicht auf eine “vars.cmd” sowie des Einhängens der Schattenkopie als Laufwerk wird die Nutzung extrem einfach.
Ein Beispiel samt Ausgabe des Befehls:
c:\test>shadowrun.exe -env -mount -nq -exec=C:\Windows\System32\cmd.exe E: -- /C dir %SHADOW_DRIVE_1% ShadowRun.exe v0.5.1 - Volume Shadow Copy Runner. Copyright (C) 2020 Albertony. All rights reserved. (Option: Set process environment) (Option: Mount shadow copies as temporary drives) (Option: Wait after shadow copy has been created) (Option: Do not force quotes around arguments specified with -arg or after -- with quotes) (Option: Execute binary/script after shadow creation 'C:\Windows\System32\cmd.exe') (Option: Create shadow copy set) - Setting the VSS context to: 0x00000010 Creating shadow set {608edea2-a927-4d90-91df-5c61a341c81c} - Adding volume \\?\Volume{65eded96-880a-465e-8e8e-b1f4d9b707b6}\ [E:\] to the shadow set... Creating the shadow (DoSnapshotSet) ... (Waiting for the asynchronous operation to finish...) Shadow set succesfully created. Mounting shadow copies ... - Mounted A: to \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy11 Setting process environment variables ... Executing command: "C:\Windows\System32\cmd.exe" /C dir %SHADOW_DRIVE_1% ----------------------------------------------------- Datenträger in Laufwerk A: ist Hyper-V - 180GD SSD Volumeseriennummer: 1234-5678 Verzeichnis von A:\ 20.09.2021 16:50 <DIR> Hyper-V 0 Datei(en), 0 Bytes 1 Verzeichnis(se), 60.056.428.544 Bytes frei ----------------------------------------------------- Command returned with exit code: 0 Suspending program while any created shadow copies are still available. Unounting shadow copies ... - Unmounted A: from \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy11 Program completed, returning exit code 0.
Persönliche Bemerkung
ShadowRun hat sich innerhalb kürzester Zeit zu meinem Liebling in Sachen VSS und Batch entwickelt, besser und einfacher kann es wohl nicht sein. Als weiterer positiver Punkt kann die ausgezeichnete Dokumentation von VShadow und ShadowRun auf der Projektseite gewertet werden.
Verheiratet, Vater von zwei Kindern, eines an der Hand, eines im Herzen. Schon immer Technik-Freund, seit 2001 in der IT tätig und seit über 10 Jahren begeisterter Blogger. Mit meiner Firma IT-Service Weber kümmern wir uns um alle IT-Belange von gewerblichen Kunden und unterstützen zusätzlich sowohl Partner als auch Kollegen.
Hallo Andy, interessanter Artikel! Was ist die einfachste Methode um in einem Script zu ermitteln, ob ein Volume VSS überhaupt unterstützt, ohne eine Operation durchzuführen?
Chris
Hallo Chris,
spontan fällt mir folgendes dazu ein:
VSS funktioniert nur mit NTFS und ReFS.
vssadmin list volumes
wäre eine weitere Option.
diskpart list volumes
liefert die genutzten Dateisysteme
powershell get-volume
ebenso
Hallo Andy,
ich finde deinen Artikel ebenfalls sehr interessant! Ich habe nun etwas mit ShadowRun & Powershell rumgespielt, da ich diese Combi sehr gut für Profilbackups unserer Anwender verwenden kann. Als ich aus der gemounteten VSS-Kopie per Powershell/Robocopy meine Profildaten als Test gesichert habe und Robocopy zur Outlook-OST-Datei gekommen ist, konnte ich auf einmal nicht mehr auf mein Outlook-Profil zugreifen (OST-Datei sei durch einen anderen Prozess in Verwendung). Damit habe ich nun garnicht gerechnet, da ich glaubte vollständig aus einer Kopie zu arbeiten. Bin dann aber auf den MS-Artikel: https://learn.microsoft.com/de-de/windows/win32/vss/excluding-files-from-shadow-copies gestoßen und habe mich gefragt, ob es bei meinem Outlook-Verhalten einen Zusammenhang gibt. Kannst Du hier Licht ins Dunkle bringen?
LG
Sascha
Hallo Sascha,
generell geht man immer davon aus, das bei VSS alles gesichert werden kann. Die Erfahrung die du jetzt gemacht hast kenne ich ebenfalls, allerdings mit anderen Dateien.
Kurz und knapp: Ja, Microsoft hat die *.ost-Datei(en) von VSS ausgenommen.
Beispielweise hier findet man eine Erklärung:
https://www.tgrmn.com/web/kb/item75.htm
Und hier findet sich z.B. der Key und das man diesen entfernen kann:
https://superuser.com/questions/1371504/outlook-ost-files-not-backed-up-by-vss-engine
Hallo Andy,
ja danke dafür, dass erklärts erstmal! Ich habe allerdings eine weitere Auffälligkeit, die ich mir nicht erklären kann: Wenn ich meine Profildaten aus VSS mit Robocopy vollständig (ohne OST-Datei) sichere, wird das Backup viel größer als die Quelle. In VSS sieht man beim Blick auf die Ordnerstruktur (englisches OS), dass diverse Ordner mehr existieren als in der “Realität”. Diese Orte sind alle samt eine quasi Spiegelung/Übersetzung von vorhandenen Pfaden. Beispiele: (VSS) c:users\Anwendungsdaten -> (Real) c:users\Appdataroaming oder (VSS) c:users\Lokale Einstellungen -> (Real) c:users\appdatalocal.
Da die realen Pfade in VSS aber zusätzlich erhalten sind und ich ein Vollbackup durchführe, verbrauche ich viel mehr Speicherplatz als das eigentliche Profil aufweist. Kannst Du mir erklären, warum das so ist und mir ggf. Hilfestellung geben, welche Orte das insgesamt betrifft? Meine aktuelle Liste beinhaltet bislang: Anwendungsdaten, Lokale Einstellungen, Eigene Dateien, Druckumgebung, Netzwerkumgebung, Send To, Zuletzt verwendet.
Es müssten aber noch mehr sein, da wie gesagt die Differenz zwischen Quelle und Ziel noch viel zu hoch ist. Teilweise scheinen es vielleicht aufgelöste Umgebungsvariablen zu sein, aber eben auch nur teilweise.
Fragen über Fragen …
LG
Sascha
Generell verhält es sich so, das manche Anwendungen bzw. Dienste während eine VSS-Sicherung läuft die eigentliche Datei sozusagen in Ruhe lassen und parallel hierzu eine temporäre Datei befüllen. Sobald der Snapshot dann beendet ist, werden die Änderungen in die eigentliche Datei geschrieben. Ob das nun bei Outlook auch so ist, kann ich leider nicht sagen, da alle unsere Outlooks i.d.R. an einem MDaemon Email Server “hängen” und da gibt es dann keine OST oder PST.
Wie sieht denn dein Robocopy-Aufruf (Befehl) aus?
Ab Werk und sofern man es nicht unterbindet folgt Robocopy jedem Symlink und das führt im schlimmsten Fall sogar zu einer Schleife die einem das Backup-Ziel bis zum Anschlag zumüllt.
An dieser Stelle sollte unbedingt “/xj” verwendet werden.
Hallo Andy,
vielen Dank für den Hinweis auf ‘vssadmin list volumes’, das funktioniert im Prinzip gut und falls das noch jemand liest, hier ein Powershell Snippet um aus der Ausgabe eine Liste von Volumes des Systems zu erzeugen (ohne ” am Ende, z.B. “C:”, “F:”):
$vssAdminOutput = & vssadmin list volumes
$vssAdminOutput = $vssAdminOutput | Where-Object {$_ -match ‘Volume path:’} | ForEach-Object { $_ -replace ‘^Volume path:s+’,” -replace ‘\$’,” }
Das Problem ist hier natürlich dass das so nur in Englisch funktioniert, in einem deutschen Windows wird die Ausgabe anders sein. Falls Dir noch etwas sprachunabhängiges einfällt wäre das super. Übrigens, ja, VSS funktioniert nur in den von Dir genannten Dateisystemen, allerdings nicht immer. Konkret habe ich hier eine SD-Karte in einem Laufwerk, mit Bitlocker verschlüsselt, die zwar mit NTFS formatiert ist aber kein VSS unterstützt und damit das ansonsten tolle Restic Windows Backup Script immer Fehler erzeugen lässt (https://github.com/kmwoley/restic-windows-backup).
Grüsse, Chris
Hallo Andy,
ich habe Deine Empfehlung mit dem /xj – Schalter eingebaut, die Ordnerausschlüsse auskommentiert und nun funktioniert es einwandfrei. Vielen Dank!!!
Der Powershell-Anteil für Robocopy sieht nun so aus:
$params = @($localprofilpath,$Userprofil,”/E”,”/DCOPY:DAT”,”/MIR”,”/Z”,”/R:2″,”/W:2″,”/MT:8″,”/XJ”,”/Compress”,”/TEE”,”/Log:$profilbackuppathProfilbackup.log”)
$XF = @(“*.ost”)
$XD = @(“$localprofilpathAnwendungsdaten”,”$localprofilpathLokale Einstellungen”,”$localprofilpathEigene Dateien”,”$localprofilpathDruckumgebung”,”$localprofilpathNetzwerkumgebung”,”$localprofilpathSend To”,”$localprofilpathStartmenü”,”$localprofilpathVorlagen”,”$localprofilpathZuletzt verwendet”)
robocopy $params /XF $XF #/XD $XD
LG
Sascha