Подтвердить что ты не робот

Сопоставление сетевого диска без жесткого кодирования буквы диска в пакетном файле

Мне нужно сопоставить сетевой диск с командным файлом, но не хочу указывать букву диска.

Пакетный файл используется как часть процесса развертывания; Я вызываю командный файл из 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
4b9b3361

Ответ 1

Если у вас нет нескольких общих сетевых подключений, подключаемых одновременно, вы можете сделать 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

EDIT:

Как я узнал из некоторых исследований, вы можете просто сопоставить общий ресурс, не присваивая букву диска. Затем он отображается анонимно, только по его удаленному пути 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

Ответ 2

Я использую это, чтобы позволить 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

Ответ 3

Некоторые могут найти следующий пакетный файл.

Он не полагается на внешние программы.

Пакетный файл содержит функцию :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

Ответ 4

Хорошо... это может быть не гламурно, но вот как я это делаю сейчас; основной подход к подходу к попыткам. Попробуйте сопоставить диск, и если он используется, перейдите к следующему шагу. Я проиллюстрировал это всего двумя попытками, но не трудно расширить его до 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

Ответ 5

Возможное решение - применить 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%`.

Ответ 6

Самый простой способ:

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>

Ответ 7

@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 piped через 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

Подпрограмма parse здесь не очень полезна и только иллюстрирует концепцию.