【问题标题】:batch and for each entry批处理和每个条目
【发布时间】:2018-05-04 09:06:07
【问题描述】:

我们需要一个批处理脚本来查看哪些映射已经处于活动状态,删除映射并重新映射一次,但使用新密码。

我有以下代码示例:

@echo off
set server=srv1

for /f "tokens=1,2*" %%a in ('wmic logicaldisk get Caption^, providername^| find /I "%server%"')  do ( 
    for /f "tokens=1,2*" %%d in ("%%a") do ( 
        echo net use %%a /del 
        for /f "tokens=1,2*" %%e in ("%%a", "%%b") do (
            echo net use %%a %%b /user:dom/uid1 pwd
        )
    )
)        

问题是我需要先删除所有映射,然后再进行所有重新映射。

我当前的代码会:删除、重新映射、删除、重新映射。

有人可以帮我写代码示例吗?

【问题讨论】:

  • 你几乎运行了 3 个循环,可以用一个循环完成。
  • 怎么回事?
  • 在下面试试我的答案。
  • 请在此处具体说明。您要检查所有映射的驱动器并重新映射它们,还是要指定单个映射并重新映射?
  • 我建议您从运行以下命令开始,WMIC NetUse Get LocalName,RemoteName,UserName 这有望为您提供重新映射所需的解析信息。您当然可以尝试在批处理文件For 循环中使用它来将信息保存为变量。一个未经测试的例子可能是('WMIC NetUse Where "RemotePath Like '\\\\srv1\\%%' And UserName='dom\\uid1'" Get LocalName^,RemotePath^|Find /V ""'),但你可能不得不用它来输出你需要的东西!

标签: batch-file for-loop wmic


【解决方案1】:

要做你想做的事,你需要存储当前的映射。我会在类似数组的环境变量中执行此操作,例如 $MAP[1]$MAP[2]。由于Caption 属性似乎总是​​一个驱动器号加上一个冒号,而ProviderName 属性似乎总是​​一个UNC 路径,变量$MAP[1] 可以包含类似<Caption>|<ProviderName> 的内容。

所以让我们建立两个独立的循环,第一个执行删除和数据存储,第二个执行重新映射活动——例如:

@echo off
set "SERVER=srv1"

rem // Initialise index counter:
set /A "COUNT=0"
rem /* Capture output of the `wmic` command line that is filtered by a `where` clause;
rem    this returns only the drives, filtered for network drives (`DriveType=4`);
rem    two nested loops avoid text conversion artefacts like orphaned CR marks: */
for /F "delims=" %%K in ('
    wmic LogicalDisk where "DriveType=4 and ProviderName like '\\\\%SERVER%\\%%'" get DeviceID /VALUE
') do for /F "tokens=1* delims==" %%I in ("%%K") do (
    rem /* Capture output of the `wmic` command line that returns the mapping target
    rem    that corresponds with the current drive: */
    for /F "delims=" %%G in ('
        wmic LogicalDisk where "DeviceID='%%J'" get ProviderName /VALUE
    ') do for /F "tokens=1* delims==" %%E in ("%%G") do (
        rem // Increment index counter:
        set /A "COUNT+=1"
        rem // Revert handling of `&` by `wmic`, hence replace `&` by `&`:
        set "NAME=%%F" & call set "NAME=%%NAME:&=&%%"
        rem /* Store current mapping into array-like variable;
        rem    `call` and double-`%` in `%%COUNT%%` are necessary as `COUNT` is modified
        rem    and read within the same block of code (`%COUNT%` would return `0`): */
        call set "$MAP[%%COUNT%%]=%%J|%%NAME%%"
        rem // Delete the current mapping:
        ECHO net use %%J /DELETE
    )
)

rem // Loop over all array elements:
for /F "tokens=1-2* delims=|=" %%H in ('2^> nul set $MAP[') do (
    rem // Establish remapping with new user data:
    ECHO net use %%I "%%J" pwd /USER:dom/uid1
    rem // Delete handled array element:
    set "%%H="
)

当然,您首先需要设置和调整您的过滤器变量SERVER(用于where 子句,它替换了您的find 命令)。我将搜索字符串更改为\\%SERVER%\,因此仅匹配完整的服务器名称。

这种方法可以正确处理包含 SPACEs 和 & 符号 (&) 的网络路径。

要实际删除和重新映射远程路径,请删除大写的ECHO 命令。

【讨论】:

  • 感谢您在没有任何理由的情况下投反对票!!
  • 忘记我的帖子!!是我的错! aschipfl 的代码 100% 有效!非常感谢您的帮助,一切正常。 wrbrgds AxelF
  • 好的,非常感谢您删除 cmets,下次我会努力做得更好。另一个问题,如果目录路径中有一个空格,如\\srv1\shared folder,会发生什么?非常感谢大家!
  • 如果出现空格,比如\\srv1\shared folder,脚本只使用\\srv1\shared;告诉我你是否也需要处理空格,然后我会相应地更新脚本......
  • 是的,请,确实我们有一个目录,其中有一个空格。我试图将代码从 for /F "tokens=1,2" 更改为 for /F "tokens=1,2*" 并将 call set "$MAP[%%COUNT%%]=%%I|%%J" 添加到 call set "$MAP[%%COUNT%%]=%%I|%%J %%K" 以显示完整路径,但随后我有带空格的引号 :-(
【解决方案2】:

非常感谢 aschipfl! Scipt 工作得非常好!如果连接到多个域,我已经添加了一个关于cmdkey 的部分来处理用户/密码。最后这里是我的compl scipt:

@echo off
::# ------------------------------------------------------------------
::# specify Server Name (FQDN or IP Adresse)
::# IP: 10.0.0.1
::# FQDN: srv1.foo.bar
::# ------------------------------------------------------------------
set SERVER=10.0.0.1
::#
::# ------------------------------------------------------------------
::# delete old mappings for Server
::# ------------------------------------------------------------------
rem // Initialise index counter:
set /A "COUNT=0"
rem /* Capture output of the `wmic` command line that is filtered by a `where` clause;
rem    this returns only the drives, filtered for network drives (`DriveType=4`);
rem    two nested loops avoid text conversion artefacts like orphaned CR marks: */
for /F "delims=" %%K in ('
    wmic LogicalDisk where "DriveType=4 and ProviderName like '\\\\%SERVER%\\%%'" get DeviceID /VALUE
') do for /F "tokens=1* delims==" %%I in ("%%K") do (
    rem /* Capture output of the `wmic` command line that returns the mapping target
    rem    that corresponds with the current drive: */
    for /F "delims=" %%G in ('
        wmic LogicalDisk where "DeviceID='%%J'" get ProviderName /VALUE
    ') do for /F "tokens=1* delims==" %%E in ("%%G") do (
        rem // Increment index counter:
        set /A "COUNT+=1"
        rem // Revert handling of `&` by `wmic`, hence replace `&` by `&`:
        set "NAME=%%F" & call set "NAME=%%NAME:&=&%%"
        rem /* Store current mapping into array-like variable;
        rem    `call` and double-`%` in `%%COUNT%%` are necessary as `COUNT` is modified
        rem    and read within the same block of code (`%COUNT%` would return `0`): */
        call set "$MAP[%%COUNT%%]=%%J|%%NAME%%"
        rem // Delete the current mapping:
        net use %%J /DELETE
        cmdkey /delete:%SERVER%
    )
)
::#
::# ------------------------------------------------------------------
::# Get User Information
::# ------------------------------------------------------------------
set /p U-ID=Bitte U-ID eingeben: 
set /p Pwd=Bitte das NEU vergebene Passwort eingeben: 
::#
::# ------------------------------------------------------------------
::# New mappings for Server
::# ------------------------------------------------------------------
rem // Loop over all array elements:
for /F "tokens=1-2* delims=|=" %%H in ('2^> nul set $MAP[') do (
    rem // Establish remapping with new user data:
    cmdkey /add:%SERVER% /user:%U-ID%@foo.bar /pass:%PWD%
    net use %%I "%%J" /PERSISTENT:YES
    rem // Delete handled array element:
    set "%%H="
)

当然,cmdkey 会运行一段时间,但这没关系。 非常感谢您的帮助! Beste 重新毕业 AxelF

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-17
    • 1970-01-01
    • 2019-05-18
    • 1970-01-01
    • 2018-12-05
    相关资源
    最近更新 更多