В работе Макросы реестра

Dragokas

Angry & Scary Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,726
Реакции
6,208
Читал:
http://safezone.cc/threads/desjat-sovetov-po-tonkoj-nastrojke-windows-xp-s-pomoschju-reestra.7780/

Заметил в самом конце pushd %L
Логично предположить, что %L - это видимо текущий каталог (с возможностью вернуться в системный командой popd). Хороший хинт.

А какие еще макросы бывают?
Я знаю только %1 - путь с именем целевого объекта, над которым выполняется глагол.
 

Кирилл

Команда форума
Администратор
Ассоциация VN
Сообщения
14,306
Реакции
6,310
Dragokas, тут нам предстоит совместная работа.

Раздел Command ,насколько я знаю, работает с COMMAND.COM или чем то подобным,так думаю потому что не все команды CMD воспринимаются в разделе.
Возможно это было из за разницы в версиях cmd ,тут надо поэкспериментировать-вдруг COMMAND.COM окажется не при делах.


Заметил в самом конце pushd %L

Тут мы имеем дело с тем,что не до конца известно и в принципе я не нашел документации.

Скажу что всего 10 макросов цифровых+ как минимум 2 буквенных,это %I %L

%0 - возвращает имя директории и файла
% 1 действие передается файлу
% 2 принтер
% 3 драйвер (?)
% 4 порт
Остальные не знаю.
Надо подумать.


Цифры после 1 касаются настроек печати.

Давай попробуем толкнуться от аргументов cmd?
Расскажи о них.
 

Dragokas

Angry & Scary Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,726
Реакции
6,208
На счет цифр после 1, здесь для меня загадка.
Не расскажешь ли, где слышал о них. И как симмитировать действие хотя бы одной из них?
% 1 действие передается файлу
Наверное, более корректно сказать "... от файла".

Раздел Command ,насколько я знаю, работает с COMMAND.COM или чем то подобным,так думаю потому что не все команды CMD воспринимаются в разделе.
Возможно это было из за разницы в версиях cmd ,тут надо поэкспериментировать-вдруг COMMAND.COM окажется не при делах.
Но-но. Ты вспомни еще Windows 3.11 -))) Command.com, это тот же CMD только для Win 9x и находился он в корне %SystemDisk%-a.
Никакого отношения нет. И ничего общего нет.
Если ты напишешь %Буква в глаголе рядом с CMD, то после запуска он получит уже готовые обработанные системой макросы реестра,
имена которых не имеют ничего общего (кроме внешнего вида :) с похожими модификаторами CMD.

Итак, исследование.
Я вооружился первой методикой поиска секретов от Сергея Ткаченко, сделав незамысловатый скрипт, который:
  • создает строку со всеми вариантами макросов,
  • создает в реестре глагол Test_Verb с этой строкой;
  • вызывает глагол или предлагает сделать пользователю это самостоятельно;
  • глагол записывает вывод в файл на рабочем столе в одну строку,
затем после нажатия ОК перекодирует файл во многострочный лог.

Смотрите 3, 5 строки - настройка true или false
VB.NET:
' Automatic Invoke Verb on Script (Имитировать выполнение глагола на самом скрипте автоматически (программно))
' In this case %W macros will be omitted (в этом случае исключаю макрос %W, т.к. получим исключение о неопределенном родителе)
SelfInvoke = false
' Удалить глагол после отработки скрипта
AutoDeleteVerb = false

RegVerb = "Test_Verb"
RegKey = "HKCR\AllFilesystemObjects\Shell\" & RegVerb & "\"

Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oShell = CreateObject("WScript.Shell")

LogFile = oShell.SpecialFolders("Desktop") & "\" & RegVerb & "_Result.log"
if oFSO.FileExists(LogFile) then oFSO.DeleteFile(LogFile)

' Make me Admin :) Получаем права Администратора
if WScript.Arguments.Count = 0 then
    if not isAdminRights() then
        Elevate()
        WScript.Quit
    end if
end if

cur = oFSO.GetParentFolderName(WScript.ScriptFullName)
msgbox "ok"
' Generating Verb string (генерирую строку команды для глагола)
s = "cmd /c for /f ""delims="" %%a in ("""
for n = 0 to 255
    if (n>=65 and n<=90) or (n>=97 and n<=122) then
        s = s & "/n" & chr(n) & "=%" & chr(n)
    end if
next
for n = 0 to 9
        s = s & "/n" & n & "=%" & n
next
s = s & """) do echo %%a > """ & LogFile & """"""
if SelfInvoke then s = replace(s, "%w", "BLOCKED by Script", 1, -1, vbTextCompare)

' Writing to the registry (создаю в реестре глагол)
oShell.RegWrite RegKey, RegVerb
oShell.RegWrite RegKey & "command\", s

' Invoke Test Registry Verb onto this script themself (самовыполнение глагола скриптом себя)
me_file = WScript.ScriptFullName
if SelfInvoke then
    CreateObject("Shell.Application").Namespace(left(me_file, 3)).ParseName(mid(me_file, 4)).InvokeVerb(RegVerb)
    WScript.Sleep(2000)
end if

if not SelfInvoke then msgbox "Теперь выполните глагол контекстного меню " & RegVerb & " на любом файле или папке."

' Clear the registry (удаление глагола контекстного меню)
if AutoDeleteVerb then
    oShell.RegDelete RegKey & "command\"
    oShell.RegDelete RegKey
end if

' Replace \n -> 0x0D 0x0A (заменяю в однострочном выводе псевдопереносы на перевод каретки)
with oFSO.OpenTextFile(LogFile,1) '1 - for Reading only
    s = .ReadAll()
    .Close
end with

s = Replace (s, "/n", vbCrLf)

with oFSO.CreateTextFile(LogFile, true) 'перезаписываю файл
    .Write s
    .Close
end with

' Open Log-file (открываю файл)
oShell.Run "explorer """ & LogFile & """", 1, false

Set oFSO = Nothing: Set oShell = Nothing

Sub Elevate()
  Const DQ = """"
  Set colOS = GetObject("winmgmts:\root\cimv2").ExecQuery("Select * from Win32_OperatingSystem")
  For Each oOS In colOS
    strOSLong = oOS.Version
  Next
  If Left(strOSLong, 1) = "6" Then
    If Not isAdminRights Then
        Set oShellApp = CreateObject("Shell.Application")
        oShellApp.ShellExecute WScript.FullName, DQ & WScript.ScriptFullName & DQ & " " & DQ & "Twice" & DQ, "", "runas", 1
        WScript.Quit
    End If
  End If
  set oOS = Nothing: set colOS = Nothing: set oShellApp = Nothing
End Sub

Function isAdminRights()
    Const KQV = &H1, KSV = &H2, HKCU = &H80000001, HKLM = &H80000002
    Set oReg = GetObject("winmgmts:root\default:StdRegProv")
    strKey = "System\CurrentControlSet\Control\Session Manager"
    intErrNum = oReg.CheckAccess(HKLM, strKey, KQV + KSV, flagAccess)
    isAdminRights = flagAccess
    Set oReg = Nothing
End Function

A=A
B=B
C=C
D=C:\Users\Alex\Desktop\Special Character.txt
E=E
F=F
G=G
H=0
I=:192046304:2236

J=J
K=K
L=C:\Users\Alex\Desktop\Special Character.txt
M=M
N=N
O=O
P=P
Q=Q
R=R
S=1
T=T
U=U
V=C:\Users\Alex\Desktop\Special Character.txt
W=C:\Users\Alex\Desktop
(прим.: это текущая папка, а не папка с вызываемым файлом)
X=X
Y=Y
Z=Z
a=a
b=b
c=c
d=C:\Users\Alex\Desktop\Special Character.txt
e=e
f=f
g=g
h=0
i=:192046304:2236
j=j
k=k
l=C:\Users\Alex\Desktop\Special Character.txt
m=m
n=n
o=o
p=p
q=q
r=r
s=1
t=t
u=u
v=C:\Users\Alex\Desktop\Special Character.txt
w=C:\Users\Alex\Desktop
x=x
y=y
z=z
0=C:\Users\Alex\Desktop\Special Character.txt
1=C:\Users\Alex\Desktop\Special Character.txt

2=
3=
4=
5=
6=
7=
8=
9=

Из анализа видно, что:
  • регистр букв макроса не имеет значения;
  • для папок и файлов результаты не отличаются;
  • Доступные макросы: %D, %H, %I, %L, %S, %V, %W, %0 - %9
  • %D,%L,%V,%0,%1 - выдают одинаковую информацию - путь и имя целевого объекта
  • %W - выдает путь к папке, в которой находится объект;
  • %H - всегда показывает 0
  • %S - всегда показывает 1
  • %I - что такое для меня сначала было загадкой. :192046304:2236 ??? при этом последние 4 цифры за время тестов всегда были одинаковы.

1) Также я долго не мог понять, почему получаю ошибку при попытке исполнить глагол контекстного меню программно из скрипта
(да, такое возможно. Я ранее описывал полезность это метода для установки inf).

Методом исключения виновником нашелся макрос %W,
который не просто выдает путь к каталогу, в котором находится целевой файл или каталог,
а обращает внимание на родителя (а именно процесса), из которого вызван глагол для объекта.

В чем это выражается:
когда я нажимаю в Total Commander-e правой клавишей по любому файлу и выполняю глагол, получаю ту же ошибку:
Error.png


Т.е. родитель - не Explorer, а TC.
Тоже самое, когда я делаю это программно. Родитель - wscript.exe

Забавно, что если в реестре оставить только само значение %W - это не вызывает ошибки. И в ответ на глагол открывается стандартное окно "Открыть с помощью"
связанное с типом файла целевого объекта.

Но при попытке явно раскрыть его как строку, передав в качестве аргумента любому приложению, например, если пропишу в Verb\Command: @=
Код:
explorer %W
получаем ту же ошибку.

Напрашивается вывод: неужели внутри самих реестровых значений также существует некий подтип данных
(например, строка и Nothing - отсутствие объекта, вызывающее "исключение" у самой среды)?

2) И когда я обошел эту проблему путем удаления макроса %W из строки
и запустил глагол программно, макрос %%I поменял последние цифры !!!

Вуаля, первая мысль ProcessID. И команда tasklist | find "2236" указала на explorer.exe, что
так и есть. Глагол умеет определять ProcessID родителя, который его запустил.
Но там же не только PID.
192046304

Вбиваю не задумываясь:
Код:
wmic process where caption="explorer.exe" get /value
Но дальше ждет облом, т.к. никакой зависимости я не нашел :D
wscript.exe, запускающий глагол самого себя:
(поэтому PID всегда разный)

2980272:6116
3850752:4676
4785408:6752
2710240:6068

Запуск глагола через проводник:

275734032:2236
275733024:2236
275733600:2236

-- здесь выдержал некоторое время:

189618384:2236
189616656:2236
189618240:2236
189618096:2236

192040688:2236
191547376:2236
191545360:2236

Первые 5 цифр у explorer.exe часто совпадают,
да и их общее кол-во больше чем у wscript.exe
Но что это такое - остается загадкой.
На счет цифровых макросов нужно больше информации.
С 2 по 9 - пустые значения (но они точно есть, а иначе бы вывелась цифра)
На счет %H = 0, %S = 1. Также неизвестно, что это.

Продолжение следует...
 

Вложения

  • Generate_All.zip
    1.8 KB · Просмотры: 13
Последнее редактирование:

Кирилл

Команда форума
Администратор
Ассоциация VN
Сообщения
14,306
Реакции
6,310
О...смотри:
Код:
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\*\shell\help]
@="help command"

[HKEY_CLASSES_ROOT\*\shell\help\command]
@="help"

И получаем:
Безымянный.jpg



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

Dragokas

Angry & Scary Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,726
Реакции
6,208

Кирилл

Команда форума
Администратор
Ассоциация VN
Сообщения
14,306
Реакции
6,310
Оказывается есть макросы,которые воспринимаются определенными глаголами.
После некоторых поисков по реестру я удостоверился что есть цифровые макросы и для глагола printto.
Глагол позволяет напечатать выбранный файл или папку, просто перетаскивая его на принтер. Можно указать принтер, используя "% 1", "% 2", "% 3" и т.д., в зависимости от того, сколько есть принтеров.

По тем макросам что ты эксперементировал тоже все неоднозначно - в зависимости от того есть ли исполняемый файл прописанный в глаголе команда выполняется под разными условиями,пока точно не разобрал еще.
 
Последнее редактирование:

Кирилл

Команда форума
Администратор
Ассоциация VN
Сообщения
14,306
Реакции
6,310
Вот еще один нюанс,я по ходу с принтерами поторопился.
Код:
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\txtfile\shell\open\command
%SystemRoot%\system32\NOTEPAD.EXE /p %1
%SystemRoot%\system32\notepad.exe /pt "%1" "%2" "%3" "%4"
Такой вариант будет отправлять объект на печать при отрытии в блокноте.
Здесь %1 это открытие файла,как обычно.
%2 - отправка на принтер
%3 вызов драйвера печати
%4 номер порта

% 3 и% 4 не заключаются в кавычки.
Аргументы
%fn - путь к файлу
%pt - имя принтера

например
Код:
notepad.exe /pt "%fn" "%pt"
отправляет файл %fn на принтер %pt

printo и pt печатает файл на указанном принтере. Используется Оболочка с поддержкой drag-and-drop для принтеров.

%1-это имя файла и %2-имя принтера. Можно игнорировать %3 и %4 для Windows 95 и более поздних системах. Для систем Windows 3.1, %3 представляет собой имя драйвера и %4 имя порта

надо попробовать изучить:
http://technet.microsoft.com/en-us/library/ee156618.aspx
 
Последнее редактирование:

Dragokas

Angry & Scary Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,726
Реакции
6,208

Dragokas

Angry & Scary Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,726
Реакции
6,208
Что означает %*
например:
Код:
[HKEY_CLASSES_ROOT\exefile\shell\open\command]
@="\"%1\" %*"
"IsolatedCommand"="\"%1\" %*"
 

Dragokas

Angry & Scary Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,726
Реакции
6,208
Вот, что прописано для дефолтовой ассоциации .zip:
Код:
 %SystemRoot%\Explorer.exe /idlist,%I,%L

%I - это оказывается хендл ItemIDList. IDList - это идентификатор, который можно альтернативно использовать для задания пути к файлу.
А %I постоянно менялся для одного и того же файлового объекта, потому что это не сам ID, а хендл ("указатель") на него внутри процесса с ProcessID, заданным через 2-ю часть макроса %I
Код:
:Handle:ProcessID

Для справки:
Configuring Windows Explorer - Command Line Options
The Windows Explorer Command Line

Получается, согласно данным от Geoff Chappell в качестве файлового объекта для макроса %I может использоваться только папка, а также объекты которые к ней приравниваются из-за своей специфики, например, Cabinet-архивы, архивы Zip и Windows Search Protocol.
 
Последнее редактирование:
Сверху Снизу