Announcement

Collapse
No announcement yet.

Zugriffsverletzung beim Starten der DLL

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Zugriffsverletzung beim Starten der DLL

    Hallo Gemeinde,

    ich möchte (habe) eine Prozedure geschrieben, die einen Eintrag in einem Outlook-Ordner sucht und danach das Kontaktfenster üffnet:
    <pre>
    procedure StartContact(FiledAs : OleVariant); //stdcall;
    var
    Outlook : Application_;
    objContact : Variant;
    objContacts : MAPIFolder;
    objNameSpace : NameSpace;
    FindVariable : String;
    begin
    FindVariable:= '[FileAs] = ' + Format('%s', [FiledAs]);
    Outlook := CoApplication_.Create;
    objNameSpace := Outlook.GetNamespace('MAPI');
    objContacts:= objNameSpace.Folders.Item('öffentliche Ordner').Folders.Item('Alle öffentlichen Ordner').Folders.Item('Spediteure');
    objContact:= objContacts.Items.Find(FindVariable);
    objContact.Display;
    end;
    </pre>
    der dll handle sieht wie folgt aus:
    <pre>
    procedure StartContact(FiledAs : OLEVariant);
    var KontaktProzedur: TKontaktProzedur;
    Handle: THandle;
    begin
    Handle:=LoadLibrary('Contact.dll');
    if Handle <> 0 then begin
    @KontaktProzedur := GetProcAddress(Handle, 'StartContact');
    if @KontaktProzedur <> nil then begin
    KontaktProzedur(FiledAs);
    end;
    FreeLibrary(Handle);
    end;
    end;
    </pre>
    Leider erhalte ich stets eine Zugriffsverletzung wenn folgende Prozedure die dll aufruft:
    <pre>
    procedure TfmMain.NameListChange(Sender: TObject);
    var
    FiledAs : Variant;
    begin
    FiledAs:= QuotedStr(NameList.Text);
    StartContact(FiledAs);
    end;
    </pre>
    Der Benutzer kann im Hauptformular aus einer Drop Down Liste einen Eintrag auswählen, dann startet die dll und das Programm bleibt stehen. Füge ich die "dll-Prozedure" jedoch ins Hauptprogramm ein, läuft das Progi sauber durch. Was mache ich falsch?
    <br>
    So sieht i.&Uuml; die dll aus - vielleicht liegt ja hier der Fehler.
    <pre>
    library Contact;

    uses
    Windows, Messages, SysUtils, ComObj, Outlook_TLB;

    procedure StartContact(FiledAs : OleVariant); stdcall;
    var
    Outlook : Application_;
    objContact : Variant;
    objContacts : MAPIFolder;
    objNameSpace : NameSpace;
    FindVariable : String;
    begin
    FindVariable:= '[FileAs] = ' + Format('%s', [FiledAs]);
    Outlook := CoApplication_.Create;
    objNameSpace := Outlook.GetNamespace('MAPI');
    objContacts:= objNameSpace.Folders.Item('öffentliche Ordner').Folders.Item('Alle öffentlichen Ordner').Folders.Item('Spediteure');
    objContact:= objContacts.Items.Find(FindVariable);
    objContact.Display;
    end;

    exports
    StartContact;

    begin
    end.
    </pre>
    Viele Gr&uuml;sse<br>
    Uwe

  • #2
    Hallo,

    was passiert, wenn die DLL statisch eingebunden wird (d.h. FreeLibrary nie greift)? Wenn das funktioniert, ist <i>objContact : Variant;</i> der "Übeltäter". In Delphi haben wir immer dann keine Kontrolle über die Lebensdauer eines Interface-Zeigers, wenn dieser über die späte Bindung angefordert und einer (Ole)Variant-Variable zugewiesen wurde. Nur dann, wenn die Interface-Variable direkt für das Dual Interface deklariert wird, können wie über <b>nil</b> den Zeitpunkt exakt bestimmen.

    In meinen DLLs, die COM nutzen, sehe ich zusätzlich immer einen eigenen CoInitialize/CoUninitilize-Block vor, so dass der Zugriff in jedem Fall (unabhängig vom DLL-Aufrufer) aus einem gültigen Apartment heraus erfolgt

    Comment


    • #3
      Hallo Andreas,

      danke für Deine Antwort.<br>
      Wenn die dll statisch eingebunden wird habe ich den Fehler sofort beim Programmstart. Ich habe auch schon vermutet dass die Variant Variable der Übeltäter ist - ersetze ich aber den Datentyp durch 'ContactItem' wird der Source gar nicht erst kompiliert. Fehlermeldung: "inkompatible Typen IDispatch und _ContactItem".<br><br>
      Das mit dem CoInitialize/CoUninitilize-Block kenne ich leider nicht. Wenn Du das kurz erkl&auml;ren k&ouml;nntest, w&auml;re das super.

      Gruss
      Uw

      Comment


      • #4
        Siehe eine Zeile weiter unten, dort ist bei "ADO-Komponente in eine DLL einbinden" ein Beispiel zu finden.

        <pre>
        var
        bDoCoUninitialize : Boolean;
        bDoDestroyDM_ADO : Boolean;
        sMDBPath : String; resourcestring
        cCONNECTSTRING = 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=';
        function DBInit(const pNewMDBPath: PChar): Integer;
        var
        aCatalog : _Catalog;
        sDS : String;
        sMsg : String;
        begin
        Result := 1;
        bDoCoUninitialize := False;
        bDoDestroyDM_ADO := False;
        try
        //
        sMsg := 'CoInitialize-Fehler';
        CoInitialize(nil);
        bDoCoUninitialize := True;
        //
        sMsg := 'ACCESS-Datenbankdatei konnte nicht gelöscht werden.';
        sMDBPath := pNewMDBPath;
        if FileExists(sMDBPath) then
        DeleteFile(sMDBPath);
        //
        sMsg := 'Fehler beim Zugriff auf die ADOX-Objekte.';
        aCatalog := CoCatalog.Create;
        sConnectionStr := Format('%s%s',[cCONNECTSTRING, sMDBPath]);
        sDS := aCatalog.Create(sConnectionStr);
        aCatalog := nil;
        //
        sMsg := 'Fehler beim Erzeugen des Datenmoduls';
        DM_ADO := TDM_ADO.Create(nil);
        bDoDestroyDM_ADO := True;
        sMsg := 'Fehler beim Erzeugen der Tabelle »Adressen«';
        DM_ADO.DoCreateTable;
        //
        ... Datensatz eintragen
        //
        if bDoDestroyDM_ADO then
        DM_ADO.Free;
        if bDoCoUninitialize then
        CoUninitialize;
        except
        ShowExceptionMsg(sMsg);
        Result := 0;
        end;
        end;
        </pre&gt

        Comment

        Working...
        X