如果phone连接到网络,如何播放声音?
How to play sound if phone connects to network?
我尝试写一个小的批处理脚本。如果我的 phone 加入我的网络,它应该会播放声音。
@echo off
:A
ping -n 1 xxx.xxx.xxx.xx | findstr TTL && start airsiren.wav
goto A
现在的问题是,如果检测到phone,它会重复启动声音。但它应该只播放一次。
有人知道简单的解决方法吗?也许有 IF 条件?
我对批处理的了解不多,但我想我已经掌握了一些基本知识。
使用 %errorlevel%
和 IF
语句可以很容易地解决这个问题。
Jelle Geerts 的原创脚本。
@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
set "LastExitCode=1"
:Loop
%SystemRoot%\System32\ping.exe -n 1 xxx.xxx.xxx.xx | %SystemRoot%\System32\find.exe /C "TTL" >nul
if not %ErrorLevel% == %LastExitCode% set "LastExitCode=%ErrorLevel%" & if %ErrorLevel% == 0 start "Play sound" airsiren.wav
%SystemRoot%\System32\timeout.exe /T 5 /NOBREAK
if not errorlevel 1 goto Loop
PING 如果对回显请求有响应,则输出一行 TTL
,通常在接收到响应时以值 0
退出,并以 1
没有回应。但是 PING 并不总是以 0
退出,这就是使用 FIND.
的原因
FIND 处理 PING 的输出并搜索包含字符串 TTL
的行。 FIND 在找到至少一行 TTL
时以值 0
退出,否则以 1
表示没有找到包含搜索字符串的行。 FIND 处理 STDOUT 的输出没有意义,因此通过使用选项 /C
减少到最低限度并重定向到设备 NUL.
现在 FIND 的退出代码与环境变量进行比较,该环境变量保存 FIND 的最后一个退出值,初始化值为 1
.
当前退出代码与上次退出代码相同时,被 ping 设备在网络上的可用性没有变化,因此无需执行任何操作。
否则,将当前退出代码分配给下一个循环的环境变量 运行 和 当前退出代码与值 0
进行比较.如果第二个条件为真,则被 ping 的设备第一次通过 PING 发送对回显请求的肯定响应。在这种情况下播放声音。
在网络上不再可用的 ping 设备上没有执行任何其他操作,即退出代码从 0
更改为 1
。
然后使用 TIMEOUT 开始延迟 5 秒,并让用户使用 Ctrl+C 中断它。这减少了处理器核心的使用,使 Windows 有可能将处理器核心用于其他进程,并且当 ping 设备此时在网络上可用时,也减少了网络使用。当然,被 ping 的设备不再需要永久响应回显请求。
如果 TIMEOUT 在没有用户中断的情况下正常退出,则跳转到标签 Loop
。否则,当用户按下 Ctrl+C 时,批处理文件处理也会结束。
TIMEOUT 参数 /NOBREAK
需要 Windows 7 或更新的 Windows 版本。
要了解使用的命令及其工作原理,请打开命令提示符 window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
echo /?
find /?
goto /?
if /?
ping /?
set /?
start /?
timeout /?
另请参阅 single line with multiple commands using Windows batch file 以了解运算符 &
的解释和 if not errorlevel 1
的含义。
我的解决方案:
@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
你的代码有两个问题
即使在 phone 连接后,您的代码也会无条件地转到开头,因此它会重复播放声音。您可以使用 ... && (start airsiren.wav & goto :EOF)
终止批处理文件或使用 :EOF
以外的其他标签来执行其他操作。但这并没有让您选择继续监视 phone 以进行断开连接和重新连接。
您必须检查默认媒体播放器(通常是 Windows 媒体播放器)的设置,并确保它没有设置为连续循环播放或重复播放媒体。此外,仅仅为了播放一个简短的通知声音而启动一个完整的媒体播放器也太过分了,而且有些不方便,而且通常你必须在之后关闭媒体播放器。
所以这是我提出的代码,它通过提供持续监视 phone 的连接状态的选项解决了上述障碍,还提供了一种更编程的方式来自行播放通知声音使用混合 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%\media\ringout.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();
}
我尝试写一个小的批处理脚本。如果我的 phone 加入我的网络,它应该会播放声音。
@echo off
:A
ping -n 1 xxx.xxx.xxx.xx | findstr TTL && start airsiren.wav
goto A
现在的问题是,如果检测到phone,它会重复启动声音。但它应该只播放一次。
有人知道简单的解决方法吗?也许有 IF 条件?
我对批处理的了解不多,但我想我已经掌握了一些基本知识。
使用 %errorlevel%
和 IF
语句可以很容易地解决这个问题。
Jelle Geerts 的原创脚本。
@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
set "LastExitCode=1"
:Loop
%SystemRoot%\System32\ping.exe -n 1 xxx.xxx.xxx.xx | %SystemRoot%\System32\find.exe /C "TTL" >nul
if not %ErrorLevel% == %LastExitCode% set "LastExitCode=%ErrorLevel%" & if %ErrorLevel% == 0 start "Play sound" airsiren.wav
%SystemRoot%\System32\timeout.exe /T 5 /NOBREAK
if not errorlevel 1 goto Loop
PING 如果对回显请求有响应,则输出一行 TTL
,通常在接收到响应时以值 0
退出,并以 1
没有回应。但是 PING 并不总是以 0
退出,这就是使用 FIND.
FIND 处理 PING 的输出并搜索包含字符串 TTL
的行。 FIND 在找到至少一行 TTL
时以值 0
退出,否则以 1
表示没有找到包含搜索字符串的行。 FIND 处理 STDOUT 的输出没有意义,因此通过使用选项 /C
减少到最低限度并重定向到设备 NUL.
现在 FIND 的退出代码与环境变量进行比较,该环境变量保存 FIND 的最后一个退出值,初始化值为 1
.
当前退出代码与上次退出代码相同时,被 ping 设备在网络上的可用性没有变化,因此无需执行任何操作。
否则,将当前退出代码分配给下一个循环的环境变量 运行 和 当前退出代码与值 0
进行比较.如果第二个条件为真,则被 ping 的设备第一次通过 PING 发送对回显请求的肯定响应。在这种情况下播放声音。
在网络上不再可用的 ping 设备上没有执行任何其他操作,即退出代码从 0
更改为 1
。
然后使用 TIMEOUT 开始延迟 5 秒,并让用户使用 Ctrl+C 中断它。这减少了处理器核心的使用,使 Windows 有可能将处理器核心用于其他进程,并且当 ping 设备此时在网络上可用时,也减少了网络使用。当然,被 ping 的设备不再需要永久响应回显请求。
如果 TIMEOUT 在没有用户中断的情况下正常退出,则跳转到标签 Loop
。否则,当用户按下 Ctrl+C 时,批处理文件处理也会结束。
TIMEOUT 参数 /NOBREAK
需要 Windows 7 或更新的 Windows 版本。
要了解使用的命令及其工作原理,请打开命令提示符 window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
echo /?
find /?
goto /?
if /?
ping /?
set /?
start /?
timeout /?
另请参阅 single line with multiple commands using Windows batch file 以了解运算符 &
的解释和 if not errorlevel 1
的含义。
我的解决方案:
@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
你的代码有两个问题
即使在 phone 连接后,您的代码也会无条件地转到开头,因此它会重复播放声音。您可以使用
... && (start airsiren.wav & goto :EOF)
终止批处理文件或使用:EOF
以外的其他标签来执行其他操作。但这并没有让您选择继续监视 phone 以进行断开连接和重新连接。您必须检查默认媒体播放器(通常是 Windows 媒体播放器)的设置,并确保它没有设置为连续循环播放或重复播放媒体。此外,仅仅为了播放一个简短的通知声音而启动一个完整的媒体播放器也太过分了,而且有些不方便,而且通常你必须在之后关闭媒体播放器。
所以这是我提出的代码,它通过提供持续监视 phone 的连接状态的选项解决了上述障碍,还提供了一种更编程的方式来自行播放通知声音使用混合 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%\media\ringout.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();
}