映射网络驱动器而不在批处理文件中硬编码驱动器号

发布于 2024-09-19 08:12:59 字数 865 浏览 9 评论 0原文

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

批处理文件用作部署过程的一部分;我从 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

I need to map a network drive with a batch file, but don't want to specify the drive letter.

The batch file is used as part of a deployment process; I call the batch file from CruiseControl.Net, the batch file needs to map a UNC path which requires credentials to authenticate. Then the batch file calls RoboCopy to deploy the website from the output directory to the destination (and excludes some files and folders). Finally the batch deletes the network drive.

The problem is that this isn't scalable, it's fine when there are only a few projects but we've now got 20 projects using this approach and are running out of drive letters to map. I don't want to re-use drive letters as they could collide - which would be bad.

This is an example of the batch file:

@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

and formatted for readability:

@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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

粉红×色少女 2024-09-26 08:12:59

如果您没有同时连接多个网络共享,您可以让 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

If you don't have multiple network shares connected simultaniously, you can make net use * assign a free drive letter for you. Afterwards you can use robocopy to access the share via its UNC path and release any connected share with net use * /delete.

Something like this:

@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

EDIT:

As I learned from some researches, you can simply map the share without assigning a drive letter. It is then mapped anonymously, only by its remote UNC path. This way you can also remove the mapping by specifiying only its remote name.

This should work:

@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
月亮是我掰弯的 2024-09-26 08:12:59

我使用它让 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

i use this to let NET pick a free drive letter, then use NET to find out what letter it assigned:

net use * \\server\share
for /f "tokens=2" %%i in ('net use ^| find "\\server\share"') do set netdrive=%%i
echo %netdrive% has been mapped
甜柠檬 2024-09-26 08:12:59

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

它不依赖于外部程序。

该批处理文件包含一个函数 :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

Some may find the following batch file useful.

It does not rely on external programs.

The batch file contains a function :freedrive, which finds a free drive letter and returns it in a variable. It also correctly detects optical drives that have no media as occupying a drive letter.

@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
一片旧的回忆 2024-09-26 08:12:59

可能的解决方案是应用 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%`.

A possible solution is to apply the pushd command to a UNC path that exists for sure, so a temporary drive letter is created that points to that path. The current directory, namely the root of the temporary drive, can be determined to get the drive letter. Finally, the popd command must be used to delete the temporary drive letter:

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%`.

The variable COMPUTERNAME and the share \\%COMPUTERNAME%\ADMIN$ should exist on all modern (NT-based) Windows systems.


If you do not want the current environment to become even temporarily "polluted" by the attempt of pushd to derive a free drive letter, you may want to use the following approach:

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%`.
旧城烟雨 2024-09-26 08:12:59

好吧……这可能不那么迷人,但这就是我现在所做的;基本的 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

Ok... this might not be glamourous but this is how I'm doing this now; a basic try catch approach. Try to map a drive and if it's in use then goto the next step. I've illustrated this with just 2 attempts, but it's not hard to extend it to 4, 10 or more drive letters.

Yes it does offend my programming sensibilities, I don't like the repetion of code. Unfortunately I don't know how I could pass the path and credentials into the batch file as I don't call it myself, CruiseControl.net calls it without parameters.

@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
找个人就嫁了吧 2024-09-26 08:12:59

最简单的方法:

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>

Simplest method:

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

Pushd will automatically map a network drive to an available letter, and popd will remove it. They are internal CMD commands; using UNC paths requires extensions enabled. Batch example:

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

Note: in this implementation using a command line argument, the path on command line must be quoted.

Sample session:

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>
一百个冬季 2024-09-26 08:12:59

@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

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

@longneck, I use something like this:

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

This avoids the second call to net piped through find.

You can also expand on this so that instead of calling set netdrive directly, you do it in a subroutine. This allows you to do more error checking or processing.

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

The parse subroutine here isn't terribly useful and only illustrates the concept.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文