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

Вниз

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 вся ветка

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

Наверх




Память: 0.52 MB
Время: 0.024 c
1-1105002566
Федюлин Григорий
2005-01-06 12:09
2005.01.23
Работа с ReadDirectoryChangesW


6-1099294965
Ivolg
2004-11-01 10:42
2005.01.23
Http


8-1097603406
miek
2004-10-12 21:50
2005.01.23
новый компрессор изображений


4-1102433538
Eagle Owl
2004-12-07 18:32
2005.01.23
Температура процессора...


1-1104904307
rus9
2005-01-05 08:51
2005.01.23
Excel