Asignar una unidad de red sin codificar una letra de unidad en un archivo por lotes

StackOverflow https://stackoverflow.com/questions/3716422

  •  02-10-2019
  •  | 
  •  

Pregunta

Necesito una unidad de red con un archivo por lotes, pero no quiero especificar la letra de unidad.

El archivo se utiliza como parte de un proceso de implementación; Me llamo el archivo por lotes desde CruiseControl.Net, las necesidades del archivo por lotes para trazar una ruta UNC que requiere credenciales para autenticarse. A continuación, las llamadas de archivos por lotes RoboCopy para desplegar la página web desde el directorio de salida hasta el destino (y excluye algunos archivos y carpetas). Finalmente el lote elimina la unidad de red.

El problema es que esto no es escalable, está bien cuando hay sólo unos pocos proyectos pero ahora Tienen 20 proyectos que utilizan este enfoque y se están quedando sin letras de unidad de mapa. No quiero a las cartas reutilización de unidad, ya que podrían colisionar -. Lo que sería malo

Este es un ejemplo del archivo por lotes:

@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

y formateado para facilitar la lectura:

@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
¿Fue útil?

Solución

Si no se dispone de varios recursos compartidos de red conectados simultaneamente, se puede hacer net use * asignar una letra de unidad libre para usted. Después se puede utilizar robocopy para acceder al recurso compartido a través de su ruta UNC y liberar cualquier recurso compartido conectado con net use * /delete.

Algo como esto:

@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:

Como he aprendido de algunas investigaciones, sólo tiene que asignar el recurso compartido sin asignar una letra de unidad. A continuación, se asigna de forma anónima, sólo por su ruta UNC remoto. De esta manera también se puede quitar la asignación por specifiying sólo su nombre remoto.

Esto debería funcionar:

@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

Otros consejos

Lo utilizo para dejar NET elegir una letra de unidad libre, entonces el uso neto para averiguar qué letra asignada:

net use * \\server\share
for /f "tokens=2" %%i in ('net use ^| find "\\server\share"') do set netdrive=%%i
echo %netdrive% has been mapped

Algunos pueden encontrar el siguiente archivo por lotes útil.

No se basan en programas externos.

El archivo por lotes contiene un :freedrive función, que encuentra una letra de unidad y lo devuelve en una variable. También detecta correctamente las unidades ópticas que no tienen los medios de comunicación como ocupando una letra de unidad.

@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

Ok ... esto podría no ser atractivo pero esta es la forma en que estoy haciendo esto ahora; un enfoque básico intento de captura. Tratar de asignar una unidad y si está en uso entonces goto el siguiente paso. He ilustrado esto con solo 2 intentos, pero no es difícil de extenderlo a 4, 10 o más letras de unidad.

Si se ofende mi sensibilidad de programación, no me gusta el La repetición de código. Por desgracia, no sé cómo podría pasar a la ruta y credenciales en el archivo por lotes, ya que no llamo a mí mismo, CruiseControl.net lo llama sin parámetros.

@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

Una posible solución es aplicar el pushd comando a un UNC camino que existe a ciencia cierta, por lo que se crea una letra de unidad temporal que apunta a ese camino. El directorio actual, es decir, la raíz de la unidad temporal, se puede determinar para obtener la letra de la unidad. Por último, el popd comando debe utilizarse para borrar la letra de unidad temporal:

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

El COMPUTERNAME variable y la cuota de \\%COMPUTERNAME%\ADMIN$ debe existir en todos los sistemas modernos (basados ??en NT) de Windows.


Si no desea que el entorno actual para convertirse incluso temporalmente "contaminado" por el intento de pushd para derivar una letra de unidad, es posible que desee utilizar el siguiente enfoque:

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

método más simple:

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

comandos Pushd le asignará automáticamente una unidad de red a una letra disponible, y popd lo eliminará. Son comandos internos CMD; utilizando rutas UNC requiere habilitadas las extensiones. ejemplo de lote:

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

Nota:. En esta aplicación utilizando un argumento de línea de comandos, el camino de línea de comandos debe ser citado

sesión de ejemplo:

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, utilizo algo como esto:

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

Esto evita la segunda llamada a través de tuberías neta hallazgo.

También puede ampliar esto a fin de que en lugar de llamar directamente netdrive conjunto, lo haces en una subrutina. Esto le permite hacer más cheques o de procesamiento de errores.

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

La subrutina de análisis aquí no es terriblemente útil y sólo ilustra el concepto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top