Хочу рассказать вам историю, как решение конкретных прикладных задач привело меня к использованию реестра Windows в качестве платформы для хранения и исполнения кода.

Приоритеты


Давным-давно, когда я переходил с ХР на Семерку, одним из важных преимуществ новой системы я считал введение приоритетов на ввод-вывод и на пейджинг, а не только на процессор. Однако сейчас у нас Десятка на дворе, а удобных штатных средств управления этими приоритетами так и не появилось.
Как я с удивлением обнаруживаю, большинство пользователей вообще не в курсе о такой замечательной возможности. Их удовлетворяет опция в Task Manager по смене текущего приоритета CPU для уже запущенного процесса (и то только если им это будет позволено). А ситуацию, когда даже выставленный в LOW фоновый процесс своим дисковым обменом или свопингом мешает работать более приоритетным задачам, считают неизбежным злом.

Некоторые, устав от обращения к Task Manager при каждом запуске, вставляют в ярлыки запуска критичных программ перед самим объектом что-то вроде

cmd /c start /realtime

Это позволяет запустить что-то с приоритетом HIGH (а не realtime, как они думают), но никак не затрагивает проблему с приоритетом ввода-вывода. Кроме того, ряд приложений используют файл-запускальщик, который, в свою очередь, запускает основную программу. А она в таком варианте будет запущена с приоритетом по умолчанию, и лишь уже не нужный запускальщик будет красоваться в Task Manager с приоритетом HIGH.

Решением проблемы является создание веток в «Image File Execution Options» в реестре, но руками это делать достаточно утомительно.

Конечно, есть ряд сторонних приложений, которые позволят вам прописать правильные ветки в реестре для нужной программы, но я специально упомянул в первом абзаце слово «штатных»: зачастую это нужно делать на машине, на которой запрещена установка сторонних экзешников, отключены сменные носители, и затруднено получение (как из интернета, так и по почте) любых исполняемых файлов, пакетов, архивов, BAT, CMD и даже REG-файлов. В особо серьезных случаях контролируется реальное содержимое файла на предмет смены типа или внедрение в документ-контейнер вложения недозволенного типа.

Итак, намаявшись с реестром, я поставил себе задачу написать утилитку, которая позволяет менять базовый приоритет запуска программы как для CPU, так и для IO и Paging, и при этом:

  • использует только штатные средства, присутствующие в дефолтной инсталляции windows.
  • избавляет от необходимости вписывать имя файла (например, активируясь из его контекстного меню)
  • избавляет от необходимости во введении пароля администратора в командной строке или в предварительном открытии сессии под администратором (единственно, что допустимо – всплывающее окно UAC)
  • (необязательно) не оставляет никаких постоянных файлов на диске (дабы не нервировать сотрудников Первого отдела)
  • (необязательно) поддерживает деинсталляцию
  • (главное) может быть получена, как текст (по почте или с web-страницы), а не файл.

Последнее требование важно не только в плане доставки. Это универсальный способ показать пользователю, что утилита не содержит закладок или нежелательного функционала. Заодно и выполнение одного из требований GPL – предоставления исходного кода.

Изложенные требования определили выбор, что это должен быть скриптовый язык, последующие исследования показали, что даже к PowerShell прибегать не нужно, достаточно будет обычного синтаксиса CMD и VBS, затем попробовал уместить одно действие в одну строку, а не в bat-файл, а далее, так как в любом случае требовалась запись в реестр, родилась мысль уместить все в самом реестре, тем самым выполнив условие по отсутствию файлов.

В итоге получилась утилитка, которая выглядит, как выпадающее подменю в свойствах исполняемых файлов:

image

А вот она сама:

Windows Registry Editor Version 5.00 

;Copyright 2016 Trottle 
;This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3. 
;This program is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
;See <http://www.gnu.org/licenses/> for more details. 

[-HKEY_CLASSES_ROOT\exefile\shell\Bpc] 

[HKEY_CLASSES_ROOT\exefile\shell\Bpc] 
"HasLUAShield"="" 
"MUIVerb"="Set base priority" 
"subcommands"=""

[HKEY_CLASSES_ROOT\exefile\shell\Bpc\shell\01low] 
"MUIVerb"="Idle CPU, lowest IO, low paging" 
"Icon"="comres.dll,9" 

[HKEY_CLASSES_ROOT\exefile\shell\Bpc\shell\01low\command] 
@="cmd /q /c echo Windows Registry Editor Version 5.00>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & for /f \"delims=<\" %%i in (\"%1\") do echo [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%%~nxi\\PerfOptions]>>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & echo \"CpuPriorityClass\"=dword:00000001>>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & echo \"IoPriority\"=dword:00000000>>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & echo \"PagePriority\"=dword:00000001>>%%TEMP%%\\pr.reg & regedit /s %%TEMP%%\\pr.reg & del %%TEMP%%\\pr.reg & msg * %~ni priority is set to IDLE" 

[HKEY_CLASSES_ROOT\exefile\shell\Bpc\shell\02below] 
"MUIVerb"="Below normal CPU, low IO" 
"Icon"="comres.dll,12" 

[HKEY_CLASSES_ROOT\exefile\shell\Bpc\shell\02below\command] 
@="cmd /q /c echo Windows Registry Editor Version 5.00>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & for /f \"delims=<\" %%i in (\"%1\") do echo [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%%~nxi\\PerfOptions]>>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & echo \"CpuPriorityClass\"=dword:00000005>>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & echo \"IoPriority\"=dword:00000001>>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & echo \"PagePriority\"=->>%%TEMP%%\\pr.reg & regedit /s %%TEMP%%\\pr.reg & del %%TEMP%%\\pr.reg & msg * %~ni priority is set to BELOW NORMAL" 

[HKEY_CLASSES_ROOT\exefile\shell\Bpc\shell\03above] 
"Icon"="comres.dll,8" 
"MUIVerb"="Above normal CPU" 

[HKEY_CLASSES_ROOT\exefile\shell\Bpc\shell\03above\command] 
@="cmd /q /c echo Windows Registry Editor Version 5.00>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & for /f \"delims=<\" %%i in (\"%1\") do echo [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%%~nxi\\PerfOptions]>>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & echo \"CpuPriorityClass\"=dword:00000006>>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & echo \"IoPriority\"=->>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & echo \"PagePriority\"=->>%%TEMP%%\\pr.reg & regedit /s %%TEMP%%\\pr.reg & del %%TEMP%%\\pr.reg & msg * %~ni priority is set to ABOVE NORMAL" 

[HKEY_CLASSES_ROOT\exefile\shell\Bpc\shell\04high] 
"MUIVerb"="High CPU" 
"Icon"="comres.dll,16" 
"CommandFlags"=dword:00000040

[HKEY_CLASSES_ROOT\exefile\shell\Bpc\shell\04high\command] 
@="cmd /q /c echo Windows Registry Editor Version 5.00>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & for /f \"delims=<\" %%i in (\"%1\") do echo [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%%~nxi\\PerfOptions]>>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & echo \"CpuPriorityClass\"=dword:00000003>>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & echo \"IoPriority\"=->>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & echo \"PagePriority\"=->>%%TEMP%%\\pr.reg & regedit /s %%TEMP%%\\pr.reg & del %%TEMP%%\\pr.reg & msg * %~ni priority is set to HIGH" 

[HKEY_CLASSES_ROOT\exefile\shell\Bpc\shell\06ask] 
"MUIVerb"="Show current priorities" 
"Icon"="shell32.dll,23" 

[HKEY_CLASSES_ROOT\exefile\shell\Bpc\shell\06ask\command] 
@="cmd /q /c for /f \"delims=<\" %%i in (\"%1\") do reg query \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%%~nxi\\PerfOptions\" /s | msg *" 

[HKEY_CLASSES_ROOT\exefile\shell\Bpc\shell\07default] 
"MUIVerb"="Restore to default" 
"Icon"="comres.dll,4" 

[HKEY_CLASSES_ROOT\exefile\shell\Bpc\shell\07default\command] 
@="cmd /q /c echo Windows Registry Editor Version 5.00>%%TEMP%%\\pr.reg & echo.>>%%TEMP%%\\pr.reg & for /f \"delims=<\" %%i in (\"%1\") do echo [-HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%%~nxi\\PerfOptions]>>%%TEMP%%\\pr.reg & regedit /s %%TEMP%%\\pr.reg & del %%TEMP%%\\pr.reg & msg * %~ni priority is restored to default" 

; If you do not want to have uninstaller you can skip next part: 

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\BpcSubMenu] 
"DisplayName"="'Set base priority' submenu" 
"DisplayIcon"="imageres.dll,73" 
"UninstallString"="cmd /q /c echo Windows Registry Editor Version 5.00>%TEMP%\\pr.reg & echo.>>%TEMP%\\pr.reg & echo [-HKEY_CLASSES_ROOT\\exefile\\shell\\Bpc]>>%TEMP%\\pr.reg & echo.>>%TEMP%\\pr.reg & echo [-HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\BpcSubMenu]>>%TEMP%\\pr.reg & regedit /s %TEMP%\\pr.reg & del %TEMP%\\pr.reg" 
"DisplayVersion"="1.1" 
"URLInfoAbout"="http://habrahabr.ru/post/317802/" 
"NoModify"=dword:00000001 
"NoRepair"=dword:00000001

Соответственно, процесс инсталляции выглядит так: получаем вышеизложенный исходник, сохраняем его, как reg-файл, и запускаем. После чего его можно смело удалять. А мы получаем новое подменю по правому клику мышки на исполняемом файле.

При этом, правда, стоит учитывать две вещи:

1. То, что делает утилитка, разрешено только админам, поэтому, если вы не член группы админов, одним только запросом UAC не обойдется.

2. Windоws почему-то показывает подменю не только на самих.ЕХЕ, но и на их ярлыках, но при этом не вызывает на последних пункты подменю.

Также вы, должно быть, заметили, что:

— во-первых, нет приоритета Realtime,
— во вторых, все приоритеты, кроме CPU, идут только в сторону уменьшения
— в третьих, приоритет Paging ставится чуть выше, чем приоритет IO.

Это соответствует рекомендациям Microsoft по работе с приоритезацией:

— уменьшать у ненужного, а не увеличивать у нужного;
— свопинг важнее работы с файлами;
— не работать с Realtime («честный» риалтайм действительно может быть опасен для стабильности всей системы, поэтому через реестр ни его, ни высокий приоритет IO не выставить).

Брандмауэр


Между первой и второй промежуток небольшой – решил таким же образом упростить работу со штатным брандмауэром. Многим он хорош, но не удобством обращения с ним. В данном случае решил ускорить создание разрешений или запрещений на программу. (Считаю возможность привязывать правила к программам главным преимуществом внутреннего брандмауэра перед внешним.) Я использую брандмауэр в режиме блокировки исходящих соединений по умолчанию, поэтому добавлять новую программу, как правило, приходится часто.

Получилось такое:

image

и текст:

Windows Registry Editor Version 5.00 

;Copyright 2016 Trottle 
;This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3. 
;This program is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
;See <http://www.gnu.org/licenses/> for more details. 

[-HKEY_CLASSES_ROOT\exefile\shell\FWc] 

[HKEY_CLASSES_ROOT\exefile\shell\FWc] 
"MUIVerb"="Set firewall rules" 
"Icon"="imageres.dll,102" 
"subcommands"=""

[HKEY_CLASSES_ROOT\exefile\shell\FWc\shell\01] 
"MUIVerb"="block inbound" 
"Icon"="imageres.dll,100" 

[HKEY_CLASSES_ROOT\exefile\shell\FWc\shell\01\command] 
@="cmd /q /c echo CreateObject(\"Shell.Application\").ShellExecute \"cmd\", \"/q /c chcp 1251 & netsh advfirewall firewall add rule name=\"\"%1\"\" dir=in action=block program=\"\"%1\"\" enable=yes | msg * \", \"\", \"runas\" > %%temp%%\\ev.vbs & cscript %%temp%%\\ev.vbs & del %%temp%%\\ev.vbs" 

[HKEY_CLASSES_ROOT\exefile\shell\FWc\shell\02] 
"MUIVerb"="allow inbound" 
"Icon"="imageres.dll,101" 

[HKEY_CLASSES_ROOT\exefile\shell\FWc\shell\02\command] 
@="cmd /q /c echo CreateObject(\"Shell.Application\").ShellExecute \"cmd\", \"/q /c chcp 1251 & netsh advfirewall firewall add rule name=\"\"%1\"\" dir=in action=allow program=\"\"%1\"\" enable=yes | msg * \", \"\", \"runas\" > %%temp%%\\ev.vbs & cscript %%temp%%\\ev.vbs & del %%temp%%\\ev.vbs" 

[HKEY_CLASSES_ROOT\exefile\shell\FWc\shell\03] 
"Icon"="imageres.dll,100" 
"MUIVerb"="block outbound" 

[HKEY_CLASSES_ROOT\exefile\shell\FWc\shell\03\command] 
@="cmd /q /c echo CreateObject(\"Shell.Application\").ShellExecute \"cmd\", \"/q /c chcp 1251 & netsh advfirewall firewall add rule name=\"\"%1\"\" dir=out action=block program=\"\"%1\"\" enable=yes | msg * \", \"\", \"runas\" > %%temp%%\\ev.vbs & cscript %%temp%%\\ev.vbs & del %%temp%%\\ev.vbs" 

[HKEY_CLASSES_ROOT\exefile\shell\FWc\shell\04] 
"MUIVerb"="allow outbound" 
"Icon"="imageres.dll,101" 
"CommandFlags"=dword:00000040

[HKEY_CLASSES_ROOT\exefile\shell\FWc\shell\04\command] 
@="cmd /q /c echo CreateObject(\"Shell.Application\").ShellExecute \"cmd\", \"/q /c chcp 1251 & netsh advfirewall firewall add rule name=\"\"%1\"\" dir=out action=allow program=\"\"%1\"\" enable=yes | msg * \", \"\", \"runas\" > %%temp%%\\ev.vbs & cscript %%temp%%\\ev.vbs & del %%temp%%\\ev.vbs" 

[HKEY_CLASSES_ROOT\exefile\shell\FWc\shell\06] 
"MUIVerb"="Show firewall panel" 
"Icon"="imageres.dll,109" 

[HKEY_CLASSES_ROOT\exefile\shell\FWc\shell\06\command] 
@="mmc.exe wf.msc" 

; If you do not want to have uninstaller you can skip next part: 

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\FWcSubMenu] 
"DisplayName"="'Set firewall rules' submenu" 
"DisplayIcon"="imageres.dll,102" 
"UninstallString"="cmd /q /c echo Windows Registry Editor Version 5.00>%TEMP%\\pr.reg & echo.>>%TEMP%\\pr.reg & echo [-HKEY_CLASSES_ROOT\\exefile\\shell\\FWc]>>%TEMP%\\pr.reg & echo.>>%TEMP%\\pr.reg & echo [-HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\FWcSubMenu]>>%TEMP%\\pr.reg & regedit /s %TEMP%\\pr.reg & del %TEMP%\\pr.reg" 
"DisplayVersion"="1.1" 
"URLInfoAbout"="http://habrahabr.ru/post/317802/" 
"NoModify"=dword:00000001 
"NoRepair"=dword:00000001 

Замечу, что, в отличие от первой утилитки, здесь клик на одном пункте не отменяет другие, т.е. создание запрещающего правила не стирает разрешающее, и наоборот. Сделано это на случай, когда создается несколько правил на одну программу и в дальнейшем каждое уточняется (по портам, адресам, режимам, и т.д.). Таким образом, если кликнуть и на «allow», и на «block», будет создано 2 правила, а сетевой доступ программе будет закрыт (запрещающие правила имеют приоритет перед разрешающими).

Деинсталляция для обеих утилит штатная – заходим в «Программы и компоненты» и удаляем:

image

P.S. Друзья, благодаря вашим отзывам улучшил отображение подменю в Win10, исходники обновлены до версии 1.1
Поделиться с друзьями
-->

Комментарии (35)


  1. icoz
    17.12.2016 00:06

    Забавно. Спасибо


  1. ReinRaus
    17.12.2016 01:27

    Спасибо. Пригодится. Есть ли возможность аналогичным удобным путем ограничить сетевой траффик ?


    1. roversochi
      28.03.2017 15:09

      Вместе со скоростью теряется и крутящий момент, так что медленно она может ехать очень плохо. Да и в таком режиме начинают проявляться отличия моторчиков. Например при напруге в 6 вольт они оба крутятся вроде бы одинаково, а вот при ШИМ на 3 вольта, уже есть отличия. А например при 2 вольт один мотор вообще уже не справляется.


  1. tzlom
    17.12.2016 02:05

    Не хватает записей в «Установка и удаление» и деинсталлятора по той же методике.


    1. Trottle
      17.12.2016 13:51

      Судя по фразе «Установка и удаление», а не «Программы и компоненты», вы всё ещё используете ХР. Жаль, нет её сейчас под рукой, но я рассчитывал, что первая утилитка будет и под ней работать, посему обошелся без PowerShell (правда, пользы от нее там не так много — в ХР только приоритет CPU поддерживается). А вот вторая использует новый синтаксис netsh и в ХР не заработает…


  1. safinaskar
    17.12.2016 04:27
    +10

    Это прекрасно. Вы используете винду как линукс. Поясню свою мысль. На линуксе можно по-быстрому нахакать какой-нибудь шел-скрипт, который будет генерить скрипт на седе, который будет генерить какой-нибудь юнит-файл для systemd, который ещё чё-нибудь куда-нибудь пропишет и так далее и тому подобное. Теперь выясняется, что в винде так тоже можно. В связи с этим у меня к вам как к эксперту по использованию винды в качестве линукса (ну и к другим хабравчанам), есть пара вопросов. Ответьте, если не сложно. Ну или ссылки дайте или направление хотя бы.


    • В линуксе при написании скриптов на баше, программ на си, всемозможных sed'овых регексов и так далее нужно знать, что и когда эскейпить, помещать в кавычки и так далее. Скажем, вот так писать нельзя: find -name *.txt, надо так: find -name '*.txt', а вот у rm, напротив, надо так: rm *.txt. Расскажите, как с этим в винде. Как работают все эти кавычки в cmd? Скажем, в баше баш сам звёздочки раскрывает. А в винде что?
    • Тесно связанный с предыдущим вопрос. В линуксе есть exec-команды и есть shell-команды (термины мои, но сами понятия, стоящие за ними, разумеется, не мои). Exec-команда — это команда, предназначенная непосредственно для исполнения ядром (т. е. для передачи системным вызовам семейства exec). Shell-команда — это команда, которая будет обработана шелом. Скажем, chroot воспринимает свои аргументы, начиная со второго, как exec-команду, т. е. сразу передаёт её ядру. Поэтому, скажем, нельзя написать chroot / cd. Т. к. cd — это внутренная команда bash'а, здесь так не прокатит. А вот, скажем, ssh принимает в качестве аргументов, начиная со второго, shell-команду. Так что писать ssh user@host cd можно (хотя ничего эта команда не даст), да и вообще вторым аргументом в ssh можно запихнуть любую башевую команду, пускай даже с ветвлениями и прочее. С chroot такое не прокатит. Как со всем этим обстоят дела в винде? Если запустить команду "cmd /q /c ..." (вижу у вас там в посте такую) каким конкретно преобразованиям будет подвергнута команда, переданная в cmd (ну там, убирания кавычек и т. д.)? Какими функциями WinAPI запускаются команды для запуска сразу ядром и какими — шелом? И вообще, в линуксе shell-команда — это строка, а exec-команда — это массив строк. А в винде? Как формируется argv[], который получает программа на си?
    • Каковы, скажем так, "правила поведения" для виндовых программ (всех, консольных и графических)? Как им себя вести, чтобы не мешать другим программам? Где, скажем, хранить настройки и прочее-прочее? В линуксах я знаю, конфиги — в /etc, логи — в /var/log и так далее. В линуксе есть хороший гайд по требования к пакетам свободного ПО: https://wiki.debian.org/UpstreamGuide. На многие мелкие темы можно найти кучу подробных ответов, скажем, где хранить временные файлы: http://0pointer.net/blog/projects/tmp.html .
    • А существуют ли специфичные "правила поведения" для консольных программ? Как лучше всего распространять консольные программы? Неужели для консольной программы писать графический инсталлятор со всякими Далее-Далее-Готово?
    • Как распространять библиотеки на си? Чтобы пользователь после установки мог сразу их заюзать в своём visual studio. Куда хедеры класть? Вот у меня есть библиотека на си: http://github.com/safinaskar/libsh. Поддерживает линукс и винду. На линуксе собирается и ставится при помощи "cmake. && make && make install". На винде собирается при помощи "cmake. && cmake --build .". А вот что делать дальше, куда ставить и главное, зачем, не понятно. Куда принято ставить библиотеки в винде и как их потом использовать?

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


    1. Akon32
      17.12.2016 10:40
      +1

      Неужели для консольной программы писать графический инсталлятор со всякими Далее-Далее-Готово?

      Это не относится к только консольным программам, но можно взять генератор инсталляторов (InnoSetup etc) и написать только небольшой конфиг к нему (есть даже графические утилиты для "написания" таких конфигов). Полученный инсталлятор, как правило, можно запустить и в "тихом" режиме.


    1. RumataEstora
      17.12.2016 12:23
      +1

      В винде шаблоны раскрываются аналогично интерпретатором (в большинстве случаев). Но надо всё закавычивать (например, dir "", чтобы вывести каталог с пробелом)


      Встроенные команды надо передавать интерпретатору, то есть cmd /c "dir c:\"


      Есть проблема манипуляции с аргументами: %1, %2,… и % для доступа ко всем аргументам. Но в большинстве случаев % бесполезен. Нет такой возможности как ${@:n:m}. И кавычки снова надо "закавычивать" или "искейпить".


      На отальные вопросы будет ответ — как бог на душу положит. Кто-то работает с реестром, кто-то пишет ini-файлы и разбирает их, кто-то пишет конфиг-файлы по типу самого скрипта (аналогия, sourced фвйлы в юникс).


      1. RumataEstora
        17.12.2016 12:30

        имелось в виду
        например, dir "* *", чтобы вывести каталог с пробелом
        %1, %2,… и %* для доступа ко всем аргументам. Но в большинстве случаев %* бесполезен


    1. Trottle
      17.12.2016 14:03

      Тут уже откликнулись на ваш пост, так что добавлю немного: действительно, с разделителями (да и не только) единообразия нет:
      — во-первых, строки команд в реестре — это не полноценная shell-строка, а именно «программа и её аргументы», т.е. если вы зададите встроенную команду (echo, start, set и т.д.), вас не поймут. Если используете %переменную%, вас не поймут, если зададите команду & команду, вас не поймут. Поэтому в тексте вы часто видите «cmd /c» — это получение «полноценной» командной строки
      — набор параметров, передаваемых в программу, в реестре свой — %0=%1,%l,%w,%i,…
      — обработка разделителей -вообще мрак: вы видите в примерах, что \ и " нужно предварять \, < и > — оставлять как есть, а % где-то нужно дублировать, а где-то нет.


    1. kush07
      17.12.2016 14:20

      Интересно, давай статью!!!


      1. safinaskar
        17.12.2016 15:44
        -2

        Мне расхотелось писать статью, в следующей жизни напишу :)


    1. Ivanq
      17.12.2016 14:20

      Все не знаю, но попробую ответить.

      • Звездочки не раскрываются, этим должна заниматься программа. Например, del dir/* (в linux это rm) удаляет все файлы в директории dir, при этом кавычки вокруг «dir/*» можно ставить, а можно нет. И так в любом случае со звездочкой. Но зато кавычки можно ставить только вокруг всего параметра (например, так можно: del "file.txt"; "/path to my program/some good program.exe" data.txt — здесь в кавычки берем путь к исполняемому файлу, так как в нем пробелы). А так нельзя: del "file with spaces".txt
      • Чего-то похожего на chroot в Windows я не знаю, но разделения на shell- и exec-команд нет. Разделение только на исполняемые файлы и команды. Например, Вы можете из командной строки выполнить:
        C:\Users\user\> dir C:\ /w
        ...
        Users         Program Files         Program Data
        ...
        
        C:\Users\user\> "C:\Program Files\Google\Chrome\chrome.exe"
        # Chrome запустился
        

        А, скажем, выполнить файл dir C:\ /w из, скажем, VBS, не получится, зато получится chrome.exe.

        cmd /q /c запускает команду как из шелла, то есть, скажем, пример выше нужно написать так, чтобы он заработал не из командной строки: cmd /q /c "dir C:\ /w". Я обернул команду в кавычки. Экранирование — это, внезапно, ^. То есть выполнить dir "C:\long path" можно примерно так: cmd /q /c "dir ^"C:\long path^""

        Пусть программа лежит в корне, перед выполнением сделали cd C:\. argv[] при выполнении команды C:\exec abc def будет "C:\exec", "abc", 'def". При выполнении exec abc def будет "exec" "abc" "def" и т. д. Кавычки остаются.
      • Настройки и прочее-прочее принято хранить в «C:\Program Data\Chrome», «C:\Users\user\AppData\Roaming\Chrome», «C:\Users\user\AppData\Local\Chrome» или в реестр. Логи туда же (только в реестр нельзя). Временные файлы в «C:\Users\user\AppData\Local\Temp».


      1. PsyHaSTe
        19.12.2016 19:26

        Логи можно вполне прилично складывать в EventLog


    1. safinaskar
      17.12.2016 15:38
      -1

      Спасибо за ответы. В общем, больше не надо, я дальше как-нибудь сам разберусь. Разве что ссылки не помешают


  1. Samoglas
    17.12.2016 07:49

    Прикольный хак

    Для автоматического повышения приоритета юзаю AnVir, не помогало, все съедал своп, но как психотерапия сойдет.

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


  1. RumataEstora
    17.12.2016 12:13

    "UninstallString"="cmd /q /c echo Windows Registry Editor Version 5.00>%TEMP%\\pr.reg ...


    Не пишите так больше.


    1. можно допустить ошибку и все пойдет совсем не так.
    2. можно писать во временные файлы, потом запускать regedit /s, но для этого давно есть команды reg add / reg delete, Пользуйтесь ими
    3. Всё что больше 2-3 слов пишите в скрипт. То есть не вызов кучи cmd /c с параметрами, а один простой пакетный скрипт. И короче, и понятнее, и параметры можно передавать.


    1. Trottle
      17.12.2016 14:10

      1. Errare humanum est, что поделаешь… Это может случиться где угодно.
      2. Вы не совсем поняли — в двух утилитках я использую разные способы повышения привилегий. Если бы я использовал REG для внесения в реестр, мне пришлось бы делать VBS-ную обвязку, чтобы команда сработала. А у regedit очень удобный «побочный эффект» — он сам рисует окно UAC
      3. Поначалу это и было скриптом, но потом я понял, что смогу выполнить и 4-й пункт задачи.


  1. igor_kuznetsov
    17.12.2016 14:20

    А зачем принудительно повышать приоритет? Я так понял для лишнего тяжело софта?


    1. Trottle
      17.12.2016 14:25

      не столько для тяжелого, сколько для критичного к задержкам (например, для VR здорово помогает убрать отдельные рывки — а это там самое неприятное), а они возникают чаще по причине ожидания диска, а не CPU. Но все в основном крутят на подъем приоритета, хотя лучше — наоборот снижать у фоновых процессов.


  1. Kriminalist
    17.12.2016 14:20

    Спасибо, очень понравился и подход, и исполнение.


  1. titanrain
    17.12.2016 16:10

    Что-то у меня вместо разделяющей полосы отображается надпись «05delim».


    1. Trottle
      17.12.2016 16:13

      Это интересно… У меня на всех машинах — если пункт подменю без MUIVerb, то выводится горизонтальная черта. (в отличие от пунктов основного меню — там если нет MUIVerb, берется название раздела.) Какая у вас версия Windows?


      1. titanrain
        17.12.2016 17:06

        Windows 10 1607 x64


      1. DariuS32bit
        17.12.2016 17:58

        У меня так же «05delim»
        Windows 10 Pro 1607 x64

        image


        1. Trottle
          17.12.2016 17:59

          OK, изменил способ задания разделителя, исходники обновлены до версии 1.1 (можно ставить поверх предыдущей, без анинсталла)


          1. titanrain
            18.12.2016 04:27

            То есть вы убрали разделитель, а не изменили способ его создания (разделитель исчез)?


          1. DariuS32bit
            18.12.2016 16:28

            Теперь разделителя вообще нету)

            image


  1. VasiliyLiGHT
    17.12.2016 16:13

    Прощай Диспетчер задач (на время)


    1. Trottle
      17.12.2016 16:18

      Почему «прощай»? Как раз в нем — сортируем по максимальному CPU, «Прочитано-» или «Записано байт», далее по right click «Открыть место хранения файла» и снижаем ему приоритет.
      Единственно, осторожней с svchost.exe — это понизит приоритет почти всех служб (впрочем, если до below normal, то работает нормально)


  1. dm9
    17.12.2016 17:15
    +4

    Респект автору за Uninstall. Не остановился на полпути :-)


  1. mihmig
    17.12.2016 20:32
    +1

    Спасибо за информацию об аналоге ionice под Windows.
    Но вернёмся к открытому более десяти лет вопросу:
    Как ограничить в ресурсах пользователя сервера терминалов:
    Пусть есть некий терминальный сервер, на нём — 1С, браузер (клиент-банк).
    Пользователь может (а раз может — значит обязательно сделает) запустить криво написанный отчёт, отжирающий память и ядра CPU. Также пользователь может запустить неограниченное число (очень нужных вот прямщас) вкладок браузера.
    Можно ли ограничить память на процесс?
    Оптимальным было бы также «шейпить» CPU и дисковую подсистему. Не выставлять приоритет, а именно шейпить.

    Возможно ли это в принципе на платформе Windows?


    1. MKudryavcev
      17.12.2016 23:17
      +1

      Возможно. Оснастка называется «Политики выделения ресурсов».


  1. neumeika
    18.12.2016 07:36
    +1

    «Но вернёмся к открытому более десяти лет вопросу»
    не гуглить с 2009 года? а вы профессионал :)
    wsrm
    блин, веткой промахнулся


  1. Sta2s
    24.12.2016 02:38

    Спасибо, прекрасная идея и интересная реализация
    Обратите внимание на ключ Extended="" в элементах меню.
    При его использовании меню будет появляться только с нажатым shift (как в случае с пунктом «копировать как путь») и стандартное же останется нетронутым.
    Согласитесь, несмотря на бесспорную полезность вышеописанного функционала — он требуется не каждый день.

    никому не нужный пример на написание которого я потратил неприлично много времени и, скорее всего можно было сделать по-другому
    [-HKEY_CLASSES_ROOT\exefile\shell\SCs]

    [HKEY_CLASSES_ROOT\exefile\shell\SCs]
    "MUIVerb"="Set autorun"
    "Icon"="imageres.dll,99"
    "subcommands"=""
    "Extended"=""

    [HKEY_CLASSES_ROOT\exefile\shell\SCs\shell\01]
    "MUIVerb"="add to autorun"
    "Icon"="imageres.dll,101"

    [HKEY_CLASSES_ROOT\exefile\shell\SCs\shell\01\command]
    @="cmd /q /c echo CreateObject(\"Shell.Application\").ShellExecute \"cmd\", \"/q /c reg add hkcu\\software\\microsoft\\windows\\currentversion\\run /v %1 /t reg_sz /d %1 /f & echo autorun %1 added | msg * \", \"\", \"runas\" > %%temp%%\\ar.vbs & cscript %%temp%%\\ar.vbs & del %%temp%%\\ar.vbs"

    [HKEY_CLASSES_ROOT\exefile\shell\SCs\shell\02]
    "MUIVerb"="remove autorun"
    "Icon"="imageres.dll,100"

    [HKEY_CLASSES_ROOT\exefile\shell\SCs\shell\02\command]
    @="cmd /q /c echo CreateObject(\"Shell.Application\").ShellExecute \"cmd\", \"/q /c reg delete hkcu\\software\\microsoft\\windows\\currentversion\\run /v %1 /f & echo autorun %1 deleted | msg * \", \"\", \"runas\" > %%temp%%\\ar.vbs & cscript %%temp%%\\ar.vbs & del %%temp%%\\ar.vbs"