- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试在 VBscript 中处理/过滤输入,但仅如果输入已通过管道传输到脚本中。我不希望脚本处理用户/键盘输入。我想将其编码为如下所示:
stdin_is_tty = ...
if not stdin_is_tty then
...
input = WScript.StdIn.ReadAll
end if
否则,脚本将挂起,在执行 WScript.StdIn.ReadAll
时等待用户输入(如果我使用 WScript.StdIn.AtEndOfStream
测试流,甚至更早) >).
在 C# 中,我会使用:
stdin_is_tty = not System.Console.IsInputRedirected // NET 4.5+
accepted answer对于 Q: "How to detect if Console.In (stdin) has been redirected?"展示了如何通过 P/Invoke 使用 Win32 调用来构建该结果(对于 NET 4.5 之前的 NET 版本)。但我不知道有什么方法可以将该方法转换为 VBscript。
我使用 SendKeys
构建了一个笨拙的部分解决方案,将流结束序列发送到脚本的键盘缓冲区中。但是,如果 STDIN 被重定向,解决方案会将 key 留在缓冲区中,除非我知道 STDIN 被重定向,否则我无法清理这些 key ...所以,同样的问题。
我更愿意将脚本保留在一个打包的片段中,因此我宁愿避免单独的包装脚本或通用 Windows 7+ 安装中不可用的任何内容。
有什么绝妙的想法或解决方法吗?
编辑:添加初始解决方案的副本
我在这里添加了改进的初始解决方案的副本(诚然,这是一个“黑客”),它现在可以自行清理,但仍然有一些负面影响:
input = ""
stdin_is_tty = False
test_string_length = 5 ' arbitrary N (coder determined to minimize collision with possible inputs)
sendkey_string = ""
test_string = ""
for i = 1 to test_string_size
sendkey_string = sendkey_string & "{TAB}"
test_string = test_string & CHR(9)
next
sendkey_string = sendkey_string & "{ENTER}"
wsh.sendkeys sendkey_string ' send keyboard string signal to self
set stdin = WScript.StdIn
do while not stdin.AtEndOfStream
input = input & stdin.ReadLine
if input = test_string then
stdin_is_tty = True
else
input = input & stdin.ReadAll
end if
exit do
loop
stdin.Close
if not stdin_is_tty then
set stdin = fso.OpenTextFile( "CON:", 1 )
text = stdin.ReadLine
stdin.Close
end if
该解决方案存在三个问题:
在命令行留下可见的痕迹(尽管现在只是一个可见性较低的空行)
测试字符串(一组 N 个[编码器确定的] TAB,后跟一个 NEWLINE)与任何重定向输入的第一行可能发生冲突,导致误报重定向确定。由于 TAB 的数量可以修改,因此编码器可以将这种可能性任意降低。
竞争条件,如果另一个窗口在执行 SendKeys
部分之前获得焦点,则错误的窗口将接收代码字符串,从而导致错误的否定重定向确定。我估计这种情况发生的可能性很低。
最佳答案
简而言之,不,但是......
我已经测试了我能想到的所有东西,但还没有找到合理的方法来做到这一点。
使用 WScript.StdIn
或 fso.GetStdStream
检索的 TextStream 包装器公开的属性/方法都没有提供足够的信息来确定输入是否被重定向/管道传输。
尝试从生成进程的行为/环境中获取信息(如何创建可执行文件是另一回事)也不太可能有用,因为
WshShell.Execute
始终生成进程,并重定向其输入和输出句柄
WshShell.Run
创建一个不继承当前进程句柄的新进程
Shell.Application.ShellExecute
与 WshShell.Run
因此,这些方法都不允许生成的进程继承当前进程的句柄来检查它们是否被重定向。
使用 WMI 从正在运行的进程检索信息不会返回任何可用的内容(嗯,当存在重定向时,进程的 HandleCount
属性会有所不同,但它不可靠)
因此,无法从 vbs 代码确定是否存在重定向,剩下的选项是
不检测:如果管道输入必须存在,则在所有情况下都表现为 more
命令尝试找回它
指出:如果管道输入并不总是需要,请使用参数来确定是否需要读取标准输入流。
就我而言,我通常使用单个斜杠 /
作为参数(为了与某些也使用斜杠表示标准输入的 findstr
参数保持一致)。然后在vbs代码中
If WScript.Arguments.Named.Exists("") Then
' here the stdin read part
End If
.cmd
,但通过一些技巧,可以将两个文件(.cmd
和 .vbs
)合并为一个保存为.cmd
<?xml : version="1.0" encoding="UTF-8" ?> ^<!------------------------- cmd ----
@echo off
setlocal enableextensions disabledelayedexpansion
timeout 1 >nul 2>nul && set "arg=" || set "arg=/"
endlocal & cscript //nologo "%~f0?.wsf" //job:mainJob %arg% %*
exit /b
---------------------------------------------------------------------- wsf --->
<package>
<job id="mainJob">
<script language="VBScript"><![CDATA[
If WScript.Arguments.Named.Exists("") Then
Do Until WScript.StdIn.AtEndOfStream
WScript.StdOut.WriteLine WScript.StdIn.ReadLine
Loop
Else
WScript.StdOut.WriteLine "Input is not redirected"
End If
]]></script>
</job>
</package>
它是存储在 .cmd
内的 .wsf
文件。批处理部分确定输入是否被重定向(timeout
命令无法获取重定向输入的控制台句柄)并将参数传递给脚本部分。
然后,该过程可以被调用为
< inputfile.txt scriptwrapper.cmd input redirected
type inputfile.txt | scriptwrapper.cmd input piped
scriptwapper.cmd no redirection
虽然这是一种方便的处理方法,但从 .cmd
调用 .wsf
部分虽然稳定并且工作没有问题,但依赖于脚本主机/cmd 组合的未记录行为。
当然,您可以执行相同的操作,但使用两个单独的文件。不太干净,但行为已记录。
关于vbscript - 有什么方法可以检测 STDIN 是否已在 VBscript 中重定向?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26683756/
我有以下代码可以完全按预期工作: from subprocess import Popen process = Popen( ["/bin/bash"], stdin=sys.stdi
我有一个关于 php-cli 的新问题。 我正在使用这个: define("STDIN", fopen('php://stdin','r')); $input = ""; while($input =
这个问题在这里已经有了答案: Can fseek(stdin,1,SEEK_SET) or rewind(stdin) be used to flush the input buffer inste
我正在编写一个 python 程序,它将所有输入都大写(替代非工作 tr '[:lowers:]' '[:upper:]')。语言环境是 ru_RU.UTF-8,我使用 PYTHONIOENCODIN
自从我发现 fflush(stdin) 不是处理熟悉的“换行潜伏在输入缓冲区中”问题的可移植方法,我一直在使用当我必须使用scanf时如下: while((c = getchar()) != '\n'
当我使用时在 Perl 模块( *.pm )文件中,它不会从键盘读取输入,但是当我使用 时在同一个地方它工作得很好。 为什么我使用时没有得到输入? 最佳答案 STDIN 是记录的文件句柄。还有 st
stdin 是否是一个指针,正如我在 fgets() 中看到的那样。 我使用“0”作为标准输入的读取或写入错误,并在 fgets 期间出现段错误。 STDIN宏和0是否相同。 stdin 是文件指针吗
我想知道 STDIN 和 $stdin 之间是否有任何真正的区别。我在 irb: STDIN == $stdin 并返回 true。它们只是同一事物的两个名称吗?还是有什么不同? 最佳答案 来自 Ru
有没有一种简单的方法可以将内容通过管道传输到编辑器原子? 例如: echo "Content." | atom 不幸的是atom没有获取到内容。当前版本的 gedit 具有参数 - 以启用读取 STD
这个问题已经有答案了: Using fflush(stdin) (7 个回答) 已关闭 9 年前。 我有一个这样的测试代码 #include #include #include int main
我有一个 bash启动 scp 的脚本通过以下方式: echo "${SCP_PASS:-$PASSWORD}" | ( exec 3<&0; scp -qp ${SCP_PORT:+-P$SCP_P
我正在创建一个 NASM 汇编代码来从标准输入读取文件中存在的二维数字数组我正在运行这样的可执行文件 -> ./abc < input.txt . 之后,我将在终端上显示读取的二维数组,然后我想获取箭
这是一个循环,它重复地从 stdin 获取两个字符并输出它们。 char buf[2]; while (1) { printf("give me two characters: ");
我有一个 golang 程序,可以为 jq 做一个简单的 repl。 .我希望能够在程序启动时从 stdin 读取输入到一个临时文件中,这样我就可以将 repl 与管道输入一起使用。 cat file
有没有非阻塞的 PHP 从 STDIN 读取: 我试过了: stream_set_blocking(STDIN, false); echo fread(STDIN, 1); 还有这个: $stdin
这实际上与我已经回答的另一个问题有关。这个问题在这里:Redirecting stdout of one process object to stdin of another 我的问题是(我认为)获取
我只是一个java初学者,目前正在大学学习,但由于某些原因我不会深入,我无法询问我的导师。 我在 Netbeans 中使用 StdIn 库时遇到问题。在类里面我们使用 DrJava,但由于我无法让它在
Ruby 有两种引用标准输入的方法:STDIN 常量和$stdin 全局变量。 除了我可以将不同的 IO 对象分配给 $stdin 因为它不是常量(例如,在我的 child 中 fork 重定向 IO
我是 Pythonizer 的作者我正在尝试将 CGI.pm 的代码从标准 perl 库转换为 Python。我在 read_from_client 中看到这段代码: read(\*STDIN, $$
我正在使用 laravel 5.6 并遇到问题,当我在控制台中使用命令“php artisan vendor:publish”时,出现以下错误: [ERROR] Use of undefined co
我是一名优秀的程序员,十分优秀!