Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2017.07.09;
Скачать: CL | DM;

Вниз

IActiveScript в Delphi (создание Msxml2.DOMDocument в vbs = AV)   Найти похожие ветки 

 
Кто б сомневался ©   (2016-05-20 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 ©   (2016-05-20 16:36) [1]

Вот так если не работает из под cmd,
то дело в битности сриптера, оси и самих активиксов

c:\windows\SysWOW64\WScript.exe your.vbs


 
Кто б сомневался ©   (2016-05-20 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 ©   (2016-05-20 17:09) [3]

а в чем вообще надобность запускать vbs из под обертки а не через createprocess?

или вообще обойтись только vbs или только delphi?


 
Кто б сомневался ©   (2016-05-20 17:09) [4]

В примере Step2 этот код работает.

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

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

В чем же может быть проблема, вроде все так же создается .. и другой vbs код работает..


 
Кто б сомневался ©   (2016-05-20 17:13) [5]

Да еще один момент, этот IActiveScriptParse код работает в dll, в котором не используются формы может в этом проблема?


 
iop ©   (2016-05-20 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 ©   (2016-05-20 17:17) [7]

я бы еще кодировку самого файла скрипта проверил


 
Кто б сомневался ©   (2016-05-20 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 скриптами раньше все работало с отключенным механизмом подсчета ссылок (мне бы без него сделать..)


 
Кто б сомневался ©   (2016-05-20 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 ©   (2016-05-20 19:43) [10]

почему нельзя-то?

если наследником intfobj планируется пользоваться в стиле обычного tobject (с намерением потом явно удалить ), то _addRef позволяет не бояться счетчика ссылок.
не умрет пока сам не кильнешь


 
Кто б сомневался ©   (2016-05-20 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 ©   (2016-05-20 23:27) [12]

тоже так думал, и тоже пользовался им в стиле TObject - и все нормально работало

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

например TXMLDocument.

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

если же в конструктор пришел нил в качестве оунера - будет интерфейсное поведение.
и тут уже следить за ссылками и не вызывать free



Страницы: 1 вся ветка

Текущий архив: 2017.07.09;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.005 c
1-1352355762
Дмитрий Белькевич
2012-11-08 10:22
2017.07.09
Ищу дефолтный library path для xe3.


2-1444440112
Е95
2015-10-10 04:21
2017.07.09
Как можно экспортировать функцию по EntryPoint (ordinal)?


2-1444454791
steremin
2015-10-10 08:26
2017.07.09
MS Access ошибка при открытии файла!


4-1281966850
istok
2010-08-16 17:54
2017.07.09
узнать, находится ли фокус ввода в окне или нет...


4-1282815533
RG
2010-08-26 13:38
2017.07.09
в Windows7 не работает IsWindowVisible