Кажется, я понимаю, в чем твоя проблема. Вы хотите, чтобы 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();
or
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.
Скрыть окно командной строки при использовании Exec()
Это пример реализации их кода для jscript.
Дальше полный бред. Это относится только к jscript, запускаемому wscript.exe. Для jscript из родного cscript в этом нет необходимости.
Это могло бы иметь смысл, если бы jscript запускался по умолчанию в процессе wscript. Но в jscript для этого в любом случае нужен ярлык windows для этого, который сам по себе может скрыть работу jscript без дополнительного кода.
Хотя, возможно, реализация этого кода была бы полезна при создании многопоточных приложений.
================
Вы должны сделать это в другом потоке, который вы скрыли.
Неважно, какой это будет поток, jscript, PS, Cmd.
Главное - дождаться его ответа с помощью сна или каким-то другим способом.
Самый простой способ получить ответ — в буфер обмена.
Exec останавливает ваш поток и работает только при получении параметров. Код останавливается, и вы ничего не можете с этим поделать.
Возможность запускать скрыто и получать результат есть в vbs. Omegastripes answer Скрыть окно командной строки при использовании Exec().
А по факту работа того скрипта как химера, но без перезапуска самого себя. Новый запуск собственного кода, при этом скрытого, в новом процессе в пространстве {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();
}
person
Garric
schedule
28.04.2021