windows 从 powershell 访问卷影复制 (VSS) 快照

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14207788/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 10:10:21  来源:igfitidea点击:

Accessing Volume Shadow Copy (VSS) Snapshots from powershell

windowspowershellvolume-shadow-service

提问by jordanm

I am attempting to create and access a Volume Shadow Copy snapshot using the Windows Power Shell in Windows 7. I found that I can create snapshots using the following via a previous superuser question:

我正在尝试使用 Windows 7 中的 Windows Power Shell 创建和访问卷影复制快照。我发现我可以通过之前的超级用户问题使用以下方法创建快照:

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

I am unable to find any documentation indicating that it is possible to set a shadow copy to "Exposed" so that it can be mapped to a drive letter using WMI. An articlelinked in the same question shows a hack using a junction to access the snapshot.

我找不到任何文档表明可以将卷影副本设置为“公开”,以便可以使用WMI. 同一问题中链接的一篇文章展示了使用联结访问快照的黑客攻击。

When I try to access the symlink, I get the following:

当我尝试访问符号链接时,我得到以下信息:

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

Attempting to access the snapshot directly gives the following:

尝试直接访问快照会显示以下内容:

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

How can I access a VSS snapshot from a powershell script?

如何从 powershell 脚本访问 VSS 快照?

回答by Ansgar Wiechers

How did you create the symlink? As outlined in that article, you have to specify the device path with a trailing backslash:

你是如何创建符号链接的?如该文章所述,您必须使用尾部反斜杠指定设备路径:

$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"

After this, I was able to access the shadow copy mounted to C:\shadowcopyjust fine.

在此之后,我能够访问安装的卷影副本C:\shadowcopy就好了。

To unmount the shadow copy call $s2.Delete(), as @KeyszerS pointed out in the comments.

$s2.Delete()如@KeyszerS 在评论中指出的那样,卸载 shadow copy call 。

回答by JJ Fullmer

So with the information provided here and the official microsoft documentation here https://docs.microsoft.com/en-us/previous-versions/windows/desktop/vsswmi/create-method-in-class-win32-shadowcopyI created a couple powershell functions/cmdlets that solve this problem. Random note, as of powershell 5 new-item has the itemType of symbolicLink but when I tried to make one with the target being the shadow snapshot it fails saying the path doesn't exist, so the mklink tool is still the way to go.

因此,根据此处提供的信息和此处的官方微软文档https://docs.microsoft.com/en-us/previous-versions/windows/desktop/vsswmi​​/create-method-in-class-win32-shadowcopy我创建了一个结合解决此问题的 powershell 函数/cmdlet。随机说明,从 powershell 5 开始,新项目的 itemType 为symbolicLink,但是当我尝试将目标设为阴影快照时,它无法说明路径不存在,因此 mklink 工具仍然是可行的方法。

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;
}

}

}

These could be utilized by copy pasting both functions then running them like this

这些可以通过复制粘贴两个函数然后像这样运行它们来使用

$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.

回答by Andrew Butler

This is because the Invoke-Expressionin the New-ShadowLinkreturns a string. If you modify the line to:

这是因为Invoke-ExpressioninNew-ShadowLink返回一个字符串。如果将该行修改为:

Invoke-Expression -Command "cmd /c mklink /d '$linkPath' '$target'" | Out-Null

it will fix the problem.

它将解决问题。

回答by Daniel Ribera

Try replacing $shadow.Delete()with Remove-CimInstance -InputObject $shadow

尝试更换$ shadow.Delete()删除,CimInstance -InputObject $阴影

This has worked for me

这对我有用

Before I was getting similar error:

在我收到类似错误之前:

$shadow.Delete()was giving me error:

$shadow.Delete()给了我错误:

Error en la invocación del método porque [Microsoft.Management.Infrastructure.CimInstance] no contiene ningún método llamado 'Delete'. En línea: 42 Carácter: 9 + $shadow.Delete(); + ~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (Delete:String) [], RuntimeException + FullyQualifiedErrorId : MethodNotFound

错误 en la invocación del método porque [Microsoft.Management.Infrastructure.CimInstance] no contiene ningún método llamado 'Delete'。En línea: 42 Carácter: 9 + $shadow.Delete(); + ~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (Delete:String) [], RuntimeException +fullyQualifiedErrorId : MethodNotFound