Mapping a network drive without hardcoding a drive letter in a batch file

前端 未结 7 1270
无人及你
无人及你 2020-12-05 19:24

I need to map a network drive with a batch file, but don\'t want to specify the drive letter.

The batch file is used as part of a deployment process; I call the batc

相关标签:
7条回答
  • 2020-12-05 19:46

    If you don't have multiple network shares connected simultaniously, you can make net use * assign a free drive letter for you. Afterwards you can use robocopy to access the share via its UNC path and release any connected share with net use * /delete.

    Something like this:

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

    As I learned from some researches, you can simply map the share without assigning a drive letter. It is then mapped anonymously, only by its remote UNC path. This way you can also remove the mapping by specifiying only its remote name.

    This should work:

    @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 讨论(0)
  • 2020-12-05 19:46

    @longneck, I use something like this:

    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
    

    This avoids the second call to net piped through find.

    You can also expand on this so that instead of calling set netdrive directly, you do it in a subroutine. This allows you to do more error checking or processing.

    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
    

    The parse subroutine here isn't terribly useful and only illustrates the concept.

    0 讨论(0)
  • 2020-12-05 19:47

    Simplest method:

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

    Pushd will automatically map a network drive to an available letter, and popd will remove it. They are internal CMD commands; using UNC paths requires extensions enabled. Batch example:

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

    Note: in this implementation using a command line argument, the path on command line must be quoted.

    Sample 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 讨论(0)
  • 2020-12-05 19:53

    Ok... this might not be glamourous but this is how I'm doing this now; a basic try catch approach. Try to map a drive and if it's in use then goto the next step. I've illustrated this with just 2 attempts, but it's not hard to extend it to 4, 10 or more drive letters.

    Yes it does offend my programming sensibilities, I don't like the repetion of code. Unfortunately I don't know how I could pass the path and credentials into the batch file as I don't call it myself, CruiseControl.net calls it without parameters.

    @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
    
    0 讨论(0)
  • 2020-12-05 19:54

    A possible solution is to apply the pushd command to a UNC path that exists for sure, so a temporary drive letter is created that points to that path. The current directory, namely the root of the temporary drive, can be determined to get the drive letter. Finally, the popd command must be used to delete the temporary drive letter:

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

    The variable COMPUTERNAME and the share \\%COMPUTERNAME%\ADMIN$ should exist on all modern (NT-based) Windows systems.


    If you do not want the current environment to become even temporarily "polluted" by the attempt of pushd to derive a free drive letter, you may want to use the following approach:

    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%`.
    
    0 讨论(0)
  • 2020-12-05 19:58

    Some may find the following batch file useful.

    It does not rely on external programs.

    The batch file contains a function :freedrive, which finds a free drive letter and returns it in a variable. It also correctly detects optical drives that have no media as occupying a drive letter.

    @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 讨论(0)
提交回复
热议问题