Форум: "Сети";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.03.28;
Скачать: [xml.tar.bz2];




Вниз

Доспуп к свойтвам Internet Explorer (СОМ) при работе с SHTTP, а работа с СОМ при использовании потоков 


Ramid   (2002-01-16 13:37) [0]

Проблема заключается в следующем:
1. Создается СОМ обьект: IE5
var v: variant;

V := CreateOleObject("InternetExplorer.Application.1");
V.Visible := Vis;
V.Navigate(open_url);

2. Получем доступ к его методам, может загружать страницы, проводить их разбор,
V.document.script.window.document.title;

4. Проблема 1 Невозможно обрататся к обьекту V из потока, выдает ошибку, обращение из синхронизированого потока к внешнему или еще что похлеще.

3. Проблемма 2 заключается при просмотре страницы SecureHTTP
в этом случае не доступа с V.document.script.window.document можно как нибудь это обойти и получить содержимое страниы?
ведь браузер показывает страницу и значит знает ее содержимое :)



Digitman   (2002-01-16 14:33) [1]

Проблема 1 решается так:


CoInitialize(nil)// обязательно при обращении к механизму OLE/COM из потока !!

...
try
...
V := CreateOleObject("InternetExplorer.Application.1");
V.Visible := Vis;
V.Navigate(open_url);
...
finally
CoUninitialize; // обязательно при обращении к механизму OLE/COM из потока !!
...
end;
...




Ramid   (2002-01-16 16:14) [2]

Да спасибо все получилось,
я тоже использовал CoInitialize(nil), но
СОМ создавался вне потока и до него,
при этом все равно выводится ошибка "EOleSysError:Приложении обратмлось к интерфейсу относящемуся к другому потоку"
Вот это можно как-нибудь обойти.

И если можно поподробнее что CoInitialize делает.



Digitman   (2002-01-16 17:01) [3]

"СОМ создавался вне потока и до него" - этого не может быть) На основании чего ты сделал такое умозаключение ?

CoInitialize делает то, что написано в Delphi Win32 SDK help. Ты туда сходил, прежде чем спрашивать об этом ?



Ramid   (2002-01-16 17:16) [4]

пример когда выдает ошибку:
procedure TForm1.SpeedButton2Click(Sender: TObject);
// отдельно создается обект
begin
V := CreateOleObject("InternetExplorer.Application.1");
V.Visible := true;
end;

после этого создается поток и запускается на выполнение
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
SecondProcess := TSub.Create(false);
end;

и если этому потоку принадлежит функция
procedure TSub.Execute;
begin
CoInitialize(nil);
try
form1.label2.caption := V.Visible; // выдается ошибка
finally
CoUninitialize();
Suspend();
Terminate();
Destroy();
end;
end;


можно ли этого избежать.

На счет Delphi Win32 SDK help мои извениения действительно не читал, прости, что отнял у тебя немного времени.



Digitman   (2002-01-16 17:52) [5]

>> пример когда выдает ошибку:
procedure TForm1.SpeedButton2Click(Sender: TObject);
>> // отдельно создается обект
// в ОСНОВНОМ ПОТОКЕ он создается - это ты понимаешь ?
begin
V := CreateOleObject("InternetExplorer.Application.1");
V.Visible := true;
end;

>> после этого создается поток и запускается на выполнение
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
SecondProcess := TSub.Create(false);
end;

>> и если этому потоку принадлежит функция
// не ПОТОКУ ПРИНАДЛЕЖИТ ФУНКЦИЯ, а ОБЪЕКТ-ПОТОК реализует метод EXECUTE
procedure TSub.Execute;
begin
CoInitialize(nil); // это зачем ? разве OLE-объект создается в доп.потоке ??
try
form1.label2.caption := V.Visible; // выдается ошибка
// 1. ошибка ?? ну, разумеется !! асинхронные обращение к объектам-наследникам TWinControl из доп.потоков недопустимы !!
// на то есть метод TThread.Synchronize()
// 2. объект V создан в осн.потоке, а манипулируешь им в другом доп.потоке. Для объекта IE.Application это недопустимо, как и для многих распространенных OLE-серверов от MS (имеющих ThreadingModel = Apartment)
finally
CoUninitialize(); // а это зачем ?
Suspend(); // а здесь что делаешь ?
Terminate(); // а здесь ?
Destroy(); // а здесь ?
// комментируй свои мысли. полным-полно несуразиц в этих 3-х строчках
end;
end;





Digitman   (2002-01-16 17:55) [6]

>> пример когда выдает ошибку:
procedure TForm1.SpeedButton2Click(Sender: TObject);
>> // отдельно создается обект
// в ОСНОВНОМ ПОТОКЕ он создается - это ты понимаешь ?
begin
V := CreateOleObject("InternetExplorer.Application.1");
V.Visible := true;
end;

>> после этого создается поток и запускается на выполнение
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
SecondProcess := TSub.Create(false);
end;

>> и если этому потоку принадлежит функция
// не ПОТОКУ ПРИНАДЛЕЖИТ ФУНКЦИЯ, а ОБЪЕКТ-ПОТОК реализует метод EXECUTE
procedure TSub.Execute;
begin
CoInitialize(nil); // это зачем ? разве OLE-объект создается в доп.потоке ??
try
form1.label2.caption := V.Visible; // выдается ошибка
// 1. ошибка ?? ну, разумеется !! асинхронные обращение к объектам-наследникам TWinControl из доп.потоков недопустимы !!
// на то есть метод TThread.Synchronize()
// 2. объект V создан в осн.потоке, а манипулируешь им в другом доп.потоке. Для объекта IE.Application это недопустимо, как и для многих распространенных OLE-серверов от MS (имеющих ThreadingModel = Apartment)
finally
CoUninitialize(); // а это зачем ?
Suspend(); // а здесь что делаешь ?
Terminate(); // а здесь ?
Destroy(); // а здесь ?
// комментируй свои мысли. полным-полно несуразиц в этих 3-х строчках
end;
end;





Ramid   (2002-01-16 18:21) [7]

постой, неругай все сразу :)

да я понимаю что обьект TThread создается в основном потоке.

теперь давай посмотрим такой случай
procedure TSubmit.Execute;
begin
Synchronize(PrintTime);
end;


где
procedure TSubmit.PrintTime();
begin
form1.label2.caption := V.Visible; // генегирует исключение
//EOleSysError: Не удается выполнить выполнить исходящий вызов
//так как выполняется входящий синхроный вызов
end;



теперь на счет
Suspend(); // приостанавливается поток
Terminate(); // дается запрос на его прекращение



Digitman   (2002-01-16 18:38) [8]

1. при чем здесь поток, в котором создается TThread ? Здесь важно совсем другое : OLE-объекты, созданные производителем в атрибутом Apartment, допускают обращение к их св-вам/методам лишь в том потоке, в котором они создаются !

2. form1.label2.caption := V.Visible
Нет желания вдаваться в подробности интерфейса объекта IE.App, но, imho, св-во IE.App.Visible д.иметь тип Boolean, в то время как TLabel.Caption - строковое св-во. Что на это скажешь ?

3. Suspend(); // приостанавливается поток
а кто, когда и в каком месте кода в каком потоке его возобновляет после самоприостановки по Suspend ? Ведь следующая строчка никогда не выполнится, если внешний по отношению к приостановленному поток не возобновит его вызовом метода Resume()

Terminate(); // дается запрос на его прекращение
кому - запрос ? поток запрашивает прекращение самого себя ? нонсенс ! Читай внимательно хэлп на этот метод и вникай в его реализацию в модуле classes.



Ramid   (2002-01-16 19:09) [9]

На счет Terminate(); как мне тогда завершить поток когда он закончил работу которую должен был сделать?

form1.label2.caption := V.Visible - ничего страшного boolean - перечисляемый тип
type boolean = (false,true);

P.S. не суди строго за незнание чего либо, все когда то узнаешь впервые



kig   (2002-01-16 19:31) [10]

Если хотите использовать в потоке (например Б) COM-объект, созданный в другом потоке (А), и объект не ThreadingModel != Free (Both), необходимо проделать примерно следующее:

1. в потоке Б вызвать CoInitialize (или CoInitializeEx)

2. в потоке А выполнить
CoMarshalInterThreadInterfaceInStream
Marshals an interface pointer from one thread to another thread in the same process.

HRESULT CoMarshalInterThreadInterfaceInStream(
REFIID riid, //Reference to the identifier of the interface
LPUNKNOWN pUnk, //Pointer to the interface to be marshaled
LPSTREAM * ppStm //Address of output variable that receives the
// IStream interface pointer for the marshaled
// interface
);

например CoMarshalInterThreadInterfaceInStream(WebBrowser.Document)

3. В потоке Б выполнить

Забрать ppStm и использовать его в

CoGetInterfaceAndReleaseStream
Unmarshals a buffer containing an interface pointer and releases the stream when an interface pointer has been marshaled from another thread to the calling thread.

HRESULT CoGetInterfaceAndReleaseStream(
LPSTREAM pStm, //Pointer to the stream from which the object is
// to be marshaled
REFIID riid, //Reference to the identifier of the interface
LPVOID * ppv //Address of output variable that receives the
// interface pointer requested in riid
);

Затем пользовать ppv (как WebBrowser.Document)

4. В потоке Б перед окончание вызвать CoUninitialize

Читать лучше первоисточники ))
MSDN
Platform SDK
Component service
COM



Digitman   (2002-01-17 13:34) [11]

>Ramid

1. Не надо никаких вызовов метода Terminate() в твоей реализации метода Execute() - реализовано сквозное безусловное выполнение кода, циклы никакие не используются и с завершением работы метода завершается (ну, с некоторой долей условности - см.реализацию класса TThread в модуле classes) и сам отработавший поток как объект ОС.
А для того, чтобы был автоматически разрушен и поток как VCL-объект (тот самый созданный тобой экземпляр класса TSubmit), достаточно сделать так :


TSubmit = class(TThread)
...
public
...
constructor Create(CreateSuspended: Boolean);
...
end;

constructor TSubmit.Create(CreateSuspended: Boolean);
begin
inherited Create(True); // создаем приостановленный поток
...
// взводим флаг автоматич.разрушения экземпляра после завершения создаваемого им потока как объекта ОС
FreeOnTerminate:= True;
...
// если параметр конструктора был True - стартуем поток немедленно
if CreateSuspended then Resume;
end;


2. Перечислимый тип никак не соответствует строковому типу : первый относится к семейству Ordinal-типов, второй - к литерным типам. Необходимо явное преобразование наподобие следующего :


with form1.label2 do
if V.Visible then
Caption := "true"
else
Caption := "false"


Азы Паскаля !! А ты COM-объектами занялся ...



Ramid   (2002-01-17 16:25) [12]

На счет СОМ с тобой спорить не буду, ты тут без сомнения лучше меня все знаешь, и я благодарен твоим советам.



Digitman   (2002-01-17 17:23) [13]

>Ramid
Ну, разберись хоть с семействами типов Паскаля и их совместимостью. Ведь грубые ошибки делаешь, ну в самом деле !




Форум: "Сети";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.03.28;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.77 MB
Время: 0.033 c
6-91015           Victoz                2002-01-16 12:12  2002.03.28  
Как узнать название сети?


1-90955           skywalker             2002-03-14 11:36  2002.03.28  
Ресурс курсора


4-91097           kirya85               2002-01-16 09:06  2002.03.28  
Как програмно узнать сколько занимает памяти чужое приложение?


1-90950           -Stealtch-            2002-03-14 17:31  2002.03.28  
Преобразования цвета от цветовой палитры экрана


1-90921           SB                    2002-03-13 21:56  2002.03.28  
Случайное число