How to find and open previous versions of a folder programmatically (using PowerShell, WMI, etc)?
Solution 1
The volrest
utility, available from the
Windows Server 2003 Resource Kit Tools,
can be used to list the previous versions of a folder.
It worked for me on Windows 7 and should still work on Windows 8.
Just be careful with your parameters, since it can also restore previous versions.
An example of use (from the below-quoted link):
C:\>volrest "\\test220\reports\Annual Reports 2004\doc.4.rtf"
VOLREST 1.1 - Previous Version command-line tool
(C) Copyright 2003 Microsoft Corp.
Searching previous versions on \\test220\reports\annual report 2004\doc.4.rtf
07/01/2004 01:28 PM 37,786 \\test220\reports\@GMT-2004.07.01-18.34.35\annual
report 2004\doc.4.rtf
07/01/2004 01:27 PM 37,740 \\test220\reports\@GMT-2004.07.01-18.28.02\annual
report 2004\doc.4.rtf
07/01/2004 11:47 AM 37,690 \\test220\reports\@GMT-2004.07.01-18.24.41\annual
report 2004\doc.4.rtf
3 File(s) 113,216 bytes
0 Dir(s)
With the output of this program, maybe used with the /B
parameter for bare format,
you should be able to construct a script that will explore one of the listed versions.
For more info see : Windows Server Hacks: Restoring Shadow Copies Using the Command Line.
Solution 2
Here's an example of how to use volrest
in a batch file to find the path to the newest and oldest shadow copies on a local or remote server. The paths returned can be used directly without the need to use mklink
. Tested locally on Windows Server 2019 and remotely from Windows 10.
:: Proof of concept for finding shadow copy paths on a local or remote server.
:: Requires volrest.exe from the Windows Server 2003 Resource Kit Tools:
:: https://www.microsoft.com/en-us/download/details.aspx?id=17657
@ECHO OFF
SET SERVER=LOCALHOST
:: Loop through output of volrest run against a test folder. Note that volrest returns
:: items in reverse chronological order and skips shadow copies if the folder hasn't
:: changed between shadow copies. I found that the Windows\Temp folder was updated
:: frequently enough for my purposes.
::
:: If we're run after the last shadow copy but BEFORE the Windows\Temp folder has been
:: updated, then volrest won't list the latest shadow copy. We can fix this by writing a
:: dummy file to the Windows\Temp folder first and then deleting it. Uncomment the
:: following two commands if this might be an issue for you.
:: Optional code to force a dummy update to ensure latest shadow copy is found
:: TYPE NUL > \\%SERVER%\C$\Windows\Temp\ShadowCopyFind.tmp
:: DEL \\%SERVER%\C$\Windows\Temp\ShadowCopyFind.tmp
FOR /F "TOKENS=3 DELIMS=\" %%A IN ('volrest.exe /B \\%SERVER%\C$\Windows\Temp*') DO (
IF NOT DEFINED GMT_TOKEN_NEWEST SET GMT_TOKEN_NEWEST=%%A
SET GMT_TOKEN_OLDEST=%%A
)
ECHO Path to Newest Shadow Copy: \\%SERVER%\C$\%GMT_TOKEN_NEWEST%
ECHO Path to Oldest Shadow Copy: \\%SERVER%\C$\%GMT_TOKEN_OLDEST%
Sample output:
Path to Newest Shadow Copy: \\LOCALHOST\C$\@GMT-2020.05.05-16.30.02
Path to Oldest Shadow Copy: \\LOCALHOST\C$\@GMT-2020.03.20-22.30.01
I use this as part of a nightly robocopy
job that I've scheduled to run after my Server's last shadow copy of the day. This lets me leverage the Previous Versions shadow copies my server is already creating, ensures that my robocopy
job doesn't encounter any locked files, and provides a true "point in time" consistency.
Solution 3
Late reply, but I tried volrest
and it doesn't seem to work on Windows 10. As the OP observed, the @GMT-yadayadayada
magic folder doesn't appear until you bring the folder up in Explorer from the Previous Versions tab in Properties.
An approach that has worked for me is to use mklink
. As administrator on the computer/server in question, open a Command Prompt and type vssadmin list shadows
:
C:\WINDOWS\system32>vssadmin list shadows
vssadmin 1.1 - Volume Shadow Copy Service administrative command-line tool
(C) Copyright 2001-2013 Microsoft Corp.
Contents of shadow copy set ID: {5a052a28-96de-4924-b669-9e671b5ce069}
Contained 1 shadow copies at creation time: 4/07/2019 4:31:12 PM
Shadow Copy ID: {aaeab260-fef9-4ddc-9190-78d226de07a7}
Original Volume: (C:)\\?\Volume{010e4355-9f97-4911-99f7-4ef45974b946}\
Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1
Originating Machine: DESKTOPPC.domain.local
Service Machine: DESKTOPPC.domain.local
Provider: 'Microsoft Software Shadow Copy provider 1.0'
Type: ClientAccessibleWriters
Attributes: Persistent, Client-accessible, No auto release, Differential, Auto recovered
Contents of shadow copy set ID: {f2494e05-cb0c-4161-aa67-a545fe562b50}
Contained 1 shadow copies at creation time: 11/07/2019 3:00:16 AM
Shadow Copy ID: {c3e0566b-0b39-4080-b5ae-ca6e2a2c56c4}
Original Volume: (C:)\\?\Volume{010e4355-9f97-4911-99f7-4ef45974b946}\
Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy2
Originating Machine: DESKTOPPC.domain.local
Service Machine: DESKTOPPC.domain.local
Provider: 'Microsoft Software Shadow Copy provider 1.0'
Type: ClientAccessibleWriters
Attributes: Persistent, Client-accessible, No auto release, Differential, Auto recovered
Contents of shadow copy set ID: {aa9f8acb-0a06-4584-9f9e-dee2269b88f3}
Contained 1 shadow copies at creation time: 19/07/2019 3:45:20 AM
Shadow Copy ID: {9e3044a8-19e9-4fa8-82ea-b97a836a71d2}
Original Volume: (C:)\\?\Volume{010e4355-9f97-4911-99f7-4ef45974b946}\
Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy3
Originating Machine: DESKTOPPC.domain.local
Service Machine: DESKTOPPC.domain.local
Provider: 'Microsoft Software Shadow Copy provider 1.0'
Type: ClientAccessibleWriters
Attributes: Persistent, Client-accessible, No auto release, Differential, Auto recovered
Look for the Shadow Copy Volume field, and use the following command to map the one you need to a new folder (in this case, the last one in the list):
C:\>mklink /d C:\vsstest \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy3\
symbolic link created for vsstest <<===>> \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy3\
Make sure you add the trailing backslash as I did above, or it won't work.
You will now have your own magic folder for accessing a previous version of your hard drive's contents:
C:\>dir vsstest
Volume in drive C is Local Disk
Volume Serial Number is DEAD-BEEF
Directory of C:\vsstest
26/06/2018 12:49 PM 1,024 .rnd
01/07/2019 01:01 PM <DIR> apps
20/12/2018 10:51 AM <DIR> ESD
29/05/2019 09:16 PM <DIR> inetpub
29/01/2018 12:33 PM <DIR> Intel
19/03/2019 02:52 PM <DIR> PerfLogs
04/07/2019 04:32 PM <DIR> Program Files
16/07/2019 12:40 PM <DIR> Program Files (x86)
30/05/2019 11:26 AM <DIR> Scripts
14/06/2019 10:46 AM <DIR> temp
16/10/2018 01:12 PM <DIR> Tools
28/05/2019 09:19 AM <DIR> Users
18/06/2019 09:22 AM <DIR> VMs
11/07/2019 03:39 AM <DIR> Windows
1 File(s) 1,024 bytes
14 Dir(s) 107,573,796,864 bytes free
To remove it after you're done, use rmdir
.
Solution 4
$DST_info = Get-WmiObject -Class Win32_TimeZone |select @{n='DST_end';e={get-date ([string]$_.StandardMonth+'/'+$_.StandardDay+'/'+(get-date).year) -f "MM/dd/yy"}},@{n='DST_Start';e={get-date ([string]$_.DaylightMonth+'/'+$_.DaylightDay+'/'+(get-date).year) -f "MM/dd/yy"}}
# DST_end DST_Start
# ------- ---------
# 11/01/20 03/02/20
$shadows = Get-CimInstance -ClassName Win32_ShadowCopy -ComputerName MyFileServer
# $shadows | select installDate
foreach($shadow in $shadows)
{
if ([datetime]$shadow.installdate -ge [datetime]$DST_info.DST_Start -and [datetime]$shadow.installdate -lt [datetime]$DST_info.DST_end) {$offset = 4} else {$offset = 5}
ls ("K:\@GMT-" + (get-date (get-date $shadow.installdate).addhours($offset) -f "yyyy.MM.dd-HH.mm.ss"))
}
Solution 5
I've found a solution using .NET.
I searched and searched for the ability to list previous versions programmatically, but could not find a solution for viewing previous versions on an SMB / CIFS share. Volrest, vssadmin, alphaVss, etc. Even win32_shadowCopy failed because our target machines are netapps. Nothing worked.
Then I found this post that says they can use SMB commands in Perl to view them. If Perl can do it, surely WinAPI could also. FSCTL_SRV_ENUMERATE_SNAPSHOTS
is the SMB command needed.
Finally, I found this DLL created by kenjiuno for .NET. After adding a reference to kenjiuno's DLL, I called it:
Dim s() as String = LibEnumRemotePreviousVersion.PreviousversionOnRemote("\\server\share")
It returned all previous versions as @GMT-blablabla
. Then all you need to do is append the one you want to the end of your UNC path.
No mklink
, no mapping drives, etc. Everything works exactly and simply.
Vladimir Reshetnikov
Updated on September 18, 2022Comments
-
Vladimir Reshetnikov over 1 year
I am running Windows 8 Enterprise x64. When I open
\\localhost\c$
as a network folder, and then using a context menu open the Properties window of a subfolder (e.g.\\localhost\c$\Deploy
as in the example below), there is the Previous Versions tab where I can see a list of available previous versions of the folder, along with corresponding timestamps:
If I select a version and click the Open button, a new Explorer window is opened where I can browse the selected previous version of the folder:
The address bar displays a location where a timestamp (in a long human-readable form) is appended to each folder name. This location, if copied from there, cannot be directly used as a valid path in another Explorer window or a command line tool. But if I open the Properties window of a subfloder, then it displays a location of the subfolder in a form like
\\localhost\c$\@GMT-2013.08.27-04.01.18\Deploy
. This form can actually be used both in the Explorer and the command line:C:\>dir \\localhost\c$\@GMT-2013.08.27-04.01.18\Deploy /s Volume in drive \\localhost\c$ is OSDisk Volume Serial Number is ����-���� Directory of \\localhost\c$\@GMT-2013.08.27-04.01.18\Deploy 04/11/2013 10:53 AM <DIR> . 04/11/2013 10:53 AM <DIR> .. 04/11/2013 10:53 AM <DIR> Tools 0 File(s) 0 bytes Directory of \\localhost\c$\@GMT-2013.08.27-04.01.18\Deploy\Tools 04/11/2013 10:53 AM <DIR> . 04/11/2013 10:53 AM <DIR> .. 04/11/2013 10:53 AM <DIR> x64 0 File(s) 0 bytes Directory of \\localhost\c$\@GMT-2013.08.27-04.01.18\Deploy\Tools\x64 04/11/2013 10:53 AM <DIR> . 04/11/2013 10:53 AM <DIR> .. 08/30/2012 06:10 PM 325,272 ��������.dll 1 File(s) 325,272 bytes Total Files Listed: 1 File(s) 325,272 bytes 8 Dir(s) 70,546,321,408 bytes free
And in PowerShell too:
PS C:\> pushd \\localhost\c$\@GMT-2013.08.27-04.01.18\Deploy PS Microsoft.PowerShell.Core\FileSystem::\\localhost\c$\@GMT-2013.08.27-04.01.18\Deploy> ls -r Directory: \\localhost\c$\@GMT-2013.08.27-04.01.18\Deploy Mode LastWriteTime Length Name ---- ------------- ------ ---- d---- 4/11/2013 10:53 AM Tools Directory: \\localhost\c$\@GMT-2013.08.27-04.01.18\Deploy\Tools Mode LastWriteTime Length Name ---- ------------- ------ ---- d---- 4/11/2013 10:53 AM x64 Directory: \\localhost\c$\@GMT-2013.08.27-04.01.18\Deploy\Tools\x64 Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 8/30/2012 6:10 PM 325272 ��������.dll
It looks like the folder with a magic name
@GMT-2013.08.27-04.01.18
(presumably representing a timestamp in the GMT time zone) behaves as if it actually existed there, except that you cannot discover its existence using thedir
command unless you already know its name. All files and folders below this folder are read-only: nothing can be created, deleted, renamed or changed there (including file/folder attributes and permissions). If you are an administrator, but do not have permissions to view certain files, you cannot change that, unless you first manage to copy a containing folder to a non-readonly location.Question: Is it possible to get the list of versions of a certain folder, like the one shown on the first screenshot, and open one of them in a new Explorer window programmatically (using PowerShell, WMI, WSH, BAT, Win32 API, etc)? Is it possible to get the list of corresponding folders with magic names like
@GMT-2013.08.27-04.01.18
programmatically? -
Kirt Carson over 3 yearsGet-CimInstance -ClassName Win32_ShadowCopy -ComputerName MyFileServer | select InstallDate will provide local time information