使用 WMIC 和 netsh 根据索引命名网络接口

使用 WMIC 和 netsh 根据索引命名网络接口

我有两个英特尔网卡,需要根据它们的索引号进行重命名,WMIC 的优点在于它似乎总是按数字顺序返回索引号,因此我们可以直接获取输出,而无需对结果进行排序或运行任何比较操作。

不幸的是,我遇到了一个问题,如果我在 FOR 循环中使用 netsh 来显示接口信息,并使用索引标记中的变量,它会返回“无效索引”。我认为问题在于在 FOR /F 中使用反引号来切换到命令处理而不是文件处理。希望有人能够指出一个简单的错误或为我尝试做的事情提供更清晰的解决方案。代码如下:

SET INTERFACENAME=LAN1
FOR /F "skip=1 tokens=1 delims=" %%a in (
    'WMIC path Win32_NetworkAdapter where "Manufacturer='Intel'" get index'
) do (
    call :sub1 %%a
)

:sub1
:: %1 = index
FOR /F "skip=2 tokens=1,2 delims=:" %%b in (
    'netsh interface ip show interface index=%index%'
) do (
    if "%%b"=="User-friendly Name" (
        netsh interface set interface name = "%%c" newname = "%INTERFACENAME%" && set INTERFACENAME=LAN2 && exit /b
    )
)

第一个 FOR 循环正确解析并将索引号传递给子例程,但第二个子例程中的 netsh 命令返回无效索引。子例程中的其余代码尚未测试,因此我不确定 INTERFACENAME 变量是否正确更新。理想情况下,整个过程将运行两次,将 WMIC 命令的第一个结果重命名为 LAN1,将 WMIC 命令的第二个结果重命名为 LAN2。

答案1

我能够仅使用 WMIC 重写脚本来查询适当网络接口的信息。

该脚本的工作方式是查询 WMI 以查找 ipenabled 状态设置为 true 的网络适配器。这将剔除所有不是实际以太网适配器的接口。然后,我们存储输出的第一行(实际以太网适配器的最低索引号)并将其传递给第二个 WMI 查询。该查询反过来利用索引号来获取 netconnectionid,即适配器“IE 本地连接 1”的实际配置名称。然后,我们可以将 netconnectionid 传递给 netsh 命令以更改该特定适配器的配置。然后,我们通过 exit /b 将控制权交还给第一个 FOR 循环以提取下一个索引号并再次重复该过程。

通过在 netsh 命令后添加更多 IF / ELSE 比较,可以将其扩展到两个以上的 NIC。开头的 NEWNICNAME 值将是应用于最低索引的名称。IF / ELSE 比较后的 set NEWNICNAME 行将应用于报告的下一个最低索引。超级业余代码如下:

set NEWNICNAME=Internet
FOR /F "skip=1 tokens=1 delims=" %%a in (
    'wmic path Win32_NetworkAdapterConfiguration where 'ipenabled^="true"' get index'
    ) do (
    set index=%%a && Call :sub1
)

:sub1
FOR /F "skip=1 tokens=1 delims=" %%b in (
    'wmic path Win32_NetworkAdapter where index^=%index% get NetConnectionId'
) do (
    set OGNICNAME=%%b
)
netsh interface set interface name=%OGNICNAME% newname=%NEWNICNAME%
if %NEWNICNAME%==InternalLAN (
    GOTO EOL
) else (
    set NEWNICNAME=InternalLAN
)
exit /b

然而,在 XP 上,这存在一个大问题。有关使用 netsh 重命名网络适配器的文档明确指定在 name 和 newname 值周围使用双引号。但是,在未从 Windows XP 的提升的 CMD 提示符运行/调用的批处理文件中执行此操作会破坏命令并返回“具有此名称的接口未在路由器上注册”。不知何故,这个完全相同的命令没有双引号会毫无问题地更改适配器名称。然后问题变成如果 NetConnectionId 返回空格,您的脚本将失败。这种行为在我的实例中实际上是可以接受的,因为我可以将主映像部署到我的机群中,两个 NIC 都重命名为 LAN1/LAN2,而不是带有空格的名称。然后我在实际的金属上执行基于索引的重新配置部署后。

答案2

如果没有延迟变量扩展,我就无法让 Sam Martin 的批处理脚本运行。

下面是一个与此类似的脚本,我用它来将 DNS 服务器设置为特定地址 快速设置DNS

@echo off
setlocal EnableDelayedExpansion
Pushd "%~dp0"

goto start

:Trim
set Params=%*
for /f "tokens=1*" %%a in ("!Params!") do EndLocal & set %1=%%b
exit /b

:exitProg
echo.
echo Operations were completed successfully for any connected network adapters.
echo.
pause
exit

:start 
echo Looking up connected network adapters...
set NICNAME=""

FOR /F "skip=1 tokens=1 delims=" %%a in (
    'wmic path Win32_NetworkAdapterConfiguration where 'ipenabled^="true"' get index'
    ) do (
    set indexMain=%%a
    set indexMainS=!indexMain!
    set index=!indexMainS: =!
    
    set indexTrim=""
    call :Trim indexTrim !index!
    
    if not "!indexTrim!"=="" (
        REM echo Index is !index!
        Call :sub1
    )
)

goto exitProg

:sub1
FOR /F "skip=1 tokens=1 delims=" %%b in (
    'wmic path Win32_NetworkAdapter where index^=%index% get NetConnectionId'
) do (
    set OGNICNAME=%%b
    set NICNAME=!OGNICNAME!
    set NICNAMETRIM=""
    set containerStr=
    call :Trim NICNAMETRIM !NICNAME!
    if not "!NICNAMETRIM!"=="" (
        REM echo calling findstring
        echo !NICNAMETRIM! | findstr /b /l "VirtualBox">temp.txt
        set /p containerStr=<temp.txt
        del temp.txt
        REM echo containerStr is !containerStr!
        if "!containerStr!" == "" (
            echo. 
            echo Network adapter connected to the internet is named "!NICNAMETRIM!"
            echo Calling QuickSetDNS on "!NICNAMETRIM!"
            QuickSetDNS.exe /SetDNS "{IPv4_ONE_ADDR_HERE},{IPv4_TWO_ADDR_HERE}" "!NICNAMETRIM!"
            QuickSetDNS.exe /SetDNS6 "{IPv6_ONE_ADDR_HERE},{IPv6_TWO_ADDR_HERE}" "!NICNAMETRIM!"
        )
    )
)

相关内容