2010-09-15 9 views
13

necesito asignar una unidad de red con un archivo por lotes, pero no quieren para especificar la letra de unidad.Asignar una unidad de red sin codificar una letra de unidad en un archivo por lotes

El archivo se utiliza como parte de un proceso de implementación; Llamo al archivo por lotes desde CruiseControl.Net, el archivo por lotes necesita asignar una ruta UNC que requiere credenciales para autenticarse. A continuación, el archivo por lotes llama al RoboCopy para implementar el sitio web desde el directorio de salida al 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 en el mapa. No quiero volver a usar letras 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 

Respuesta

28

Si no dispone de varios recursos compartidos de red conectados simultaneamente, puede hacer net use * asignar una letra de unidad gratuita para usted. Luego puede usar 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. Luego se mapea de forma anónima, solo por su ruta UNC remota. De esta forma, también puede eliminar la asignación especificando solo 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 
+0

Hay es una posibilidad de múltiples recursos compartidos de red conectados simultáneamente, de lo contrario, siempre podría asignar Z: o una letra codificada por proyecto. net use */delete también liberará TODOS los recursos compartidos conectados y eso sería un problema en el servidor –

+0

@Simon Martin: ver mi respuesta actualizada. –

+0

eso es mucho mejor que mi solución :) –

2

Ok ... esto podría no ser atractivo pero esta es la forma en que estoy haciendo esto ahora; un enfoque de captura básica. Intente mapear una unidad y, si está en uso, vaya al siguiente paso. Lo he ilustrado con solo 2 intentos, pero no es difícil extenderlo a 4, 10 o más letras de unidad.

Sí que ofende mi sensibilidad de programación, no me gusta el La repetición de código. Lamentablemente, no sé cómo podría pasar la ruta y las credenciales en el archivo por lotes, ya que no lo llamo yo 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 
10

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 
5

Algunos pueden encontrar el siguiente archivo por lotes útil.

No se basa en programas externos.

El archivo por lotes contiene una función :freedrive, que encuentra una letra de unidad libre y lo devuelve en una variable. También detecta correctamente las unidades ópticas que no tienen medios que ocupan 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 
+0

Me gusta este enfoque; no "verificar para ver qué está disponible y usarlo" sino "usarlo y ver si funcionó". – Ben

0

método más simple:

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

Pushd automáticamente asignarán una unidad de red a una letra disponible, y popd lo eliminará. Son comandos internos de CMD; el uso de rutas UNC requiere extensiones habilitadas. por lotes de ejemplo:

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

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> 
+0

No hay forma de definir credenciales según lo requiera OP. –

+0

@thomas: Solo 2 de las 6 respuestas aquí hoy ilustran el uso de credenciales, sin embargo, ¿esta es la única respuesta que merece un voto negativo? El uso de pushd en lugar de un bucle For es mucho más directo y simple, por la parte del problema al que se dirige. –

+1

Las otras respuestas usan el comando 'net'. Aunque no ilustran cómo usar las credenciales, al menos es posible. –

0

@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 Net hilo hallazgo.

También puede ampliar esto para que, en lugar de llamar a set netdrive directamente, lo haga en una subrutina. Esto le permite hacer más comprobaciones o procesamientos 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 no es muy útil y solo ilustra el concepto.

1

Una posible solución es aplicar la pushd command a una ruta UNC que existe a ciencia cierta, por lo que una letra de unidad temporal se crea que los puntos de 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 comando popd debe ser utilizado 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%`. 

La variable COMPUTERNAME y la proporción \\%COMPUTERNAME%\ADMIN$ debe existir en todos los sistemas Windows modernos (basados ​​en NT).


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