Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 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
Ну, разберись хоть с семействами типов Паскаля и их совместимостью. Ведь грубые ошибки делаешь, ну в самом деле !



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

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

Наверх





Память: 0.49 MB
Время: 0.008 c
4-91107
IronHawk
2002-01-28 16:00
2002.03.28
Преобразование String to TCaption и Наоборот ..??


7-91086
again Lizard
2001-12-24 20:49
2002.03.28
Как заставить прогу открывать определенный ключ реестра с помощью Regedit.exe.


3-90803
arnold lane
2002-03-04 20:59
2002.03.28
вопрос


3-90743
roottim
2002-02-28 15:31
2002.03.28
месяц-год... и тп


1-90953
novom
2002-03-13 15:06
2002.03.28
Преобразовать в стандартный формат.





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский