Перенаправление вывода консольного приложения, запускаемого через ярлык.

У меня на домашнем сервере установлен VirtualBox, под управлением которого крутятся три виртуальные машины. Одна машина выделена под haproxy, на второй трудятся VPN сервер от SoftEther и FuguHub, а на третьей - всевозможный софт, начиная от облачного хранилища NextCloud и заканчивая Transmission. Но сейчас не об этом.

Если у вас есть виртуалки, обязательно наступит момент, когда захочется ими управлять. У меня на сервере установлен Windows 10 Pro, поэтому долгое время я просто использовал подключение к удаленному рабочему столу: подключался по RDP, запускал VirtualBox и выполнял требуемые действия. Но, как обычно, появилось смутное желание как-нибудь улучшить (?!), как говорится, сложившиеся практики. Однако, сейчас тоже не об этом.

В поставке VirtualBox имеется специальная программа с говорящим названием VBoxWebSrv. Эта программа предоставляет доступ к основному API (это то самое API, которое используется стандартным GUI клиентом VirtualBox), выступая в качестве HTTP сервера, который может обрабатывать SOAP запросы.

Естественно, сторонние разработчики не могли оставить без внимания такую возможность и, как результат, стали появляться утилиты для удаленного управления VirtualBox, такие, как RemoteBox и phpVirtualBox. И, конечно же, все эти утилиты требуют, чтобы в обязательном порядке был запущен экземпляр VBoxWebSrv.

В первое (и довольно длительное) время, я довольствовался тем, что для запуска этой программы сделал ярлык на Рабочем Столе. Все было здорово и замечательно: запустил один раз web сервер VirtualBox и пользуйся утилитами удаленного управления виртуальными машинами. Но потом я вычитал где-то в "этих ваших интернетах", что если перенаправить вывод VBoxWebSrv в специальное устройство с многозначительным названием nul, то можно получить значительный выигрыш в производительности. Сделать это перенаправление из командной строки не вызывает никаких затруднений:

vboxwebsrv > nul

Всего и делов-то. А вот как это сделать при запуске с использованием ярлыка?

Попытка прописать перенаправление вывода в свойствах ярлыка провалилась - программа просто перестала запускаться. И тогда пришлось вспоминать дела "давно минувших дней".

Когда выполняется консольное приложение, а VBoxWebSrv является именно консольным приложением, то, обычно, ввод/вывод осуществляется при помощи так называемых стандартных устройств ввода/вывода: в случае ввода - это клавиатура, а в случае вывода - экран (консоли). Но эти самые операции ввода/вывода можно перенаправить, например, осуществить ввод не с клавиатуры, а из файла (предварительно записав в него все, что нужно), или же вывод осуществить не на экран (окно консоли), а, например, в файл или в другое (именованное) устройство. Перенаправлением занимается командный процессор, но для этого ему надо дать указания при помощи специальных символов: >, >>, <, <<.

При запуске же программы из ярлыка командный процессор не имеет возможности обработать указания о необходимости перенаправления вывода (или ввода). Все, что указывается после имени выполняемого файла программы, рассматривается исключительно в качестве параметров, передаваемых именно этой самой программе.

И тут следует вспомнить, что командный процессор сам по себе тоже является программой, которой можно передавать параметры, и которую, конечно же, можно запускать из ярлыка. У стандартного командного процессора Windows cmd.exe есть ключ, который указывает ему, что надо выполнить команду, переданную в качестве параметра, после чего завершить выполнение. Это ключ /C. То есть, можно написать так:

cmd /C "vboxwebsrv"

и командный процессор выполнит программу vboxwebsrv (если найдет ее) и, после ее завершения, сам прекратит свое выполнение. А самое интересное (и важное для нас), что эту команду можно слегка подкорректировать и написать примерно так:

cmd /C "vboxwebsrv > nul"

и весь вывод программы vboxwebsrv будет перенаправлен в устройство с именем nul.

Вот, собственно и все. Ярлык должен вызывать не саму программу VBoxWebSrv, а командный процессор, которому, при помощи параметра, будет предписано выполнить нужную программу с требуемым перенаправлением вывода.

И, в завершении, хотелось бы отметить следующее: полый путь к VBoxWebSrv указывать не пришлось, потому что у ярлыка есть поле Start in. Если же надо указать полный путь, да еще в этом пути будут присутствовать пробелы, то могут возникнуть проблемы с использованием вложенных кавычек ("). Но и тут есть выход: существует ключ /S, который специальным образом обрабатывает вложенные кавычки - он отбрасывает первую кавычку (если она - первый символ передаваемого в cmd.exe параметра) и последнюю обнаруженую в параметре кавычку. Поэтому такая команда:

C:\Windows\System32\cmd.exe /S /C ""C:\Program Files\Oracle\VirtualBox\VBoxWebSrv.exe" > nul"

будет замечательным образом работать. И еще один важный момент: /S должен стоять перед /C. Вот теперь, пожалуй, все...