I currently use DISKSHADOW to remove shadow copies from our Hyper-V servers. To do this I have to log onto the server but psexec doesn't work.

psexec \\hyper-v-server diskshadow
The handle is invalid.


I think vssadmin works doing the above, but I'd like to script this with PowerShell and slectively remove the shadow copies. Neither of these tools provide usable output in PowerShell.

I've done a bit of research but not found any way to query snapshots with PowerShell, either locally or remotely. I imagine doing this will involve use of the Get-WMIObject CMDlet to query the relevant info from WMI, but I can only find the Win32_ShadowCopy.Create() method.

EDIT: To be clear, what I would like are objects I can manipulate using PowerShell.

-

You can use the Get-WMIObject cmdlet to remotely remove shadow copies. The example below demonstrates how it might work. It should be noted that the Get-WMIObject cmdlet returned a null object in the case where there were not any remote shadow copies available. This means that might still need a combination of PowerShell remoting and the vssadmin tool to remotely create shadow copies.

On the target server (from an elevated command prompt), let's first create a shadow copy so that one is available:

vssadmin create shadow /for=c:


From the management server:

$shadowCopies = Get-WMIObject -Class Win32_ShadowCopy -Computer <TARGET SERVER NAME>$shadowCopies | % {$_.DeviceObject} # Lists out just the names of the copies$shadowCopies | Get-Member -View All # Lists all members even hidden ones such as "delete"
$shadowCopies[0].Delete() # Deletes the first shadow copy when more than one exists$shadowCopies.Delete()               # Works when only a single shadow copy exists

-
Thanks, I'll give that a try and get back to you. – john Jul 30 '13 at 19:40
It looks perfect. I didn't see the Delete() method listed in this article msdn.microsoft.com/en-us/library/aa394428(v=vs.85).aspx. Presumably this method is inherited from somewhere? – john Jul 31 '13 at 6:52
+1. I was exploring the very same path as @tchester, when $shadowCopies[0] | Get-Member -Force did not contain .Delete() I started looking elsewhere. This is a great answer, I'd love to here where .Delete() is inherited from and why it's not "shown". – jscott Aug 1 '13 at 11:25 I see now. $shadowCopies[0].GetType() is ManagementObject, which does provide .Delete() -- still not sure why it wouldn't be shown with Get-Member. – jscott Aug 1 '13 at 11:35
One more try: \$shadowCopies[0] | Get-Member -Force -View All will show .Delete(). Guess you learn something new everyday. :) – jscott Aug 1 '13 at 12:01

You can do this remotely with diskshadow. To accomplish this, write a batch file containing the wanted commands and place it somewhere on the target server, then: psexec \\remotehost diskshadow /s C:\path\to\script.bat. You can also use a network location for the path.

-
Thanks @NathanC. I was aware of this also, but I don't like the idea of having to maintain the batch files on each of our hosts. It just feels a bit "hacky". – john Jul 25 '13 at 14:44
You can specify a remote path so you only have to have a single batch file. – Nathan C Jul 25 '13 at 14:48