web-dev-qa-db-fra.com

Accès aux instantanés VSS (Volume Shadow Copy) à partir de Powershell

J'essaie de créer et d'accéder à un instantané de cliché instantané de volume à l'aide de Windows Power Shell dans Windows 7. J'ai constaté que je pouvais créer des instantanés à l'aide des éléments suivants via une précédente question - superutilisateur :

(Get-WmiObject -list win32_shadowcopy).create("C:\","ClientAccessible")

Je ne trouve aucune documentation indiquant qu'il est possible de définir un cliché instantané sur "Exposé" afin qu'il puisse être mappé sur une lettre de lecteur à l'aide de WMI. Un article lié dans la même question montre un piratage utilisant une jonction pour accéder à l'instantané.

Lorsque j'essaie d'accéder au lien symbolique, j'obtiens ce qui suit:

PS C:\Windows\system32> ls C:\shadowcopy
Get-ChildItem : The parameter is incorrect.

At line:1 char:3
+ ls <<<<  C:\shadowcopy
    + CategoryInfo          : ReadError: (C:\shadowcopy:String) [Get-ChildItem], IOException
    + FullyQualifiedErrorId : DirIOError,Microsoft.PowerShell.Commands.GetChildItemCommand

Tenter d'accéder à l'instantané directement donne les éléments suivants:

PS C:\Windows\system32> ls '\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy14'
Get-ChildItem : Paths that begin with \\?\GlobalRoot are internal to the kernel and should not be opened by managed applications.
At line:1 char:3
+ ls <<<<  '\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy14'
    + CategoryInfo          : NotSpecified: (:) [Get-ChildItem], ArgumentException
    + FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.GetChildItemCommand

Comment puis-je accéder à un instantané VSS à partir d'un script PowerShell?

16
jordanm

Comment avez-vous créé le lien symbolique? Comme indiqué dans cet article, vous devez spécifier le chemin du périphérique avec une barre oblique inverse de fin:

$s1 = (Get-WmiObject -List Win32_ShadowCopy).Create("C:\", "ClientAccessible")
$s2 = Get-WmiObject Win32_ShadowCopy | Where-Object { $_.ID -eq $s1.ShadowID }

$d  = $s2.DeviceObject + "\"   # <-- this here

cmd /c mklink /d C:\shadowcopy "$d"

Après cela, j'ai pu accéder au cliché instantané monté sur C:\shadowcopy parfaitement.

Pour démonter l'appel de copie fantôme $s2.Delete(), comme l'a souligné @ KeyszerS dans les commentaires.

24
Ansgar Wiechers

Donc, avec les informations fournies ici et la documentation Microsoft officielle, cliquez ici https://docs.Microsoft.com/en-us/previous-versions/windows/desktop/vsswmi/create-method-in-class-win32-shadowcopy J'ai créé quelques fonctions/applets de commande powershell qui résolvent ce problème. Note aléatoire, à partir de powershell 5, new-item a le type itemTypicLink mais quand je tente d'en créer un avec la cible comme instantané fantôme, il échoue en indiquant que le chemin n'existe pas. L'outil mklink est donc toujours le chemin à parcourir.

function New-ShadowLink {
[CmdletBinding()]
param (
    $linkPath="$($ENV:SystemDrive)\ShadowCopy"
)

begin {
    Write-Verbose "Creating a snapshot of $($ENV:SystemDrive)\"
    $class=[WMICLASS]"root\cimv2:win32_shadowcopy";
    $result = $class.create("$ENV:SystemDrive\", "ClientAccessible");
    Write-Verbose "Getting the full target path for a symlink to the shadow snapshot"
    $shadow = Get-CimInstance -ClassName Win32_ShadowCopy | Where-Object ID -eq $result.ShadowID
    $target = "$($shadow.DeviceObject)\";
}

process {
    Write-Verbose "Creating SymLink to shadowcopy at $linkPath"
    Invoke-Expression -Command "cmd /c mklink /d '$linkPath' '$target'";
}

end {
    Write-Verbose "Created link to shadowcopy snapshot of $($ENV:SystemDrive)\ at $linkPath";
    Write-Verbose "Returning shadowcopy snapshot object"
    return $shadow;
}

}

function Remove-ShadowLink {
[CmdletBinding()]
param (
    $shadow,
    $linkPath="$($ENV:SystemDrive)\ShadowCopy"
)

begin {
    Write-verbose "Removing shadow copy link at $linkPath"
}

process {
    Write-Verbose "Deleting the shadowcopy snapshot"
    $shadow.Delete();
    Write-Verbose "Deleting the now empty folder"
    Try {
        Remove-Item -Force -Recurse $linkPath -ErrorAction Stop;
    }
    catch {
        Invoke-Expression -Command "cmd /c rmdir /S /Q '$linkPath'";
    }
}

end {
    Write-Verbose "Shadow link and snapshot have been removed";
    return;
}

}

Celles-ci pourraient être utilisées en copiant-collant les deux fonctions puis en les exécutant comme ceci

$shadow = New-ShadowLink -Verbose;
ls C:\ShadowCopy # would show snapshot version of c drive
Remove-ShadowLink -shadow $shadow -Verbose;
ls C:\ShadowCopy # will give error as it doesn't exist

$s = New-ShadowLink -verbose
VERBOSE: Creating a snapshot of C:\
VERBOSE: Getting the full target path for a symlink to the shadow snapshot
VERBOSE: Creating SymLink to shadowcopy at C:\ShadowCopy
VERBOSE: Created link to shadowcopy snapshot of C:\ at C:\ShadowCopy
VERBOSE: Returning shadowcopy snapshot object
PS C:\> ls C:\ShadowCopy
    Directory: C:\ShadowCopy
#ommitted my C drive listing, but it would be here
PS C:\> Remove-ShadowLink -shadow $s -Verbose
VERBOSE: Removing shadow copy link at C:\ShadowCopy
VERBOSE: Deleting the shadowcopy snapshot
VERBOSE: Deleting the now empty folder
VERBOSE: Shadow link and snapshot have been removed
PS C:\> ls C:\ShadowCopy
ls : Cannot find path 'C:\ShadowCopy' because it does not exist.
2
JJ Fullmer