<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title type="html"><![CDATA[Серый форум &mdash; WSH: Работа с командной строкой]]></title>
	<link rel="self" href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=2526&amp;type=atom" />
	<updated>2011-06-12T21:53:49Z</updated>
	<generator>PunBB</generator>
	<id>https://forum.script-coding.com/viewtopic.php?id=2526</id>
		<entry>
			<title type="html"><![CDATA[Re: WSH: Работа с командной строкой]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=49101#p49101" />
			<content type="html"><![CDATA[<p>А пока никто не знает, что делать с п. 5, <img src="//forum.script-coding.com/img/smilies/smile.png" width="15" height="15" /> разобрался, наконец, с вопросом выполнения из-под JScript команд, да и прочих приложений в консоли cmd. <br />Ну это мне сейчас все очевидно: win-&gt; dos -&gt; запись в StdIn (dos) -&gt; выполнение (dos) -&gt; чтение StdOut (dos) -&gt; win, а до этого тема порядком достала непонятками с корректным преобразованием кодировок.<br />Оформил в виде 2 функций (если надо больше модульности, легко встроить одну в другую):<br /></p><div class="codebox"><pre><code>/** Выполняет последовательно указанные аргументами команды в консоли cmd и возвращает вывод их выполнения одной строкой. 
 * Ввод-вывод в родной для WSH кодировке Win-1251, выполнение - в родной для консоли 866.
 */
function sExecDosCommand(sCommand, sAnotherCommand) {
  if (arguments.length == 0) return &quot;&quot;;
  var oSh = WScript.CreateObject(&quot;WScript.Shell&quot;);
  var oEx, oIn, oOut, sRes;
  try {
    oEx = oSh.Exec(&quot;cmd /k&quot;);
    oIn = oEx.StdIn;
    oOut = oEx.StdOut;
    for ( var i = 0; i &lt; arguments.length; i++)
      oIn.WriteLine(sDOS2Win(arguments[i] + &quot;&quot;, true));
    oIn.WriteLine(&quot;exit&quot;);
    sRes = sDOS2Win(oOut.ReadAll());
  }
  catch(e) {
    return(&quot;Err. &quot; + e.number + &quot;: &quot; + e.message);
  }
  //Минус внутренняя exit и последний перенос строки
  return sRes.substring(0, sRes.lastIndexOf(&quot;\r\n&quot;, sRes.length - 3) - 2); 
}

/** Возвращает текст sText преобразованный из кодировки cp866 (DOS) в windows-1251. 
 * Или наоборот - из 1251 в DOS - если флаг bInsideOut равен true.
 */
function sDOS2Win(sText, bInsideOut) {
  var aCharsets = [&quot;windows-1251&quot;, &quot;cp866&quot;];
  sText += &quot;&quot;;
  bInsideOut = bInsideOut ? 1 : 0;
  with (new ActiveXObject(&quot;ADODB.Stream&quot;)) { //http://www.w3schools.com/ado/ado_ref_stream.asp
    type = 2; //Binary 1, Text 2 (default) 
    mode = 3; //Permissions have not been set 0,  Read-only 1,  Write-only 2,  Read-write 3,  
    //Prevent other read 4,  Prevent other write 8,  Prevent other open 12,  Allow others all 16
    charset = aCharsets[bInsideOut];
    open();
    writeText(sText);
    position = 0;
    charset = aCharsets[1 - bInsideOut];
    return readText();
  }
}</code></pre></div><p>Пример использования:<br /></p><div class="codebox"><pre><code>WScript.Echo(&quot;***&quot; + sExecDosCommand(&quot;cd /d c:\\windows&quot;, &quot;dir *.ini&quot;, &quot;chcp&quot;, &quot;echo Из командной строки&quot;) + &quot;***&quot;);
WScript.Echo(&quot;WScript.Echo ФЫВА!&quot;);</code></pre></div><p>Кириллица корректно обрабатывается как на этапе воода данных, так и на выводе.</p><p>Результат выполнения:<br /></p><div class="codebox"><pre><code>***D:\00\_0_assets\_files-args-run&gt;cd /d c:\windows

C:\WINDOWS&gt;dir *.ini
 Том в устройстве C имеет метку bar_sys
 Серийный номер тома: 682B-5C99

 Содержимое папки C:\WINDOWS

07.05.2009  14:45                35 A5W.INI
8&lt; пропущено &gt;8
11.02.2011  16:24               323 win.ini
              22 файлов          9 492 байт
               0 папок   4 058 451 968 байт свободно

C:\WINDOWS&gt;chcp
Текущая кодовая страница: 866

C:\WINDOWS&gt;echo Из командной строки
Из командной строки***
WScript.Echo ФЫВА!</code></pre></div><p>Кстати, я так и не смог понять, как работает механизм преобразования кодировок ADODB.Stream: почему надо <em>вначале</em> писать в поток в той кодировке, которую хотим получить, а <em>затем</em> читать в той, из которой преобразуем. И не один я задавался этим вопросом, и <a href="http://forum.script-coding.com/viewtopic.php?pid=9094#p9094">кто-то даже кажется постиг причины</a>...<br />Но главное, работу функций проверил и перепроверил, ничего не напутано, они делают то, что должны делать, и называются правильно.</p>]]></content>
			<author>
				<name><![CDATA[jite]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=25851</uri>
			</author>
			<updated>2011-06-12T21:53:49Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=49101#p49101</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: Работа с командной строкой]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=49079#p49079" />
			<content type="html"><![CDATA[<p>После некоторых раздумий решил не открывать новой темы, а использовать эту для своеобразного подведения итогов. Название подходящее.<br /></p><div class="codebox"><pre><code>
/*--- Процесс чтения вывода приложения, запущенного из скрипта методом Exec() ---
 * 1) После запуска приложения, его StdOut.AtEndOfStream =&gt; false и переходит в true только после закрытия приложения
 * 2) Команда чтения (ReadLine, Read и ReadAll) работает так: ждет сколь угодно долго появления в буфере StdOut либо 
 * строки/символов вывода, либо положительного StdOut.AtEndOfStream (т.е. завершения работы приложения). В последнем 
 * случае возвращает финальную NewLine (\r\n) или - в случае с ReadLine(),- съедает ее, возвращая пустую строку (потому 
 * что всегда ест переносы). Т.е. даже если приложение ничего не выводит, с него прочтется хотя бы пустая строка
 * 3) Контролировать чтение потока из внешнего приложения - через while (!oEx.StdOut.AtEndOfStream)
 * 4) При больших объемах вывода за одну строку (более 4 KB) надо контролировать oSh.Exec -&gt; while (oEx.Status == 0), 
 *    внутри которого уже будет if (oEx.StdOut.AtEndOfStream) break;
 *    Если же следовать только стандартной проверке StdOut.AtEndOfStream, то при объеме вывода приложения более 4KB на 
 *    строку, чтение этого самого вывода просто вешается
 *    4.1) Следует учитывать, что при контроле через oEx.Status буфер oEx.StdOut к моменту завершения внешнего 
 *         приложения вполне может НЕ быть прочтен полностью, поэтому его следует дочитывать добавля ниже цикл из п.3 
 * 5) Если запущенное приложение и не думает завершаться (cmd /k), а мы с него читаем, то мы зависаем вместе с этим 
 * приложением навечно, что весьма печально.
*/</code></pre></div><p>Примечания: <br /> по п. 4 см. тему <a href="http://forum.script-coding.com/viewtopic.php?id=5839">JScript: Проблема с WshScriptExec.Exec</a><br /> по п. 4.1 Эффект можно наблюдать, если в примере, описанном постом выше, &quot;while (!oEx.StdOut.AtEndOfStream)&quot; заменить на &quot;while (oEx.Status == 0)&quot;</p><p>Вопросы:</p><p>1) Прошу уточнить, если что не так в данных рассуждениях.</p><p>2) П. 5. Что делать?<br />Например вот в этой ситуации, как заставить скрипт самостоятельно завершаться/прерываться?<br /></p><div class="codebox"><pre><code>var oSh = WScript.CreateObject(&quot;WScript.Shell&quot;);
var oEx = oSh.Exec(&quot;cmd /k&quot;);
var oOut = oEx.StdOut;
while (!oEx.StdOut.AtEndOfStream) {
  WScript.Echo(oOut.ReadLine());
}</code></pre></div>]]></content>
			<author>
				<name><![CDATA[jite]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=25851</uri>
			</author>
			<updated>2011-06-11T00:27:11Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=49079#p49079</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: Работа с командной строкой]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=49077#p49077" />
			<content type="html"><![CDATA[<div class="quotebox"><cite>mbf пишет:</cite><blockquote><p>Есть ли возможность получать стандартный вывод консоли непосредственно в процессе работы консольного приложения? Обычно он получается только после завершения работы приложения, а работа может занять длительное время... нужен хоть какой-то промежуточный лог.</p></blockquote></div><p>Конечно есть:<br /></p><div class="codebox"><pre><code>var oSh = WScript.CreateObject(&quot;WScript.Shell&quot;);
var oEx = oSh.Exec(&quot;cmd /k&quot;);
var oIn = oEx.StdIn;
var oOut = oEx.StdOut;
var n = 0;
oIn.WriteLine(sDOS2Win(&quot;cd /d c:\\windows&quot;, true)); //sDOS2Win() нужна при наличии в команде символов кириллицы
oIn.WriteLine(sDOS2Win(&quot;dir /s *.ini&quot;, true));
oIn.WriteLine(&quot;exit&quot;);
while (!oEx.StdOut.AtEndOfStream) {
  WScript.Echo(sDOS2Win(oOut.ReadLine()));
  n++;
}
WScript.Echo(&quot;Строк прочтено: &quot; + n);

/** Возвращает текст sText преобразованный из кодировки cp866 (DOS) в windows-1251. 
 * Или наоборот - из 1251 в DOS - если bInsideOut true.
 */
function sDOS2Win(sText, bInsideOut) {
  var aCharsets = [&quot;windows-1251&quot;, &quot;cp866&quot;];
  sText += &quot;&quot;;
  bInsideOut = bInsideOut ? 1 : 0;
  with (new ActiveXObject(&quot;ADODB.Stream&quot;)) { //http://www.w3schools.com/ado/ado_ref_stream.asp
    type = 2; //Binary 1, Text 2 (default) 
    mode = 3; //Permissions have not been set 0,  Read-only 1,  Write-only 2,  Read-write 3,  
    //Prevent other read 4,  Prevent other write 8,  Prevent other open 12,  Allow others all 16
    charset = aCharsets[bInsideOut];
    open();
    writeText(sText);
    position = 0;
    charset = aCharsets[1 - bInsideOut];
    return readText();
  }
}</code></pre></div>]]></content>
			<author>
				<name><![CDATA[jite]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=25851</uri>
			</author>
			<updated>2011-06-10T23:15:57Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=49077#p49077</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: Работа с командной строкой]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=46121#p46121" />
			<content type="html"><![CDATA[<p>Есть ли возможность получать стандартный вывод консоли непосредственно в процессе работы консольного приложения? Обычно он получается только после завершения работы приложения, а работа может занять длительное время... нужен хоть какой-то промежуточный лог.</p>]]></content>
			<author>
				<name><![CDATA[mbf]]></name>
			</author>
			<updated>2011-03-12T21:18:10Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=46121#p46121</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: Работа с командной строкой]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=16522#p16522" />
			<content type="html"><![CDATA[<p>Вы справку читаете?<br /></p><div class="codebox"><pre><code>oShell.run &quot;cmd /K dir C:\&quot;, 0</code></pre></div>]]></content>
			<author>
				<name><![CDATA[alexii]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=1844</uri>
			</author>
			<updated>2008-12-02T00:41:13Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=16522#p16522</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: Работа с командной строкой]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=16521#p16521" />
			<content type="html"><![CDATA[<p>Надо было написать подробнее:</p><div class="quotebox"><blockquote><p>…либо «cd /d c:\ <strong>&amp; dir</strong>».</p></blockquote></div>]]></content>
			<author>
				<name><![CDATA[alexii]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=1844</uri>
			</author>
			<updated>2008-12-02T00:38:27Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=16521#p16521</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: Работа с командной строкой]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=16519#p16519" />
			<content type="html"><![CDATA[<p>The gray Cardinal, спасибо за интересный пример &quot;VBScript: запуск консольного приложения с чтением его вывода&quot;. Возьму на вооружение.<br />Обратил внимание, что при старте скрипта мелькает окно консоли. Как это окно &quot;загасить&quot;?</p>]]></content>
			<author>
				<name><![CDATA[mon]]></name>
			</author>
			<updated>2008-12-01T21:32:57Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=16519#p16519</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: Работа с командной строкой]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=16517#p16517" />
			<content type="html"><![CDATA[<p>alexii, Ваше &quot;используйте ... «dir c:\»&quot; - помогло.<br />Строку кода:<br /></p><div class="codebox"><pre><code>oShell.run &quot;cmd /K CD C:\ &amp; Dir&quot;</code></pre></div><p>изменил на:<br /></p><div class="codebox"><pre><code>oShell.run &quot;cmd /K CD &amp; dir C:\&quot;</code></pre></div><p>Спасибо!</p>]]></content>
			<author>
				<name><![CDATA[mon]]></name>
			</author>
			<updated>2008-12-01T21:12:20Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=16517#p16517</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: Работа с командной строкой]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=16515#p16515" />
			<content type="html"><![CDATA[<p>Всё правильно, так и должно быть. Команда «cd &lt;Диск:\Путь&gt;» меняет текущую папку на указанном диске, но <strong>не меняет сам текущий диск</strong>. Используйте либо «dir <strong>c:\</strong>», либо «cd <strong>/d</strong> c:\». Посмотрите также в сторону пары «pushd/popd».</p><p>P.S. Будьте осторожны с использованием UNC-путей.</p>]]></content>
			<author>
				<name><![CDATA[alexii]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=1844</uri>
			</author>
			<updated>2008-12-01T20:52:21Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=16515#p16515</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: Работа с командной строкой]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=16513#p16513" />
			<content type="html"><![CDATA[<p>Уточнение: если скрипт запускать из любой папки диска С - то отрабатывает корректно. Если скрипт запускается с другого диска, то &quot;результатом работы скрипта является не список файлов и папок диска С (как подразумевается в коде скрипта), а той директории, откуда запущен скрипт&quot;.</p>]]></content>
			<author>
				<name><![CDATA[mon]]></name>
			</author>
			<updated>2008-12-01T20:47:19Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=16513#p16513</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: Работа с командной строкой]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=16506#p16506" />
			<content type="html"><![CDATA[<p>Хмм… У меня и приведённый код работает корректно.</p>]]></content>
			<author>
				<name><![CDATA[alexii]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=1844</uri>
			</author>
			<updated>2008-12-01T19:25:26Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=16506#p16506</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: Работа с командной строкой]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=16499#p16499" />
			<content type="html"><![CDATA[<p><a href="http://forum.script-coding.com/viewtopic.php?id=923">VBScript: запуск консольного приложения с чтением его вывода</a><br />Наверное, просто добавить второй амперсанд.</p>]]></content>
			<author>
				<name><![CDATA[The gray Cardinal]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=2</uri>
			</author>
			<updated>2008-12-01T18:25:36Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=16499#p16499</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[WSH: Работа с командной строкой]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=16496#p16496" />
			<content type="html"><![CDATA[<p>Возникла необходимость работы с CMD. Глянул в хелп Микрософта &quot;Windows Script Host&quot;, там приведен такой пример (ключевое слово strCommand, Example 2): <br /></p><div class="codebox"><pre><code>Dim oShell
Set oShell = WScript.CreateObject (&quot;WSCript.shell&quot;)
oShell.run &quot;cmd /K CD C:\ &amp; Dir&quot;
Set oShell = Nothing</code></pre></div><p>Пример работает, но есть проблема - результатом работы скрипта является не список файлов и папок диска С (как подразумевается в коде скрипта), а той директории, откуда запущен скрипт.<br />Подскажите пожалуйста, где &quot;собака порылась&quot;?</p>]]></content>
			<author>
				<name><![CDATA[mon]]></name>
			</author>
			<updated>2008-12-01T18:15:25Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=16496#p16496</id>
		</entry>
</feed>
