Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Probleme bei der Registrierung einer OCX (https://www.delphipraxis.net/212396-probleme-bei-der-registrierung-einer-ocx.html)

freimatz 4. Feb 2023 10:01

Probleme bei der Registrierung einer OCX
 
Hallo, ich verwende schon seit zig Jahren eine OCX. Die wird üblicherweise registriert vom Setup, welches dabei als Admin läuft. Das funktioniert soweit auch.
Allerdings gibt es Fälle wobei die Registrierung nicht mehr in Ordnung ist (keine Ahnung was die Anwender machen)
Das Hauptprogramm kann auch registrieren, mangels Admin klappt das aber nicht sicher (oder nie?).
Für die Registrierung verwende ich einen alten Code, der wohl ursprünglich von Borland ist. (analog zu dem).
Nun war meine Idee bei Bedarf dass das Hauptprogramm sich selber als Admin aufruft und die Registrierung vornimmt. Allerdings klappt das nicht. DllRegisterServer liefert immer einer 1 zurück.
Spasseshalber habe ich nun stattdessen versucht:
Delphi-Quellcode:
RunAsAdmin(Application.Handle, 'regsvr32', '/s ' + Ocx);
Das hat funktioniert.
Bevor ich nun weiter den Fehler suche die Fragen: Ist es vielleicht sogar sinnvoll es so zu machen? Kann ich mich darauf verlassen dass regsvr32 überall vorhanden ist und auch funktioniert? (Win10/11). Falls Ja, dann kann ich mir weitere Arbeit sparen.

himitsu 4. Feb 2023 10:31

AW: Probleme bei der Registrierung einer OCX
 
Das ist natürlich überall vorhanden,
aber wer die Rückgaben nicht prüft, ist selbst Schuld, falls es mal knallt.

Und laut Hesteller vielleicht besser inkl. Pfad, aber eigentlich egal, da die beiden System32 eigentlich immer im Suchpfad (%PATH%) stehen sollten.
%systemroot%\SysWoW64\regsvr32.exe (bzw. %systemroot%\System32\regsvr32.exe in einem 32 Bit-Windows, aber wo gibt es das heute noch)
Auch %systemroot% ist eigentlich nicht mehr notwendig, da Microsoft, wegen zu vieler saudämlicher Entwickler, inzwischen das Systemlaufwerk immer C: und das Verzeichnis immer Windows nennt, aber wer weiß was die Zukunft bringt.
Wobei System32 in einem 64 Bit-Windows für 32 Bit-Programme auf SysWoW64 umgeleitet wird, außer DU hast die Verzeichnisvirtualisierung deaktiviert. (aber bei der externen Console besser doch direkt SysWoW64 verwenden)

https://learn.microsoft.com/en-us/wi...mands/regsvr32
https://support.microsoft.com/de-de/...a-3f4e0cb543e5

https://stackoverflow.com/questions/...ll-using-c-api

peterbelow 4. Feb 2023 16:26

AW: Probleme bei der Registrierung einer OCX
 
Zitat:

Zitat von freimatz (Beitrag 1518301)
Hallo, ich verwende schon seit zig Jahren eine OCX. Die wird üblicherweise registriert vom Setup, welches dabei als Admin läuft. Das funktioniert soweit auch.
Allerdings gibt es Fälle wobei die Registrierung nicht mehr in Ordnung ist (keine Ahnung was die Anwender machen)
Das Hauptprogramm kann auch registrieren, mangels Admin klappt das aber nicht sicher (oder nie?).
Spasseshalber habe ich nun stattdessen versucht:
Delphi-Quellcode:
RunAsAdmin(Application.Handle, 'regsvr32', '/s ' + Ocx);
Das hat funktioniert.
Bevor ich nun weiter den Fehler suche die Fragen: Ist es vielleicht sogar sinnvoll es so zu machen? Kann ich mich darauf verlassen dass regsvr32 überall vorhanden ist und auch funktioniert? (Win10/11). Falls Ja, dann kann ich mir weitere Arbeit sparen.

RegSvr32 ist immer vorhanden, aber kennen deine User das für RunAsAdmin notwendige Passwort?

Nur mal so erwähnt als Alternative: wenn dein OCX ein simpler COM Server ist und kein ActiveX Control kann man ihn vermutlich auch ohne Registrierung verwenden. Dafür macht man einfach in Code was das COM Subsystem sonst intern macht: Die DLL laden, sich den
DllGetClassObject Einsprungpunkt besorgen, von selbigem das interface der class factory besorgen, mittels dieser das COM-Objekt erzeugen.

Delphi-Quellcode:
//NODOC-BEGIN
var
  globalIsis: isisbase = nil;
  IsisLibHandle: HMODULE;
//NODOC-END

{! Load the isislib.dll from our fallback location, if it is not already
   loaded }
procedure LoadIsisLib;
const
  CIsisLib = 'ISISLIB.DLL';
var
  LOldPath, LDLLPath, LDLLFolder: string;
begin
  IsisLibHandle:= GetModuleHandle(CIsisLib);
  if IsisLibHandle = 0 then begin
    // first check the applications home folder
    LDLLFolder := TPath.GetDirectoryName(ParamStr(0));
    LDllPath := TPath.Combine(LDLLFolder, CIsisLib);
    if not TFile.Exists(LDLLPath) then begin
      LDllFolder := SPathToolsFolder;
      LDllPath := TPath.Combine(LDLLFolder, CIsisLib);
    end;
    if not TFile.Exists(LDLLPath) then
      raise EOleSysError.Create(SIsisLibNotFound, E_FAIL, 0);
    LOldPath := TDirectory.GetCurrentDirectory;
    try
      TDirectory.SetCurrentDirectory(LDLLFolder);
      IsisLibHandle := SafeLoadLibrary(LDllPath);
      if IsisLibHandle = 0 then
        RaiseLastOSError;
    finally
      TDirectory.SetCurrentDirectory(LOldPath);
    end;
  end; {if}
end;

{! Try to create an instance of the ISIS automation server directly
  from the fallback copy of the ISIS Dll. }
function CreateServerFromFallback: isisbase;
const
  IID_IClassFactory: TGUID = (
    D1:$00000001;D2:$0000;D3:$0000;D4:($C0,$00,$00,$00,$00,$00,$00,$46));
var
  DllProc :
    function (const CLSID: TGUID;
      const IID: TGUID; out Factory: IClassFactory): HRESULT; stdcall;
  LFactory: IClassFactory;
  LBase: isisbase;
  LResult: HRESULT;
begin
  Result := nil;
  if IsisLibHandle = 0 then
    LoadIsisLib;
  @DllProc := GetProcAddress(IsisLibHandle, 'DllGetClassObject');
  if Assigned(DLLProc) then begin
    LResult:= DllProc(LIBID_BaseType, IID_IClassFactory, LFactory);
    case LResult of
      S_OK: begin
          LResult:= LFactory.CreateInstance(nil, isisbase, LBase);
          if Succeeded(LResult) then
            Result := LBase
          else
            raise EOleSysError.Create(SFailedToCreateISISServer,LREsult, 0);
        end;
      E_NOINTERFACE:
        raise EOleSysError.Create(SIClassFactoryNotSupported, LResult, 0);
      CLASS_E_CLASSNOTAVAILABLE:
        raise EOleSysError.Create(SLIBID_BaseTypeNotSupported, LResult, 0);
    else
      raise EOleSysError.Create(SUnexpectedError, LResult, 0);
    end;
  end
  else
    raise EOleError.Create(SDllEntryPointNotFound);
end;

{!
<summary>
 Return an instance of the ISIS/Base OLE automation server</summary>
<returns>
 the interface for the automation server.</returns>
<param name="newInstance">
 determines whether we return a new instance or the existing one
 (if there is any). This parameter is only used if the function is
 called from the main thread.</param>
<exception cref="EOleSysError">
 is raised if the server instance cannot be created.</exception>
<remarks>
 The function will keep a single instance of the server for the main
 thread, unless NewInstance is passed as True. If you call this function
 from a secondary thread, make sure to call OleInitialize in the thread's
 context first! And remember that the ISIS automation server is not
 thread-safe!</remarks>
}
function CreateIsisServer(newInstance: Boolean): isisbase;
  function DoCreateServer: isisbase;
  begin
    try
      result:= isisbase(CreateOleObject(cIsisbase))
    except
      result := nil;
    end;
    if not Assigned(result) then
      result := CreateServerFromFallback;
  end;
begin
  if not NewInstance and (GetCurrentThreadID = MainThreadID) then begin
    if not Assigned(globalIsis) then
      globalIsis := DoCreateServer;
    Result := globalIsis;
  end { If }
  else
    Result := DoCreateServer;
end;

freimatz 4. Feb 2023 18:01

AW: Probleme bei der Registrierung einer OCX
 
Danke für Deine Antwort. (Und auch an himitsu)

a) Passwort? Keine Ahnung, ich muss nie eines angeben. Vermutlich habe ichmich auch nur falsch ausgedrückt. Das RunAsAdmin ruft ShellExecuteEx mit dem Verb "runas" auf.

b) Ich fürchte ich habe den Unterschied zwischen COM und ActiveX nicht verstanden. Danach ist es ein umfangreiches Control das auf einem Form plaziert ist und dann auch vom Anwender bedient wird.

peterbelow 5. Feb 2023 13:01

AW: Probleme bei der Registrierung einer OCX
 
Zitat:

Zitat von freimatz (Beitrag 1518308)
Danke für Deine Antwort. (Und auch an himitsu)

a) Passwort? Keine Ahnung, ich muss nie eines angeben. Vermutlich habe ichmich auch nur falsch ausgedrückt. Das RunAsAdmin ruft ShellExecuteEx mit dem Verb "runas" auf.

Wenn der aktive Benutzeraccount selbst keine Admin-Privilegien besitzt erfordert runas das Password des Admin-Accounts. Wenn man keines angiebt sollte der Benutzer danach gefragt werden. Sonst wäre die Schutz vor Mißbrauch doch ein Witz, oder?

Zitat:

Zitat von freimatz (Beitrag 1518308)
b) Ich fürchte ich habe den Unterschied zwischen COM und ActiveX nicht verstanden. Danach ist es ein umfangreiches Control das auf einem Form plaziert ist und dann auch vom Anwender bedient wird.

Wenn es ein Control ist muß man es wohl registrieren, fürchte ich. Das muß aber nicht unbedingt über die Registry gehen (das macht DllRegisterServer normalerweise). Es gibt seit einigen Windows-Versionen einen Mechanismus über das Manifest der Anwendung, in dem diese angiebt, welches OCX sie braucht und welche interfaces das zur Verfügung stellt. Ich hab das nie benutzt und weis daher kaum mehr darüber als das es diesen Weg gibt. Google mal nach "side by side actvex registration".


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:14 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz