Total Commander Knowledge Base

Есть вопрос?

Поищите ответ в самой большой русскоязычной базе знаний по Total Commander!

Портабельность ActiveX-компонентов на примере TCScript Helper

© Copyright
Эта статья защищена авторским правом, и на её правку наложены ограничения.


Предисловие

Не секрет, что многие пользователи ТС в повседневной жизни используют для своих нужд его переносную копию, где по логике должны быть предусмотрены все нюансы, не нарушающие полноценную работу заложенных в сборку функций. И естественно то, что касаться это должно в том числе и прилагаемых средств автоматизации.

Одним таким средством, довольно известным в кругу местных скриптописцев, является замечательный ActiveX-компонент Script Helper for TC, который помогает расширить функционал WSH-сценариев при работе в окне Total Commander.

Так как системный набор библиотек часто ограничивает потребности разработчиков скриптов, им приходится прибегать к внедрению подобного рода дополнительных ActiveX-компонентов, несомненно требующих регистрации в системе.
Одним из способов обойти такую необходимость является авто-регистрация библиотеки на этапе выполнения скрипта и последующее её отключение (дерегистрация) после отработки. На самом деле при таком подходе возникает несколько потенциальных проблем:

  • Во-первых, регистрация библиотек предусмотрена только в режиме работы под учётной записью администратора.
  • Во-вторых, садясь за чужую машину нельзя быть уверенным наперёд, что подобные игры с реестром позволительны или вообще могут понравиться владельцу испытуемой системы.
  • В-третьих, в ряде компаний любые системные записи могут строго караться администрирующей группой вплоть до жалобы руководству и, как бы странным это не казалось, увольнения нарушителя.
  • Ну, и в-четвёртых, это некоторое ограничение скорости работы скрипта, без которого тоже в ряде случаев неплохо было бы обойтись.

Для того, чтобы всего этого избегать, существует способ выполнять скрипты, работающие на COM-технологии, без ущерба системе, рабочим условиям, ну и, наконец, собственной психике.
Называется это технология - Side-by-Side, подразумевающая псевдорегистрацию, которая позволяет COM-серверу предоставлять доступ к своим объектам без занесения соответствующей информации в реестр. Исходная цель данной технологии заключалась в устранении конфликтов оси с dll-сорками, а именно проблемы с кричащим названием DLL hell.
Нужно иметь в виду, что данная технология поддерживается в Windоws не ниже XP-версии. Полагаю, на сегодняшний день это обстоятельство очень мало кого может огорчить.


Техническая часть

Итак, распишу попунктно комплекс мер по подлючению ActiveX-компонентов в формате DLL:

1) Для начала следует скопировать (для компонентов с 32-битной разрядностью, как в нашем случае, при работе в Windows x86 из папки из %Windir%\SYSTEM32 или при работе в Windows x64 из папки %Windir%\SysWOW64) интерпретатор WScript.exe в подходящую директорию на переносном или системном устройстве.

2) После этого скопируйте подключаемую dll-библиотеку в тот же каталог.

3) Рядом создайте файл с базовым именем библиотеки и окончанием ".sxs.manifest". К, примеру, на базе обсуждаемого TCScript.dll манифестом станет TCScript.sxs.manifest.

4) Откройте созданный manifest-файл в текстовом редакторе.

5) Теперь перейдём к самой сложной процедуре, а именно к составлению манифестов.

Здесь, конечно, можно углубиться в теорию с подетальным разжёвыванием терминов и XML-синтаксиса данного документа, но дабы не усложнять путь читателю, ограничимся указанием только необходимых для работы скриптов строк и деталей манифеста. Желающие углубиться в подробности могут ознакомиться со статьями на MSDN.

Итак. Первые две стартовые строки неизменны, и принимают такой вид:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly  manifestVersion="1.0">

Далее следует элемент

<assemblyIdentity type="win32" name="TCScript.sxs" version="1.0.0.14" />

, где в атрибуте name после знака = (как и в отношении других атрибутов) прописывается базовое имя библиотеки с расширением sxs и его версия в атрибуте version, соответсвенно. Версию той или иной билиотеки можно посмотреть с помощью Листер-плагинов PEViewer или FileInfo.

Следом открываем элемент <file name>, где записывается полное имя dll-файла.
Внутри него должны присутвовать два элемента <typelib> и <comClass>.
Записи version="1.0" и helpdir="" внутри <typelib> будут достаточными.
Что же касается tlbid в <typelib>, а также clsid, progid в <comClass>, то эти вещи придётся смотреть в выше оговоренных плагинах либо других прикладных ПО. В плагине FileInfo это будет вкладка ActiveX/OCX. Как правило, сверху рабочей области страницы, где есть uuid(...), вместо троеточия в фигурных скобках записан tlbid, а снизу - clsid.
Стоит отметить, что значения этих данных меняются от версии к версии, поэтому при обновлении компонента их придётся переписывать.
Для некоторых компонентов в элементе <typelib> также может быть востребован атрибут threadingModel (его значение можно найти на той же странице). В случае TCHelper он не потребуется.

Иногда автор шифрует эту информацию, и тогда узнать о данных атрибутах можно из примеров в сети либо путём временной регистрации с созданием манифестов из спецсредств (см. ниже) или сравнением снимков реестра "до/после" с помощью утилит типа RegShot и System Explorer. В лучшем случае автор предоставляет регистрационные данные, которые можно обозревать плагином PEViewer в разделе REGISTRY на вкладке Ресурсы.

Итоговый вид TCScript.sxs.manifest для версии 1.0.0.14 (см. ссылку ниже) представляется следующим образом:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly  manifestVersion="1.0">
  <assemblyIdentity type="win32" name="TCScript.sxs" version="1.0.0.14"/>
  <file name="TCScript.dll">
     <typelib
        tlbid="{99BD528D-BC20-47E4-A2CC-7D8DEE830EB4}"
        version="1.0"
        helpdir="" />
     <comClass
        clsid="{F66C60F1-EB21-4DE6-8472-F725FE7EDC19}"
        progid="TCScript.Helper" />
  </file>
</assembly>

Примечание: в некоторые библиотеки внедрено сразу несколько классов (каждый со своим ProgID), также требуемых описания в манифесте.
Иногда в определённых библиотеках после закрывающего элемента </file> требуется прописывать строки для элемента <comInterfaceExternalProxyStub>.
Углубляться в эти тонкости здесь не буду, лишь покажу пример для nonnoi_APPEncrypt.dll:

<comInterfaceExternalProxyStub
   name="IControlEvents"
   iid="{EE85ACDD-7499-4719-A173-FCC56CE6FA1D}"
   proxyStubClsid32="{00020420-0000-0000-C000-000000000046}"
   baseInterface="{00000000-0000-0000-C000-000000000046}"
   tlbid="{40CC9252-A25A-4D28-A906-9BD3F752934A}" />

6) Далее следует создание манифеста непосредственно для самого интерпретатора WScript.exe с содержанием регистрации всех требуемых библиотек.
В отличии от предшественника исходное расширение интерпретатора на sxs не заменяется, т.е. полное имя будет таким: WScript.exe.manifest.
Составление данного манифеста куда проще, ибо не требует никаких копаний в идентификаторах. Неизменными строками в нём будут:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly  manifestVersion="1.0">
  <assemblyIdentity type="win32" name="wscript.exe" version="1.0.0.0" />

и самый нижний закрывающий элемент </assembly>.
Далее для каждого компонента создаётся запись вида:

  <dependency>
     <dependentAssembly>
        <assemblyIdentity type="win32" name="TCScript.sxs" version="1.0.0.14" />
     </dependentAssembly>
  </dependency>

, где как и в случае выше для name и version подставляются соответствующие значения.

На примере TCHelper и dsofile итоговый файл с двумя вариантами записи будет выглядеть так:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly  manifestVersion="1.0">
  <assemblyIdentity type="win32" name="wscript.exe" version="1.0.0.0" />

  <dependency>
     <dependentAssembly>
        <assemblyIdentity type="win32" name="TCScript.sxs" version="1.0.0.14" />
     </dependentAssembly>
  </dependency>

  <dependency>
     <dependentAssembly>
        <assemblyIdentity
           type="win32"
           name="dsofile.sxs"
           version="2.1.0.0" />
     </dependentAssembly>
  </dependency>

</assembly>

В помощь по составлению манифестов прилагаю ссылки на вспомогательные средства:

Важно! После запуска скрипта информация из задействованных манифестов кэшируется в памяти, в результате после их обновления сервер сценариев вернёт ошибку. Чтобы это быстро исправить, нужно намеренно допустить любую ошибку в WScript.exe.manifest, например, временно дописав лишний символ, и единожды запустить скрипт, после вернуться к правильной редакции.

7) Ну, и последнее приготовление - это непосредственный запуск скриптов.

Там, где востребован сторонний компонент, скрипт необходимо запускать с указанием пути к скопированному ранее интерпретатору.
Расположение самих скриптов значения не имеет. На примере результирующей кнопки для однострочного VBS-скрипта

MsgBox CreateObject("TCScript.Helper").GetInfo("SC")

выглядит это следующим образом:

Код кнопки
TOTALCMD#BAR#DATA:
%COMMANDER_PATH%\Scripts\Components\wscript.exe "%COMMANDER_PATH%\Scripts\ShowCountOfDisplayedItems.vbs"

wciconex.dll,84
Показать число отображаемых объектов в активной панели

-1

Скачать готовую сборку для TCHelper

Ссылка на обновлённую версию со встроенным интерпретатором


Заключение

Разумеется, на вспомогательном объекте ТС для местной публики свет клином не сошёлся. Полезных компонентов, скомпиллированных в dll, в сети можно найти достаточное количество. Из наиболее востребованных помимо двух указанных могу отметить JSSys3.dll, jsShell.dll, WshExtra.dll, MediaInfoActiveX.dll, WSO.dll, dynwrapx.dll, Chameleon.FileTimesEditor.dll, HTMLParser.dll, newobjectspack1.dll, библиотеки Chilkat, XStandard и других марок, без проблем находящихся Web-поиском.

P.S.: Если возникли вопросы или проблемы при составлении манифестов, прошу обращаться на форум wincmd.ru. Спасибо за внимание!

Flasher
24.11.2015

Ключевые слова: ActiveX, Helper, TCHelper, Хелпер, Portable, Script, VBS, VBScript, JSCript, WSH, WSF, COM, OLE, компонент, портабельность, флешка, съёмный диск, съёмный носитель