RSS

Hyper-V Sicherung mittels Powershell Skript für Windows Server 2012 [Update 1 auf v0.2]

Im Juni 2010 hat mein Kollege Carsten Rachfahl ein PowerShell-Script geschrieben, welches Ihnen die Möglichkeit bietet, zeitgesteuert per Aufgabenplanung eine VM herunterzufahren, zu exportieren und wieder zu starten. Das Script ist hier einzusehen:

Hyper-V Sicherung mittels Powershell Script

Da es sich um Hyper-V unter Windows Server 2008 R2 handelt, funktioniert das Script unter Windows Server 2012 nicht mehr. Uns haben einige Anfragen erreicht, ob wir auch für Server 2012 ein solches Script erstellen können. Ich habe mich der Thematik einmal angenommen und habe solch ein Script erstellt.

Update 16.03.2013: Die Version 0.2 ist online, die Änderungen finden Sie weiter unten in diesem Beitrag.

Wichtiger Hinweis: Es handelt sich bei virtuellen Systemen meist um wichtige Daten. Prüfen Sie die Nutzung des Scripts vorab an Test- oder Demo-Daten. Wir übernehmen keine Haftung für verlorene oder inkonsistente Dateien oder VMs sowie sonstigen Fehlern oder Problemen. Sie können sich jederzeit den Quelltext des Scripts anschauen und nachvollziehen, was mit den einzelnen Befehlen bewirkt wird. Die Nutzung dieses Scripts erfolgt auf eigene Gefahr!


Die Funktionsweise

Wenn Sie das Script heruntergeladen und entpackt haben finden Sie zwei Dateien vor: Export.ps1 und ReadMe.txt. Die Textdatei beinhaltet eine Beschreibung der Funktionen, die verfügbaren und teilweise benötigten Parameter sowie eine Beschreibung der Parameter. Im weiteren Verlauf finden Sie Beispiele für den Aufruf des Scripts, zusätzlich wird ein Changelog geführt, in dem Änderungen mitgeführt werden.

Der Aufruf des Scripts mit dem Parameter –verbose zeigt den folgenden Inhalt:

image

Wie Sie erkennen können, protokolliert das Script mit, was genau passiert. Der Aufruf mit fehlerhaften oder nicht vorhandenen (zwingend benötigten) Parametern endet in einer Fehlermeldung:

SNAGHTML999acb

Neben der Ausgabe innerhalb des PowerShell-Fenster erzeugt das Script Ihnen eine Logdatei, in der der Vorgang ebenfalls protokolliert wird. Dies ist hilfreich, wenn Sie das Script per Taskplaner ausführen lassen und somit keine aktive Sitzung haben. Standardmäßig wird das Logfile unter C:\temp abgelegt. Wenn der Ordner nicht vorhanden ist wird er erstellt, wenn Sie einen anderen Ordner angeben kann die Logdatei auch dort gespeichert werden.

image

Pro VM und pro Tag wird ein eigenes Logfile erstellt, wenn an einem Tag mehrere Vorgänge ausgeführt werden wird das Log jeweils “hinten” verlängert. Die Datei sieht wie folgt aus:

image

Wenn Sie Ihre VM nicht herunterfahren möchten, können Sie diese auch mit dem Parameter –Speichern in den Gespeicherten Zustand versetzen und dann Exportieren lassen:

image

Das Logfile ändert sich ebenfalls dementsprechend:

image

Ein Export in eine Freigabe direkt ist ebenfalls möglich, Bedingung hierfür ist allerdings ein Dateiserver mit Windows Server 2012 (SMB 3.0 ist hier das Stichwort) und einer Freigabe, auf die das Computerobjekt des Hyper-V Hosts einen Schreibzugriff hat. Wenn dies gegeben ist, funktioniert auch ein Export, siehe Screenshot:

image

Einschränkungen

Dieses Script funktioniert nur unter Windows Server 2012 in der deutschen Sprachvariante. Der Grund hierfür ist, dass die Namen der Integrationskomponenten eingedeutscht wurden und so eine Nutzung auf englischen Systemen ohne Anpassung nicht möglich ist. Ich werde versuchen, diese Einschränkung zu entfernen und eine Abfrage einbauen, die die Sprache der Umgebung ausliest und sich dementsprechend anpasst.

Eine weitere Einschränkung besteht aktuell noch darin, dass ein bereits vorhandener Export überschrieben bzw. gelöscht wird. Ich plane eine Anpassung, in der ein Parameter wahlweise eine Kopie des bereits vorhandenen Exports anfertigt.

Bei der Anzeige der Logdatei bzw. der Ausgabe der Konsole zeigt die Ausgabe vielleicht nicht den korrekten Status. Dies liegt daran, dass bei Erreichen von gewissen Zuständen eine Ausgabe gemacht wird. Wenn Sie während eines Exports diesen manuell per Hyper-V-Manager abbrechen, wird Ihnen die Konsole mit aktivem Export-Script dies mit einer roten Fehlermeldung quittieren, die geschriebene Logdatei wird dies allerdings nicht aufnehmen und der Export sieht (laut Logdatei) korrekt aus. Eine Aufnahme der System-Fehlermeldungen ist geplant.

All diese Dinge hier werden (vielleicht) angegangen, wenn Zeit dafür vorhanden ist. Da es sich hierbei um eine unentgeltliche Entwicklung handelt, passiert dies immer dann, wenn für so etwas Zeit ist. Wir können Ihnen weder versprechen wann etwas hinzugefügt wird noch ob dies überhaupt passiert. Gerne können wir Ihnen ein auf Ihre Umgebung angepasstes Script erstellen, dies wäre dann eine kostenpflichtige Dienstleistung.

Vorbereitungen auf dem System

Um das Script starten zu können, müssen Sie die Script-Datei nach dem entpacken Zulassen. Dies passiert über die Eigenschaften im Reiter Allgemein:

SNAGHTML6eaad1

Weiterhin müssen Sie die Ausführung von nicht signierten Skripten erlauben, dies konfigurieren Sie über den Befehl

Set-ExecutionPolicy Unrestricted

Persönliches Statement

Ich habe bisher noch kein PowerShell-Script mit mehr als fünf Zeilen erstellt, daher ist dies quasi meine Feuertaufe. Die Programmierung ging nach ein paar Stunden Einarbeitung und Suche nach der korrekten Syntax recht einfach von der Hand, PowerShell als Sprache ist sehr einfach aufgebaut. Ich kann mich noch an die Programmierung mit C oder C++ erinnern, mit denen wir in der Schule gequält wurden. PowerShell hat nur noch wenig damit zu tun, die Erstellung von funktionstüchtigen Skripten geht recht schnell mit wenig Quelltext. Gehen Sie einmal offen auf das Thema PowerShell zu, Sie werden es nicht bereuen :)

Download

Version 0.2 – ExportScript fuer Hyper-V unter Windows Server 2012

Version 0.1 – ExportScript fuer Hyper-V unter Windows Server 2012

Feedback

Ich würde mich über ein Feedback zu diesem Script freuen. Da es mich stark wundern würde wenn ich direkt ein fehlerfreies Script geschrieben habe, bitte ich um Rückmeldung zu aufgetretenen Fehlern und Problemen. Ich werde versuchen diese zeitnah zu beseitigen und die jeweilige Version anzupassen. Rückmeldung können Sie mir als Kommentar oder gern auch per Mail zukommen lassen. Bitte haben Sie Verständnis dafür, wenn ich nicht zeitnah reagieren kann.

Update 16.03.2013 – Version 0.2

Ich habe das Script in einer neuen Version zum Download freigegeben, die größte Änderung: Sie können sich das Logfile der Sicherung per Mail schicken lassen. Bedingung hierfür ist ein Mailer, der Emails per SMTP entgegennimmt und zustellen kann.

Wichtig: Wenn Sie die Funktion nicht nutzen möchten

{ brauchen Sie entweder nichts machen und auf Version 0.1 bleiben }

oder

{ auf Version 0.2 updaten und zum einen nichts anpassen und zum anderen den Parameter nicht anpassen! }

Weitere Einzelheiten zur Syntax finden Sie in der Hilfe-Datei, hier ein paar Screenshots der Konfiguration und der Nutzung:

Sie müssen das Script auf Ihre Werte anpassen. Standardmäßig sieht es wie folgt aus

image

Dies muss wie folgt angepasst werden

image

Tragen Sie Ihre persönlichen Daten ein und achten Sie darauf, dass Ihr Mailer die Emails annimmt. Die Ausführung des Scripts sieht nun wie folgt aus, je nach Parameter erfolgt entweder ein Versand oder nicht.

SNAGHTML380d395

Die zugestellte Email sieht wie folgt aus

image

Wie immer gilt: Bei Fehlern oder Problemen bitte kurz einen Kommentar dalassen. Die alte Version bleibt ebenfalls verfügbar, falls benötigt. Viel Spaß mit dem Script :)

Eingabe Informationen

Unter: Management

Tags:

Über den Autor: Jan Kappen ist ausgebildeter Fachinformatiker in der Richtung Systemintegration. Er hat seine Ausbildung im Sommer 2008 abgeschlossen und arbeitet seitdem bei der Rachfahl IT-Solutions GmbH & Co. KG. Jan Kappen ist unter anderen MCITP Server Administrator, Enterprise Administrator und Enterprise Messaging Administrator 2010 sowie MCTS für System Center Virtual Machine Manager 2008, Windows Server 2008 Active Directory, Windows Server Virtualization und Windows Server 2008 Network Infrastructure.

30 Responses to “Hyper-V Sicherung mittels Powershell Skript für Windows Server 2012 [Update 1 auf v0.2]”

  1. DS sagt:

    Besteht die Möglichkeit auch einen (VSS) Snapshot per Script zu erstellen und zu sicheren?
    Dann bräuchte die Maschine nicht heruntergefahren oder gespeichert werden.
    Gruß

  2. Christoph K. sagt:

    Hallo Jan,

    vielen Dank für die Zurverfügungstellung des Skriptes. Habe es bei mir auf Server 2012 getestet und (bisher) keine Fehler finden können. Werde es -Dein Einverständnis vorausgesetzt- für meine tägliche Datensicherung verwenden.

    Schöne Grüße
    Christoph

  3. R. sagt:

    Danke darauf habe ich gewartet.

  4. Tobias Bunse sagt:

    Sehr geehrter Herr Kappen,

    vielen Dank für das Skript, welches auf Windows Server 2012 läuft!

    Ich habe jedoch ein Problem, welches zum Abbruch des Skripts führt. Außerdem meine ich einen kleinen Fehler in der ReadMe-Datei gefunden zu haben.

    Erst mal zu dem Problem:

    Folgende Fehlermeldung erhalte ich beim Ausführen des Skripts:
    Get-VMIntegrationService : Die Benennung “Get-VMIntegrationService” 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 D:\Datensicherung\Export.ps1:60 Zeichen:35
    + $vmHeartBeat = Get-VM -Name $VM | Get-VMIntegrationService -Name Herunterfahren
    + ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (Get-VMIntegrationService:String) [], CommandNot
    FoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Meine Syntax:
    .\Export.ps1 -VM RDS01 -Exportpfad D:\VMExports -Logpfad D:\VMExports\ -verbose

    Mein System:
    Windows Server 2012 Standard (Deutsch) – Core Installation

    Nun zu dem kleinen Fehler:

    In der ReadMe-Datei ist im Bereich “Beispiele” bei dem letzten Beispiel von dem Parameter “-Logfile” die Rede. Ich denke jedoch, dass es “-Logpfad” heißen müsste.

    Ich hoffe sehr, dass Sie Zeit finden um mir zu helfen.

    Vielen Dank im Voraus!

  5. Jan Kappen sagt:

    Hallo Christoph,
    die Nutzung (egal wie) ist kein Problem, dafür wurde es ja unter anderem erstellt :)
    Gruß und schönes Wochenende
    Jan

  6. Jan Kappen sagt:

    Hallo Herr Bunse,
    funktioniert der Aufruf der einzelnen Zeile

    Get-VM -Name VMNAME | Get-VMIntegrationService -Name Herunterfahren

    in einer einzelnen Sitzung? Alternativ: Was sagt der Befehl

    Get-VM -Name VMNAME | Get-VMIntegrationService

    Dort müssten insgesamt fünf Dienste aufgeführt werden…
    Danke für den Hinweis in der ReadMe-Datei, werd ich korrigieren :)
    Gruß, Jan

  7. Jan Kappen sagt:

    Hallo DS,
    mit Bordmitteln funktioniert das nicht, das sind dann schon die höheren Weihen :) Bei Bedarf einer Online-Sicherung muss auf ein vernünftiges Programm zurückgegriffen werden, ich kann hier Veeam empfehlen.
    Gruß, Jan

  8. HaWa sagt:

    Eine Online-Sicherung via VSS beherrscht seit Windows 2012 auch die Serversicherung von Windows!

  9. Jan Kappen sagt:

    Meine Aussage bezog sich darauf, das die Export eines Exports nicht mit Bordmitteln und im eingeschalteten Zustand möglich ist. Eine Sicherung per Windows Sicherung ist natürlich nutzbar, es gibt aber scheinbar einige Techniker, die gerne eine Portierung des 2008 R2-Scripts auf 2012 haben wollten, daher dieses Script :)
    Gruß, Jan

  10. Tobias Bunse sagt:

    Hallo Herr Kappen,

    ich habe die Zeilen ausgeführt.
    Die ausgegebenen Fehlermeldungen sind nahezu identisch:
    PS C:\Users\Administrator> Get-VM -Name VMNAME | Get-VMIntegrationService -Name Herunterfahren
    Get-VM : Die Benennung “Get-VM” 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:1 Zeichen:1
    + Get-VM -Name VMNAME | Get-VMIntegrationService -Name Herunterfahren
    + ~~~~~~
    + CategoryInfo : ObjectNotFound: (Get-VM:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    PS C:\Users\Administrator> Get-VM -Name VMNAME | Get-VMIntegrationService
    Get-VM : Die Benennung “Get-VM” 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:1 Zeichen:1
    + Get-VM -Name VMNAME | Get-VMIntegrationService
    + ~~~~~~
    + CategoryInfo : ObjectNotFound: (Get-VM:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Vielleicht noch als Hintergrundinformation:
    Ich habe zuerst fälschlicherweise das Powershell Script von Carsten Rachfahl probiert. Also habe ich auch die PSHyperv Library von James O`Neill installiert. Könnte es damit zusammenhängen?

    Vielen Dank für die Mühe.

  11. Jan Kappen sagt:

    Hallo,
    dann ist das vermutlich der Fehler. Bitte einmal alle Änderungen rückgängig machen und erneut probieren.
    Gruß, Jan

  12. Tobias Bunse sagt:

    Hallo Herr Kappen,

    haben Sie einen Tipp für mich, wie ich es wieder Rückgängig machen kann? ich kenne die Standard-Werte der Registry nicht :-(
    Muss ich Funktionen wie “NetFx2-ServerCore” und “MicrosoftWindowsPowerShell” dann auch disablen?

    Danke im Voraus!

    Lieben Gruß

    Tobias Bunse

  13. Ralf Schneider sagt:

    Hallo Herr Kappen,

    vielen Dank für das Script, ich nutze es neben der täglichen Sicherung über die Windows Serversicherung (der VM) um einmal in der Woche die komplette VM als Export auf ein NAS zu sichern – Funktioniert wunderbar.
    Ein Highlight wäre es, wenn nach erfolgreicher Sicherung und Start der VM (oder bei Fehlschlag des Exports) eine E-Mail versendet würde.

    Grüße
    Ralf

  14. Jan Kappen sagt:

    Hallo Ralf,
    das steht auf der Liste der möglichen Features… Mal gucken wann ich Zeit finde :)
    Gruß, Jan

  15. Jan Kappen sagt:

    Zeit gefunden, viel Spaß damit :)

  16. Ralf Schneider sagt:

    Schon eingebaut und getestet, erneut meinen Dank :-)

  17. Hallo Jan,

    vielen Dank für das tolle Script – es funktioniert hervorragend.

    Ich habe mir erlaubt, es auf meine Zwecke noch etwas anzupassen bzw. zu erweitern und poste daher hier einmal die Änderungen, vielleicht ist es ja für jemanden interessant.

    ##############################################################################################
    # Script zum Export von VMs unter Hyper-V mit Windows Server 2012 oder Windows 8 Pro #
    # erstellt von Jan Kappen – j.kappen@rachfahl.de #
    # Version 0.2 #
    # 16. Maerz 2013 #
    # Diese Script wird bereitgestellt wie es ist, ohne jegliche Garantie. Der Einsatz #
    # erfolgt auf eigene Gefahr. Es wird jegliche Haftung ausgeschlossen. #
    # #
    # Dieses Script beinhaltet keine Hilfe. RTFM. #
    # #
    # http://www.hyper-v-server.de | http://www.rachfahl.de #
    # #
    ##############################################################################################

    ##############################################################################################
    # Funktionserweiterung: #
    # – Export auf ext. Laufwerk, Mailversand über ext Mailserver mit Authentifizierung, #
    # zusätzliche Statusmeldungen in der Email #
    # erweitert von Nils Rochholl – rochholl@implec.de #
    # Version 0.2.nr1 #
    # 16. Mai 2013 #
    # #
    # http://www.implec.de #
    # #
    ##############################################################################################

    Param(
    [string] $VM =”",
    [string] $Exportpfad = “”,
    [string] $Remotepfad = “”,
    [string] $Logpfad = “”,
    [string] $Kunde = “”,
    [string] $Server = “”,
    [switch] $Speichern,
    [switch] $Auslassen,
    [switch] $verbose,
    [switch] $statusmail
    )

    ########################
    # Logging des Vorgangs #
    ########################
    $LogDateiDatum = Get-Date -Format yyyy-MM-dd
    if (!$Logpfad) {
    $LogPfadVorhanden = Test-Path ${env:homedrive}\temp\
    if ($LogPfadVorhanden -eq $False)
    { new-item ${env:homedrive}\temp\ -itemtype directory }
    $Logdatei = “${env:homedrive}\temp\$VM-$LogDateiDatum.log” }
    else
    { $Logdatei = “$Logpfad\$VM-$LogDateiDatum.log” }

    ####################################
    # Test auf (in-)korrekte Parameter #
    ####################################
    if (!$VM) { Write-Host (Get-Date) “Parameter -VM muss vorhanden sein und einen Namen enthalten. Abbruch!”
    $temp1 = (Get-Date)
    $temp2 = “Parameter -VM muss vorhanden sein und einen Namen enthalten. Abbruch!”
    $temp3 = “———————————”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    “$temp3″ | Out-File $Logdatei -Append
    exit }
    if (!$Exportpfad) { Write-Host (Get-Date) “Parameter -RemotePfad muss vorhanden sein und einen Pfad enthalten. Abbruch!”
    $temp1 = (Get-Date)
    $temp2 = “Parameter -RemotePfad muss vorhanden sein und einen Pfad enthalten. Abbruch!”
    $temp3 = “———————————”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    “$temp3″ | Out-File $Logdatei -Append
    exit }

    #################
    # Zeit ausgeben #
    #################
    if ($verbose -eq $true) { Write-Host (Get-Date) “Export der VM $VM gestartet” }
    $temp1 = (Get-Date)
    $temp2 = “Export der VM $VM gestartet”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    ####################################################
    # Test auf Integrationskomponente “Herunterfahren” #
    ####################################################
    $vmHeartBeat = Get-VM –Name $VM | Get-VMIntegrationService –Name Herunterfahren
    if($vmHeartBeat.enabled -match “True”)
    {
    if ($verbose -eq $true) { Write-Host (Get-Date) “Der Integrationsdienst ‘Herunterfahren’ ist aktiviert” }
    $temp1 = (Get-Date)
    $temp2 = “Der Integrationsdienst ‘Herunterfahren’ ist aktiviert”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    }
    else
    {
    if ($verbose -eq $true) { Write-Host (Get-Date) “Der Integrationsdienst ‘Herunterfahren’ ist NICHT aktiviert. VM kann nur gespeichert werden!” }
    $temp1 = (Get-Date)
    $temp2 = “Der Integrationsdienst ‘Herunterfahren’ ist NICHT aktiviert. VM kann nur gespeichert werden!”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    if($Speichern.IsPresent -match “True”) {
    if ($verbose -eq $true) { Write-Host (Get-Date) “VM kann trotzdem exportiert werden, da sie gespeichert wird” }
    $temp1 = (Get-Date)
    $temp2 = “VM kann trotzdem exportiert werden, da sie gespeichert wird”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    }
    else
    {
    if ($verbose -eq $true) { Write-Host (Get-Date) “Vm wird nicht exportiert, Abbruch!” }
    $temp1 = (Get-Date)
    $temp2 = “Vm wird nicht exportiert, Abbruch!”
    $temp3 = “———————————”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    “$temp3″ | Out-File $Logdatei -Append
    exit
    }
    }

    ##################################################################
    # Test auf Integrationskomponente “Herunterfahren” abgeschlossen #
    ##################################################################
    # In welchem Zustand befindet sich die VM? #
    ############################################

    $vmstatus = Get-VM –Name $VM
    if($vmstatus.State -match “Running”)
    {
    if ($verbose -eq $true) { Write-Host (Get-Date) “VM ist eingeschaltet” }
    $temp1 = (Get-Date)
    $temp2 = “VM ist eingeschaltet”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    #################################
    # Abfrage auf Speichern-Zustand #
    #################################
    if($Speichern.IsPresent -match “True”)
    {
    ####################
    # Speichern der VM #
    ####################
    if ($verbose -eq $true) { Write-Host (Get-Date) “VM wird gespeichert” }
    $temp1 = (Get-Date)
    $temp2 = “VM wird gespeichert”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    Save-VM -Name $VM
    }
    else
    {
    #########################################
    # Kein Speichern, Herunterfahren der VM #
    #########################################
    if ($verbose -eq $true) { Write-Host (Get-Date) “VM wird heruntergefahren” }
    $temp1 = (Get-Date)
    $temp2 = “VM wird heruntergefahren”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    ################################
    # Warten auf ausgeschaltete VM #
    ################################
    Stop-VM -Name $VM -Force
    }
    }
    else
    {
    if ($verbose -eq $true) { Write-Host (Get-Date) “VM ist bereits ausgeschaltet” }
    $temp1 = (Get-Date)
    $temp2 = “VM ist bereits ausgeschaltet”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    }

    ######################################################
    # Speichern oder Herunterfahren der VM abgeschlossen #
    ######################################################
    # Export der VM #
    #################
    if ($verbose -eq $true) { Write-Host (Get-Date) “Export der VM” }
    $temp1 = (Get-Date)
    $temp2 = “Export der VM”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    #######################################################
    # Falls Export-Ordner nicht vorhanden, Export starten #
    #######################################################
    $ZielPfadVorhanden = Test-Path $Exportpfad\$VM
    if ($ZielPfadVorhanden -eq $False)
    { Export-VM -Name $VM -Path $Exportpfad }
    else
    { Remove-Item -Recurse -Force $Exportpfad\$VM
    Export-VM -Name $VM -Path $Exportpfad }
    if ($verbose -eq $true) { Write-Host (Get-Date) “Export der VM abgeschlossen” }
    $temp1 = (Get-Date)
    $temp2 = “Export der VM abgeschlossen”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    ########################
    # Export abgeschlossen #
    ########################
    # Start der VM #
    ################
    if ($verbose -eq $true) { Write-Host (Get-Date) “Ueberpruefung auf Startverhalten nach Export” }
    $temp1 = (Get-Date)
    $temp2 = “Ueberpruefung auf Startverhalten nach Export”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    ###################################
    # Ueberpruefung auf Stop-Schalter #
    ###################################
    if ($Auslassen.IsPresent -eq $False)
    { if ($verbose -eq $true) { Write-Host (Get-Date) “VM wird eingeschaltet” }
    $temp1 = (Get-Date)
    $temp2 = “VM wird eingeschaltet”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    Start-VM -Name $VM }
    else
    { if ($verbose -eq $true) { Write-Host (Get-Date) “VM bleibt ausgeschaltet” }
    $temp1 = (Get-Date)
    $temp2 = “VM bleibt ausgeschaltet”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append }

    ##############################
    # Start der VM abgeschlossen #
    ##############################

    ##############################
    # ist Remotepfad gesetzt #
    # Kopie der VM auf weiteres #
    # Laufwerk, danach Löschung #
    # auf Exportpfad #
    ##############################
    if($Remotepfad -ne “”) {
    if(Test-Path $Remotepfad\$VM) {
    if ($verbose -eq $true) { Write-Host (Get-Date) “Loesche Verzeichnis $Remotepfad\$VM” }
    $temp1 = (Get-Date)
    $temp2 = “Loesche Verzeichnis $Remotepfad\$VM”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    Remove-Item $Remotepfad\$VM -recurse
    }

    if($verbose -eq $true) { Write-Host (Get-Date) “Kopiere $Exportpfad\$VM nach $Remotepfad\$VM” }
    Copy-Item $Exportpfad\$VM $Remotepfad\$VM -Recurse
    $temp1 = (Get-Date)
    $temp2 = “Kopiere $Exportpfad\$VM nach $Remotepfad\$VM”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    if($verbose -eq $true) { Write-Host (Get-Date) “Loesche Verzeichnis $Exportpfad\$VM” }
    $temp1 = (Get-Date)
    $temp2 = “Loesche Verzeichnis $Exportpfad\$VM”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    Remove-Item $Exportpfad\$VM -recurse
    }

    ##############################
    # Ende Remotepfad-Kopie #
    ##############################

    if ($verbose -eq $true) { Write-Host (Get-Date) “Ueberpruefung auf Sendung einer Status-Mail” }
    $temp1 = (Get-Date)
    $temp2 = “Ueberpruefung auf Sendung einer Status-Mail”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    ###########################################################################

    if ($statusmail.IsPresent -eq $False)
    { if ($verbose -eq $true) { Write-Host (Get-Date) “Es wird keine Email versendet” }
    $temp1 = (Get-Date)
    $temp2 = “Es wird keine Email versendet”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append }
    else
    ##################################
    # Email versenden mit Status-Log #
    ##################################
    { if ($verbose -eq $true) { Write-Host (Get-Date) “Es wird eine Email versendet” }
    $temp1 = (Get-Date)
    $temp2 = “Es wird eine Email versendet”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append

    ########################################################################
    # Ab hier muessen die persoenlichen Einstellungen konfiguriert werden! #
    ########################################################################

    #HOW TO CREATE A PSCREDENTIAL OBJECT
    $secpasswd = ConvertTo-SecureString “PasswordHere” -AsPlainText -Force
    $mycreds = New-Object System.Management.Automation.PSCredential (“from@mail.de”, $secpasswd)

    #Datei auslesen
    $Logtext = Get-Content -path $Logdatei

    #Check ob VM läuft
    $vmstatus = Get-VM –Name $VM
    if($vmstatus.State -match “Running”) { $StatusVM = “VM eingeschaltet” }
    else { $StatusVM = “VM ausgeschaltet” }

    #Check ob Datei aktuell
    $BackupDate = (get-date).AddDays(-0.5)
    if($Remotepfad -ne “”) { $Backuppfad = (Get-Item -Path “$Remotepfad\$VM”) }
    else { $Backuppfad = (Get-Item -Path “$Exportpfad\$VM”) }
    $BackupAlter = (Get-Date) – $Backuppfad.CreationTime
    $BackupAlter = ‘{0:0}’ -f $BackupAlter.TotalDays

    if ($BackupDate -lt $Backuppfad.LastWriteTime) {
    $StatusSicherung = “Sicherung aktuell.`r`nDer Ordner “+$Backuppfad.name+” ist vom “+$Backuppfad.LastWriteTime+”.” }
    else {
    $StatusSicherung = “Sicherung nicht aktuell, $BackupAlter Tage alt.`r`nDer Ordner “+$Backuppfad.name+” ist vom “+$Backuppfad.LastWriteTime+”.” }

    #Mail zusammenstellen
    $mail = @{
    SmtpServer = ‘smtpserver.de’
    Port = 25
    From = ‘from@mail.de’
    To = ‘to@mail.de’
    Subject = “Script-Sicherung der VM $VM”
    Body = “Anbei das Log der Export-Sicherung `r`n`r`nVM $VM `r`nKunde: $Kunde `r`nServer: $Server `r`nStatus: $StatusVM `r`nAlter: $StatusSicherung”
    Attachments = “$Logdatei”
    }

    Send-MailMessage @mail -credential $mycreds

    Write-Host (Get-Date) “################################”
    $temp1 = (Get-Date)
    $temp2 = “################################”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    }

    ########################
    # Script abgeschlossen #
    ########################

    Gruß,
    Nils

  18. Christian sagt:

    Hallo in die Runde!

    Läuft dieses Script nun sowohl unter 2012 Server als auch auf 2008R2?

    Grüße

    Christian

  19. Jan Kappen sagt:

    Hallo Christian,
    dieses Skript läuft nur unter Windows Server 2012, da unter 2008 R2 keine native PowerShell-Unterstützung vorhanden ist und durch die PS-Library (die nachträglich per Codeplex installiert werden muss) andere Befehle und Parameter nutzt. Für 2008 R2 muss weiterhin das Skript meines Kollegen verwendet werden.
    Gruß, Jan

  20. Sören Wagner-Emden sagt:

    Funktioniert das Script auch mit dem Hyper-V Server 2012 ?

  21. Jan Kappen sagt:

    Hallo Sören,
    das Script funktioniert auch unter Hyper-V Server 2012.
    Gruß, Jan

  22. Sören Wagner-Emden sagt:

    Danke – werd ich gleich mal testen :)

  23. Timo Fritz sagt:

    Habe mir erlaubt, meine eigenen Wünsche einfließen zu lassen. Bin kein Profi, Code ist daher evtl. nicht optimal, aber funktioniert.
    Änderungen siehe weiter unten.

    ##############################################################################################
    # Script zum Export von VMs unter Hyper-V mit Windows Server 2012 oder Windows 8 Pro #
    # erstellt von Jan Kappen – j.kappen@rachfahl.de #
    # Version 0.2 #
    # 16. Maerz 2013 #
    # Diese Script wird bereitgestellt wie es ist, ohne jegliche Garantie. Der Einsatz #
    # erfolgt auf eigene Gefahr. Es wird jegliche Haftung ausgeschlossen. #
    # #
    # Dieses Script beinhaltet keine Hilfe. RTFM. #
    # #
    # http://www.hyper-v-server.de | http://www.rachfahl.de #
    # #
    ##############################################################################################

    ##############################################################################################
    # Funktionserweiterung: #
    # – Export auf ext. Laufwerk, Mailversand über ext Mailserver mit Authentifizierung, #
    # zusätzliche Statusmeldungen in der Email #
    # erweitert von Nils Rochholl – rochholl@implec.de #
    # Version 0.2.nr1 #
    # 16. Mai 2013 #
    # #
    # http://www.implec.de #
    # #
    ##############################################################################################

    ##############################################################################################
    # Funktionserweiterung: #
    # – Mailversand über ext. Mailserver mit Authentifizierung von Nils Rochholl entfernt und #
    # durch eigene, ähnliche Lösung ersetzt #
    # – Eventlog wird auf Hyper-V Einträge überprüft. Mailversand erfolgt gekennzeichnet als #
    # erfolgreich oder fehlerhaft in Abhängigkeit von den Events. #
    # – Syntaxfehler in Version 0.2.nr1 entfernt #
    # erweitert von Timo Fritz – timo-fritz@heldele.de #
    # Version 0.2.nr2 #
    # 28. Oktober 2013 #
    # http://www.heldele.de #
    ##############################################################################################

    Param(
    [string] $VM =”Servername”,
    [string] $Exportpfad = “UNC oder lokalen Pfad angeben”,
    [string] $Remotepfad = “”,
    [string] $Logpfad = “UNC oder lokalen Pfad angeben”,
    [string] $Kunde = “Kundenname”,
    [string] $Eventlogcheck = “Yes”, #”Yes” = aktiviert, “No” = deaktiviert
    [string] $Server = “Servername”,
    [switch] $Speichern,
    [switch] $Auslassen,
    [switch] $verbose,
    [switch] $statusmail
    )

    ########################
    # Logging des Vorgangs #
    ########################
    $LogDateiDatum = Get-Date -Format yyyy-MM-dd
    if (!$Logpfad) {
    $LogPfadVorhanden = Test-Path ${env:homedrive}\temp\
    if ($LogPfadVorhanden -eq $False)
    { new-item ${env:homedrive}\temp\ -itemtype directory }
    $Logdatei = “${env:homedrive}\temp\$VM-$LogDateiDatum.log” }
    else
    {
    #Check if log file exists.
    $ChkFile = “$Logpfad\$VM-$LogDateiDatum.log”
    $FileExists = (Test-Path $ChkFile -PathType Leaf)
    if ($FileExists)
    {
    remove-item $Logpfad\$VM-$LogDateiDatum.log
    $Logdatei = “$Logpfad\$VM-$LogDateiDatum.log”
    }
    elseif (!($FileExists))
    {
    $Logdatei = “$Logpfad\$VM-$LogDateiDatum.log”
    }
    }

    ####################################
    # Test auf (in-)korrekte Parameter #
    ####################################
    if (!$VM) { Write-Host (Get-Date) “Parameter -VM muss vorhanden sein und einen Namen enthalten. Abbruch!”
    $temp1 = (Get-Date)
    $temp2 = “Parameter -VM muss vorhanden sein und einen Namen enthalten. Abbruch!”
    $temp3 = “———————————”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    “$temp3″ | Out-File $Logdatei -Append
    exit }
    if (!$Exportpfad) { Write-Host (Get-Date) “Parameter -RemotePfad muss vorhanden sein und einen Pfad enthalten. Abbruch!”
    $temp1 = (Get-Date)
    $temp2 = “Parameter -RemotePfad muss vorhanden sein und einen Pfad enthalten. Abbruch!”
    $temp3 = “———————————”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    “$temp3″ | Out-File $Logdatei -Append
    exit }

    #################
    # Zeit ausgeben #
    #################
    if ($verbose -eq $true) { Write-Host (Get-Date) “Export der VM $VM gestartet” }
    $temp1 = (Get-Date)
    $temp2 = “Export der VM $VM gestartet”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    ####################################################
    # Test auf Integrationskomponente “Herunterfahren” #
    ####################################################
    $vmHeartBeat = Get-VM –Name $VM | Get-VMIntegrationService –Name Shutdown
    if($vmHeartBeat.enabled -match “True”)
    {
    if ($verbose -eq $true) { Write-Host (Get-Date) “Der Integrationsdienst ‘Herunterfahren’ ist aktiviert” }
    $temp1 = (Get-Date)
    $temp2 = “Der Integrationsdienst ‘Herunterfahren’ ist aktiviert”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    }
    else
    {
    if ($verbose -eq $true) { Write-Host (Get-Date) “Der Integrationsdienst ‘Herunterfahren’ ist NICHT aktiviert. VM kann nur gespeichert werden!” }
    $temp1 = (Get-Date)
    $temp2 = “Der Integrationsdienst ‘Herunterfahren’ ist NICHT aktiviert. VM kann nur gespeichert werden!”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    if($Speichern.IsPresent -match “True”) {
    if ($verbose -eq $true) { Write-Host (Get-Date) “VM kann trotzdem exportiert werden, da sie gespeichert wird” }
    $temp1 = (Get-Date)
    $temp2 = “VM kann trotzdem exportiert werden, da sie gespeichert wird”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    }
    else
    {
    if ($verbose -eq $true) { Write-Host (Get-Date) “Vm wird nicht exportiert, Abbruch!” }
    $temp1 = (Get-Date)
    $temp2 = “Vm wird nicht exportiert, Abbruch!”
    $temp3 = “———————————”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    “$temp3″ | Out-File $Logdatei -Append
    exit
    }
    }

    ##################################################################
    # Test auf Integrationskomponente “Herunterfahren” abgeschlossen #
    ##################################################################
    # In welchem Zustand befindet sich die VM? #
    ############################################

    $vmstatus = Get-VM –Name $VM
    if($vmstatus.State -match “Running”)
    {
    if ($verbose -eq $true) { Write-Host (Get-Date) “VM ist eingeschaltet” }
    $temp1 = (Get-Date)
    $temp2 = “VM ist eingeschaltet”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    #################################
    # Abfrage auf Speichern-Zustand #
    #################################
    if($Speichern.IsPresent -match “True”)
    {
    ####################
    # Speichern der VM #
    ####################
    if ($verbose -eq $true) { Write-Host (Get-Date) “VM wird gespeichert” }
    $temp1 = (Get-Date)
    $temp2 = “VM wird gespeichert”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    Save-VM -Name $VM
    }
    else
    {
    #########################################
    # Kein Speichern, Herunterfahren der VM #
    #########################################
    if ($verbose -eq $true) { Write-Host (Get-Date) “VM wird heruntergefahren” }
    $temp1 = (Get-Date)
    $temp2 = “VM wird heruntergefahren”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    ################################
    # Warten auf ausgeschaltete VM #
    ################################
    Stop-VM -Name $VM -Force
    }
    }
    else
    {
    if ($verbose -eq $true) { Write-Host (Get-Date) “VM ist bereits ausgeschaltet” }
    $temp1 = (Get-Date)
    $temp2 = “VM ist bereits ausgeschaltet”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    }

    ######################################################
    # Speichern oder Herunterfahren der VM abgeschlossen #
    ######################################################
    # Export der VM #
    #################
    if ($verbose -eq $true) { Write-Host (Get-Date) “Export der VM” }
    $temp1 = (Get-Date)
    $temp2 = “Export der VM”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    #######################################################
    # Falls Export-Ordner nicht vorhanden, Export starten #
    #######################################################
    $ZielPfadVorhanden = Test-Path $Exportpfad\$VM
    if ($ZielPfadVorhanden -eq $False)
    { Export-VM -Name $VM -Path $Exportpfad }
    else
    { Remove-Item -Recurse -Force $Exportpfad\$VM
    Export-VM -Name $VM -Path $Exportpfad }
    if ($verbose -eq $true) { Write-Host (Get-Date) “Export der VM abgeschlossen” }
    $temp1 = (Get-Date)
    $temp2 = “Export der VM abgeschlossen”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    ########################
    # Export abgeschlossen #
    ########################
    # Start der VM #
    ################
    if ($verbose -eq $true) { Write-Host (Get-Date) “Ueberpruefung auf Startverhalten nach Export” }
    $temp1 = (Get-Date)
    $temp2 = “Ueberpruefung auf Startverhalten nach Export”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    ###################################
    # Ueberpruefung auf Stop-Schalter #
    ###################################
    if ($Auslassen.IsPresent -eq $False)
    { if ($verbose -eq $true) { Write-Host (Get-Date) “VM wird eingeschaltet” }
    $temp1 = (Get-Date)
    $temp2 = “VM wird eingeschaltet”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    Start-VM -Name $VM }
    else
    { if ($verbose -eq $true) { Write-Host (Get-Date) “VM bleibt ausgeschaltet” }
    $temp1 = (Get-Date)
    $temp2 = “VM bleibt ausgeschaltet”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append}
    ##############################
    # Start der VM abgeschlossen #
    ##############################

    ##############################
    # ist Remotepfad gesetzt #
    # Kopie der VM auf weiteres #
    # Laufwerk, danach Löschung #
    # auf Exportpfad #
    ##############################
    if($Remotepfad -ne “”) {
    if(Test-Path $Remotepfad\$VM) {
    if ($verbose -eq $true) { Write-Host (Get-Date) “Loesche Verzeichnis $Remotepfad\$VM” }
    $temp1 = (Get-Date)
    $temp2 = “Loesche Verzeichnis $Remotepfad\$VM”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    Remove-Item $Remotepfad\$VM -recurse
    }
    if($verbose -eq $true) { Write-Host (Get-Date) “Kopiere $Exportpfad\$VM nach $Remotepfad\$VM” }
    Copy-Item $Exportpfad\$VM $Remotepfad\$VM -Recurse
    $temp1 = (Get-Date)
    $temp2 = “Kopiere $Exportpfad\$VM nach $Remotepfad\$VM”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    if($verbose -eq $true) { Write-Host (Get-Date) “Loesche Verzeichnis $Exportpfad\$VM” }
    $temp1 = (Get-Date)
    $temp2 = “Loesche Verzeichnis $Exportpfad\$VM”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    Remove-Item $Exportpfad\$VM -recurse
    }
    ##############################
    # Ende Remotepfad-Kopie #
    ##############################

    #Datei auslesen
    $Logtext = Get-Content -path $Logdatei

    #Check ob VM läuft
    $vmstatus = Get-VM –Name $VM
    if($vmstatus.State -match “Running”) { $StatusVM = “VM eingeschaltet” }
    else { $StatusVM = “VM ausgeschaltet” }

    #Check ob Datei aktuell
    $BackupDate = (get-date).AddDays(-0.5)
    if($Remotepfad -ne “”) { $Backuppfad = (Get-Item -Path “$Remotepfad\$VM”) }
    else { $Backuppfad = (Get-Item -Path “$Exportpfad\$VM”) }
    $BackupAlter = (Get-Date) – $Backuppfad.CreationTime
    $BackupAlter = ‘{0:0}’ -f $BackupAlter.TotalDays

    #Eventlog auf Hyper-V-Exportfehler prüfen
    $Stundenzurück = (Get-Date).AddHours(-1) #Log wird eine Stunde zurück überprüft. Je nach dauer der Sicherung erhöhen.
    #Nicht zu hoch ansetzen, da sonst evtl. Fehler von der vorherigen Sicherung ausgelesen werden.

    if ($Eventlogcheck -eq “Yes”)
    {
    if (Get-WinEvent -FilterHashtable @{ LogName = “Microsoft-Windows-Hyper-V-VMMS-Admin”; StartTime = $Stundenzurück; ID = 18280})
    {
    if ($verbose -ne “”)
    {
    [int] $Eventlogstatus = “2″
    { Write-Host (Get-Date) “Hyper-V Export canceled – Event 18280″ }
    $temp1 = (Get-Date)
    $temp2 = “Hyper-V Export canceled – Event 18280″
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    }
    }
    elseif (Get-WinEvent -FilterHashtable @{ LogName = “Microsoft-Windows-Hyper-V-VMMS-Admin”; StartTime = $Stundenzurück; ID = 16010})
    {
    if ($verbose -ne “”)
    {
    [int] $Eventlogstatus = “2″
    { Write-Host (Get-Date) “Hyper-V Export Operation failed – Event 16010″ }
    $temp1 = (Get-Date)
    $temp2 = “Hyper-V Export Operation failed – Event 16010″
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    }
    }
    elseif (Get-WinEvent -FilterHashtable @{ LogName = “Microsoft-Windows-Hyper-V-VMMS-Admin”; StartTime = $Stundenzurück; ID = 18300})
    {
    if ($verbose -ne “”)
    {
    [int] $Eventlogstatus = “2″
    { Write-Host (Get-Date) “Hyper-V Export failed to delete export directory – Event 18300″ }
    $temp1 = (Get-Date)
    $temp2 = “Hyper-V Export failed to delete export directory – Event 18300″
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    }
    }
    else
    {
    [int] $Eventlogstatus = “1″
    { Write-Host (Get-Date) “Keine Hyper-V Exportfehler” }
    $temp1 = (Get-Date)
    $temp2 = “Keine Hyper-V Exportfehler”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    }
    }

    if ($verbose -eq $true) { Write-Host (Get-Date) “Ueberpruefung auf Sendung einer Status-Mail” }
    $temp1 = (Get-Date)
    $temp2 = “Ueberpruefung auf Sendung einer Status-Mail”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append
    ###########################################################################

    if ($statusmail.IsPresent -eq $False)
    { if ($verbose -eq $true) { Write-Host (Get-Date) “Es wird keine Email versendet” }
    $temp1 = (Get-Date)
    $temp2 = “Es wird keine Email versendet”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append }
    else
    ##################################
    # Email versenden mit Status-Log #
    ##################################
    { if ($verbose -eq $true) { Write-Host (Get-Date) “Es wird eine Email versendet” }
    $temp1 = (Get-Date)
    $temp2 = “Es wird eine Email versendet”
    “$temp1 – $temp2″ | Out-File $Logdatei -Append

    ########################################################################
    # Ab hier muessen die persoenlichen Einstellungen konfiguriert werden! #
    ########################################################################

    #{ if ($verbose -eq $true) { Write-Host (Get-Date) “Diese Zeile muss auskommentiert werden, wenn Emailversand erwünscht!” }

    if ($Eventlogstatus -eq “1″)
    {
    #(Get-Credential).password | ConvertFrom-SecureString > MailPW.txt
    $pw = Get-Content D:\Install\Hyper-V_Export\MailPW.txt | ConvertTo-SecureString #Vollständiger Pfad bei Nutzung mit TaskScheduler erforderlich
    $cred = New-Object System.Management.Automation.PSCredential “Login Mailprovider”, $pw

    if ($BackupDate -lt $Backuppfad.LastWriteTime) {
    $StatusSicherung = “Sicherung aktuell.`r`nDer Ordner “+$Backuppfad.name+” ist vom “+$Backuppfad.LastWriteTime+”.” }
    else {
    $StatusSicherung = “Sicherung nicht aktuell, $BackupAlter Tage alt.`r`nDer Ordner “+$Backuppfad.name+” ist vom “+$Backuppfad.LastWriteTime+”.” }

    $mail = @{
    SmtpServer = ‘Mailserver ausgehend’
    Port = 25
    Credential = $cred
    From = ‘Absendermailadresse’
    To = ‘Empfänermailadresse’
    Subject = “Hyper-V Export der VM ‘$VM’ erfolgreich”
    Body = “Anbei das Log der Export-Sicherung `r`n`r`nVM $VM `r`nKunde: $Kunde `r`nServer: $Server `r`nStatus: $StatusVM `r`nAlter: $StatusSicherung”
    Attachments = “$Logdatei”
    }
    Send-MailMessage @mail
    }

    elseif ($Eventlogstatus -eq “2″)
    {
    #(Get-Credential).password | ConvertFrom-SecureString > MailPW.txt
    $pw = Get-Content D:\Install\Hyper-V_Export\MailPW.txt | ConvertTo-SecureString #Vollständiger Pfad bei Nutzung mit TaskScheduler erforderlich
    $cred = New-Object System.Management.Automation.PSCredential “Login Mailprovider”, $pw

    if ($BackupDate -lt $Backuppfad.LastWriteTime) {
    $StatusSicherung = “Sicherung aktuell.`r`nDer Ordner “+$Backuppfad.name+” ist vom “+$Backuppfad.LastWriteTime+”.” }
    else {
    $StatusSicherung = “Sicherung nicht aktuell, $BackupAlter Tage alt.`r`nDer Ordner “+$Backuppfad.name+” ist vom “+$Backuppfad.LastWriteTime+”.” }

    $mail = @{
    SmtpServer = ‘Mailserver ausgehend’
    Port = 25
    Credential = $cred
    From = ‘Absendermailadresse’
    To = ‘Empfängermailadresse’
    Subject = “! Fehler: Hyper-V Export der VM ‘$VM’ nicht erfolgreich”
    Body = “Anbei das Log der Export-Sicherung `r`n`r`nVM $VM `r`nKunde: $Kunde `r`nServer: $Server `r`nStatus: $StatusVM `r`nAlter: $StatusSicherung”
    Attachments = “$Logdatei”
    }
    Send-MailMessage @mail
    }
    }

    ########################
    # Script abgeschlossen #
    ########################

  24. Timo Fritz sagt:

    Habe vergessen, mich für die Vorarbeit von Jan und Nils zu bedanken. Ohne Vorlage hätte ich das nie zum Laufen gebracht. Danke.

    Gruß Timo

  25. Michael sagt:

    Vielen Dank für das super Script.
    Eine Frage habe ich allerdings noch – für eine VM mal eben zu sichern klappt das wunderbar aber wie muss es aussehen wenn ich gerne 10VMs hintereinander
    sichern möchte in einem Script.

    Grüße

  26. [...] vergleichbares Skript für Hyper-V habe ich im Hyper-V Blog der Fa. Rachfahl IT Solutions gefunden. Nebenbei angemerkt: die Website bekommt generell meine uneingeschränkte Empfehlung, wenn [...]

  27. Hallo. Vielen Dank für das Skript und generell für die vielen hilfreichen Informationen in eurem Blog.
    Ich habe das Skript für unsere Zwecke etwas geändert und erweitert. Das Ergebnis und Infos zu Änderungen und Ergänzungen findet ihr hier: http://noltenet.de/2014/02/18/hyper-v-backup-alle-vms-mit-einem-powershell-skript-sichern/
    Vielleicht ist es für den ein oder anderen auch hilfreich…

    Michael

  28. TESTI sagt:

    Hallo zusammen,

    wie genau sicher ich den 2 bestimmte VM´s? :>
    bekomm das irgendwie nicht hin…
    also nicht nur 1 und auch nicht alle vorhandenen VM´s
    sondern nur 2 bestimmte mit Namen

  29. Das hattest du in meinem Blog doch auch schon gefragt… Ich hatte dir übrigens auch geantwortet ;)

    http://noltenet.de/2014/02/18/hyper-v-backup-alle-vms-mit-einem-powershell-skript-sichern/comment-page-1/#comment-1799

    Bei Jans Variante müsstest du das PS1-Skript halt per Batchdatei 2x aufrufen.

  30. TESTI sagt:

    Stimmt, dankeee..wollte aber beide mal testen..
    in deinen blog kann man keine coments mehr schreiben bzw ich nicht…
    fehler = “Achtung: Du hast die datenschutzrechtlichen Hinweise nicht akzeptiert.” der punkt zum akzep wird aber nicht mehr angeboten zumindest bei mir nicht :P

Antworten