I use Window's Shell CopyHere method to unzip archives in some batches. It generally works, as shown in the script example below, but gives an error in some cases. In particular, I found it gives an error when unzipping an archive to a special system folder like Downloads, if it was moved by a user to a new location, despite the folder symlink was left by OS in its default location in the user profile, and the user has write permissions for the new location.
Is there a way to work around this limitation or modify the code below without changing its overall batch hybrid approach?
<!-- : Begin batch script
@echo off
set "dir=%temp%" & set "file=%USERPROFILE%\Backup\archive.zip\"
cscript //nologo "%~f0?.wsf" "%dir%" "%file%"
exit /b
----- Begin wsf script --->
<job><script language="VBScript">
set fso = CreateObject("Scripting.FileSystemObject")
Set Ag=Wscript.Arguments
If NOT fso.FolderExists(Ag(0)) Then
fso.CreateFolder(Ag(0))
End If
set objShell = CreateObject("Shell.Application")
set FilesInZip = objShell.NameSpace(Ag(1)).items
objShell.NameSpace(Ag(0)).CopyHere(FilesInZip)
set fso = Nothing
set objShell = Nothing
</script></job>
:: Error if user profile's Downloads folder was moved from default location
\test.bat?.wsf(15, 3) Microsoft VBScript runtime error: Object required: 'objShell.NameSpace(...)'
It appears CopyHere method doesn't support special folder path redirection. If a user changed location of a special Windows folder listed in the Enumerating Special Folders document like My Documents, a simple VBS construct would allow to find current folder and file path:
set objShell = CreateObject("Shell.Application")
set objFolder = objShell.Namespace(&H5&)
set FilesInZip = objShell.NameSpace(Ag(1)).items
objShell.NameSpace(objFolder).CopyHere(FilesInZip)
Otherwise, VBS doesn't offer any method to find current special folder path. The only way I found to get it in a hybrid batch & VBS script is by querying the Registry key HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders. Current .zip file path is then sent as cscript argument using script in question.
For example, if archive.zip to be unzipped to current Downloads folder:
@echo off
setlocal EnableDelayedExpansion
set "key=HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
for /f "tokens=* Skip=2" %%g in ('reg query "%key%" 2^>nul') do (
echo %%g | find /i "Downloads" >nul && for %%o in (%%g) do (
set "disk=%%o" & if exist "!disk:~0,3!" set dir=%%o ))
echo !dir!
K:\Downloads