17

我需要使用批处理文件映射网络驱动器,但不想指定驱动器号。

批处理文件用作部署过程的一部分;我从 调用批处理文件CruiseControl.Net,批处理文件需要映射一个需要凭据才能进行身份验证的 UNC 路径。然后批处理文件调用RoboCopy将网站从输出目录部署到目标(并排除一些文件和文件夹)。最后批量删除网络驱动器。

问题是这不是可扩展的,当只有几个项目时这很好,但我们现在有 20 个项目使用这种方法并且正在用完驱动器号来映射。我不想重复使用驱动器号,因为它们可能会发生冲突——这很糟糕。

这是批处理文件的示例:

@echo off
net use x: \\192.168.0.1\Share\wwwroot\MyProject /user:mydomain\myuser MyP455w0rd
robocopy.exe "W:\wwwroot\MyProject" x:\ *.* /E /XO /XD "App_Data/Search" "*.svn" /XF "sitefinity.log" "Thumbs.db" /NDL /NC /NP
net use x: /delete

并格式化为可读性:

@echo off
net use x: \\192.168.0.1\Share\wwwroot\MyProject 
    /user:mydomain\myuser MyP455w0rd
robocopy.exe "W:\wwwroot\MyProject" x:\ *.* /E /XO /XD 
    "App_Data/Search" "*.svn" /XF "sitefinity.log" "Thumbs.db" /NDL /NC /NP
net use x: /delete
4

7 回答 7

35

如果您没有同时连接多个网络共享,您可以net use *为您分配一个空闲的驱动器号。之后,您可以使用robocopy通过其 UNC 路径访问共享并使用net use * /delete.

像这样的东西:

@echo off
net use * \\192.168.0.1\Share\wwwroot\MyProject /user:mydomain\myuser MyP455w0rd
robocopy.exe "W:\wwwroot\MyProject" "\\192.168.0.1\Share\wwwroot\MyProject" *.* /E /XO /XD "App_Data/Search" "*.svn" /XF "sitefinity.log" "Thumbs.db" /NDL /NC /NP
net use * /delete /yes

编辑:

正如我从一些研究中了解到的,您可以简单地映射共享而不分配驱动器号。然后匿名映射,仅通过其远程 UNC 路径。这样,您还可以通过仅指定其远程名称来删除映射。

这应该有效:

@echo off
net use \\192.168.0.1\Share\wwwroot\MyProject /user:mydomain\myuser MyP455w0rd
robocopy.exe "W:\wwwroot\MyProject" "\\192.168.0.1\Share\wwwroot\MyProject" *.* /E /XO /XD "App_Data/Search" "*.svn" /XF "sitefinity.log" "Thumbs.db" /NDL /NC /NP
net use \\192.168.0.1\Share\wwwroot\MyProject /delete
于 2010-09-15T10:03:59.237 回答
11

我用它让 NET 选择一个空闲的驱动器号,然后使用 NET 找出它分配的字母:

net use * \\server\share
for /f "tokens=2" %%i in ('net use ^| find "\\server\share"') do set netdrive=%%i
echo %netdrive% has been mapped
于 2012-01-25T14:19:39.407 回答
6

有些人可能会发现以下批处理文件很有用。

它不依赖外部程序。

批处理文件包含一个函数:freedrive,它找到一个空闲的驱动器号并将其返回到一个变量中。它还可以正确检测没有介质的光驱占用驱动器号。

@echo off
setlocal

call :freedrive mydriveletter && goto :cont
echo ERROR: No free drive letter found.
goto :exit
:cont
echo Found drive letter: %mydriveletter%

goto :exit

rem Finds a free drive letter.
rem
rem Parameters:
rem     %1 = Output variable name.
rem
rem Example:
rem     call :freedrive mydriveletter && goto :cont
rem     echo ERROR: No free drive letter found.
rem     goto :EOF
rem     :cont
rem     echo Found drive letter: %mydriveletter%
:freedrive
setlocal EnableDelayedExpansion
set exitcode=0
set "output_var=%~1"
for %%i in (A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) do (
    set "drive=%%i:"
    rem If 'subst' fails, the drive letter is already in use.
    rem This way we can even detect optical drives that have a drive
    rem letter but no media in them, a case that goes undetected when
    rem using 'if exist'.
    subst !drive! %SystemDrive%\ >nul
    if !errorlevel! == 0 (
        subst !drive! /d >nul
        goto :freedrive0
    )
)
set exitcode=1
set drive=
:freedrive0
endlocal & set "%output_var%=%drive%" & exit /b %exitcode%

:exit
pause
于 2013-12-18T14:42:57.673 回答
2

好吧……这可能不是很迷人,但这就是我现在这样做的方式;一个基本的 try catch 方法。尝试映射驱动器,如果它正在使用中,则转到下一步。我仅通过 2 次尝试就说明了这一点,但将其扩展到 4、10 或更多驱动器号并不难。

是的,它确实冒犯了我的编程敏感性,我不喜欢代码的重复。不幸的是,我不知道如何将路径和凭据传递到批处理文件中,因为我自己不调用它,CruiseControl.net 调用它时不带参数。

@echo off

:START
net use z: \\192.168.0.1\Share\wwwroot\MyProject /user:mydomain\myuser MyP455w0rd
if %ERRORLEVEL% ==2 goto Y
ROBOCOPY HERE
net use z: /delete
exit

:Y
net use y: \\192.168.0.1\Share\wwwroot\MyProject /user:mydomain\myuser MyP455w0rd
if %ERRORLEVEL% ==2 goto W
ROBOCOPY HERE
net use y: /delete
exit

:W
sleep 20
goto START
于 2010-09-15T12:08:52.777 回答
1

最简单的方法:

pushd "\\server\share\wwwroot\My Project"
robocopy . x:\ *.* /E ...etc
popd

Pushd会自动将网络驱动器映射到可用的盘符,popd会删除它。它们是内部 CMD 命令;使用 UNC 路径需要启用扩展。批处理示例:

@echo off
pushd %1
  echo. --- Processing %1 as "%cd%"
  echo. ...
  rem do thing here
  echo. Done.
popd

注意:在这个使用命令行参数的实现中,命令行上的路径必须被引用。

示例会话:

E:\temp>.\demo-pushd.bat "\\server\share\wwwroot\My Project"
 --- Processing "\\server\share\wwwroot\My Project" as "X:\wwwroot\My Project"
    ...
    Done.

E:\temp> net use X:
The network connection could not be found.

More help is available by typing NET HELPMSG 2250.
E:\temp>
于 2015-04-02T17:37:27.073 回答
1

一种可能的解决方案是将pushd命令应用于肯定存在的 UNC 路径,因此会创建一个指向该路径的临时驱动器号。当前目录,即临时驱动器的根目录,可以确定得到盘符。最后,popd必须使用该命令删除临时驱动器号:

pushd "\\%COMPUTERNAME%\ADMIN$"
rem /* Do stuff here with the root of the temporarily created drive
rem    used as the current working directory... */
rem // Store the current drive in variable `DRIVE` for later use:
for /F "delims=:" %%D in ("%CD%") do set "DRIVE=%%D:"
popd
echo The next free drive letter is `%DRIVE%`.

变量COMPUTERNAME和共享\\%COMPUTERNAME%\ADMIN$应该存在于所有现代(基于 NT 的)Windows 系统上。


如果您不希望当前环境因尝试pushd派生空闲驱动器号而暂时“污染”,您可能需要使用以下方法:

for /F "delims=:" %%D in ('
    pushd "\\%COMPUTERNAME%\ADMIN$" ^& ^
        for %%Z in ^(.^) do popd
') do set "DRIVE=%%D:"
echo The next free drive letter is `%DRIVE%`.
于 2017-01-31T18:02:22.720 回答
0

@longneck,我使用这样的东西:

for /f "tokens=2" %%i in ('net use * \\server\share') do (
    if defined netdrive goto :cont
    set netdrive=%%i
)

:cont
echo.%netdrive% has been mapped
pause

net use %netdrive% /d /y
pause

这避免了通过 find 对 net 管道的第二次调用。

您还可以对此进行扩展,以便在子例程中执行此操作,而不是直接调用 set netdrive。这允许您进行更多的错误检查或处理。

for /f "tokens=2" %%i in ('net use * \\server\share') do (
    if defined netdrive goto :cont
    call :parse %%i
)

:parse
if ~%1==%1~ goto :eof
if Z:==%1 (
    set netdrive=%1
)
goto :eof

:cont
echo.%netdrive% has been mapped
pause

net use %netdrive% /d /y
pause

这里的 parse 子例程并不是很有用,只是说明了这个概念。

于 2015-06-26T23:35:05.997 回答