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

Вниз

BindToObject   Найти похожие ветки 

 
Polevi ©   (2004-04-13 11:50) [0]

Возникла задача получить ссылки на открытые в системе книги Excel - то есть на их интерфейс IWorkbook
Решаю ее с помощью RunningObjectTable

На некоторых машинах HResultCode(BindToObject(...)) возвращает 8 - ERROR_NOT_ENOUGH_MEMORY. Причем не время от времени, а всегда. То есть есть машины на которых код просто отказывается работать.

program rot;
{$APPTYPE CONSOLE}

uses
 SysUtils,
 ActiveX,
 ComObj,
 Windows;

var
 rotbl:IRunningObjectTable;
 em:IEnumMoniker;
 m:IMoniker;
 bc:IBindCtx;
 celtFetched:longint;
 unk:IUnknown;
 rst:HResult;
const
 IID__Workbook: TGUID = "{000208DA-0000-0000-C000-000000000046}";
begin
 Writeln("Search "+GuidToString(IID__Workbook));
 CoInitialize(nil);
 OleCheck(CreateBindCtx(0, bc));
 OleCheck(GetRunningObjectTable(0,rotbl));
 OleCheck(rotbl.EnumRunning(em));
 OleCheck(em.Reset);
 OleCheck(em.Next(1,m,@celtFetched));
 while celtFetched=1 do
 try
   try
     rst:=m.BindToObject(bc,nil,IID__Workbook,unk);
     if Succeeded(rst) then
       Writeln("OK. Object binding.")
     else
       raise Exception.CreateFmt("BindToObject failed. Return code %d",[HResultCode(rst)]);
   except
     on E:Exception do writeln(E.Message);
   end;
 finally
   OleCheck(em.Next(1,m,@celtFetched));
 end;
 CoUninitialize;
 readln;
end.

если моникер не ссылается на интерфейс, передаваемый в BindToObject - он возвращает error 87 -  ERROR_INVALID_PARAMETER

иначе должен вернуть S_OK и ссылку на интерфейс в последнем параметре
в большинчстве случаев так и просиходит,  но на некоторых машинах возвращает 8 ошибку -   ERROR_NOT_ENOUGH_MEMORY

может есть у кого идеи ?

на всех тестируемых машинах 98 Win SE, Office 2000


 
VMcL ©   (2004-04-13 14:46) [1]

>>Polevi ©  (13.04.04 11:50)

Возможно я сейчас ляпну глупость, но почему просто не создать Excel.Application и не перебрать в цикле WorkBooks"ы?


 
Polevi ©   (2004-04-13 15:32) [2]

сам то пробовал ?


 
VMcL ©   (2004-04-14 10:29) [3]

Ну если ты настаиваешь :)

Кинул на форму (D6):
* Button1: TButton
* Memo1: TMemo
* ExcelApplication1: TExcelApplication {из Excel2000.pas}

Установил свойство ExcelApplication1.ConnectKind в ckRunningInstance.

procedure TForm1.Button1Click(Sender: TObject);
var
 I: Integer;
 W: _Workbook;
 S: String;
begin
 Memo1.Clear;

 ExcelApplication1.Connect;
 try
   for I := 1 to ExcelApplication1.Workbooks.Count do
   begin
     W := ExcelApplication1.Workbooks[I];
     S := W.Name;
     Memo1.Lines.Add(S);
   end;
 finally
   ExcelApplication1.Disconnect;
 end;
end;


 
Nikolay M. ©   (2004-04-14 11:41) [4]


> VMcL ©   (14.04.04 10:29) [3]

А если запустить новый Instance екселя? Не пойдеть :(

Есть мнение, что нужно биндиться непосредственно через ROT (IRunningObjectTable::GetObject).


 
VMcL ©   (2004-04-14 11:47) [5]

>>Nikolay M. ©  (14.04.04 11:41) [4]

Ну я ж сразу написал, что "ляпну глупость" [1] :)
Я таким не занимался, а только как вариант предложил.


 
Polevi ©   (2004-04-15 10:22) [6]

Заменил BindToObject на IRunningObjectTable::GetObject

...
 OleCheck(rotbl.GetObject(m,unk));
 OleCheck(unk.QueryInterface(IID__Workbook,wb));
...

IUnknown я получаю без ошибок
А вот вызов QueryInterface на "проблемных" машинах возвращает "неверный тип переменной"

???


 
Polevi ©   (2004-04-15 13:05) [7]

Переписал все на VC, результат аналогичный..
Мдя..


 
VMcL ©   (2004-04-15 13:35) [8]

>>Polevi ©  (15.04.04 10:22) [6]

wb у тебя OleVariant?


 
Polevi ©   (2004-04-15 13:48) [9]

>VMcL ©   (15.04.04 13:35) [8]
IUnknown, вот последняя версия на С

#include "stdafx.h"

int main(int argc, char* argv[])
{
     IBindCtx *bc;
IRunningObjectTable *rotbl;
IEnumMoniker *em;
IMoniker *m;
unsigned long celtFetched;
IUnknown *unk, *wb;

CoInitialize(NULL);

   IID   IID_Workbook;
   char*   szCLSID = "{000208DA-0000-0000-C000-000000000046}";
   WCHAR   szWideProgID[128];
   long lLen = MultiByteToWideChar( CP_ACP,
                    0,
                    szCLSID,
                    strlen( szCLSID ),
                    szWideProgID,
                    sizeof( szWideProgID ) );
   szWideProgID[ lLen ] = "\0";
   CLSIDFromString(szWideProgID,&IID_Workbook);

     CreateBindCtx(0,&bc);
GetRunningObjectTable(0,&rotbl);
rotbl->EnumRunning(&em);
em->Reset();
em->Next(1,&m,&celtFetched);
while(1==celtFetched)
{
 rotbl->GetObject(m,&unk);
 unk->QueryInterface(IID_Workbook,(void **)&wb);
 if(wb!=NULL)
  printf("Ok.\n");
 em->Next(1,&m,&celtFetched);
}
Sleep(2000);
return 0;
}


 
VMcL ©   (2004-04-15 14:25) [10]

>>Polevi ©  (15.04.04 13:48) [9]

Так по идее надо не IID__Workbook получать, а IID__Application
(IID__Application: TGUID = "{000208D5-0000-0000-C000-000000000046}";)

У меня на IID__Workbook писало "Интерфейс не поддерживается".

Написал вот так и заработало:

program Polevi;
{$APPTYPE CONSOLE}

uses
 SysUtils,
 ActiveX,
 ComObj,
 Windows,
 Excel2000;

var
 rotbl: IRunningObjectTable;
 em: IEnumMoniker;
 m: IMoniker;
 bc: IBindCtx;
 celtFetched: longint;
 unk, wb: IUnknown;
//const
//  IID__Workbook: TGUID = "{000208DA-0000-0000-C000-000000000046}";
//  IID__Application: TGUID = "{000208D5-0000-0000-C000-000000000046}";
begin
 Writeln("Search " + GuidToString(IID__Workbook));
 CoInitialize(nil);
 OleCheck(CreateBindCtx(0, bc));
 OleCheck(GetRunningObjectTable(0,rotbl));
 OleCheck(rotbl.EnumRunning(em));
 OleCheck(em.Reset);
 OleCheck(em.Next(1, m, @celtFetched));
 while celtFetched = 1 do
   try
     try
       OleCheck(rotbl.GetObject(m, unk));
       //OleCheck(unk.QueryInterface(IID__Workbook, wb));
       OleCheck(unk.QueryInterface(IID__Application, wb));

       Writeln("OK. Object binding.");
     except
       on E: Exception do
         MessageBox(0, PChar(E.Message), "Error", MB_OK or MB_TASKMODAL);
     end;
   finally
     OleCheck(em.Next(1, m, @celtFetched));
   end;
 CoUninitialize;
 readln;
end.


 
VMcL ©   (2004-04-15 14:33) [11]

>>VMcL ©  (15.04.04 14:25) [10]

Ой, забыл с ручника сняться. Сначала Application получаем, а потом и Workbook. Так что можно и по-твоему писать.


 
VMcL ©   (2004-04-15 14:53) [12]

Вот такой вариант на моем компе работает (WinXP Pro SP1):

program Polevi;
{$APPTYPE CONSOLE}

uses
 SysUtils,
 ActiveX,
 ComObj,
 Windows,
 Excel2000;

function AnsiToOem(const Src: String): String;
begin
 SetLength(Result, Length(Src));
 if Src <> "" then
   CharToOemA(PChar(Src), PChar(Result));
end;

var
 rotbl: IRunningObjectTable;
 em: IEnumMoniker;
 m: IMoniker;
 bc: IBindCtx;
 celtFetched: longint;
 unk: IUnknown;
 wb: Excel2000._Workbook;
begin
 Writeln("Search " + GuidToString(IID__Workbook));
 Writeln;

 CoInitialize(nil);
 OleCheck(CreateBindCtx(0, bc));
 OleCheck(GetRunningObjectTable(0,rotbl));
 OleCheck(rotbl.EnumRunning(em));
 OleCheck(em.Reset);
 OleCheck(em.Next(1, m, @celtFetched));
 while celtFetched = 1 do
   try
     try
       OleCheck(rotbl.GetObject(m, unk));
       OleCheck(unk.QueryInterface(IID__Workbook, wb));

       writeln("OK: " + AnsiToOem(String(wb.Name)));
     except
       on E: Exception do
         writeln("Error: ", AnsiToOem(E.Message));
     end;
   finally
     OleCheck(em.Next(1, m, @celtFetched));
   end;
 CoUninitialize;
 Writeln;
 Write("Press ENTER...");
 readln;
end.


Выдает error на Application"ы Excel"я; с Workbook"ами же всё ОК.


 
Polevi ©   (2004-04-15 16:54) [13]

>VMcL ©   (15.04.04 14:53) [12]
дык проблема то в том что на моем компе тоже все работает
а вот на некоторых - нет
ненавижу такие штуки :(


 
VMcL ©   (2004-04-15 17:04) [14]

>>Polevi ©  (15.04.04 16:54) [13]

Win98SE? Может на нее или на Офис какой-нить патч натравить нужно?


 
Polevi ©   (2004-04-15 17:59) [15]

у меня уже руки опускаются
представь себе ситуацию
стоят 2 машины, Win98 SE, Office 2000, IE6
установлено с одного диска
на одной машине работает, на другой - нет
да и других программ нет никаких - обычные офисные машины
разве что на одной Acrobat Reader 6 - на другой 5
мистика какаято..


 
VMcL ©   (2004-04-15 18:04) [16]

>>Polevi ©  (15.04.04 17:59) [15]

Ну тогда только Breakpoint, при останове - View CPU (Ctrl+Alt+C) и F7, F7, F7...
Или вообще SoftIce"ом :)


 
Polevi ©   (2004-04-15 19:02) [17]

так я наверно и сделаю



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

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

Наверх




Память: 0.49 MB
Время: 0.037 c
1-1104904755
KyPCAHT
2005-01-05 08:59
2005.01.23
вызов функции из dll, написанной на Delphi, из Visual Basic 6.0


1-1105093809
Hadroran
2005-01-07 13:30
2005.01.23
Цветные строки в ExpressQuantumGrid


1-1104959131
maxXP
2005-01-06 00:05
2005.01.23
Cписок файлов


3-1103539744
Tek
2004-12-20 13:49
2005.01.23
Подскажите плз, как перегнать таблицу с одной базы в другую..


4-1102421435
Erazser
2004-12-07 15:10
2005.01.23
Как сделать чтобы окно передвинулось на передний план?





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