Announcement

Collapse
No announcement yet.

CoCreateInstance nicht aus Konsolenanwendung?

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

  • CoCreateInstance nicht aus Konsolenanwendung?

    Das folgende Codefragment funktioniert in einem normalen Delphi-Programm, in einer Dos-Anwendung kommt in hres aber -2147221008 zurück, bekommt man das irgendwie auch aus einer Dos-Anwendung zum laufen?!
    <p>
    <pre>
    var
    psl : IShellLink;
    hres : hresult;
    begin
    hres := CoCreateInstance(CLSID_ShellLink, Nil,
    CLSCTX_INPROC_SERVER, IID_IShellLinkA, psl);
    </pre>

  • #2
    okay, sorry, coinitialize war wohl noch nötig, also die folgende aus dem sdk übernommene routine funktioniert jetzt einwandfrei, der link wird angelegt, funktioniert und der hint ist auch drin, der einzige schönheitsfehler: wenn die beiden Release-aufrufe am ende auskommentiert werden läuft es ohne fehlermeldung, ist mindestens einer von beiden drin erscheint (erst beim verlassen der funktion!) eine access violation (0x00000000) woran kanns liegen? Auch eine durchlauf mit debug dcus hat mich nicht weitergebracht.
    <p>
    <pre>
    //HRESULT CreateLink(LPCSTR lpszPathObj,
    // LPSTR lpszPathLink, LPSTR lpszDesc)
    function CreateLink(lpszPathObj : LPCSTR; lpszPathLink, lpszDesc : LPSTR):Boolean;
    VAR
    // HRESULT hres;
    // IShellLink* psl;
    psl : IShellLink;
    ppf : IPersistFile;
    //WORD wsz[MAX_PATH];
    wsz : ARRAY[0..max_path] OF Word;
    bla : String;
    begin
    result := false;
    // Get a pointer to the IShellLink interface.
    //hres = CoCreateInstance(&CLSID_ShellLink, NULL,
    // CLSCTX_INPROC_SERVER, &IID_IShellLink, &psl);
    hres := CoCreateInstance(CLSID_ShellLink, Nil,
    CLSCTX_INPROC_SERVER, IID_IShellLinkA, psl);
    //if (SUCCEEDED(hres)) [
    if hres = 0 then begin
    // IPersistFile* ppf; s.o.
    // Set the path to the shortcut target, and add the
    // description.
    //psl->lpVtbl->SetPath(psl, lpszPathObj);
    psl.SetPath(lpszPathObj);
    //psl->lpVtbl->SetDescription(psl, lpszDesc);
    psl.SetDescription(lpszDesc);

    // Query IShellLink for the IPersistFile interface for saving the
    // shortcut in persistent storage.
    //hres = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf);
    hres := psl.QueryInterface(IID_IPersistFile,ppf);
    //if (SUCCEEDED(hres)) [
    if hres = 0 then begin
    //WORD wsz[MAX_PATH];

    // Ensure that the string is ANSI.
    //MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1,
    // wsz, MAX_PATH);
    MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1,
    @wsz, MAX_PATH);
    // Save the link by calling IPersistFile::Save.
    //hres = ppf->lpVtbl->Save(ppf, wsz, TRUE);
    hres := ppf.Save(@wsz,True);
    //ppf->lpVtbl->Release(ppf);
    hres := ppf._Release;
    ppf := nil;//vorsichtshalber, falls delphi sonst noch was macht?!
    //???????????????
    // ]
    end;
    //psl->lpVtbl->Release(psl);
    hres := psl._Release;
    psl := nil;
    //???????????????????
    // ]
    end;
    // return hres;
    result := (hres = 0);
    end;

    var
    prog,
    ziel,
    desc : String;

    initialization
    prog := 'C:\etest\EasyCalc.exe'+#0;
    ziel := 'c:\test.LNK'+#0;
    desc := 'Dies ist ein Wunder'+#0;

    hres := coinitialize(nil);

    createLink(@prog[1],@ziel[1],@desc[1]);

    finalization
    if hres = 0 then couninitialize;
    </pre>
    <p>
    Einzig auffällig, der zweite release aufruf gibt eins zurück statt 0 aber zumindest olecheck hält dies nicht für einen fehler

    Comment


    • #3
      Hallo,

      im Gegensatz zu C/C++ (bei denen viele Firmen am Sprachstandard mitkochen) kann Borland bei Object Pascal die Details zu COM fest integrieren. Somit ist es nicht sinnvoll, in Delphi ein C-Beispiel 1:1 nachzubauen.

      Das folgende Beispiel demonstriert, wie man über den "Delphi-Way-Of-Live" aus einer Konsolenanwendung heraus eine Verknüpfung anlegt:
      <pre>
      program LinkFromConsole;
      {$APPTYPE CONSOLE}
      uses
      sysutils, Windows, ShlObj, ActiveX, ComObj;

      procedure MakeLink(const sEXE: String);
      var
      aObject : IUnknown;
      aSLink : IShellLink;
      aPFile : IPersistFile;
      sDirectory : String;
      wsFileName : WideString;
      szWinDir : array[0..29] of Char;
      pIIL : PItemIDList;
      szPath : array[0..MAX_PATH] of Char;
      aMalloc : IMalloc;
      begin
      FillChar(szWinDir, SizeOf(szWinDir), #0);
      GetWindowsDirectory(szWinDir, SizeOf(szWinDir));
      // ShellLink-Objekt anfordern
      aObject := CreateComObject(CLSID_ShellLink);
      // Verbindung zum IShellLink-Interface herstellen
      aSLink := aObject as IShellLink;
      // Verbindung zum IPersistFile-Interface herstellen
      aPFile := aObject as IPersistFile;
      // Verknüpfung über IShellLink definieren
      with aSLink do begin
      // Programmpfad festlegen
      SetPath(PChar(sEXE));
      // Programmparameter festlegen
      SetArguments(PChar(''));
      // Arbeitsverzeichnis festlegen
      SetWorkingDirectory(szWinDir);
      end;
      // Pfad des gewünschten Shellfolders ermitteln
      OleCheck(SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, pIIL));
      SHGetPathFromIDList(pIIL, szPath);
      OleCheck(SHGetMalloc(aMalloc));
      aMalloc.Free(pIIL);
      sDirectory := szPath;
      wsFileName := sDirectory + '\Test.lnk';
      // Verknüpfung über IPersistFile anlegen
      aPFile.Save(PWChar(wsFileName), False);
      end;

      begin
      CoInitialize(nil);
      MakeLink('C:\ABLAGE\REDSYS2.EXE');
      CoUninitialize;
      end.
      </pre>
      &#10

      Comment


      • #4
        Naja, ist doch so anders gar nicht
        <p>
        D.h. man muß also wie ich sehe keins dieser Objekte wieder freigeben?

        Comment


        • #5
          Hallo,

          darum kümmert sich Delphi automatisch. Da IUnknown fest in den Compiler eingebaut ist, wird _Release automatisch immer dann aufgerufen, wenn die lokale Variable ungültig wird oder mit einem neuen Wert gefüllt wird. Und anstelle von QueryInterface sorgt die Typumwandlung über AS dafür, dass Delphi hinter den Kulissen QueryInterface aufruft

          Comment

          Working...
          X