![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Обращение к удаленном OLE-объекту
GrBob © (2006-06-27 11:07:00)Здравствуйте.
На удаленном компьютере есть OLE-объект, у которого известно только название. (ну и соответственно легко получается CLSID, в реестре на данном компьютере информация об объекте есть). Вопрос: можно ли как-нибудь к нему обраться? CreateOLEObject работает только на текущей машине, а CreateRemoteComObject возвращает интерфейс, название которого я не знаю. (Как его получить?)
Заранее спасибо за ответы.
GrBob (2006-06-30 09:24:00) [21]Огромное спасибо, тут я более-менее разобрался, осталось узнать как вызывать методы, а не только менять свойства.
PS. Методы возвращают другие COM-объекты.
Жду с большим нетерпением подсказки, наконец я хоть немного продвинулся.
AbrosimovA (2006-06-29 15:53:00) [22]
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComObj, AxCtrls, ExtCtrls, ComCtrls;
type
TForm1 = class(TForm)
btnReadProp: TButton;
ListBox1: TListBox;
ServNameEdit: TEdit;
Label1: TLabel;
Label4: TLabel;
btnExec: TButton;
Timer1: TTimer;
ValuePropEdit: TEdit;
btnReadInterf: TButton;
btnConnect: TButton;
BtnRemConnect: TButton;
StatusBar1: TStatusBar;
procedure btnReadPropClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure btnExecClick(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure btnReadInterfClick(Sender: TObject);
procedure BtnRemConnectClick(Sender: TObject);
private
ServerName: string[255];
procedure SetInvoke(const ID: integer; const Command: OleVariant);
public
end;
var
Form1: TForm1;
Srv: IDispatch;
ID,DID: integer;
iIndex: integer;
implementation
{$R *.dfm}
uses ActiveX;
//Перечисление свойств
procedure EnumProperties(Dispatch: IDispatch; Entries: TStrings);
var iDispID,i: integer;
NameRefs: array[0..0] of PWideChar;
HR: HResult;
begin
Entries.Clear;
Entries.NameValueSeparator:='-';
EnumDispatchProperties(Dispatch, GUID_NULL, VT_EMPTY, Entries);
for i:=0 to Entries.Count-1 do begin
NameRefs[0]:=PWideChar(WideString(Entries[i]));
HR:=Dispatch.GetIDsOfNames(GUID_NULL, @NameRefs, 1,
LOCALE_SYSTEM_DEFAULT, @iDispID);
if HR=S_OK then
Entries.Strings[i]:= Format('%d-%s',[iDispID,Entries[i]]);
end
end;
//Перечисление интерфейсов
procedure EnumInterface(Dispatch: IDispatch; Entries: TStrings; Functions: Boolean);
var
TypeInfo: ITypeInfo;
TypeAttr: PTypeAttr;
FuncDesc: PFuncDesc;
Vardesc: PVarDesc;
hr: HResult;
iMethode: Integer;
nNames : integer;
sNameLst: TBSTRList;
begin
Dispatch.GetTypeInfoCount(iMethode);
if iMethode > 0 then
begin
hr := Dispatch.GetTypeInfo(0,GetUserDefaultLCID,TypeInfo);
OleCheck(hr);
hr := TypeInfo.GetTypeAttr(TypeAttr);
OleCheck(hr);
if Functions then
begin
for iMethode := 0 to TypeAttr.cFuncs-1 do
begin
hr := TypeInfo.GetFuncDesc(iMethode, FuncDesc);
OleCheck(hr);
hr := TypeInfo.GetNames(FuncDesc.memid, @sNameLst,1,nNames);
OleCheck(hr);
Entries.Add(Format('%d-%s', [FuncDesc.memid, sNameLst[0]]));
end;
end
else
begin
for iMethode := 0 to TypeAttr.cVars-1 do
begin
hr := TypeInfo.GetVarDesc(iMethode, Vardesc);
OleCheck(hr);
hr := TypeInfo.GetNames(Vardesc.memid, @sNameLst,1,nNames);
OleCheck(hr);
Entries.Add(Format('%d-%s', [Vardesc.memid, sNameLst[0]]));
end;
end;
end;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Srv:=nil;
end;
function GetDispIDFromName(const Disp: IDispatch; const PropertyName: WideString;
var iDispID: Integer): OleVariant;
var
PName: PWideChar;
ExcepInfo: TExcepInfo;
DispParams: TDispParams;
Status: HResult;
begin
if Disp = nil then Exit;
PName := PWideChar(PropertyName);
if PropertyName = '' then
Result := DISPID_UNKNOWN
else
Disp.GetIDsOfNames(GUID_NULL, @PName, 1, GetThreadLocale, @iDispID);
FillChar(DispParams, SizeOf(DispParams), 0);
Status := Disp.Invoke(iDispID, GUID_NULL, 0, DISPATCH_PROPERTYGET, DispParams,
@Result, @ExcepInfo, nil);
if Status <> S_OK then
DispatchInvokeError(Status, ExcepInfo);
end;
procedure TForm1.SetInvoke(const ID: integer; const Command: OleVariant);
var
vSet : OLEVariant;
aDispParams : TDispParams;
aDispId : TDispId;
aEI : TExcepInfo;
iError : UINT;
ptinfo: ITypeInfo;
begin
vSet := Command;
FillChar(aDispParams, SizeOf (aDispParams), 0);
with aDispParams do begin
rgvarg := @vSet;
cArgs := 1;
cNamedArgs := 1;
end;
aDispId := DISPID_PROPERTYPUT;
aDispParams.rgdispidNamedArgs := @aDispId;
OleCheck (Srv.Invoke (ID, GUID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYPUT, aDispParams, NIL, @aEI, @iError));
end;
procedure TForm1.ListBox1Click(Sender: TObject);
begin
iIndex:=Listbox1.ItemIndex;
if (iIndex<>-1)and(Tag=1) then
ValuePropEdit.Text:=GetDispIDFromName(Srv, Listbox1.Items.ValueFromIndex[iIndex],DID)
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
btnExec.Enabled:=(iIndex<>-1)and(Tag=1);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
iIndex:=-1;
end;
//интерфейсы
procedure TForm1.btnReadInterfClick(Sender: TObject);
begin
Tag:=2;
ListBox1.Clear;
ValuePropEdit.Clear;
if Assigned(Srv) then EnumInterface(Srv,ListBox1.Items,True)
end;
//свойства
procedure TForm1.btnReadPropClick(Sender: TObject);
begin
Tag:=1;
ListBox1.Clear;
ValuePropEdit.Clear;
if Assigned(Srv) then begin
EnumProperties(Srv,ListBox1.Items);
end;
end;
//Изменение свойств
procedure TForm1.btnExecClick(Sender: TObject);
begin
if (ValuePropEdit.Text = '')or(Tag=2) then Exit;
try
SetInvoke(DID, ValuePropEdit.Text);
except
end
end;
//Запуск
procedure TForm1.BtnRemConnectClick(Sender: TObject);
var CLSID: TGUID;
begin
//для Word.Application
CLSID:=StringToGUID('{000209FF-0000-0000-C000-000000000046}');
try
Srv:=CreateRemoteComObject('Server5',CLSID) as IDispatch;
except
Exit;
end;
btnReadProp.Enabled:=True;
btnReadInterf.Enabled:=True;
end;
end.
GrBob (2006-06-28 16:47:00) [23]Дело в том, что мне его нужно запустить на удаленной машине. CreateOLEObject делает это только на локальной, все замечательно работает. А вот CreateRemoteCOMObject возвращает интерфейс, который нужно чему-то присвоить. Просто IInterface'у его не присвоишь, вернее потом методы не повызываешь.
Согласен, возможно интерфейс знать и не нужно совсем, но тогда как запустить OLE сервер на удаленном компьютере и еще им управлять при этом? :)
tesseract (2006-06-28 13:56:00) [24]Если есть GUID - на кой его по имени знать?
GrBob (2006-06-27 15:15:00) [25]
> enuminterfaces??
??
> описание интерфейса есть?
Я знаю его методы и свойства. Мне нужно узнать как он называется. (I...)
tesseract (2006-06-27 14:57:00) [26]
> а CreateRemoteComObject возвращает интерфейс, название которого
> я не знаю. (Как его получить?)
enuminterfaces??
описание интерфейса есть?