ShadowCopyHandling.psm1
function Get-ShadowCopy { <# .SYNOPSIS Show all Shadow Copies .DESCRIPTION Shows all Shadow Copies on a system .NOTES A function for each message type is present so addition tasks can be competed when a message of a specific type is written. Copyright (C) MosaicMK Software LLC - All Rights Reserved Unauthorized copying of this application via any medium is strictly prohibited Proprietary and confidential Written by MosaicMK Software LLC (contact@mosaicmk.com) By using this software you agree to the following: Agreement Permission is hereby granted, free of charge, to any person or organization obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software and the rights to use and distribute the software so long a no licensing and or documentation files are remove, revised or modified the Software is furnished to do so, subject to the following conditions: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Contact: Contact@MosaicMK.com Version 1.0.0 .LINK https://www.mosaicmk.com/2019/04/shadow-copy-handling-module.html #> $ShadowCopys = Get-CimInstance -ClassName Win32_ShadowCopy Foreach ($item in $ShadowCopys){ $ID = $item.ID $Shadow = Get-ItemProperty -Path HKLM:\SOFTWARE\ShadowCopyHandling\$ID -ErrorAction SilentlyContinue $ShadowCopy = New-Object -TypeName psobject $ShadowCopy | Add-Member -MemberType NoteProperty -Name DateCreated -Value $Item.InstallDate $ShadowCopy | Add-Member -MemberType NoteProperty -Name ClientAccessible -Value $Item.ClientAccessible $ShadowCopy | Add-Member -MemberType NoteProperty -Name Location -Value $Item.DeviceObject $ShadowCopy | Add-Member -MemberType NoteProperty -Name ID -Value $Item.ID $ShadowCopy | Add-Member -MemberType NoteProperty -Name MountPoint -Value $Shadow.MountPoint $ShadowCopy | Add-Member -MemberType NoteProperty -Name Status -Value $Shadow.Status $ShadowCopy | Add-Member -MemberType NoteProperty -Name Drive -Value $Shadow.Drive $ShadowCopy } } function New-ShadowCopy { <# .SYNOPSIS Create a new shadow copy .DESCRIPTION Create a shadow copy of a volume .PARAMETER Drive The Drive letter of the volume to create a shadow copy of .EXAMPLE New-ShadowCopy -Drive C Creates a shadow copy of the c drive .NOTES Copyright (C) MosaicMK Software LLC - All Rights Reserved Unauthorized copying of this application via any medium is strictly prohibited Proprietary and confidential Written by MosaicMK Software LLC (contact@mosaicmk.com) By using this software you agree to the following: Agreement Permission is hereby granted, free of charge, to any person or organization obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software and the rights to use and distribute the software so long a no licensing and or documentation files are remove, revised or modified the Software is furnished to do so, subject to the following conditions: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Contact: Contact@MosaicMK.com Version 1.0.0 .LINK https://www.mosaicmk.com/2019/04/shadow-copy-handling-module.html #> PARAM( [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] [Alias("DriveLetter","Name")] [String]$Drive ) process{ $Drive = $Drive[0] IF (Get-Volume -DriveLetter $Drive -ErrorAction SilentlyContinue){ $WmiShadowCopyClass = [WMICLASS]"root\cimv2:win32_shadowcopy" $WmiShadowCopyResult = $WmiShadowCopyClass.create("${Drive}:\", "ClientAccessible") $ReturnValue = $WmiShadowCopyResult.ReturnValue $ID = $WmiShadowCopyResult.ShadowID if ($ReturnValue -NE 0) { if ($ReturnValue -lt $NewErrorMessages.Count) {$Message = $NewErrorMessages[$ReturnValue]} else {$Message = "Unknown error $ReturnValue"} Throw "Failed to create a shadow copy of drive ${Drive}: $Message." } New-Item "HKLM:\SOFTWARE\ShadowCopyHandling\$ID" -Force | Out-Null New-ItemProperty HKLM:\SOFTWARE\ShadowCopyHandling\$ID -Name Status -Value "Unmounted" | Out-Null New-ItemProperty HKLM:\SOFTWARE\ShadowCopyHandling\$ID -Name MountPoint -Value $null | Out-Null New-ItemProperty HKLM:\SOFTWARE\ShadowCopyHandling\$ID -Name Drive -Value $Drive | Out-Null } Else {Throw "Cannot find Drive $Drive"} } } function Mount-ShadowCopy { <# .SYNOPSIS Mount a Shadow copy .DESCRIPTION Mount a shadow copy to a symbloic link .PARAMETER ShadowCopyID ID of the shadow copy to mount .PARAMETER MountPoint Path to where the shadow copy will be mounted .EXAMPLE Mount-ShadowCopy -ShadowCopyID "{418D332B-AB85-4865-AC07-7AA3DDBEE46D}" -MountPoint C:\Mount Mounts the shadow copy to C:\mount .NOTES Copyright (C) MosaicMK Software LLC - All Rights Reserved Unauthorized copying of this application via any medium is strictly prohibited Proprietary and confidential Written by MosaicMK Software LLC (contact@mosaicmk.com) By using this software you agree to the following: Agreement Permission is hereby granted, free of charge, to any person or organization obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software and the rights to use and distribute the software so long a no licensing and or documentation files are remove, revised or modified the Software is furnished to do so, subject to the following conditions: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Contact: Contact@MosaicMK.com Version 1.0.0 .LINK https://www.mosaicmk.com/2019/04/shadow-copy-handling-module.html #> PARAM( [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] [Alias("ID","ShadowID")] [string]$ShadowCopyID, [Parameter(Mandatory=$True)] [string]$MountPoint ) IF (Test-Path $MountPoint -ErrorAction SilentlyContinue){Throw "$MountPoint Already exisit"} Else { IF ((Get-ShadowCopy | Where-Object -Property ID -EQ "$ShadowCopyID").Status -eq "mounted"){Throw "$ShadowCopyID is already mounted"} $ShadowCopyPath = "$((Get-ShadowCopy | Where-Object -Property ID -eq "$ShadowCopyID").Location)\" Try {$null = [Win32.SymLink]} Catch { Add-Type @" using System; using System.Runtime.InteropServices; namespace Win32 { public class SymLink { [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, int dwFlags); [DllImport("kernel32.dll")] public static extern uint GetLastError(); public static uint Create(string lpSymlinkFileName, string lpTargetFileName, int dwFlags) { bool done = CreateSymbolicLink(lpSymlinkFileName, lpTargetFileName, dwFlags); if (done) { return 0; } else { return GetLastError(); } } } } "@ } $Error = [Win32.SymLink]::Create($MountPoint,$ShadowCopyPath,1) if ($error) {Throw "Could not create a symbolic link : $_"} If (!(Test-Path "HKLM:\SOFTWARE\ShadowCopyHandling\$ShadowCopyID" -ErrorAction SilentlyContinue)) {New-Item "HKLM:\SOFTWARE\ShadowCopyHandling\$ShadowCopyID" -Force | Out-Null} Set-ItemProperty HKLM:\SOFTWARE\ShadowCopyHandling\$ShadowCopyID -Name Status -Value "Mounted" | Out-Null Set-ItemProperty HKLM:\SOFTWARE\ShadowCopyHandling\$ShadowCopyID -Name MountPoint -Value $MountPoint | Out-Null } } Function Dismount-ShadowCopy{ <# .SYNOPSIS dismount a Shadow copy .DESCRIPTION Dismount a shadow copy from a symbloic link .PARAMETER ShadowCopyID ID of the shadow copy to dismount .EXAMPLE Dismount-ShadowCopy -ShadowCopyID "{418D332B-AB85-4865-AC07-7AA3DDBEE46D}" .NOTES Copyright (C) MosaicMK Software LLC - All Rights Reserved Unauthorized copying of this application via any medium is strictly prohibited Proprietary and confidential Written by MosaicMK Software LLC (contact@mosaicmk.com) By using this software you agree to the following: Agreement Permission is hereby granted, free of charge, to any person or organization obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software and the rights to use and distribute the software so long a no licensing and or documentation files are remove, revised or modified the Software is furnished to do so, subject to the following conditions: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Contact: Contact@MosaicMK.com Version 1.0.0 .LINK https://www.mosaicmk.com/2019/04/shadow-copy-handling-module.html #> PARAM( [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] [Alias("ID","ShadowID")] [string]$ShadowCopyID ) $MountPoint = (Get-ShadowCopy | Where-Object -Property ID -eq "$ShadowCopyID").MountPoint IF (!(Test-path $MountPoint)){Throw "Could not find mount point $MountPoint"} else { if ((Get-Item -Path $MountPoint).Attributes -band [System.IO.FileAttributes]::ReparsePoint){ try { $MountPoint = Resolve-Path $MountPoint [System.IO.Directory]::Delete($MountPoint, $false) | Out-Null Set-ItemProperty HKLM:\SOFTWARE\ShadowCopyHandling\$ShadowCopyID -Name Status -Value "Unmounted" Set-ItemProperty HKLM:\SOFTWARE\ShadowCopyHandling\$ShadowCopyID -Name MountPoint -Value $null } catch {Throw "Failed to dismount $MountPoint : $($_.Exception.Message)"} } else {Throw "There is no Shadow Copy mounted at $MountPoint"} } } Function Remove-ShadowCopy{ <# .SYNOPSIS Removes a Shoadow Copy .DESCRIPTION Removes a shadow copy using the vssadmin .NOTES A function for each message type is present so addition tasks can be competed when a message of a specific type is written. Copyright (C) MosaicMK Software LLC - All Rights Reserved Unauthorized copying of this application via any medium is strictly prohibited Proprietary and confidential Written by MosaicMK Software LLC (contact@mosaicmk.com) By using this software you agree to the following: Agreement Permission is hereby granted, free of charge, to any person or organization obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software and the rights to use and distribute the software so long a no licensing and or documentation files are remove, revised or modified the Software is furnished to do so, subject to the following conditions: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Contact: Contact@MosaicMK.com Version 1.0.0 .LINK https://www.mosaicmk.com/2019/04/shadow-copy-handling-module.html #> Param( [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] [Alias("ID","ShadowID")] [string]$ShadowCopyID, [switch]$Force ) process{ IF (!($Force)){$a = Read-Host "Are you sure you want to remove Shadow copy $ShadowCopyID, This proccess can not be undone (y,n)"}else{$a="y"} IF ($a -like "*y*"){ $ID = (Get-ShadowCopy | Where-Object -Property ID -EQ "$ShadowCopyID").ID if ($ID -eq "$null"){Throw "There is no ShadowCopy with ID $ShadowCopyID"}else{ vssadmin delete shadows /shadow=$ID /quiet | Out-Null IF ($LASTEXITCODE -ne 0){Throw "Could not delete shadow copy"} Remove-Item HKLM:\SOFTWARE\ShadowCopyHandling\$ShadowCopyID -ErrorAction SilentlyContinue -Recurse -Force | out-null } } } } |