【问题标题】:UNC paths as current directories in batch file where admin rights are requestedUNC 路径作为请求管理员权限的批处理文件中的当前目录
【发布时间】:2023-03-27 13:09:02
【问题描述】:

我目前正在尝试编写一个批处理文件,该批处理文件会自动创建一个文件夹结构,包括快捷方式。 为了创建快捷方式,我使用需要管理员权限的“mklink”。 我已经使用了这个网站上的代码
(http://winaero.com/blog/how-to-auto-elevate-a-batch-file-to-run-it-as-administrator/) 自动授予我这些权利。

但是,当我在我的机器上本地运行下面的代码时,它工作得非常好,但是当我把它放在一个打算工作的服务器位置时,命令提示符在我做出是/否选择后立即关闭在管理员权限的对话窗口中。 我没有收到错误代码,但我发现它可能与 “CMD 不支持将 UNC 路径作为当前目录”。 我曾尝试使用 pushd 和我在论坛上找到的其他东西来解决此类问题,但现在我的想法已经开始枯竭了。

有没有人知道如何解决这个问题? 提前致谢!

chcp 1252 

::::::::::::::::::::::::::::::::::::::::::::
:: Run as admin
::::::::::::::::::::::::::::::::::::::::::::
@echo off
CLS
ECHO.
ECHO =============================
ECHO The name of the main folder?    
ECHO =============================

:init
setlocal DisableDelayedExpansion
set "batchPath=%~0"
for %%k in (%0) do set batchName=%%~nk
set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs"
setlocal EnableDelayedExpansion

:checkPrivileges
NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )

:getPrivileges
if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges)
ECHO.
ECHO **************************************
ECHO Invoking UAC for Privilege Escalation
ECHO **************************************

ECHO Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%"
ECHO args = "ELEV " >> "%vbsGetPrivileges%"
ECHO For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%"
ECHO args = args ^& strArg ^& " "  >> "%vbsGetPrivileges%"
ECHO Next >> "%vbsGetPrivileges%"
ECHO UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >>      "%vbsGetPrivileges%"
"%SystemRoot%\System32\WScript.exe" "%vbsGetPrivileges%" %*
exit /B

:gotPrivileges
setlocal & pushd .
cd /d %~dp0
if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul  &  shift /1)

::::::::::::::::::::::::::::
::START
::::::::::::::::::::::::::::

::Dialogwindow.
@echo off
title message

echo Skriv nedan^^!
set/p "Projektnamn=>"

:: Creates the folder structure
md "%~dp0"%Projektnamn%

md "%~dp0""%Projektnamn%"/"1. Projektpärm"
md "%~dp0""%Projektnamn%"/"1. Projektpärm"/"1. Tekniska specifikationer"
md "%~dp0""%Projektnamn%"/"1. Projektpärm"/"2. ÄTA,Beställning & Fakturering"
md "%~dp0""%Projektnamn%"/"1. Projektpärm"/"3. Tidplan"
md "%~dp0""%Projektnamn%"/"1. Projektpärm"/"4. Projektmöten"
md "%~dp0""%Projektnamn%"/"1. Projektpärm"/"5. Dagbok"
md "%~dp0""%Projektnamn%"/"1. Projektpärm"/"6. Kvalitet"
:: Genväg enlinjeschema, se kod för genväg

md "%~dp0""%Projektnamn%"/"2. Kretsschema"
md "%~dp0""%Projektnamn%"/"2. Kretsschema"/"1. Konstruktionsunderlag från    kund"

md "%~dp0""%Projektnamn%"/"3. Stationsdokumentation"
md "%~dp0""%Projektnamn%"/"3. Stationsdokumentation"/"1. Enlinjeschema"
md "%~dp0""%Projektnamn%"/"3. Stationsdokumentation"/"2. Blockschema"
md "%~dp0""%Projektnamn%"/"3. Stationsdokumentation"/"3. Förreglingsschema"
md "%~dp0""%Projektnamn%"/"3. Stationsdokumentation"/"4. Ritningsnummer"

md "%~dp0""%Projektnamn%"/"4. Skåpsdokumentation"
md "%~dp0""%Projektnamn%"/"4. Skåpsdokumentation"/"1. Skåpslayout"
md "%~dp0""%Projektnamn%"/"4. Skåpsdokumentation"/"2. Apparatlista"
md "%~dp0""%Projektnamn%"/"4. Skåpsdokumentation"/"3. Förbindningstabell"
md "%~dp0""%Projektnamn%"/"4. Skåpsdokumentation"/"4. Skyltlista & Etiketter"

:: Skapar RELATIVA Genvägarna
mklink /D "%~dp0%Projektnamn%\1. Projektpärm\7. Enlinjeschema" "..\3.     Stationsdokumentation\1. Enlinjeschema"
mklink /D "%~dp0%Projektnamn%\1. Projektpärm\8. Blockschema" "..\3.    Stationsdokumentation\2. Blockschema"
mklink /D "%~dp0%Projektnamn%\1. Projektpärm\9. Förreglingsschema" "..\3. Stationsdokumentation\3. Förreglingsschema"
mklink /D "%~dp0%Projektnamn%\1. Projektpärm\10. Skåpslayout" "..\4. Skåpsdokumentation\1. Skåpslayout"

pause

【问题讨论】:

  • 这不是我所说的minimal, complete and verifiable example。无论如何,您可能正在寻找pushdpopd...
  • 如果您以管理员身份打开 cmd 并从共享运行批处理会发生什么?默认情况下,本地映射的共享在 UAC 模式下不可用
  • @Mofi 当批处理文件存储在我的 C: 驱动器上时,我运行批处理文件,这将带我进入获得管理员权限的对话框窗口,之后我可以写下我的主文件夹和批处理文件创建了文件夹结构,包括快捷方式。另一方面,当我将文件放在 \\server\share\Batch.bat 上并单击批处理文件(这就是我打算运行它的方式)时,命令提示符在对话框窗口后模仿关闭,它不会让我输入我的主文件夹的名称。我希望批处理文件仅位于服务器上。这不可能吗?
  • @LotPings 感谢您的帮助
  • UNC 默认路径默认关闭,因为它们用于使旧程序崩溃。[10] HKEY_CURRENT_USER\Software\Microsoft\Command Processor[10] 处的 Dword 注册表值 DisableUNCCheck 允许默认目录为 UNC。 CD 命令将拒绝更改,但将 UNC 路径放置在默认目录中的 Cmd 的快捷方式中或使用 Start 命令。 start "" /d \\127.0.0.1\C$ "cmd /k"C$ 分享给管理员)。来自我在维基百科的一份贡献。 en.wikipedia.org/wiki/…

标签: batch-file unc


【解决方案1】:

这是为这个任务重写的批处理代码并完整注释:

::::::::::::::::::::::::::::::::::::::::::::
:: Run as administrator
::::::::::::::::::::::::::::::::::::::::::::
@echo off
setlocal EnableExtensions
chcp 1252 >nul
cls

rem Define as target folder path the folder path of this batch file. This can
rem can be a folder on a local drive or on a network drive or even a UNC path.

rem It is also possible to use %CD% instead of %~dp0 to specify as target
rem folder path the current folder on starting this batch file which can
rem be different to batch file folder. But please note that Windows does
rem not support by default running a batch script from a network share
rem using UNC path. This is indicated by Windows with the message:

rem '\\ComputerName\ShareName\FolderName'
rem CMD.EXE was started with the above path as the current directory.
rem UNC paths are not supported.  Defaulting to Windows directory.

rem So on using %CD% and running this batch file from a network share using
rem UNC path the target folder would be %SystemRoot% which is usually the
rem folder C:\Windows which is most likely not wanted as target folder path.

set "TargetFolder=%~dp0"
set "vbsGetPrivileges=%TEMP%\OEgetPriv_%~n0.vbs"

rem The console application NET with parameter FILE can be executed
rem successfully only if the account used for running this batch file
rem has local administrator privileges. See the Microsoft TechNet article
rem https://technet.microsoft.com/en-us/library/bb490702.aspx for details
rem about NET FILE.

rem The output written to handle STDOUT on successful execution is redirected
rem to device NUL to suppress it. The exit code of NET assigned to ERRORLEVEL
rem is in this case 0 indicating a successful execution.

rem But on a failed execution because of not having administrator
rem privileges NET outputs to handle STDERR the two error messages
rem "System error 5 has occurred." and "Access is denied." which
rem are redirected from handle STDERR to device NUL to suppress them.
rem And exit/return code of NET is 1 indicating a failed execution.

rem Read https://technet.microsoft.com/en-us/library/bb490982.aspx
rem for details about using command redirection operators.

%SystemRoot%\System32\net.exe FILE >nul 2>nul
if not errorlevel 1 goto RunMainCode

if "%~1"=="ELEV" (

    rem This condition is just for safety. If the batch file was started
    rem already a second time with ELEV as first parameter and execution
    rem of NET FILE failed nevertheless because of missing permissions,
    rem the batch file outputs an error message, waits for any key press
    rem by the user to make sure that the user had the chance to read the
    rem error message and then exits the batch file processing without
    rem doing anything at all.

    echo %~nx0 should run already with elevated privileges, but it isn't.
    echo/
    echo Press any key to exit %~nx0 without doing anything ...
    pause >nul
    goto :EOF
)

rem This batch file can be started without any parameter result in %* being
rem expanded to nothing which results in environment variable BatchArgs being
rem deleted if already existing or with project name as parameter which must
rem be enclosed in double quotes in case of containing 1 or more spaces.

rem As the batch file needs to be executed once again in a separate command
rem process running as local administrator for full access at least on local
rem machine it is necessary to prepare the parameters/arguments list. Each
rem double quote in the arguments list must be doubled to be correct escaped
rem in the VBScript file.

rem This is necessary as otherwise running this batch file with "My Project"
rem as first parameter would result in execution of the batch file by
rem the Windows Script Host as My Project without the double quotes as
rem arguments for the batch file and therefore the first parameter is on
rem elevated execution "My" instead of "My Project" as it was initially.

rem Many "run as administrator" solutions which can be found in world wide web
rem don't handle parameter strings correct which are enclosed in double quotes
rem because the parameter string has 1 or more spaces or other critical
rem characters requiring enclosing the parameter string in double quotes.

set "BatchArgs=%*"
setlocal EnableDelayedExpansion
if defined BatchArgs set "BatchArgs= !BatchArgs:"=""!"

rem Everything output by the ECHO command lines within the next command block
rem is redirected into the VBScript file created in the folder for temporary
rem files of current user with name of batch file in VBScript file name. This
rem makes it possible that multiple batch files with different names can run
rem at the same time using same code for creating a VBScript file to run the
rem batch file once again as administrator with elevated privileges.

rem For details on ShellExecute parameters see the Microsoft MSDN article
rem https://msdn.microsoft.com/en-us/library/windows/desktop/gg537745.aspx

rem The tricky part is quoting the arguments list correct which should be
rem finally passed to cmd.exe executed from the VBScript. The command process
rem running the batch file with elevated privileges of local administrator
rem should automatically close after execution of batch file finished which
rem is the reason for first argument /C.

rem The second argument is the command to execute by `cmd.exe` which is
rem the batch file name with complete path which must be enclosed in double
rem quotes for safety in case of batch file name or path contains 1 or more
rem spaces. But additionally the batch file itself must be started with at
rem least 2 more arguments.

rem The first argument for the batch file is ELEV which is used as indication
rem to detected if this batch file is already started a second time with via
rem the VBScript using local built-in administrator account.

rem The second argument for the batch file is the target folder path which is
rem either the batch file folder or the current folder on starting this batch
rem file the first time depending or whatever is specified above as target
rem folder path.

rem And last all parameters passed to this batch file on initial run should
rem be also passed to second execution of this batch file under the different
rem environment of local built-in administrator account.

rem This nesting of batch file arguments in command processor arguments written
rem into a VBScript file which requires additionally escaping each double quote
rem within a string with one more double quote results in a strange syntax for
rem the line to write into the VBScript file.

(
    echo Set UAC = CreateObject^("Shell.Application"^)
    echo UAC.ShellExecute "%SystemRoot%\System32\cmd.exe", "/C """"%~f0"" ELEV ""!TargetFolder!""!BatchArgs!""", , "runas", 1
)>"%vbsGetPrivileges%"
endlocal

rem Now the created VBScript file can be executed with Windows Script Host.
rem Then the VBScript file can be deleted as not longer needed and processing
rem of this batch file under current user account ends resulting in returning
rem to command process which results in closing the console window if not
rem executed by cmd.exe started with option /K to keep the console window
rem open like on opening a command prompt window and running this batch
rem file from within the command prompt window.

%SystemRoot%\System32\wscript.exe "%vbsGetPrivileges%"
del "%vbsGetPrivileges%"
goto :EOF


rem Here starts the main code of the batch file which needs to be
rem executed with elevated privileges of a local administrator.

rem First is checked if the first parameter of the batch file is ELEV
rem which indicates that this batch file was started a second time
rem using local administrator account.

:RunMainCode
if "%~1"=="ELEV" (

    rem In this case the second argument is the target folder passed from
    rem initial run to this second run of the batch file. The current
    rem directory is now not anymore the initial current directory, but
    rem %SystemRoot%\System32 has set by Windows on starting a command
    rem process using RunAs and administrator account. This must be taken
    rem into account on further batch file processing.

    rem For this batch file it does not matter what is the current directory
    rem as it is written to work with the target folder defined on starting
    rem the batch file (initially). So there is no need to use  CD /D "%~dp0"
    rem or  PUSHD "%~dp0"  as many "run as administrator" solutions use to
    rem change the current directory to directory of the batch file. There
    rem is also no need for  CD /D "%~2"  or  PUSHD "%~2"  here.

    rem The two additionally added arguments ELEV and the target folder
    rem path are removed from the arguments lists by using twice the
    rem command SHIFT to restore the initial arguments list.

    set "TargetFolder=%~2"
    shift /1
    shift /1
)

setlocal EnableDelayedExpansion

rem Now it is checked if the last character of the target folder path is
rem a backslash character which is not the case when using %CD% and the
rem current directory on starting the batch file is not the root directory
rem of a drive. In this case append a backslash to target folder path.

if not "%TargetFolder:~-1%" == "\" set "TargetFolder=%TargetFolder%\"

rem If this batch file was started (initially) without any parameter string,
rem prompt the batch file user for the project folder name and use the input
rem string without checking if being valid as folder name. Otherwise interpret
rem the first parameter string as project folder name.

if "%~1" == "" (
    echo/
    echo ============================
    echo The name of the main folder?
    echo ============================
    echo/
    set "Projektnamn=:invalid:"
    set /P "Projektnamn=>"
    echo/
) else (
    set "Projektnamn=%~1"
)

rem Create the main project folder and check if this was successful. On an
rem error like such a folder exists already, or the user has no permissions
rem to create this folder, or the folder name contains characters being not
rem valid for a folder name like the default string :invalid: used in case
rem of user just hits RETURN or ENTER instead of entering a folder name,
rem the command MD outputs an appropriate error message. The batch file
rem halts in this case the batch file execution until the user hits any
rem key before exiting without doing anything at all.

md "%TargetFolder%!Projektnamn!"
if errorlevel 1 (
    echo/
    echo Press any key to exit %~nx0 without doing anything ...
    pause >nul
    endlocal
    goto :EOF
)

rem Create the folder structure and the symbolic directory links.
rem The command MD with command extensions enabled as done at top of this
rem batch file creates automatically the entire directory tree if necessary.

md "%TargetFolder%!Projektnamn!\1. Projektpärm\1. Tekniska specifikationer"
md "%TargetFolder%!Projektnamn!\1. Projektpärm\2. ÄTA,Beställning & Fakturering"
md "%TargetFolder%!Projektnamn!\1. Projektpärm\3. Tidplan"
md "%TargetFolder%!Projektnamn!\1. Projektpärm\4. Projektmöten"
md "%TargetFolder%!Projektnamn!\1. Projektpärm\5. Dagbok"
md "%TargetFolder%!Projektnamn!\1. Projektpärm\6. Kvalitet"

:: Genväg enlinjeschema, se kod för genväg
md "%TargetFolder%!Projektnamn!\2. Kretsschema\1. Konstruktionsunderlag från kund"

md "%TargetFolder%!Projektnamn!\3. Stationsdokumentation\1. Enlinjeschema"
md "%TargetFolder%!Projektnamn!\3. Stationsdokumentation\2. Blockschema"
md "%TargetFolder%!Projektnamn!\3. Stationsdokumentation\3. Förreglingsschema"
md "%TargetFolder%!Projektnamn!\3. Stationsdokumentation\4. Ritningsnummer"

md "%TargetFolder%!Projektnamn!\4. Skåpsdokumentation\1. Skåpslayout"
md "%TargetFolder%!Projektnamn!\4. Skåpsdokumentation\2. Apparatlista"
md "%TargetFolder%!Projektnamn!\4. Skåpsdokumentation\3. Förbindningstabell"
md "%TargetFolder%!Projektnamn!\4. Skåpsdokumentation\4. Skyltlista & Etiketter"

:: Skapar RELATIVA Genvägarna
mklink /D "%TargetFolder%!Projektnamn!\1. Projektpärm\7. Enlinjeschema" "..\3. Stationsdokumentation\1. Enlinjeschema" >nul
mklink /D "%TargetFolder%!Projektnamn!\1. Projektpärm\8. Blockschema" "..\3. Stationsdokumentation\2. Blockschema" >nul
mklink /D "%TargetFolder%!Projektnamn!\1. Projektpärm\9. Förreglingsschema" "..\3. Stationsdokumentation\3. Förreglingsschema" >nul
mklink /D "%TargetFolder%!Projektnamn!\1. Projektpärm\10. Skåpslayout" "..\4. Skåpsdokumentation\1. Skåpslayout" >nul
endlocal
endlocal

在使用当前用户帐户或内置本地管理员帐户启动批处理文件时,此批处理文件适用于当前目录,因为所有内容都被写入独立于当前目录的工作。

如果批处理文件存储在使用 UNC 路径打开并通过双击执行的网络共享文件夹中,则当前目录为 %SystemRoot%

如果当前用户没有管理员权限,则当前目录为 %SystemRoot%\System32 以提升的权限第二次运行它。

但是,如果本地管理员帐户对网络共享没有读取和执行权限,cmd.exe 无法直接从网络共享使用 UNC 路径执行批处理文件。

在作为第二行写入 VBScript 文件的长行中,将 /C 替换为 /K 以保持打开在提升到管理员级别后第二次执行批处理文件时打开的控制台窗口,以便能够读取错误消息Windows 命令解释器的输出。

要了解所使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

  • chcp /?
  • cls /?
  • del /?
  • echo /?
  • goto /?
  • if /?
  • md /?
  • mklink /?
  • pause /?
  • rem /?
  • set /?
  • setlocal /?
  • shift /?
  • wscript /?(也可以使用 cscript /?cscript.exe。)

批处理代码的cmets中引用的微软文章:

注意:所有以rem 开头的行在0 个或多个前导空格之后都可以像所有以:: 开头的行一样安全地删除(注释行使用了无效标签)。

【讨论】:

  • 现在我得到了对话窗口,但原来的问题仍然存在,当我在网络驱动器上运行它时,在我为管理员权限做出“是”选择后,命令提示符立即关闭。在本地它工作正常!如果我通过 CMD 运行它,它会说: Ny_mappstruktur.bat 不是内部突击队,也不是外部软件或命令文件。从一开始就是这个问题。
  • @user7305472 将批处理文件提升到管理员级别后使用的内置本地管理员帐户通常对网络中服务器上的公共共享没有任何访问权限。域中的网络管理员帐户通常对域中服务器上的共享具有完全访问权限,但 Windows 内置本地管理员帐户没有。我的测试工作正常,因为共享位于我自己的计算机上,因此本地管理员帐户也可以完全访问此共享。
  • 谢谢!所以你的意思是我不能在服务器上创建文件夹结构,因为我不是网络管理员?我将添加其他信息!
  • 你怎么看?
  • 批处理文件原样也适用于存储在共享文件夹中并使用 UNC 路径启动的批处理文件。但是批处理文件是否有可能在提升到管理员并创建文件夹结构以及符号链接后有权访问共享,这取决于共享的访问权限。另见Permission to make symbolic links in Windows 7?How do I create a link in Windows 7 home premium as a regular user?
猜你喜欢
  • 2013-05-29
  • 1970-01-01
  • 2017-11-24
  • 2015-09-13
  • 1970-01-01
  • 2016-07-30
  • 2013-04-21
  • 1970-01-01
相关资源
最近更新 更多