web-dev-qa-db-fra.com

Mappage d'un lecteur réseau sans coder en dur une lettre de lecteur dans un fichier de traitement par lots

Je dois mapper un lecteur réseau avec un fichier de commandes, mais je ne souhaite pas spécifier la lettre du lecteur.

Le fichier de commandes est utilisé dans le cadre d'un processus de déploiement. J'appelle le fichier de commandes à partir de CruiseControl.Net. Le fichier de commandes doit mapper un chemin UNC qui nécessite des informations d'identification pour s'authentifier. Ensuite, le fichier de commandes appelle RoboCopy pour déployer le site Web du répertoire de sortie vers la destination (et exclut certains fichiers et dossiers). Enfin, le lot supprime le lecteur réseau.

Le problème est que ce n'est pas évolutif, c'est bien quand il n'y a que quelques projets mais nous avons maintenant 20 projets utilisant cette approche et nous manquons de lettres de lecteur pour mapper. Je ne veux pas réutiliser les lettres de lecteur car elles pourraient entrer en collision - ce qui serait mauvais.

Voici un exemple de fichier de commandes:

@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

et formaté pour la lisibilité:

@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
14
Simon Martin

Si vous n'avez pas plusieurs partages réseau connectés simultanément, vous pouvez faire en sorte que Net Use * attribue une lettre de lecteur libre pour vous. Ensuite, vous pouvez utiliser robocopy pour accéder au partage via son chemin UNC et libérer tout partage connecté avec Net Use * /delete.

Quelque chose comme ça:

@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

MODIFIER:

Comme l'ont appris certaines recherches, vous pouvez simplement mapper le partage sans affecter de lettre de lecteur. Il est ensuite mappé anonymement, uniquement par son chemin UNC distant. De cette façon, vous pouvez également supprimer le mappage en spécifiant uniquement son nom distant.

Cela devrait fonctionner:

@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
31
Frank Bollack

j'utilise ceci pour laisser NET choisir une lettre de lecteur libre, puis utiliser NET pour savoir quelle lettre il a attribuée:

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

Certains trouveront peut-être utile le fichier de commandes suivant.

Il ne repose pas sur des programmes externes.

Le fichier de commandes contient une fonction :freedrive, qui trouve une lettre de lecteur libre et la renvoie dans une variable. Il détecte également correctement les lecteurs optiques sans support occupant une lettre de lecteur.

@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
5
Jelle Geerts

Ok ... ce n'est peut-être pas glamour mais c'est comme ça que je fais ça maintenant; une approche de base try catch. Essayez de mapper un lecteur et s'il est utilisé, passez à l'étape suivante. J'ai illustré cela avec seulement 2 tentatives, mais il n'est pas difficile de l'étendre à 4, 10 ou plus de lettres de lecteur.

Oui, cela heurte ma sensibilité à la programmation, je n'aime pas la répétition de code. Malheureusement, je ne sais pas comment je pourrais transmettre le chemin et les informations d'identification dans le fichier de commandes car je ne l'appelle pas moi-même, CruiseControl.net l'appelle sans paramètres.

@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
2
Simon Martin

Une solution possible consiste à appliquer la commande pushd à un chemin UNC qui existe déjà, afin de créer une lettre de lecteur temporaire pointant sur ce chemin. Le répertoire en cours, à savoir la racine du lecteur temporaire, peut être déterminé pour obtenir la lettre du lecteur. Enfin, la commande popd doit être utilisée pour supprimer la lettre de lecteur temporaire:

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 et le partage \\%COMPUTERNAME%\ADMIN$ doivent exister sur tous les systèmes Windows modernes (basés sur NT).


Si vous ne voulez pas que l'environnement actuel soit même temporairement "pollué" par la tentative de pushd d'obtenir une lettre de lecteur libre, vous souhaiterez peut-être utiliser l'approche suivante:

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

Méthode la plus simple:

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

Pushd mappera automatiquement un lecteur réseau sur une lettre disponible et popd le supprimera. Ce sont des commandes internes CMD; L'utilisation de chemins UNC nécessite des extensions activées. Exemple de lot:

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

Remarque: dans cette implémentation utilisant un argument de ligne de commande, le chemin sur la ligne de commande doit être cité.

Exemple de 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>
0
matt wilkie

@ Longneck, j'utilise quelque chose comme ça:

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

Cela évite le deuxième appel à Net Piped à travers Find.

Vous pouvez également développer ceci afin qu'au lieu d'appeler directement set netdrive, vous le fassiez dans un sous-programme. Cela vous permet d’effectuer plus de vérifications ou de traitement des erreurs.

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

Le sous-programme d'analyse ici n'est pas très utile et illustre uniquement le concept.

0
Ryan Beesley