我正在寻找一种方法来运行cmd命令而不向用户显示cmd窗口。
我正在使用类似的东西:
function reboot() {
var ws = new ActiveXObject("WScript.Shell");
ws.Exec("shutdown.exe -r -t 120");
}
但它仍然显示窗口,无论如何不显示它?
由于
答案 0 :(得分:5)
尝试使用Run
函数而不是Exec
并将其作为第二个参数传递0,以防止它显示命令提示符窗口:
ws.Run("shutdown.exe -r -t 120", 0);
系统关闭窗口仍会显示(我认为没有办法压制它)。
答案 1 :(得分:0)
您可以使用以下命令使窗口最小化:
cmd /c start /min SomeCommand
我认为您知道这在浏览器中不起作用,因此我假设您正在使用WSH编写独立的JScript文件。
答案 2 :(得分:-1)
我想我明白你的问题所在。您想让 jscript 像在 vbscript 中一样打开文件。但问题是 jscript (cscript) 作为控制台应用程序打开并在启动时向您显示控制台,您错误地认为它是一个 cmd 窗口,同时 wscript 没有控制台并且不会向您显示任何内容。
创建快捷方式。 cscript 替代 wscript 的一种快捷方式。强制打开文件可见。比较他们的行为差异。
但不要以为这是所有问题的解决方案。 wscript 没有 ctd (ctdout) 命令。因此,并非您拥有的所有文件都会通过此技巧。在一个简单的文件上试试这个。
C:\Windows\System32\mshta.exe "javascript:new ActiveXObject('WScript.Shell').Run('cscript E:\\path\\name.js',1,false);close()"
C:\Windows\System32\mshta.exe "javascript:new ActiveXObject('WScript.Shell').Run('wscript E:\\path\\name.js',1,false);close()"
我建议使用这样的 javascript 文件。在这两种情况下的工作方式相同。
var htmlfile=new ActiveXObject('htmlfile').parentWindow;
var alert = function(s){htmlfile.alert(s)};
alert('Hello world!')
嗯。您需要关闭 javascript 控制台窗口本身。
从使用参数隐藏的快捷方式调用 javascript(例如从快捷方式:
C:\Windows\System32\mshta.exe vbscript:Execute("CreateObject(""WScript.Shell"").Run ""cscript.exe """"С:\path\fname.js"""" """"par1 with whitespace"""" par2WithowtWhiteSpase"", 0:close")
...并且不要忘记在 msta 之后关闭任务管理器中的隐形进程。
即使是 cmd 也不会显示它的窗口。它会将数据输出到 jscript 控制台,当然如果 jscript 是从 cscript 打开的。因此,不能有 CMD 窗口。数据会直接输出到cscript控制台。
这已经直接与 cmd 和从他的进程中获取数据有关:
chcp 1251,866 - 将其更改为您的区域参数
var htmlfile=new ActiveXObject('htmlfile').parentWindow;
var alert=function(s){htmlfile.alert(s)};
var echoIt='Hi'
//...solve the problem of doubling percentages in variables during transmission by introducing the parameter /v!
var cmdCode=[
'for /F "tokens=1-6 delims=:., " %A In ("!date! !time!") Do (Echo %A.%B.%C %D:%E:%F)',
'set var='+echoIt,
'echo %var%',
'echo !var!',
'echo You will not see this output on the javascript screen >0',
];//'setlocal disableDelayedExpansion' parameter is useless becose /v
var std, arr=[];
var WshRunning=0,WshFinished=1,WshFailed=2;var i=0;tryCount=0,output=[],errors=[];
with (new ActiveXObject('WScript.Shell')) {
std=Exec("cmd /v /q /k echo off"); //Turning on the /v option last, switches the output here in its entirety, including C:\...\notepad>
std.StdIn.WriteLine("chcp 1251>nul");
for(var i=0;i<cmdCode.length;i++) {
std.StdIn.WriteLine(cmdCode[i]);
};
std.StdIn.WriteLine("chcp 866>nul");
std.StdIn.WriteLine("exit");
do{
if (std.Status==WshFailed){
errors.push('Error in string '+i+' :\n '+std.StdErr.ReadLine());
tryCount++
}
else if(std.Status==WshRunning){
output.push(std.StdOut.ReadLine());
tryCount=0;
WScript.Echo('Running ...')
}
else if(std.Status==WshFinished){
var last=std.StdOut.ReadLine();
if(last.length>0){output.push(last)};last=undefined;
tryCount=21;
WScript.Echo('Finished ...')
}i++;
}while(tryCount<21);
}
WScript.Echo('')
if (output.length>0){for(var i=0;i<output.length;i++) {WScript.Echo(output[i])}}
if (errors.length>0){alert(errors)}
var x=WScript.StdIn.ReadLine();
或
var std, arr = [];
var oWsh = new ActiveXObject("WScript.Shell");
with (new ActiveXObject('WScript.Shell')) {
std = Exec("cmd /q /k chcp 1251>nul");
with (std.StdIn){
WriteLine("dir "+ oWsh.SpecialFolders("Desktop"));
WriteLine("exit");
}
arr = std.StdOut.ReadAll().split('\n'); //чтение данных
}
for (var i = 0; i < arr.length; i++) {
WScript.echo(i+' '+arr[i]);
}
var x = WScript.StdIn.ReadLine();
对于那些坚持认为 Exec 的子线程不应该打开 javascript 窗口的人:
事实证明,那些使用 vbs 的人都缺乏黑色控制台!他们想在cscript进程中接收数据!不用说,他们想在隐藏的 vbs 窗口中进行。
Hide command prompt window when using Exec()
这是他们的 jscript 代码的示例实现。
另外,完全是废话。这仅适用于 wscript.exe 启动的 jscript。对于来自原生 cscript 的 jscript,不需要。
如果在 wscript 进程中默认运行 jscript 可能是有意义的。但是在jscript中,无论如何,我们需要一个windows的快捷方式,它本身可以隐藏jscript的工作,不需要额外的代码。
尽管此代码的实现可能对创建多线程应用程序很有用。
================
您必须在隐藏的另一个线程中执行此操作。
不管它是什么类型的流,jscript、PS、Cmd。
最重要的是 - 使用睡眠或其他方式等待他的回复。
获得答案的最简单方法是剪贴板。
Exec 停止您的线程,它仅适用于接收参数。代码停止了,您对此无能为力。
隐藏运行并获得结果的能力在vbs中。 Omegastripes 回答 Hide command prompt window when using Exec()。
但实际上,那个脚本的工作就像是chimera,只是没有重启。新推出自己的代码,同时隐藏在新进程空间{C08AFD90-F2A1-11D1-8455-00A0C91F3880}中作为cscript,其中已经从隐藏流中产生exec。然后找到自己并直接将变量注入到其先前的代码中。 (objParent.strRes = CreateObject("WScript.Shell").Exec(....)
但是在javascript中几乎不可能进行这样的变量模拟。例如,我什至无法从“这个”线程中找到我自己的新 cs 线程对象。当然我会通过wmic找到它。但是如何直接从进程中插入(抓取)一个变量?
我的非生产性代码:
看到结果不要感到惊讶。这只是一个应该返回响应并且应该隐藏的子线程,但我让它可见。
var htmlfile=new ActiveXObject('htmlfile').parentWindow;
var alert = function(s){htmlfile.alert(s)};
function sleep(milliseconds) {
function now() {return new Date().getTime();};
var date = now(), currentDate = null;
do {currentDate = now();} while (currentDate - date < milliseconds);
}
function RunCScriptHidden() // restarts the script in an invisible, child thread (now it is visible and receives the result)
{
strSignature = (new ActiveXObject("Scriptlet.TypeLib")).GUID.substring(0,38);
GetObject('new:{C08AFD90-F2A1-11D1-8455-00A0C91F3880}').putProperty(strSignature,this);
//WScript.FullName.toLowerCase().replace("cscript", "wscript") //we can start it as wscript
//"c:\windows\system32\cscript.exe" //nologo "G:\filePath\fileName.js" "/signature:{7081DE1F-FB01-40A7-9384-B676516064EF}"
objShell.Run ('"'+WScript.FullName.toLowerCase() + '" //nologo "' + WScript.ScriptFullName + '" "/signature:' + strSignature + '"', 1);
}
function WshShellExecCmd(){ // This is already executed as a child streem pass in invisible mode and should pass the result to the mine thread
try{
for(var objWnd = new Enumerator(new ActiveXObject('Shell.Application').Windows());!objWnd.atEnd();objWnd.moveNext()){
//I couldn't even find the parent process here. It appears as a windows explorer process. And I can't even imagine the possibility of working with its objects in the js space.
if (typeof(objWnd.item(WScript.Arguments.Named('signature')))=='object'){break;}
}
var objParent = objWnd.item(WScript.Arguments.Named('signature')).parent; //big problem
objWnd.Terminate;
exec = (new ActiveXObject("WScript.Shell")).Exec(strCmd);//alert('')
while (exec.Status == WshRunning){sleep(100);};
var err = null;
if (exec.ExitCode == WshFinished){err = exec.StdErr.ReadAll()}
else{output = exec.StdOut.ReadAll().split('\n')}
if (err==null){WScript.Echo('output: '+output[output.length-2])
/*objParent.*/strRes = output[output.length-2]; //here should be objParent //I can easily do it with the clipboard, but it's ugly
}
else{
/*objParent.*/wowError = err; //there should be objParent (transfer data to the main thread and bang this child), of course you need to slow down the thread
//(there is a related example on vbs where this works) https://stackoverflow.com/questions/32297699
}
}catch(e){
var strErr = 'WshShellExecCmd error: ';
strErr += '\nNumber:' + e.number;
strErr += '\nDescription:' + e.description;
WScript.Echo('errors: '+strErr)
var x = WScript.StdIn.ReadLine();
}
}
try{
var WshRunning = 0,WshFinished = 1,WshFailed = 2,objWnd,objShell,strCmd,strRes,objParent,strSignature,wowError,output,exec;
var objShell = WScript.CreateObject("WScript.Shell");
wowError=false;
var psCode="Write-Host 'Hello PS'";
strCmd='C:\\Windows\\System32\\Cmd.exe /c for /f "usebackq delims=" %a in (`C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -command "' + psCode + '"`) do echo %a';
if (WScript.Arguments.Named.Exists('signature')){
WshShellExecCmd();
// The output of the results here is for example only. Here or above, we need to pass data to the parent thread.
if (wowError==false){
WScript.Echo("result: " + strRes)
}
else{
WScript.Echo("Get result error: " + wowError.ToString());
}
var x = WScript.StdIn.ReadLine();
}else{
RunCScriptHidden();
while (strRes == strRes){sleep(1000);WScript.Echo("I am waiting to receive 'strRes'")};//Here it is possible to release your parent process, and just continue the program in over process, instead of this
}
}catch(err){
var strErr = 'error:';
strErr += '\nNumber:' + err.number;
strErr += '\nDescription:' + err.description;
WScript.Echo('errors: '+strErr)
var x = WScript.StdIn.ReadLine();
}