从 ipconfig 中获取一个未知的 IP,并使用 BATCH 脚本编辑一个未知的 .ini 行

Grab an unknown IP from ipconfig and edit an unknown .ini line with that IP with BATCH script

目前我有一个设置,程序希望我的 LAN IP 将其数据附加到该 LAN IP,并且当我重新启动系统时此 LAN IP 始终是随机的。我的 LAN IP 总是不同,因为我确实使用 VPN,所以每次我更改网络或重新启动时都会有点麻烦,因为我确实需要 运行 程序,更改它,重新启动它。

我有一个脚本可以使用正确的 IP 创建一个变量,因为它始终是第一个 IPv4 地址。我确实在这个网站上找到了它。

set ip_address_string="IPv4 Address"
rem Uncomment the following line when using older versions of Windows without IPv6 support (by removing "rem")
rem set ip_address_string="IP Address"
for /f "usebackq tokens=2 delims=:" %%f in (`ipconfig ^| findstr /c:%ip_address_string%`) do (
    echo Your IP Address is: %%f
    goto :eof
)

这是黄金,但我发现每个 .ini 编辑 post 实际上对我不起作用,因为它无限地打印该行而不是编辑该行。

由于 .ini 的大小未知,我确实需要一个 powershell 脚本才能正常工作,因为 BATCH 有限制。

Whosebug 上的一位用户有此代码:

(Get-Content C:\ProgramData\Nuance\NaturallySpeaking12\nssystem.ini) | ForEach-Object { $_ -replace 'Default NAS Address=.*','Default NAS Address=BHPAPPDGN01V' } | Set-Content C:\ProgramData\Nuance\NaturallySpeaking12\nssystem.ini

需要更改的行大多是随机的。好吧,不是随机的,但它有时会移动,因为用户可以进行一些更改,它会根据设置将 IP 线路向下或向上推。

我在 BATCH 和 powershell 方面有点新手,我还没有想出将信息传输到 powershell 的方法。例如,BATCH 将获取 IP,创建一个变量,运行 一个编辑 .ini 的 powershell 脚本。我确实记得有一个代码可以将 IP 抓取到剪贴板,但我现在找不到它。

我目前的进度是

@echo off
setlocal EnableExtensions
echo Exiting PROGRAM...
taskkill /IM PROGRAM.exe
timeout /t 1 /nobreak>nul
:check
for /F %%a in ('tasklist /NH /FI "IMAGENAME eq PROGRAM.exe"') do if %%a == PROGRAM.exe goto waiting
echo Restarting PROGRAM...
start "" "%ProgramFiles%\PROGRAM\PROGRAM.exe"
timeout /t 1 /nobreak>nul
exit
:waiting
echo PROGRAM is still running. Retrying...
timeout /t 3 /nobreak>nul
goto check

我不需要 setlocal EnableExtensions 但我确实尝试让它工作,然后需要它。 目前脚本会查看程序是否正在 运行ning,如果是,请轻轻地杀死它(等待它本机退出)然后重新启动它。我的目标是轻轻地杀死它,编辑 .ini 然后用所做的更改重新启动它。

由于 Windows 命令处理器 cmd.exe 不是为编辑文件而设计的,因此纯 PowerShell 解决方案很可能是此任务的最佳解决方案。

但这是一个纯批处理文件解决方案,用于确定当前 IPv4 地址并将其写入 INI 文件(如果当前包含不同地址)。

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "IniFile=C:\ProgramData\Nuance\NaturallySpeaking12\nssystem.ini"
if exist "%IniFile%" goto GetIpAddress

echo ERROR: File missing: "%IniFile%"
echo/
pause
goto EndBatch

:GetIpAddress
set "ip_address_string=IPv4 Address"
rem Uncomment the following line when using older versions of Windows without IPv6 support (by removing "rem")
rem set "ip_address_string=IP Address"
rem The string above must be IP-Adresse on a German Windows.
for /F "tokens=2 delims=:" %%I in ('%SystemRoot%\System32\ipconfig.exe ^| %SystemRoot%\System32\findstr.exe /C:"%ip_address_string%"') do set "IpAddress=%%I" & goto IpAddressFound

echo ERROR: Could not find %ip_address_string% in output of ipconfig.
echo/
pause
goto EndBatch

:IpAddressFound
set "IniEntry=Default NAS Address"
rem Remove leading (and also trailing) spaces/tabs.
for /F %%I in ("%IpAddress%") do set "IpAddress=%%I"
rem Do not modify the INI file if it contains already the current IP address.
%SystemRoot%\System32\findstr.exe /L /X /C:"%IniEntry%=%IpAddress%" "%IniFile%" >nul
if errorlevel 1 goto UpdateIniFile

echo The file "%IniFile%"
echo contains already the line: %IniEntry%=%IpAddress%
echo/
goto EndBatch

:UpdateIniFile
for %%I in ("%IniFile%") do set "TempFile=%%~dpnI.tmp"
(for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /N "^" "%IniFile%" 2^>nul') do (
    set "Line=%%I"
    setlocal EnableDelayedExpansion
    set "Line=!Line:*:=!"
    if not defined Line echo(
    for /F delims^=^=^ eol^= %%J in ("!Line!") do (
        set "FirstToken=%%J"
        if "!FirstToken!" == "%IniEntry%" (
            echo %IniEntry%=%IpAddress%
        ) else echo(!Line!
    )
    endlocal
))>"%TempFile%"

rem Replace the INI file by the temporary file, except the temporary file is empty.
if exist "%TempFile%" (
    for %%I in ("%TempFile%") do if not %%~zI == 0 (
        move /Y "%TempFile%" "%IniFile%" >nul
        echo Updated the file "%IniFile%"
        echo with the %ip_address_string% "%IpAddress%" for INI entry "%IniEntry%".
        echo/
    )
    del "%TempFile%" 2>nul
)

:EndBatch
endlocal

请阅读我在
上的回答 它解释了仅使用 Windows Commands.

更新 INI 文件的非常慢的代码

为了了解使用的命令及其工作原理,请打开 command prompt window,在那里执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

  • del /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • goto /?
  • if /?
  • ipconfig /?
  • move /?
  • pause /?
  • rem /?
  • set /?
  • setlocal /?

另请参阅 Single line with multiple commands using Windows batch file 以了解运算符 & 的解释。

阅读有关 Using command redirection operators 的 Microsoft 文章,了解 >2>nul| 的解释。重定向运算符 | 必须在 上使用脱字符 ^ 进行转义,以便在 Windows 命令解释器处理此命令时将其解释为文字字符 Windows执行命令 FOR 之前的行,该命令在后台启动的单独命令进程中使用 ipconfigfindstr 执行嵌入式命令行,并使用 %ComSpec% /c 和命令两个 ' 之间的行附加。

Mofi 有一个很棒的批处理解决方案,但他提到 CMD 并不是真正为这样的文件输出而设计的。所以这是一个纯 powershell 解决方案,应该可以满足您的需求。它确实借鉴了您在问题中包含的 powershell 片段。

$ip = Get-NetIPAddress -InterfaceAlias "Ethernet" #| Out-File PathTo:\net.ini
$content = get-content PathTo:\net.ini | ForEach-Object { $_ -replace "172.23.*","$($ip.IPAddress)"} 
$content | Set-Content PathTo:\net.ini

显然,这取决于您了解要获取的接口别名,但您可以使用 Get-NetIPAddress 轻松找到它,并且它不应该改变。您还需要更新路径信息。