Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Frage zu JWSCL / JEDI´s (https://www.delphipraxis.net/117043-frage-zu-jwscl-jedi%B4s.html)

kuba 10. Jul 2008 15:03


Frage zu JWSCL / JEDI´s
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

ich habe in meinen Systemdienst JWSCL/JEDI-Komponenten verwendet. Jetzt erhalte ich beim Systemstart die Fehlermeldung : der prozedureinsprung "wtscgetactiveconsolesessionid" wurde in der dll "kernel32.dll" nicht gefunden

Das OS ist Win2000, hier mein verwendeter Code:

Delphi-Quellcode:
type TWinVersion = (wvUnknown, wvWin95, wvWin98, wvWin98SE, wvWinNT, wvWinME, wvWin2000, wvWinXP, wvWinVista) ;
function GetWinVersion: TWinVersion;
var
   osVerInfo: TOSVersionInfo;
   majorVersion, minorVersion: Integer;
begin
   Result := wvUnknown;
   osVerInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo) ;
   if GetVersionEx(osVerInfo) then
   begin
     minorVersion := osVerInfo.dwMinorVersion;
     majorVersion := osVerInfo.dwMajorVersion;
     case osVerInfo.dwPlatformId of
       VER_PLATFORM_WIN32_NT:
       begin
         if majorVersion <= 4 then
           Result := wvWinNT
         else if (majorVersion = 5) and (minorVersion = 0) then
           Result := wvWin2000
         else if (majorVersion = 5) and (minorVersion = 1) then
           Result := wvWinXP
         else if (majorVersion = 6) then
           Result := wvWinVista;
       end;
       VER_PLATFORM_WIN32_WINDOWS:
       begin
         if (majorVersion = 4) and (minorVersion = 0) then
           Result := wvWin95
         else if (majorVersion = 4) and (minorVersion = 10) then
         begin
           if osVerInfo.szCSDVersion[1] = 'A' then
             Result := wvWin98SE
           else
             Result := wvWin98;
         end
         else if (majorVersion = 4) and (minorVersion = 90) then
           Result := wvWinME
         else
           Result := wvUnknown;
       end;
     end;
   end;
end;

procedure StartApp(const App, Parameters, CurDir : TJwString);
var
  StartupInfo : TStartupInfoA;
  ProcInfo : TProcessInformation;
  pEnv : Pointer;

  pCurDir,
  pCmdLine : TJwPChar;

  ServiceToken, CopiedToken, UserToken : TJwSecurityToken;
  PW      :string;
begin

    ZeroMemory(@StartupInfo, sizeof(StartupInfo));
    StartupInfo.cb         := SizeOf(StartupInfo);
    StartupInfo.lpDesktop  := 'winsta0\default';

    pCmdLine := TJwPChar('"'+App+'" ' + Parameters);

    pCurDir := Nil;
    if Length(CurDir) > 0 then
      pCurDir := TJwPChar(CurDir);


    //get the token from the service system session
    ServiceToken := TJwSecurityToken.CreateTokenEffective(MAXIMUM_ALLOWED);
    TJwAutoPointer.Wrap(ServiceToken);

    //copy the token to be able to change the TokenSessionId
    //Info: Win2000:  Only 0
    //       WinXP:    Service=0, 1.User=0, 2.User=1, 3.User=2, ...
    //       WinVista: Service=0, 1.User=1, 2.User=2, 3.User=3, ...
    CopiedToken := TJwSecurityToken.CreateDuplicateExistingToken(ServiceToken.TokenHandle, MAXIMUM_ALLOWED);
    TJwAutoPointer.Wrap(CopiedToken);

   
    //get the token of the logged in user
    if GetWinVersion = wvWin2000 then
      UserToken := TJwSecurityToken.CreateCompatibilityQueryUserToken(MAXIMUM_ALLOWED, 'explorer.exe')
    else //XP, 2003, Vista, 2008
      UserToken := TJwSecurityToken.CreateWTSQueryUserTokenEx(nil, WtsGetActiveConsoleSessionID);
    TJwAutoPointer.Wrap(UserToken);

    //give the copied token the same sessionid as the logged in user
    CopiedToken.TokenSessionId := UserToken.TokenSessionId;


    //create the environment block using the logged in user
    JwaWindows.CreateEnvironmentBlock(@pEnv, UserToken.TokenHandle, false);


    try
     if not CreateProcessAsUser(
      CopiedToken.TokenHandle,
      TJwPChar(App),    //__in_opt    LPCTSTR lpApplicationName,
      pCmdLine,         //__inout_opt LPTSTR lpCommandLine,
      nil,              //__in_opt    LPSECURITY_ATTRIBUTES lpProcessAttributes,
      nil,              //__in_opt    LPSECURITY_ATTRIBUTES lpThreadAttributes,
      false,             //__in        BOOL bInheritHandles,
      CREATE_NEW_CONSOLE or CREATE_DEFAULT_ERROR_MODE or CREATE_UNICODE_ENVIRONMENT,
                         //__in        DWORD dwCreationFlags,
      pEnv,             //__in_opt    LPVOID lpEnvironment,
      pCurDir,          //__in_opt    LPCTSTR lpCurrentDirectory,
      StartupInfo,      //__in        LPSTARTUPINFO lpStartupInfo,
      ProcInfo          //__out       LPPROCESS_INFORMATION lpProcessInformation
     ) then
     raiseLastOsError;
    finally
      DestroyEnvironmentBlock(pEnv);
    end;


    CloseHandle(ProcInfo.hProcess);
    CloseHandle(ProcInfo.hThread);

end;


...
      ReadDir(PW3);
      PW1 := 'Programm.exe';
      PW2 := '';
      if not IsExeRunning(PW1) then
      StartApp(PW1, PW2, PW3);
...
Die StartApp-Routine habe ich hier im Forum gefunden, die GetWinVersion habe ich getestet und funktioniert. Ist meine Datei "kernel32.dll" nicht i.O. oder liegt es an StartApp ?

KUBA

Phoenix 10. Jul 2008 15:25

Re: Frage zu JWSCL / JEDI´s
 
Zitat:

Zitat von kuba
der prozedureinsprung "wtscgetactiveconsolesessionid" wurde in der dll "kernel32.dll" nicht gefunden
Das OS ist Win2000

Das MSDN sagt zu dieser Methode:
Requirements
  • Client Requires Windows Vista or Windows XP.
  • Server Requires Windows Server 2008 or Windows Server 2003.
  • Header Declared in Winbase.h; include Windows.h.
  • Library Use Kernel32.lib.DLL
  • Requires Kernel32.dll.

Da steht nix davon dass das unter Windows 2000 existiert...

Dezipaitor 10. Jul 2008 15:34

Re: Frage zu JWSCL / JEDI´s
 
Wenn du die JwaWindows.pas einbindest und nicht wie von mir vorgeschlagen, über eine DCU (und damit über die mitgelieferten Pakete) die Unit kompilierst, dann passiert es, dass die verwendeten API Funktionen statisch geladen werden (=Voreinstellung).
D.h. die API wird schon vor dem Programmstart geladen. Daher bringt es nichts mit dem Überprüfen auf Win2000.

Du musst daher JwaWindows mit der Direktive DYNAMIC_LINK kompilieren oder eben die Pakete verwenden.

Die WTS Routinen gibt es erst seit XP (bis auf ein paar Ausnahmen).

generic 10. Jul 2008 15:40

Re: Frage zu JWSCL / JEDI´s
 
Phoenix hat sich etwas knapp ausgedrückt.
Du könntest versuchen die Jedi's mit "später Bindung" zu kompilieren.
Imho ging das da.

Allerdings sieht du dann alt aus, wenn die Funktion die nicht da ist, von einer deiner verwendeten Funktionen genutzt wird.

Dann bringt das nichts.

Du solltest die Plattform wechseln, Win2000 wird von Microsoft nicht mehr unterstützt.
Zumindest ist es auf der Roadmap die ich hier habe, garnicht mehr drauf.

shmia 10. Jul 2008 15:43

Re: Frage zu JWSCL / JEDI´s
 
Die Funktion WTSGetActiveConsoleSessionId gehört zur Terminal Services API und ist in älteren Windows Versionen sicher nicht in der kernel.dll enhalten.
Die MSDE sagt: "Requires Windows Vista or Windows XP"

Es gibt 3 Varianten, wie man mit dem Problem umgehen kann: die Richtige, die Falsche und die ganz Falsche!

ganz Falsch:
die Funktion wird einfach statisch gelinkt.

Falsch:
man fragt zuerst die Windows Version ab. Wenn die Windows Version >= Win 2000 (nur ein Bespiel), dann geht man davon aus, dass WTSGetActiveConsoleSessionId vorhanden ist.

Richtig:
Man ignoriert die Windows Version und holt die Einsprungadresse mit GetProcAddress().
Bekommt man nil zurück (und dass muss man immer abfragen) ist die Funktion eben nicht verfügbar
und das Programm muss seine Funktionalität einschränken (Graceful degradation)

Dezipaitor 10. Jul 2008 16:15

Re: Frage zu JWSCL / JEDI´s
 
JEDI dynamisch geladen macht es richtig und liefert eine Exception (kenne sie gerade nicht auswendig)

Die JWSCL hat übrigens TJwWindowsVersion, in JwsclVersion.pas welche die Windowsversionen feststellt.

kuba 10. Jul 2008 17:43

Re: Frage zu JWSCL / JEDI´s
 
Zitat:

Zitat von shmia
Richtig:
Man ignoriert die Windows Version und holt die Einsprungadresse mit GetProcAddress().
Bekommt man nil zurück (und dass muss man immer abfragen) ist die Funktion eben nicht verfügbar
und das Programm muss seine Funktionalität einschränken (Graceful degradation)

verstehe, wenn die Funktion in den JEDI's nicht für die Windows Version enthalten ist dann kann ich sie nicht nutzen ...

Ich möchte dass mein Dienst ein Programm startet wenn ein bestimmter User seinen Desktop "betritt", das Programm soll mit den (eingeschränkten) Benutzerrechten des Users starten.

Gibt es da (unter Delphi) keine Möglichkeit dieses Problem für alle Windows Versionen einfach zu lösen ?

KUBA

Dezipaitor 10. Jul 2008 20:12

Re: Frage zu JWSCL / JEDI´s
 
Na klar, einfach die JEDI dynamisch linken lassen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:19 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