Форум: "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.04 c