简体   繁体   English

X秒后如何使cmd命令超时

[英]How to timeout cmd command after X seconds

Using command prompt, I need to open a folder on a network location in File Explorer, and if it's not available then exit the command prompt window I ran the command from. 使用命令提示符,我需要在文件资源管理器中的网络位置上打开一个文件夹,如果该文件夹不可用,请退出我从中运行命令的命令提示符窗口。 The problem is trying to open a network location that isn't there takes extremely long (30+ seconds), and when it is there it opens immediately, so I want to try opening the location and exit after 5 seconds. 问题是尝试打开一个不存在的网络位置会花费非常长的时间(超过30秒),当它出现时,它会立即打开,因此我想尝试打开该位置并在5秒后退出。

I've already tried using taskkill but it seems accessing a network location prevents it from working the way it should, also taskkill seems to kill all command prompt windows which isn't ideal. 我已经尝试使用taskkill但是似乎访问网络位置会阻止它正常工作,而且taskkill似乎会杀死所有不理想的命令提示符窗口。 To replicate, type the following command (using an inaccessible network location) and it should take a while to finish 要复制,请键入以下命令(使用无法访问的网络位置),这需要一些时间才能完成

if exist \\\\1.2.3.4\\c$ (start \\\\1.2.3.4\\c$) else exit

When using start command/program/path , CMD will not directly launch the Explorer with the given path. 使用start command/program/path ,CMD不会直接使用给定路径启动资源管理器。 Before that it, has to examine the given parameter to determine its type (Internal command, External executable or script, some other type of file or folder) 在此之前,必须检查给定的参数以确定其类型(内部命令,外部可执行文件或脚本,其他类型的文件或文件夹)

Depending on the type it may launch it directly or attempt to open it using ShellExecute API. 根据类型的不同,它可以直接启动它,也可以尝试使用ShellExecute API打开它。 The ShellExecute API in turn examines the given object to determine which application should be used to open it. ShellExecute API依次检查给定的对象,以确定应使用哪个应用程序打开它。 If the object is a path to a local or remote folder, then it uses explorer to open that location. 如果对象是本地或远程文件夹的路径,则它将使用资源管理器打开该位置。

When dealing with the path to an unavailable network share, it will take a while for CMD (and ShellExecute) to finally determine that network share is inaccessible, Therefor the execution of your CMD command will be blocked during that time. 在处理通往不可用网络共享的路径时,CMD(和ShellExecute)将需要一段时间才能最终确定网络共享不可访问,因此在此期间将阻止执行CMD命令。

To circumvent the blocking, you need to open the network share asynchronously using a new instance of CMD and then attempt to terminate that instance after the timeout period. 为了避免阻塞,您需要使用新的CMD实例异步打开网络共享,然后在超时时间段之后尝试终止该实例。

Using taskkill to terminate that instance, it should be given a unique title in order to distinguish from other processes. 使用taskkill终止该实例时,应该给它一个唯一的标题,以便与其他进程区分开。

A very basic and simple solution would be using a batch file such as follows 一个非常基本和简单的解决方案是使用批处理文件,如下所示

:: ExploreShare.cmd
@echo off
setlocal
set "sharedLoc=%~1"
:: Basic validation
if not defined sharedLoc exit /b
if not "%sharedLoc:~0,2%"=="\\" exit /b

set "uniqTitle=ExploreShare-%time: =%-%random%"
start "%uniqTitle%" /min "CMD " /c start "" "%sharedLoc%"
>nul timeout /t 5
taskkill /fi "WINDOWTITLE eq %uniqTitle%" /f >nul 2>&1

It can be used from command line like this 可以从命令行这样使用它

> ExploreShare \\127.0.0.1\C$

The drawback of using such basic a solution is that It will wait for 5 seconds regardless, and except by visual determination from user, does not offer any way to determine if the operation was successful or not. 使用这种基本解决方案的缺点是,它将等待5秒钟,并且,除非通过用户的直观判断,否则它不会提供任何方法来确定操作是否成功。

It can be improved by a slightly more complex script which will try to minimize the wait time on successful operation and also provides a mechanism to determine success or failure. 可以通过稍微复杂一些的脚本来改进它,该脚本将尝试最小化成功操作的等待时间,并提供确定成功或失败的机制。

:: ExploreShare2.cmd
@echo off
setlocal
set "sharedLoc=%~1"
:: Basic validation
if not defined sharedLoc exit /b 1
if not "%sharedLoc:~0,2%"=="\\" exit /b 1

set "uniqTitle=ExploreShare-%time: =%-%random%"
echo Attempting to open network share "%sharedLoc%" ...
start "%uniqTitle%" /min "CMD " /c if exist "%sharedLoc%" (start "" "%sharedLoc%") else pause
>nul timeout /t 1
set "childProc="
for /F "skip=2" %%A in ('tasklist /fi "WINDOWTITLE eq %uniqTitle%"') do set "childProc=%%A"
if not defined childProc (
    echo The operation completed successfully.
    exit /b 0
)
:: Give it another 4 seconds
>nul timeout /t 4
set "childProc="
for /F "skip=2" %%A in ('tasklist /fi "WINDOWTITLE eq %uniqTitle%"') do set "childProc=%%A"
if defined childProc (
    >&2 echo The operation timed out.
    taskkill /fi "WINDOWTITLE eq %uniqTitle%" /f >nul 2>&1
    exit /b 1
) else (
    echo The operation completed successfully.
    exit /b 0
)

So for example if you need to terminate the CMD/BatchFile on failure it can be used like this 因此,例如,如果您需要在失败时终止CMD / BatchFile,可以像这样使用

From command line: 从命令行:

> ExploreShare2 "\\server\share" || exit


Within a batch file: 在批处理文件中:

call ExploreShare2 "\\server\share" || exit /b

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM