1

Тема: WshShell.Run "cmd.exe … echo … | clip.exe" … — пробелы в конце строк

Извините, если коряво сформулировал заголовок, но суть проблемы следующая.

Есть такая утилита CLIP.EXE, она есть для DOS (входит в пакет Win98 Resource Kit) и для NT (входит, вроде, в Server2003 ResKit), она позволяет копировать окно CMD (или COMMAND.COM в сеансе DOS в Win98/Me) в буфер обмена. Так вот, я хотел узнать, как можно с её помощью выводить в буфер обмена несколько строк, например, чтобы в буфере оказалось:

Hello1
Hello2

Далее привожу примеры, там и опишу непонятки:

' ПРИМЕР 1: нет пробела (тут выводится одна строка, это просто для примера)
WshShell.Run "cmd.exe /c echo Hello1|clip.exe", 1, False

' ПРИМЕР 2: так в CLIP попадает только Hello2, поэтому приходится ставить скобки
WshShell.Run "cmd.exe /c echo Hello1&echo Hello2|clip.exe", 1, False

' ПРИМЕР 3: ставлю скобки: (echo Hello1&echo Hello2)
WshShell.Run "cmd.exe /c (echo Hello_1&echo Hello_2)|clip.exe", 1, False
'
' теперь (т.е. в Примере 3) выводится в принципе нормально:
'
'   Hello1_
'   Hello2_
'
' но тогда в конце каждой строки почему-то появляются пробелы (для наглядности
' я их обозначил тут символом подчёркивания "_", но имеется в виду пробел)

' ПРИМЕР 4: как я понимаю, пробел добавляется из-за скобок:
WshShell.Run "cmd.exe /c (echo Hello1)|clip.exe", 1, False
' тут пробел есть (а в Примере 1 его нет, отличия только в наличии тут скобок)

Вопрос: как сделать так, чтобы в Примере 3 в конце строк не было дурацких пробелов?!

2 (изменено: -TOXA-, 2013-08-10 19:29:15)

Re: WshShell.Run "cmd.exe … echo … | clip.exe" … — пробелы в конце строк

У меня вот так все хорошо работает:

Text1 = "Hello1"
Text2 = "Hello2"

Set WshShell = CreateObject("WScript.Shell")
WshShell.Run "cmd.exe /C <nul set /p ""=" & Text1 & Text2 & """ | CLIP"
Программист - это не профессия, а смысл жизни (с)

3

Re: WshShell.Run "cmd.exe … echo … | clip.exe" … — пробелы в конце строк

Во-первых, ваш код (во всяком случае у меня) выводит в буфер (в смысле после вставки из буфера в Блокнот) всё в ОДНУ строку:

Hello1Hello2

А мне надо вот что: чтобы из скрипта VBS некая информация копировалась в буфер в виде НЕСКОЛЬКИХ строк и потом при вставке из буфера, например, в Блокнот по CTRL + V итп. в Блокноте было:

Hello1_  -- без вот этих концевых пробелов!
Hello2_  -- без вот этих концевых пробелов!

Во-вторых, про использование SET /P я знаю, но мне надо без него, так как в DOS (Win98) у SET ключа /P нет, я хочу универсальный способ для обоих OS, ну, или напишите, как сделать и для DOS, если знаете :)

4

Re: WshShell.Run "cmd.exe … echo … | clip.exe" … — пробелы в конце строк

Перенос строк - не проблема... Константа vbCrLf между переменными - все решает.. А вот без параметров set /p.. Подумать нужно..

Программист - это не профессия, а смысл жизни (с)

5

Re: WshShell.Run "cmd.exe … echo … | clip.exe" … — пробелы в конце строк

Ну хорошо, даже если с SET /P

Константа vbCrLf между переменными - все решает

Это вот так? :

WshShell.Run "cmd.exe /C <nul set /p ""=" & Text1 & VbCrLf & Text2 & """ | CLIP"

у меня это ничего не решило: всё равно выводит в одну строку:

Hello1Hello2

6

Re: WshShell.Run "cmd.exe … echo … | clip.exe" … — пробелы в конце строк

EgorS пишет:

как я понимаю, пробел добавляется из-за скобок

Не совсем, — если было бы перенаправление в файл, а не в конвейер, то лишние пробелы бы не добавлялись. Дело в особенности перенаправления в конвейер ввода-вывода внутренних, и, как частный случай, составных команд CMD.EXE: для них создаётся отдельный процесс CMD.EXE, при этом строка команды переформатируется (действительно, составная команда могла быть расположена на нескольких строках, а надо переделать в одну) и может быть «украшена» дополнительными пробелами.
Можно проверить, введя в CMD.EXE команду:

(echo One&echo Two&pause)|more

— и увидеть, что появился новый процесс с командной строкой (обратите внимание на пробелы):

C:\WINDOWS\system32\cmd.exe /S /D /c" ( echo One & echo Two & pause )"

Чтобы взять управление в свои руки следовало бы самому явно указать CMD.EXE с требуемой командной строкой, например:

cmd.exe /c (echo One^&echo Two^&pause)|more

В исходном случае это должно выглядеть как

WshShell.Run "cmd.exe /c cmd.exe /c (echo One^&echo Two)|clip.exe"

(ещё раз повторю: не укажи мы ещё один CMD.EXE, он всё равно будет запущен, но неподконтрольно нам).

EgorS пишет:

Во-вторых, про использование SET /P я знаю, но мне надо без него, так как в DOS (Win98) у SET ключа /P нет, я хочу универсальный способ для обоих OS

В DOS также нет скобок и «&».

EgorS пишет:

она позволяет копировать окно CMD (или COMMAND.COM в сеансе DOS в Win98/Me) в буфер обмена.

Ну, не окно, а свой входной поток, а CMD и COMMAND.COM вообще не при чём:

Set WshShell = CreateObject("WScript.Shell")
With WshShell.Exec("clip.exe").StdIn
    .WriteLine "Hello_1"
    .WriteLine "Hello_2"
    .Close
End With
EgorS пишет:

и для NT (входит, вроде, в Server2003 ResKit)

Не обнаружил.

7

Re: WshShell.Run "cmd.exe … echo … | clip.exe" … — пробелы в конце строк

wisgest пишет:

Чтобы взять управление в свои руки следовало бы самому явно указать CMD.EXE с требуемой командной строкой, например:

cmd.exe /c (echo One^&echo Two^&pause)|more

В исходном случае это должно выглядеть как

WshShell.Run "cmd.exe /c cmd.exe /c (echo One^&echo Two)|clip.exe"

— на самом деле, в таком случае скобки уже и не нужны:

cmd.exe /c echo One^&echo Two^&pause|more
WshShell.Run "cmd.exe /c cmd.exe /c echo One^&echo Two|clip.exe"

8

Re: WshShell.Run "cmd.exe … echo … | clip.exe" … — пробелы в конце строк

Благодарю за подробные разъяснения!

wisgest пишет:

Не обнаружил.

Извиняюсь, перепутал — CLIP.EXE для NT входит в Windows Server 2000 Resource Kit (а не в Server 2003). Я вообще когда-то давно скачивал эти Res-Kit'ы для Win98/2000/2003 с какого-то сайта, где их установщики уже раздербанили, вынув оттуда отдельные тулзы, чтобы были под рукой, поэтому у меня в голове Res-Kit'ы для Server2000/2003 представляются как одно и то же :)

wisgest пишет:

В DOS также нет скобок и «&»

Ой… Просто неохота было под Win98 проверять… А можете тогда написать, как в Win98 вывести в буфер в несколько строк, командой типа

WshShell.Run "command.com /c echo что_то_там |clip.exe", 1, False

т.е. чтобы в итоге в буфере было:

Hello1
Hello2

ну итд.

9

Re: WshShell.Run "cmd.exe … echo … | clip.exe" … — пробелы в конце строк

EgorS пишет:

А можете тогда написать, как в Win98 вывести в буфер в несколько строк,

А пример c WshShell.Exec("clip.exe") не работает?

EgorS пишет:

командой типа

WshShell.Run "command.com /c echo что_то_там |clip.exe", 1, False

1) с помощью bat-файла с необходимыми командами ECHO:

command.com /c tmp.bat|clip.exe

2) с помощью текстового файла с нужными строками:

command.com /c clip.exe<tmp.txt

3) без дополнительных файлов, направив на вход CLIP.EXE вывод самого скрипта, перезапустив скрипт с определённым ключом:

If WScript.Arguments.Named.Exists("echo") Then
    With WScript.StdOut
        .WriteLine "Hello_1"
        .WriteLine "Hello_2"
    End With
    WScript.Quit
End If

Set WshShell = CreateObject("WScript.Shell")
WshShell.Run _
  "command.com /c cscript.exe """ & WScript.ScriptFullName & """ /echo |clip.exe", _
  1, False

— проверить не на чем.

10

Re: WshShell.Run "cmd.exe … echo … | clip.exe" … — пробелы в конце строк

wisgest пишет:

А пример c WshShell.Exec("clip.exe") не работает?

в тех версиях WSH, которые штатно стоят на Win98/Me (win98 — 5.0, WinMe — 5.1), метода .EXEC  нет, поэтому там вываливается ошибка. .EXEC появился в WSH с версии 5.6, если поставить на Win98/Me WSH 5.6, то, наверное, работать будет, но проверять лень, да это и "некошерно" :) — я стараюсь обходиться штатными ср-вами.

wisgest пишет:

с помощью … (1)/(2)/(3)

я хотел бы избежать создания вспомогательных файлов, поэтому вар-ты (1) и (2) были бы нежелательны… Вариант (3), извиняюсь за тупость (я в этом плохо разбираюсь) — не понял, что там вообще происходит? :( буду думать …