Сопоставление сетевого диска без жесткого кодирования буквы диска в командном файле
Мне нужно сопоставить сетевой диск с командным файлом, но я не хочу указывать букву диска.
Пакетный файл используется как часть процесса развертывания; Я вызываю командный файл из 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
7 ответов
Если у вас нет нескольких сетевых ресурсов, подключенных одновременно, вы можете сделать 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
Я использую это, чтобы позволить 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
Некоторые могут найти следующий пакетный файл полезным.
Он не зависит от внешних программ.
Пакетный файл содержит функцию :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
Возможным решением является применение 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%`.
Хорошо... это не может быть гламурно, но именно так я сейчас и делаю; базовый подход попытки поймать. Попробуйте подключить диск и, если он используется, перейдите к следующему шагу. Я проиллюстрировал это всего двумя попытками, но нетрудно расширить его до 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
Самый простой метод:
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>
@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
Это позволяет избежать второго вызова net по каналу find.
Вы также можете расширить это, чтобы вместо прямого вызова 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
Подпрограмма разбора здесь не очень полезна и только иллюстрирует концепцию.