我尝试编写一个小批处理脚本。如果我的手机加入我的网络,它应该会播放声音。
@echo off
:A
ping -n 1 xxx.xxx.xxx.xx | findstr TTL && start airsiren.wav
goto A
现在的问题是,如果检测到手机,它会反复发出声音。但它应该只玩一次。
有谁知道一个简单的解决方法?也许有 IF 条件?
我没有在批处理方面做太多事情,但我想我得到了一些基础知识。
我建议使用以下代码:
@echo off
set "LastExitCode=1"
:Loop
%SystemRoot%System32ping.exe -n 1 xxx.xxx.xxx.xx | %SystemRoot%System32find.exe /C "TTL" >nul
if not %ErrorLevel% == %LastExitCode% set "LastExitCode=%ErrorLevel%" & if %ErrorLevel% == 0 start "Play sound" airsiren.wav
%SystemRoot%System32timeout.exe /T 5 /NOBREAK
if not errorlevel 1 goto Loop
如果echo 请求有响应,PING 会输出一行带有TTL
的行,通常在收到响应时以值0
退出,在收到响应时以值1
退出。但是PING并不总是以0
的正面响应退出,这就是使用FIND的原因。
FIND处理PING的输出并搜索包含字符串TTL
的行。FIND在找到至少一行带有TTL
时以值0
退出,否则使用1
表示未找到包含搜索字符串的行。用于处理STDOUT的FIND输出无关紧要,因此通过使用选项/C
并重定向到设备NUL将输出减少到最小值。
现在,将FIND 的退出代码与一个环境变量进行比较,该变量保存了用值1
初始化的FIND的最后一个退出值。
当前退出代码等于最后一个退出代码时,网络上 ping 设备的可用性没有变化,因此无事可做。
否则,在差异上,当前退出代码将分配给环境变量以进行下一次循环运行,并将当前退出代码与值0
进行比较。如果第二个条件为真,则 ping 设备第一次通过PING发送回显请求的肯定响应。在这种情况下,将播放声音。
在 ping 设备上没有其他任何操作在网络上不再可用,即退出代码从0
更改为1
。
然后使用TIMEOUT启动 5 秒的延迟,让用户使用Ctrl+C打破它。这减少了处理器核心的使用,使 Windows 可以将处理器核心用于其他进程,并且当 ping 的设备目前在网络上可用时,还可以减少网络使用量。当然,ping的设备不再需要永久响应回显请求。
如果TIMEOUT正常退出而没有用户中断,则会跳转到标签Loop
。否则,当用户按Ctrl+C时,批处理文件处理也会结束。
带有参数/NOBREAK
的超时需要 Windows 7 或更高版本的 Windows 版本。
要了解使用的命令及其工作原理,请打开命令提示符窗口,在那里执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
echo /?
find /?
goto /?
if /?
ping /?
set /?
start /?
timeout /?
另请参阅使用 Windows 批处理文件的具有多个命令的单行,了解运算符&
的说明和if not errorlevel 1
的含义。
这可以使用%errorlevel%
和IF
语句非常容易地修复。
耶勒·吉尔茨的原创剧本。
@ECHO OFF
:Search
ping -n 1 "xxx.xxx.xxx.xx" | findstr /r /c:"[0-9] *ms"
if %errorlevel% == 0 (
echo Device was found!
start airsiren.wav
pause.
) else (
goto Search
)
我的解决方案:
@echo off &:: modem_tester_xp+.bat
REM original https://www.elektroda.pl/rtvforum/topic2917839.html
setlocal EnableDelayedExpansion
rem set connection name (for newer than Win XP) from Network Connections (preferred name doesn't have space)
set _connection_name=internet
rem make file which close this script
echo @echo.^>"%~dpn0.exit"^&@del /q "%%~f0">"%~dp0close_%~nx0"
for /f "tokens=2-4 delims==." %%a in ('wmic os get Version /value ^|find "="') do if "%%~c" neq "" set "_system_version=%%~a.%%~b"
set "_con_ip="
set "_my_ip.last="
:start
::-n (seconds+1)
ping 127.0.0.1 >nul -n 3
set "_my_ip="
if not defined _con_ip call :get_con_ip "%_connection_name%"
if defined _con_ip for /f "tokens=3-5 delims= " %%p in ('route print ^|find " 0.0.0.0 "') do if "%%~r" neq "" if /i "%%~p"=="%_con_ip%" ( set "_my_ip=%%~p" ) else if /i "%%~q"=="%_con_ip%" set "_my_ip=%%~q"
rem if connection lost clean variable _my_ip.last
if not defined _my_ip (
set "_con_ip="
set "_my_ip.last="
) else if /i "%_my_ip%" neq "%_my_ip.last%" (
rem remember last connection addres
set "_my_ip.last=%_my_ip%"
call :2run
)
if not exist "%~dpn0.exit" goto start
del /q "%~dpn0.exit"
endlocal
goto :eof
:get_con_ip &::ConnectionName:return variable _con_ip
if "%_system_version%"=="5.1" (
rem XP find modem address
for /f "tokens=2 delims== " %%a in ('netsh diag show gateway WAN* ^|find "." ^|find "="') do if "!_con_ip!"=="" set "_con_ip=%%~a"
) else (
rem if newer works like win7, if not: if "%_system_version%"=="6.1" (rem Windows 7
if "%~1" neq "" for /f "tokens=1,4* delims= " %%n in ('netsh interface ipv4 show interfaces ^|find /i "%~1"') do if "!_con_ip!"=="" if /i "%%~p"=="%~1" for /f "tokens=1* delims=:" %%i in ('netsh interface ipv4 show addresses %%~n ^|find "." ^|find /i "ip"') do if "!_con_ip!"=="" set "_con_ip=%%~j"
if "!_con_ip!" neq "" set "_con_ip=!_con_ip: =!"
)
goto :eof
:2run
rem run external
rem start "modem started" /min /b cmd /c "echo %date% %time% '%_my_ip%'&pause"
start airsiren.wav
你的代码有两个问题
-
即使在连接手机后,您的代码也会无条件地转到开头,因此它会重复播放声音。可以使用
... && (start airsiren.wav & goto :EOF)
终止批处理文件,也可以使用除:EOF
以外的其他标签执行其他操作。但这并不能让您选择继续监控手机的断开连接和重新连接。 -
您必须检查默认媒体播放器(通常是Windows 媒体播放器(的设置,并确保它未设置为连续循环或重复媒体。此外,启动一个成熟的媒体播放器只是为了播放简短的通知声音是矫枉过正的,有点不方便,通常你必须在之后关闭媒体播放器。
因此,这就是我建议的代码,它通过提供持续监控手机连接状态的选项来解决上述障碍,并提供一种更具程序化的方式来使用混合 BAT/JSCript 解决方案在自包含播放器中播放通知声音。
@if (@Code)==(@BatchScript) /* Hybrid BAT/JScript line */
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set @PlaySound=start "" /b cscript //nologo //e:JScript "%~f0"
set "SoundFile.Connect=%SystemRoot%mediaringout.wav"
set "SoundFile.Disconnect=?"
set "GenFail.Localized.Text=General failure"
:: set to 0 to disable continuous connection monitoring
set "ContinuousMonitoring=1"
set "PhoneIP=xxx.xxx.xxx.xxx"
set "Timeout=3000"
setlocal EnableDelayedExpansion
set "CheckGeneralFailure=1"
echo [%TIME%] Waiting for connection...
:WaitForConnection
ping -n 1 %PhoneIP% -w %Timeout% | findstr "TTL" >nul && (
echo [!TIME!] Phone Connected.
!@PlaySound! "!SoundFile.Connect!"
if %ContinuousMonitoring% NEQ 0 goto :MonitorConnection
goto :EOF
) || (
if !CheckGeneralFailure! NEQ 0 (
ping -n 1 %PhoneIP% -w 100 | findstr /i /c:"%GenFail.Localized.Text%" >nul && (
ping -n 1 -w %Timeout% 127.255.255.255 >nul
(call,) %= Set errorlevel to 0 =%
) || set "CheckGeneralFailure=0"
)
goto :WaitForConnection
)
:MonitorConnection
ping -n 1 %PhoneIP% | findstr "TTL" >nul && (
ping -n 1 -w %Timeout% 127.255.255.255 >nul
goto :MonitorConnection
) || (
echo [!TIME!] Phone Disconnected.
echo [!TIME!] Waiting for connection...
set "CheckGeneralFailure=1"
REM Play another sound for disconnect?
goto :WaitForConnection
)
goto :EOF
/*** End of batch code ***/
@end
/*** JScript Sound Player ***/
var wmpps = {
Undefined : 0,
Stopped : 1,
Paused : 2,
Playing : 3,
ScanForward : 4,
ScanReverse : 5,
Buffering : 6,
Waiting : 7,
MediaEnded : 8,
Transitioning : 9,
Ready : 10,
Reconnecting : 11,
Last : 12
};
var SoundFile;
if (WScript.Arguments.length) SoundFile = WScript.Arguments(0);
var WaitCount = 0;
var objPlayer = new ActiveXObject("WMPlayer.OCX.7");
with(objPlayer) {
URL = SoundFile;
settings.volume = 100;
settings.setMode("loop", false);
controls.play();
while(playState == wmpps.Transitioning) {
WaitCount+=1;
if (WaitCount > 200) break;
WScript.Sleep(10);
}
if (playState == wmpps.Playing) {
while(playState != wmpps.Stopped) WScript.Sleep(1000);
}
close();
}