Скрипты WSC и раннее связывание
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 22.05.04 18:36
Оценка: 9 (1)
#Имя: FAQ.com.wsc.earlybind
OE>Написал JavaScript, оформил как COM объект, как описано в Создании COM-компонентов с помощью скриптовых языков
Автор(ы):
Дата: 25.04.2001
, зарегистрировал (успешно, проверил в OleView), создал для него tlb (тоже видна в OleView).

OE>Теперь хочу попользовать.
OE>В программе (C++,ATL/WTL) пишу
#import "C:\Scripts\scriptlet.tlb" no_namespace, named_guids

OE>пытаюсь поднять:
AutomationPtr pMyScriptPtr = NULL; 
HRESULT hr;
hr = pScriptPtr.CreateInstance( "MyScript.WSC" ); // ProgID как он есть в скрипте и в OleView

OE>результат — ошибка 0x80004002: "No such interface supported"
OE>вопрос — кто виноват ...

вообщем почитал я microsoft.public.scripting.scriptlets, было приятно, что хожу по граблям не в одиночестве , там некто Michael Harris (Microsoft.MVP.Scripting) не устает бедолага повторять:

You *can't* early bind to a WSC instance. The problem is that the IID of a WSC instance is dynamic and is determined at runtime by the scrobj.dll wrapper. The IID embedded in the typelib for a WSC that VB (or any other early bound language) looks for with QueryInterface will never match the dynamic IID of the instance at runtime.

The WSC documentation that implies that WSC early binding is supported is simply wrong.


причем, если для скрипта без событий VC еще делает #import, хотя потом ничего не работает, то при добавлении в скрипт event-ов по этой же причине происходит fatal error C1196: 'Scriptlet Event Source' : identifier found in type library xxxx is not a valid C++ identifier

OE>... и что делать?


Так что похоже самый простой выход не делать никакого #import-a, а изобразить что-то типа:

IDispatchPtr pDispatch;
HRESULT hr = pDispatch.CreateInstance( "MyScript.WSC" );

if ( SUCCEEDED( hr ) )
{
    CComDispatchDriver  pDd( pDispatch );
    _variant_t result;
    _variant_t param("123456");
    hr = pDd.Invoke1(OLESTR("MethodName"), &param, &result);

    ...
Скрипт as COM
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 21.05.04 08:28
Оценка:
Написал JavaScript, оформил как COM объект, как описано здесь
Автор(ы):
Дата: 25.04.2001
, зарегистрировал (успешно, проверил в OleView), создал для него tlb (тоже видна в OleView). Теперь хочу попользовать.
В программе (C++,ATL/WTL) пишу

#import "C:\Scripts\scriptlet.tlb" no_namespace, named_guids

при компиляции создается scriptlet.tlh:

struct __declspec(uuid("7b02ae9f-daad-4b82-b960-add399cbf208"))
/* LIBID */ __ScriptletTypeLib;
struct /* coclass */ ScriptletCoClass;
struct __declspec(uuid("b0dcdb31-6618-4d0e-b8ec-2a23382b67dc"))
/* dispinterface */ Automation;

//
// Smart pointer typedef declarations
//

_COM_SMARTPTR_TYPEDEF(Automation, __uuidof(Automation));

//
// Type library items
//

struct __declspec(uuid("ef907bc6-3ebc-49fd-8056-89da35e8c4df"))
ScriptletCoClass;
    // [ default ] dispinterface Automation

struct __declspec(uuid("b0dcdb31-6618-4d0e-b8ec-2a23382b67dc"))
Automation : IDispatch
{
    //
    // Wrapper methods for error-handling
    //

    // Methods:
    _variant_t Method2 (
        const _variant_t & uid,
        const _variant_t & code,
        const _variant_t & OptionalArgs );
    _variant_t Method1 (
        const _variant_t & uid,
        const _variant_t & OptionalArgs );
};

// ну и + GUID-ы


пытаюсь поднять:

AutomationPtr pMyScriptPtr = NULL; 

HRESULT hr;
hr = pScriptPtr.CreateInstance( "MyScript.WSC" ); // ProgID как он есть в скрипте и в OleView


результат — ошибка 0x80004002: "No such interface supported"

вопрос — кто виноват и что делать?
Re: Скрипт as COM
От: Tom Россия http://www.RSDN.ru
Дата: 21.05.04 09:21
Оценка:
OE>вопрос — кто виноват и что делать?
Как временную затычку могу посоветовать заменить в сгенерённом файле ID интерфейса на ID IDispatch-а.
Тоесть на "00020400-0000-0000-C000-000000000046"

Но ессно временное решение.
Народная мудрось
всем все никому ничего(с).
Re: Скрипт as COM
От: Vi2 Удмуртия http://www.adem.ru
Дата: 21.05.04 09:22
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>struct __declspec(uuid("b0dcdb31-6618-4d0e-b8ec-2a23382b67dc"))
OE>/* dispinterface */ Automation;
OE>...
OE>_COM_SMARTPTR_TYPEDEF(Automation, __uuidof(Automation));
OE>...
OE>вопрос — кто виноват и что делать?

Проблема в __uuidof(Automation). У меня в подобной ситуации генерит __uuidof(IDispatch), что более соответствует природе вещей.

Скрипт каждый раз генерит новую TLB и новый интерфейс, ибо параметров для LIBID и IID нет, так ведь? И скорее всего просто не регистрирует ни TLB, ни интерфейсы в ней.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[2]: Скрипт as COM
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 21.05.04 09:47
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>У меня в подобной ситуации генерит __uuidof(IDispatch), что более соответствует природе вещей.


э-э, что значит "у меня ... генерит" ? у тебя #import по другому работает?

Vi2>Скрипт каждый раз генерит новую TLB и новый интерфейс, ибо параметров для LIBID и IID нет, так ведь? И скорее всего просто не регистрирует ни TLB, ни интерфейсы в ней.


вообще-то в tlh-нике есть

//
// Named GUID constants initializations
//

extern "C" const GUID __declspec(selectany) LIBID_ScriptletTypeLib =
    {0x7b02ae9f,0xdaad,0x4b82,{0xb9,0x60,0xad,0xd3,0x99,0xcb,0xf2,0x08}};
extern "C" const GUID __declspec(selectany) CLSID_ScriptletCoClass =
    {0xef907bc6,0x3ebc,0x49fd,{0x80,0x56,0x89,0xda,0x35,0xe8,0xc4,0xdf}};
extern "C" const GUID __declspec(selectany) DIID_Automation =
    {0xb0dcdb31,0x6618,0x4d0e,{0xb8,0xec,0x2a,0x23,0x38,0x2b,0x67,0xdc}};
Re: Скрипт as COM
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 21.05.04 10:30
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>Написал JavaScript, оформил как COM объект, как описано здесь
Автор(ы):
Дата: 25.04.2001
, зарегистрировал (успешно, проверил в OleView), создал для него tlb (тоже видна в OleView). Теперь хочу попользовать.

OE>В программе (C++,ATL/WTL) пишу

что самое противное, из JavaScript все правильно отрабатывает буквально на двух строчках:

var test = new ActiveXObject("MyScript.WSC");
WScript.Echo(test.Method1("123456"));
Re[3]: Скрипт as COM
От: Vi2 Удмуртия http://www.adem.ru
Дата: 21.05.04 11:18
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

Vi2>У меня в подобной ситуации генерит __uuidof(IDispatch), что более соответствует природе вещей.
OE>э-э, что значит "у меня ... генерит" ? у тебя #import по другому работает?

Наверное. Посмотри на дату и наличие IDispatch. Это пример с coolObj.wsc, который где-то был здесь на Форуме:
После выполнения в C:\FORUMS\ALERT\
rundll32.exe scrobj.dll,GenerateTypeLib -URL:coolObj.wsc
и
#import "C:\FORUMS\ALERT\scriptlet.tlb" named_guids

дает (полный файл scriptlet.tlh)
// Created by Microsoft (R) C/C++ Compiler Version 12.00.8447.0 (c3cb88f9).
//
// c:\projects\prj1\debug\scriptlet.tlh
//
// C++ source equivalent of Win32 type library C:\FORUMS\ALERT\scriptlet.tlb
// compiler-generated file created 05/21/04 at 16:00:10 - DO NOT EDIT!

#pragma once
#pragma pack(push, 8)

#include <comdef.h>

namespace ScriptletTypeLib {

//
// Forward references and typedefs
//

struct /* coclass */ duan;
struct __declspec(uuid("231a8481-ab11-11d8-a663-004095426e66"))
/* dispinterface */ Automation;

//
// Smart pointer typedef declarations
//

_COM_SMARTPTR_TYPEDEF(Automation, __uuidof(IDispatch));

//
// Type library items
//

struct __declspec(uuid("f87907b4-5595-49fd-96b2-bdce03fc85fd"))
duan;
    // [ default ] dispinterface Automation

struct __declspec(uuid("231a8481-ab11-11d8-a663-004095426e66"))
Automation : IDispatch
{
    //
    // Wrapper methods for error-handling
    //

    // Methods:
    _variant_t qd (
        const _variant_t & x,
        const _variant_t & OptionalArgs );
};

//
// Named GUID constants initializations
//

extern "C" const GUID __declspec(selectany) LIBID_ScriptletTypeLib =
    {0x231a8480,0xab11,0x11d8,{0xa6,0x63,0x00,0x40,0x95,0x42,0x6e,0x66}};
extern "C" const GUID __declspec(selectany) CLSID_duan =
    {0xf87907b4,0x5595,0x49fd,{0x96,0xb2,0xbd,0xce,0x03,0xfc,0x85,0xfd}};
extern "C" const GUID __declspec(selectany) DIID_Automation =
    {0x231a8481,0xab11,0x11d8,{0xa6,0x63,0x00,0x40,0x95,0x42,0x6e,0x66}};

//
// Wrapper method implementations
//

#include "c:\projects\prj1\debug\scriptlet.tli"

} // namespace ScriptletTypeLib

#pragma pack(pop)
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: Скрипт as COM
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 21.05.04 14:13
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>

Vi2>>У меня в подобной ситуации генерит __uuidof(IDispatch), что более соответствует природе вещей.
OE>>э-э, что значит "у меня ... генерит" ? у тебя #import по другому работает?

Vi2>Наверное. Посмотри на дату и наличие IDispatch. Это пример с coolObj.wsc, который где-то был здесь на Форуме:

Vi2>
Vi2>// Created by Microsoft (R) C/C++ Compiler Version 12.00.8447.0 (c3cb88f9).
Vi2>


у меня

// Created by Microsoft (R) C/C++ Compiler Version 13.10.3077 (34e1d069).



VS7.1
Re[2]: Скрипт as COM
От: rus blood Россия  
Дата: 21.05.04 16:37
Оценка:
OE>
OE>var test = new ActiveXObject("MyScript.WSC");
OE>WScript.Echo(test.Method1("123456"));
OE>



Как ты регистрировал wsc-компонент?
Я воспользовался explorer-ом для генерации tlb, и для регистрации.
После регистрации

"C:\WINNT\system32\REGSVR32.EXE" /i:"%1" "C:\WINNT\system32\scrobj.dll"


код на C++ заработал — S_OK и все такое...

Перед этим ProgId не был прописан в реестре, а в CLSID было все пара записей про TypeLib и Version.
После регистрации в реестре все стало ок...
Имею скафандр — готов путешествовать!
Re[3]: Скрипт as COM
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 22.05.04 10:19
Оценка:
Здравствуйте, rus blood, Вы писали:


OE>>
OE>>var test = new ActiveXObject("MyScript.WSC");
OE>>WScript.Echo(test.Method1("123456"));
OE>>



RB>Как ты регистрировал wsc-компонент?

RB>Я воспользовался explorer-ом для генерации tlb, и для регистрации.

аналогично

RB>После регистрации

RB>код на C++ заработал — S_OK и все такое...

версия VC какая?

RB>Перед этим ProgId не был прописан в реестре, а в CLSID было все пара записей про TypeLib и Version.


ProgId, TypeLib, Version — все есть, смотрел OleView
Re[4]: Скрипт as COM
От: rus blood Россия  
Дата: 22.05.04 10:50
Оценка:
OE>версия VC какая?
Пробовал на шестерке, компилер 12-й. Но как я понимаю, генерация tlb и регистрация компоненты не должна зависеть от студии.
Впрочем, могу проверить и семерку...


OE>ProgId, TypeLib, Version — все есть, смотрел OleView

Что насчет clsid ? У меня он был урезанный после генерации и регистрации tlb.
Имею скафандр — готов путешествовать!
Re: Скрипт as COM
От: rus blood Россия  
Дата: 22.05.04 12:40
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>вопрос — кто виноват и что делать?


12 компилятор вставляет строчку __uuidof(IDispatch) в определение смарт-пойнтера. Объект создается, интерфейс query-ться.
13 компилятор вставляет строчку __uuidof(Application), из-за чего такой интерфейс из объекта не достается. Что логично, поскольку scrobj.dll создает объект, поддерживающий только с IDisaptch.

Также интересно еще вот что. При генерации tlh в методы добавляется некий параметр, хотя в wsc он не объявляется. Собственно, вызвать метод объекта (объявленный в tli) не получается ни в семерке, ни в шестерке. Вызов падает с ошибкой 0x800a01c2.

Вызов напрямую Invoke через dispid без указания этого дополнительного параметра прекрасно работает и возвращает результаты...

К чему бы это???
Имею скафандр — готов путешествовать!
Re[2]: Скрипт as COM
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 22.05.04 17:23
Оценка:
Здравствуйте, rus blood, Вы писали:

RB>Также интересно еще вот что. При генерации tlh в методы добавляется некий параметр, хотя в wsc он не объявляется. Собственно, вызвать метод объекта (объявленный в tli) не получается ни в семерке, ни в шестерке. Вызов падает с ошибкой 0x800a01c2.


О! раз уж у тебя в 6-ке объект поднимается, можешь попробовать вызвать к-л метод, добавив этот еще один параметр (просто пустой variant)?
Re[3]: Скрипт as COM
От: rus blood Россия  
Дата: 22.05.04 17:48
Оценка:
OE>О! раз уж у тебя в 6-ке объект поднимается, можешь попробовать вызвать к-л метод, добавив этот еще один параметр (просто пустой variant)?

#import "D:\Rubbish\Intellect\COM_on_WSC\scriptlet.tlb" no_namespace, named_guids

int main(int argc, char* argv[])
{
    CoInitialize(NULL);

    AutomationPtr p;
    HRESULT h = p.CreateInstance("MyScriptlet.WSC");
//  h == S_OK;

    _variant_t res;
    _variant_t param;

    try
    {
        res = p->Method1(param);
    }
    catch(_com_error& e)
    {
//  exception, код 0x800a01c2
    }

    DISPPARAMS stParams;
    memset(&stParams, 0, sizeof(stParams));
    res.Clear();
    h = p->Invoke(1, IID_NULL, 0, DISPATCH_METHOD, &stParams, &res, NULL, NULL);
//  h == S_OK, res == "Succeeded" - эту строчку возвращает метод компонента.

    EXCEPINFO stInfo;
    memset(&stInfo, 0, sizeof(stInfo));
    stParams.cArgs = 1;
    stParams.rgvarg = &param;
    res.Clear();
    UINT arg = -1;
    h = p->Invoke(1, IID_NULL, 0, DISPATCH_METHOD, &stParams, &res, &stInfo, &arg);
//  h == 0x800a01c2, в stInfo - пусто, arg не изменяется.

    CoUninitialize();
    return 0;
}


Результаты в коде.

Генерируемые 6-кой и 7-кой tli — одинаковые, tlh различаются только объявлением смарт-пойнтера.
Имею скафандр — готов путешествовать!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.