psubst: attempt to make virtual drives persistently
Posted: 05 Mar 2020 04:36
DESCRIPTION
Times ago I invented the tool PSUBST being the extended version for the standard SUBST. Both tools allow to associate some paths with virtual drives. So executing the following command we have ability to achieve the particular path in two ways by the path itself and/or by the drive:
Unfortunately these virtual drives are not persistent between the system rebooting. Another lack is that if we need SUBSTed drive on the earliest stage of booting (for example, for services or something else) we can establish SUBSTed drives. Good news that Win (since WinXP till the present) has ability to establish virtual drives. It requires some work with the Registry within the HKLM hive. So the main goal of my tool is to combine the existing functionality of the standard tool SUBST with the Registry handling. Possibility to make virtual drives persistent is turned with the special option /P standing for persistency. For long time it was working fine but sometimes it required higher permissions to update the HKLM hive. Running the tool with elevated privileges solved the issue. Couple days ago I found how to simplify usage of PSUBST -- no needs to run it especially with elevated privileges. It tries to manage them by its own.
STANDARD USAGE EXAMPLES
There is brief usage of the tool.
In fact, the tool mimics to SUBST. So there are no needs to duplicate its help page.
Display SUBSTed drives (in this case it acts absolutely as the original tool SUBST):
EXTENDED USAGE EXAMPLES
Display persistently SUBSTed drives:
Create the persistently SUBSTed drive with the current user privileges:
Create the persistently SUBSTed drive with the elevated privileges:
Delete the persistently SUBSTed drive with the current user privileges:
Delete the persistently SUBSTed drive with the elevated privileges:
Privileges elevation is based on the idea provided by Eureka! in his post SUDO for CMD.
Restore the virtual drive, reading it from the persistency storage (the Registry in fact):
The last example can be useful when:
-- you create a new SUBSTed drive (persistent one and SUBST it for the current session)
-- deleted drive and want to restore it.
Indeed, the following example (with /P or /PF):
is shorter and better than
DOWNLOADS
The latest version of the tool can be found at https://github.com/ildar-shaimordanov/psubst/releases
SOURCE
Times ago I invented the tool PSUBST being the extended version for the standard SUBST. Both tools allow to associate some paths with virtual drives. So executing the following command we have ability to achieve the particular path in two ways by the path itself and/or by the drive:
Code: Select all
subst Z: "C:\Documents and Settings\All Users\Shared Documents"
STANDARD USAGE EXAMPLES
There is brief usage of the tool.
In fact, the tool mimics to SUBST. So there are no needs to duplicate its help page.
Display SUBSTed drives (in this case it acts absolutely as the original tool SUBST):
Code: Select all
psubst
Display persistently SUBSTed drives:
Code: Select all
psubst /p
Code: Select all
psubst Z: "C:\Documents and Settings\All Users\Shared Documents" /p
Code: Select all
psubst Z: "C:\Documents and Settings\All Users\Shared Documents" /pf
Code: Select all
psubst Z: /d /p
Code: Select all
psubst Z: /d /pf
Restore the virtual drive, reading it from the persistency storage (the Registry in fact):
Code: Select all
psubst Z: /p
-- you create a new SUBSTed drive (persistent one and SUBST it for the current session)
-- deleted drive and want to restore it.
Indeed, the following example (with /P or /PF):
Code: Select all
psubst Z: "C:\Documents and Settings\All Users\Shared Documents" /p
psubst Z: /p
Code: Select all
psubst Z: "C:\Documents and Settings\All Users\Shared Documents" /p
psubst Z: "C:\Documents and Settings\All Users\Shared Documents"
The latest version of the tool can be found at https://github.com/ildar-shaimordanov/psubst/releases
SOURCE
Code: Select all
::PSUBST v3.0.1-0-gbbb9804
::
::Associates a path with a drive letter.
::Manages persistently substituted (virtual) drives.
::
::PSUBST [drive1: [drive2:]path] [/P | /PF]
::PSUBST drive1: /D [/P | /PF]
::PSUBST drive1: /P
::
:: drive1: Specifies a virtual drive to which you want to assign a path.
:: [drive2:]path Specifies a physical drive and path you want to assign to
:: a virtual drive.
:: /D Deletes a substituted (virtual) drive.
:: /P Add, delete or display persistent drives.
:: /PF Add or delete persistent drives with elevated privileges.
::
::Type PSUBST with no parameters to display a list of current virtual drives.
::Type PSUBST /P to display a list of persistent virtual drives.
::Type PSUBST drive1: /P to restore a virtual drive from persistency.
@echo off
if "%~1" == "/?" goto :print_usage
if "%~1" == "" (
rem
rem SUBST
rem
subst
goto :EOF
)
if /i "%~1" == "/P" (
rem
rem SUBST /P
rem
setlocal
call :psubst_init
call :psubst_print
endlocal
goto :EOF
)
setlocal
call :psubst_init
call :psubst_check_disk "%~1" || exit /b %ERRORLEVEL%
if /i "%~2" == "/P" (
rem
rem PSUBST X: /P
rem
call :psubst_lookup "%psubst_disk%"
if not defined psubst_persist_path (
echo:%~n0: Drive not persistent
exit /b 1
)
setlocal enabledelayedexpansion
subst "!psubst_persist_disk!" "!psubst_persist_path!"
endlocal
goto :EOF
)
if /i "%~2" == "/D" (
rem
rem PSUBST X: /D ...
rem
set "psubst_reg_op=delete"
set "psubst_path="
) else (
rem
rem PSUBST X: "..." ...
rem
call :psubst_check_path "%~2" || exit /b %ERRORLEVEL%
)
if /i "%~3" == "/P" (
rem
rem PSUBST ... /P
rem
call :psubst_persist "%~3"
) else if /i "%~3" == "/PF" (
rem
rem PSUBST ... /PF
rem
call :psubst_persist "%~3"
) else if defined psubst_path (
rem
rem SUBST X: "..."
rem
subst "%psubst_disk%" "%psubst_path%"
) else (
rem
rem SUBST X: /D
rem
subst "%psubst_disk%" /D
)
endlocal
goto :EOF
:psubst_init
set "psubst_disk="
set "psubst_path="
set "psubst_value="
set "psubst_persist_disk="
set "psubst_persist_path="
set "psubst_reg_op="
set "psubst_regkey=HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices"
goto :EOF
:psubst_check_disk
if not "%~1" == "" for %%d in ( "%~1" ) do if /i "%%~d" == "%%~dd" (
set "psubst_disk=%%~d"
exit /b 0
)
echo:%~n0: Invalid parameter: %~1
exit /b 1
:psubst_check_path
if /i "%~1" == "/D" (
set "psubst_reg_op=delete"
set "psubst_path="
exit /b 0
)
if not "%~1" == "" for %%f in ( "%~1\." ) do if exist %%~sf\nul (
set "psubst_reg_op=add"
set "psubst_path=%%~ff"
exit /b 0
)
echo:%~n0: Path not found: %~1
exit /b 1
:psubst_persist
call :psubst_lookup "%psubst_disk%"
if /i "%psubst_reg_op%" == "add" if defined psubst_persist_disk (
echo:%~n0: Drive already SUBSTed persistently
exit /b 1
)
if /i "%psubst_reg_op%" == "delete" if not defined psubst_persist_disk (
echo:%~n0: Drive not SUBSTed persistently
exit /b 1
)
set "psubst_value="
if /i "%~1" == "/PF" (
call :psubst_persist_reg_sudo
) else (
call :psubst_persist_reg
)
call :psubst_lookup "%psubst_disk%"
if /i "%psubst_reg_op%" == "add" if not defined psubst_persist_disk (
echo:%~n0: Unable to add persistently SUBSTed drive
exit /b 1
)
if /i "%psubst_reg_op%" == "delete" if defined psubst_persist_disk (
echo:%~n0: Unable to delete persistently SUBSTed drive
exit /b 1
)
goto :EOF
:psubst_persist_reg
if defined psubst_path set "psubst_value=/t REG_SZ /d "\??\%psubst_path%""
reg %psubst_reg_op% "%psubst_regkey%" /v %psubst_disk% %psubst_value% /f >nul
goto :EOF
rem Based on the solution suggested in this thread:
rem https://www.dostips.com/forum/viewtopic.php?f=3&t=9212
:psubst_persist_reg_sudo
if defined psubst_path set "psubst_value=/t REG_SZ /d \"\??\%psubst_path%\""
reg add "HKCU\Software\Classes\.elevate\shell\runas\command" /ve /d "cmd.exe /c start reg %psubst_reg_op% \"%psubst_regkey%\" /v %psubst_disk% %psubst_value% /f >nul" /f >nul
type nul > "%TEMP%\%~n0.elevate"
"%TEMP%\%~n0.elevate"
del /q "%TEMP%\%~n0.elevate"
reg delete "HKCU\Software\Classes\.elevate" /f >nul
goto :EOF
:psubst_print
setlocal
call :psubst_lookup
endlocal
goto :EOF
:psubst_lookup
set "psubst_persist_disk="
set "psubst_persist_path="
for /f "tokens=1,2,*" %%a in ( 'reg query "%psubst_regkey%"' ) do ^
for /f "tokens=1,* delims=\\" %%k in ( "%%~c" ) do ^
if "%%k" == "??" if "%~1" == "" (
echo:%%~a\: =^> %%~l
) else if /i "%~1" == "%%~a" (
set "psubst_persist_disk=%%~a"
set "psubst_persist_path=%%~l"
goto :EOF
)
goto :EOF
:print_usage
for /f "tokens=* delims=:" %%s in ( 'findstr "^::" "%~f0"' ) do echo:%%s
goto :EOF