Why do I get an access violation when I call Microsoft Communicator 2007's IMessengerContacts.Count method?
-
31-05-2021 - |
Pergunta
I want to display the contacts from my list onto a TListBox. I have Communicator installed and running on my Windows 7 PC, running Delphi XE. I am using CommunicatorAPI_TLB and CommunicatorPrivate_TLB.
I click on the login and logout buttons, and the programs works as expected: my Communicator logs in and out. Cool.
The problem is when I try to click on the list-users button. The Contacts.Count
method seems to throw me an access violation. I tried it with groups, and the same results. Can anyone spot what I am doing wrong?
{ This IMessenger3 Class Inherits from the IMessenger2 interface -> IMessenger... }
Communicator : IMessenger3;
Contacts : IMessengerContacts;
Contact : IMessengerContact;
Groups : IMessengerGroups;
Connected : Boolean;
End;
Var
frmMain: TfrmMain;
Implementation
{$R *.dfm}
{ ---------------------------------------------------------------------------- }
Procedure TfrmMain.FormCreate(Sender: TObject);
Begin
Communicator := CoMessenger.Create;
End; { FormCreate Procedure }
Procedure TfrmMain.btnSignInClick(Sender: TObject);
Begin
Communicator.AutoSignin;
Connected := True;
End; { btnSignInClick Procedure }
Procedure TfrmMain.btnSignOutClick(Sender: TObject);
Begin
Communicator.Signout;
Connected := False;
End; { btnSignOutClick Procedure }
Procedure TfrmMain.btnLoadContactsClick(Sender: TObject);
Var
ContactIndex : Integer;
Begin
{ Load my contacts into a listbox }
Contacts := IMessengerContacts (Communicator.MyContacts);
Groups := IMessengerGroups (Communicator.MyGroups);
If (Contacts <> Nil) Then Begin
try
showmessage (inttostr(Groups.Count));
showmessage (inttostr(Contacts.count));
except
end;
(*
For ContactIndex := 0 To (Contacts.Count) Do Begin
Contact := IMessengerContact (Contacts.Item (ContactIndex));
{ Add the contact to the list }
lbxContacts.AddItem (Contact.FriendlyName, Nil);
End; { For }
*)
End; { If <> Nil }
End;
Solução
Change the two typecasts to use as
instead. If the problem is that the interface isn't available, you'll at least get an error message that's meaningful.
Change
Contacts := IMessengerContacts(Communicator.MyContacts);
Groups := IMessengerGroups (Communicator.MyGroups);
to
Contacts := Communicator.MyContacts as ImessengerContacts;
Groups := Communicator.MyGroups as IMessengerGroups;
You should probably do the same thing to other places you're typecasting to get interfaces. It's always better when possible to ask for them politely than to forcibly grab them. :)
Outras dicas
It's been a loooooong time since i've written any Delphi (about 14 years) but i'm going to hazard a guess at this.
For security reasons some of the methods in the IMessenger interfaces are marked as NotScriptable. My guess is that your Delphi app is being treated by the interface as a scripting language, i.e. not native C++ code, and that's causing the Access Violation. You could prove this by looking at the reference to work out which are scriptable and which are not, and see which throw the Access Violation.
As for fixing it - as I said, i'm no Delphi expert, but is there another way you can instantiate the IMessenger objects? Or create a wrapper around the API in another language, to call from Delphi (there is an example of this here)