Имеется задача: узнать семантику вызова загадочной функции DllRegisterServerEx, о которой на MSDN практически ни слова нет. Она с недавних пор экспортируется из COM-серверов Microsoft с нетривиальной инициализацией...
Черт, лучше скажу, зачем это надо.
Дано: имеется скриптовый компонент (WSC), который условно назовем "CodeColorer.wsc". Он правильно написан и содержит в себе море JScript-ового кода. При вызове "regsvr32 CodeColorer.wsc" он правильно регистрируется в системе и доступен по ProgId (если regsvr32.exe достаточно свежей версии). Необходимо: те же действия выполнить программно, регистрацией scrobj.dll (в которой и содержится код работы с WSC).
При этом появляется загадочное сообщение "Не удается создать обработчик интерфейса: Automation". Внимание, вопрос: что же в приведенном коде неправильно?
PS: Поскольку на виртуальное пиво никто не купится, предлагаю в качестве награды крупные оценки
Здравствуйте retalik, Вы писали:
R>Всем привет!
R>Имеется задача: узнать семантику вызова загадочной функции DllRegisterServerEx, о которой на MSDN практически ни слова нет. Она с недавних пор экспортируется из COM-серверов Microsoft с нетривиальной инициализацией...
R>Черт, лучше скажу, зачем это надо.
R>Дано: имеется скриптовый компонент (WSC), который условно назовем "CodeColorer.wsc". Он правильно написан и содержит в себе море JScript-ового кода. При вызове "regsvr32 CodeColorer.wsc" он правильно регистрируется в системе и доступен по ProgId (если regsvr32.exe достаточно свежей версии). R>Необходимо: те же действия выполнить программно, регистрацией scrobj.dll (в которой и содержится код работы с WSC).
R>Вот такой код, в лоб, не проходит:
R>При этом появляется загадочное сообщение "Не удается создать обработчик интерфейса: Automation". R>Внимание, вопрос: что же в приведенном коде неправильно?
Так может создать dll с нужным именем и функцией. Запустить из отладчика и посмотреть, что будет в стеке лежать...
Хотя, я бы этот CodeColorer.wsc держал в ресурсе и о регистрации даже-бы и не думал... Он, что на столько большой?
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте TK, Вы писали: TK>Так может создать dll с нужным именем и функцией. Запустить из отладчика и посмотреть, что будет в стеке лежать...
Ты знаешь, я так и делал. Вызывается DllRegisterServerEx с (одним ли?) параметром LPCSTR — именем файла...
То есть, то же самое, что и в приведенном куске.
TK>Хотя, я бы этот CodeColorer.wsc держал в ресурсе и о регистрации даже-бы и не думал... Он, что на столько большой?
Не понял — а как потом создавать из VBA объект, который реализован в CodeColorer.wsc?
Здравствуйте retalik, Вы писали:
R>Здравствуйте TK, Вы писали: TK>>Так может создать dll с нужным именем и функцией. Запустить из отладчика и посмотреть, что будет в стеке лежать... R>Ты знаешь, я так и делал. Вызывается DllRegisterServerEx с (одним ли?) параметром LPCSTR — именем файла... R>То есть, то же самое, что и в приведенном куске.
...
TK>>Хотя, я бы этот CodeColorer.wsc держал в ресурсе и о регистрации даже-бы и не думал... Он, что на столько большой? R>Не понял — а как потом создавать из VBA объект, который реализован в CodeColorer.wsc?
что-то вида:
Set oColorer = GetObject("script:CodeColorer.wsc") 'И никаких регистраций
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
R>При этом появляется загадочное сообщение "Не удается создать обработчик интерфейса: Automation". R>Внимание, вопрос: что же в приведенном коде неправильно?
Здравствуйте TK, Вы писали: R>>Не понял — а как потом создавать из VBA объект, который реализован в CodeColorer.wsc?
TK>что-то вида: TK>
TK>Set oColorer = GetObject("script:CodeColorer.wsc") 'И никаких регистраций
TK>
А можно рабочий пример?
У меня на машине не зарегистрирован протокол script:. Если ты имел в виду javascript:, то из wsc он вызывать код не хочет (да и, в любом случае, открывает совсем не нужное окно IE).
Оценку я все же поставил, надеюсь на продолжение
PS: как вызвать из приложения код на JS, я, в общем, знаю. Но мне очень хочется уметь регистрировать скриптлеты самостоятельно (да и интерес заел: что это за функция такая секретная?).
PPS: сейчас поищу в исходниках ActivePerl (там вполне может быть ее реализация для модуля PerlScript).
Здравствуйте George Seryakov, Вы писали: GS>CoInitialize не пробовал вызвать?
О, шаман! Конечно же, нет
Кстати, иногда DllRegisterServer вызывается и без этого. Например, какой-то популярный инсталлятор (чуть ли не InstallShield) этого не делал, и сложные COM-модули не регистрировались. Но меня это не оправдывает
Добавил CoInitialize. Теперь вызывает AV, причем в дебаге поймал сообщение о порче стека. Ага, переделал описание на
HRESULT (WINAPI *pReg)( LPCSTR pszCmdLine );
, все равно валится при выходе из программы , но регистрирует! Осталось совсем чуть-чуть...
DllRegisterServerEx:
5D35A056 sub esp,10h
5D35A059 mov eax,dword ptr [esp+14h]
5D35A05D lea ecx,[esp]
5D35A060 push esi
. . .
5D35A09A pop esi
5D35A09B add esp,10h
5D35A09E ret 4
Разве это не похоже на stdcall с одним параметром?
Здравствуйте retalik, Вы писали:
R>Здравствуйте TK, Вы писали: R>>>Не понял — а как потом создавать из VBA объект, который реализован в CodeColorer.wsc?
TK>>что-то вида: TK>>
TK>>Set oColorer = GetObject("script:CodeColorer.wsc") 'И никаких регистраций
TK>>
R>А можно рабочий пример?
Alert.vbs
ScriptPath = "file://" & Replace(WScript.ScriptFullName, "vbs", "wsc")
Set oAlert = GetObject("script:" & ScriptPath)
oAlert.Message = "My Message"
oAlert.Show (Now)
Alert.wsc
<?xml version="1.0"?>
<component>
<public>
<property name="Message" />
<method name="Show" />
</public>
<script language="VBScript">
<![CDATA[
Dim Message
Function Show (Time)
MsgBox Message & ":" & Time
End Function
]]>
</script>
</component>
Все сложить в одну папку. запускать *.vbs
R>У меня на машине не зарегистрирован протокол script:. Если ты имел в виду javascript:, то из wsc он вызывать код не хочет (да и, в любом случае, открывает совсем не нужное окно IE).
Должен быть script {06290BD3-48AA-11D2-8432-006008C3FBFC} R>Оценку я все же поставил, надеюсь на продолжение
R>PS: как вызвать из приложения код на JS, я, в общем, знаю. Но мне очень хочется уметь регистрировать скриптлеты самостоятельно (да и интерес заел: что это за функция такая секретная?).
Хотя, по мне лучше когда приложение можно распространять копированием... Все-таки это удобнее...
R>PPS: сейчас поищу в исходниках ActivePerl (там вполне может быть ее реализация для модуля PerlScript).
Вряд-ли...
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте retalik, Вы писали:
R>У меня на машине не зарегистрирован протокол script:. Если ты имел в виду javascript:, то из wsc он вызывать код не хочет (да и, в любом случае, открывает совсем не нужное окно IE).
А это и есть та SCROBJ.DLL, которую ты пытаешься зарегистрировать.
HKCR\script = s 'Moniker to a Windows Script Component'
CLSID = s '{06290BD3-48AA-11D2-8432-006008C3FBFC}'
HKCR\CLSID\{06290BD3-48AA-11D2-8432-006008C3FBFC} = s 'Moniker to a Windows Script Component'
Implemented Categories = s ''
{7DD95801-9882-11CF-9FA9-00AA006C42C4} = s ''
InprocServer32 = s 'D:\WINNT\System32\SCROBJ.DLL'
ThreadingModel = s 'Apartment'
ProgID = s 'script'
Здравствуйте Vi2, Вы писали: R>>У меня на машине не зарегистрирован протокол script:. Если ты имел в виду javascript:, то из wsc он вызывать код не хочет (да и, в любом случае, открывает совсем не нужное окно IE). Vi2>А это и есть та SCROBJ.DLL, которую ты пытаешься зарегистрировать.
Спасибо, нашел.
Я стормозил, думал, что это Pluggable Protocol, а это, оказывается, URL Moniker
Спасибо, ребята! Но, если узнаете про DllRegisterServerEx, дайте знать
Set oComponent = CreateObject ("Component.TestScript")
MsgBox oComponent.Factorial(5)
<?XML version="1.0"?>
<component>
<registration
progid="Component.TestScript"description="My Test Component"
version="1"/>
<public>
<property name="name"/>
<method name="factorial"/>
</public>
<script language="VBScript">
<![CDATA[
Function factorial(n)
If isNumeric(n) Then
If n <= 1 Then
factorial = 1
Else
factorial = n*factorial(n-1)
End If
Else
factorial = -2 ' Error code.End If
End Function
]]>
</script>
</component>
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Извиняюсь за продолжительное молчание — дела были, а ответить нужно было подробно
TK>Вот упорный-то Чем тебе GetObject("script:...") то не нравится?
Да я инсталлятор пишу, и хотелось добавить в него возможность регистрации скриптлетов.
[skip]
Так вот, проверил еще раз: как я уже писал в ответе GS, не нравится тем, что падает с AV. В отладчике при выполнении CRT-кода завершения лезет какая-то мура. То ли стек портится (вряд ли, так как сразу после вызова он проверяется, и ошибку не выдает), то ли регистры... Поэтому я и подозреваю, что это не STDCALL(LPCSTR).
Теперь — о симптомах. При вызове твоего кода с твоим компонентом все замечательно регистрируется. При вызове твоего кода с этим... кгхм... CodeColorer все замечательно регистрируется,.. а потом "память не может быть read".
Вот полный текст программки:
Вот я и не пойму: у меня система такая кривая или руки Но ведь regsvr32 регистрирует оба компонента за милую душу... Может, в нем SEH втихую глотается?
skip
R>Вот я и не пойму: у меня система такая кривая или руки Но ведь regsvr32 регистрирует оба компонента за милую душу... Может, в нем SEH втихую глотается?
Вообще-то тот regsvr32, который в примерах к MSDN идет (к сожалению, сильно урезанный), работает через OleInitialize/OleUninitialize и LoadLibraryEx — попробуй их использовать. Чем черт не шутит, вдруг поможет?
Здравствуйте retalik, Вы писали:
R>Теперь — о симптомах. При вызове твоего кода с твоим компонентом все замечательно регистрируется. При вызове твоего кода с этим... кгхм... CodeColorer все замечательно регистрируется,.. а потом "память не может быть read".
Так, может, CodeColorer того-этого, а не DllRegisterServerEx — не STDCALL(LPCSTR). Не в "консерватории" же дело, если для TestScript всё нормально проходит.
Здравствуйте retalik, Вы писали:
R>Извиняюсь за продолжительное молчание — дела были, а ответить нужно было подробно
TK>>Вот упорный-то Чем тебе GetObject("script:...") то не нравится? R>Да я инсталлятор пишу, и хотелось добавить в него возможность регистрации скриптлетов.
Выкрутился Видно эти умники что-то в scrobj.dll так намудрили, что ее нужно явно выгружать...
Да нет, они, скорее всего, в DLL_PROCESS_DETACH юзают СОМ, а он уже к этому времени похерен CoUninitialize().
Наверняка, если ее не вызывать вообще все будет ОК.
Здравствуйте TK, Вы писали:
TK>Выкрутился Видно эти умники что-то в scrobj.dll так намудрили, что ее нужно явно выгружать...
Все работает. Видимо, что-то накрутили в JScript.dll.
Вот за это я и люблю форумы RSDN Как-нибудь на досуге надо будет статейку написать "DllRegisterServerEx и как с ней бороться"