Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2017.07.09;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.001 c
6-1283385235
Gu
2010-09-02 03:53
2017.07.09
Определение региона по ip


6-1283427469
dmitrynpk
2010-09-02 15:37
2017.07.09
Ограничение доступа к Серверу на TIdTCPServer


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


2-1444423211
Михапыч
2015-10-09 23:40
2017.07.09
Ошибка компиляции


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





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский