Конференция "Прочее" » IActiveScript в Delphi (создание Msxml2.DOMDocument в vbs = AV)
 
  • Кто б сомневался © (20.05.16 16:21) [0]
    Есть программа x32, которая умеет запускать скрипты vbs через COM - т.е. используются IActiveScript, IActiveScriptParse и IActiveScriptSite (больше ничего).

    Сделал примерно как описано здесь:
    http://www.delphikingdom.ru/asp/viewitem.asp?UrlItem=/helloworld/activescript.htm
    Только без IActiveScriptSiteWindow.

    Т.е. берем текст скрипта и кидаем его в IActiveScriptParse.ParseScriptText .

    Vbs cкрипты работают на ура, но появилась одна проблема.

    Если в vbs скрипте есть строчка
    set xmlDoc = CreateObject("MSXML2.DOMDocument")
    или
    set xmlDoc = createobject("Microsoft.XMLDOM")

    Это объект для парсинга xml файлов -  
    то такой скрипт в IActiveScriptParse.ParseScriptText валит всю программу по AV. Даже если в vbs файле одна эта строчка.
    Никакого текста ошибки нет. Тупо AV по адресу.
    Win XP и Win 10 - одно и то же.
    Event Viewer - пусто.

    НО, если этот же vbs скрипт запустить в Windows (напр. через cmd.exe), то все проходит замечательно - никаких ошибок - объект создается и работает, отдавая данные по xml файлу. Проблема почему-то только с COM.

    Если кто-нибудь использует IActiveScriptParse.ParseScriptText вы не могли бы проверить у себя, будет ли работать vbs со строчкой set xmlDoc = CreateObject("MSXML2.DOMDocument") .

    Я пробовал и Msxml2.DOMDocument.6.0 и Msxml2.DOMDocument.3.0 - тоже самое.

    Вот к примеру полный скрипт  для проверки vbs:



    Set objDoc = CreateObject("MSXML.DOMDocument")
    objDoc.Load "d:\Test.xml"

    Set objRoot = objDoc.documentElement
    s = ""
    t = ""
    For Each child in objRoot.childNodes
      s = s & child.getAttribute("name") & " "
    Next
    'wScript.echo(s)    ' Displays "alpha beta gamma "



    xml:

    <?xml version="1.0"?>
    <root>
      <property name="alpha" value="1"/>
      <property name="beta" value="2"/>
      <property name="gamma" value="3"/>
    </root>



    Спасибо, чес. говоря даже не знаю что делать...
  • iop © (20.05.16 16:36) [1]
    Вот так если не работает из под cmd,
    то дело в битности сриптера, оси и самих активиксов

    c:\windows\SysWOW64\WScript.exe your.vbs
  • Кто б сомневался © (20.05.16 16:51) [2]
    iop ©   (20.05.16 16:36) [1]

    Работает... :(

    А вот vbs скрипт, состоящий из одной строчки:
    set xmlDoc = CreateObject("MSXML2.DOMDocument")
    или
    set xmlDoc = createobject("Microsoft.XMLDOM")

    если его всунуть в
    IActiveScriptParse.ParseScriptText
    дает Access Violation.

    причем что на Win XP x64, что на Win 10 x64 - одно и то же.
  • iop © (20.05.16 17:09) [3]
    а в чем вообще надобность запускать vbs из под обертки а не через createprocess?

    или вообще обойтись только vbs или только delphi?
  • Кто б сомневался © (20.05.16 17:09) [4]
    В примере Step2 этот код работает.

    http://www.delphikingdom.ru/asp/viewitem.asp?UrlItem=/helloworld/activescript.htm

    Значит где-то я налажал.

    В чем же может быть проблема, вроде все так же создается .. и другой vbs код работает..
  • Кто б сомневался © (20.05.16 17:13) [5]
    Да еще один момент, этот IActiveScriptParse код работает в dll, в котором не используются формы может в этом проблема?
  • iop © (20.05.16 17:14) [6]
    Set objDoc = CreateObject("MSXML.DOMDocument")
    objDoc.Load "d:\Test.xml"


    set objDoc = CreateObject("MSXML.DOMDocument")
    objDoc.async = false

    if objDoc.Load "d:\Test.xml" then
    ....
    else
    MsgBox("kyky!")
    end if
  • iop © (20.05.16 17:17) [7]
    я бы еще кодировку самого файла скрипта проверил
  • Кто б сомневался © (20.05.16 18:43) [8]
    Нашел в чем была проблема.
    Пожалуйста объясните почему так происходит... Я не понял..


    TScriptEngine = class(TInterfacedObject, IActiveScriptSite)

    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;

    function TScriptEngine._AddRef: Integer;
    begin
     Result := -1;
    end;

    function TScriptEngine._Release: Integer;
    begin
     Result := -1;
    end;


    При вызове  fEngine.SetScriptSite(Self);
    выполняется AddRef.

    При вызове ParseText выполняется еще один _AddRef
    Дальше от скрипта приходит OnEnterScript

    А потом сразу же вызывается деструктор TScriptEngine

    Никаких _Release не приходило.

    Вот с чем это связано я так и не понял.
    Убрал AddRef Addrealese и все заработало. Деструктор не вызывается.

    Причем с другими vbs скриптами раньше все работало с отключенным механизмом подсчета ссылок (мне бы без него сделать..)
  • Кто б сомневался © (20.05.16 19:21) [9]
    Вобщем нельзя так делать. Всмысле наследоваться от TInterfacedObject и писать собственные  function _AddRef: Integer; stdcall; function _Release: Integer; stdcall;

    Если нужно отключить счетчик ссылок, нужно наследоваться от TObject и там реализовывать уже  собственные
    function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;

    Что я и сделал сейчас.

    А оказывается QueryInterface вызывает  GetInterface из TObject и там при определенных услвиях происходит тот самый IInterface(Obj)._AddRef (в моем случае вызывается уже TInrefacedObject.addRef, а не мой addRef). А потом в других методах выполняется и _Release из TinterfacedObject а там уже и  деструктор.

    Такие дела..
  • iop © (20.05.16 19:43) [10]
    почему нельзя-то?

    если наследником intfobj планируется пользоваться в стиле обычного tobject (с намерением потом явно удалить ), то _addRef позволяет не бояться счетчика ссылок.
    не умрет пока сам не кильнешь
  • Кто б сомневался © (20.05.16 23:08) [11]

    > op ©   (20.05.16 19:43) [10]
    >
    > почему нельзя-то?
    >
    > если наследником intfobj планируется пользоваться в стиле
    > обычного tobject (с намерением потом явно удалить ), то
    > _addRef позволяет не бояться счетчика ссылок.
    > не умрет пока сам не кильнешь


    Ну тогда у вас скоро будут такие же вопросы как у меня этот - случайные хрен пойми AV.
    Я тоже так думал, и тоже пользовался им в стиле TObject - и все нормально работало, пока не настал этот случай.. У меня сейчас нету времени делать детальный анализ, сроки горят:
    В случае если наследоваться от TInterfacedObject, то там RefCount при определенных условиях (я не знаю что это за условия, может знатоки объяснят) инкриминируется через TObject -  IInterface(Obj)._AddRef;

    function TObject.GetInterface(const IID: TGUID; out Obj): Boolean;
    var
     InterfaceEntry: PInterfaceEntry;
    begin
     Pointer(Obj) := nil;
     InterfaceEntry := GetInterfaceEntry(IID);
     if InterfaceEntry <> nil then
     begin
       if InterfaceEntry^.IOffset <> 0 then
       begin    
         Pointer(Obj) := Pointer(PByte(Self) + InterfaceEntry^.IOffset);
         if Pointer(Obj) <> nil then IInterface(Obj)._AddRef; <<<<<<<<<<
       end
       else
         IInterface(Obj) := InvokeImplGetter(Self, InterfaceEntry^.ImplGetter);
     end else if ObjCastGUID = IID then
       Pointer(Obj) := Pointer(Self);
     Result := Pointer(Obj) <> nil;
    end;


    Т.е. обычно выполняется код end else if ObjCastGUID = IID then. А в каких то редких условиях выполняется тот что стрелкой показан.

    Это вызовет метод TInterfacedObject.addref - который увеличит счетчик с нуля на еденицу. Дальше выполняется какой то сторонний код, на стороне COM и потом уже  отладчик показывает точку останова на _Release TInterfacedObject. Т.е. не _Release моего класса, который наследован от TInterfacedObject, а именно TInterfacedObject.
    Ну а дальше уже оттуда вызывается деструктор.
    В остальных вариантах (в большинстве случаев) код выполняется в моих Addref и Release.
  • iop © (20.05.16 23:27) [12]
    тоже так думал, и тоже пользовался им в стиле TObject - и все нормально работало

    все там нормально с адреф.
    но просто есть особенности реализации конкретных классов.

    например TXMLDocument.

    если в конструктор передан живой оунер (например он сброшен в дизайнере на форму) - поведение будет объектное.

    если же в конструктор пришел нил в качестве оунера - будет интерфейсное поведение.
    и тут уже следить за ссылками и не вызывать free
 
Конференция "Прочее" » IActiveScript в Delphi (создание Msxml2.DOMDocument в vbs = AV)
Есть новые Нет новых   [134433   +22][b:0][p:0.001]