Windows 7 logon screensaver en Delphi

j'ai des problèmes en utilisant L'application Delphi comme Windows 7 logon screensaver (pour les fenêtres 32-bit et 64-bit). Même l'application vierge (nouveau projet sans aucun code supplémentaire) jette une erreur.

Delphi 7 application lance "la mémoire ne pouvait pas être lu" erreur et Delphi 2010 application lance" l'exception logiciel inconnu exception s'est produite dans l'application "et puis"Runtime error 217". Cette erreur se produit avant toute forme d'initialisation et avant tout initialisation des gestionnaires d'exception.

Paramètre de bloc-notes.exe écran de veille d'ouverture de session fonctionne très bien.

des idées sur ce qui se passe ici?

12
demandé sur Kaitnieks 2011-04-06 18:12:56

2 réponses

comme je l'ai dit dans mon commentaire, ce n'est pas "le code invisible", juste le code dans la section d'initialisation d'une unité qui cause le problème. J'ai réussi à retrouver le coupable (au moins l'un d'eux - il peut y en avoir d'autres).

quand vous utilisez le Forms unité, il a une dépendance sur le Classes unité.

la section d'initialisation appelle InitThreadSynchronization, qui, entre autres choses appelle la suivante:

SyncEvent := CreateEvent(nil, True, False, '');
if SyncEvent = 0 then
  RaiseLastOSError;

Il semble que l'appel de l'API CreateEvent échoue lorsqu'il est appelé à partir de l'écran de connexion. Malheureusement, je ne sais pas si l'écran de connexion: (a) interdit CreateEvent dans l'ensemble (B) nécessite CreateEventEx au lieu de cela ou (c)fonctionnerait avec unlpEventAttributes argument. J'ai posté une question plus spécifique, nous l'espérons trouver: CreateEvent de Windows 7 Écran d'ouverture de session

vous pouvez vérifier le problème avec la console suivante:

program TestLoginScreensaver;

{$APPTYPE CONSOLE}

uses
  Windows,
  SysUtils;

var
  SyncEvent: THandle;

begin
  try
    SyncEvent := CreateEvent(nil, True, False, '');
    if SyncEvent = 0 then
      RaiseLastOSError;
    CloseHandle(SyncEvent); //So handle is closed if it was created (e.g. while logged in)
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
  Readln;
end.

Le but de SyncEvent activer TThread instances pour synchroniser le retour vers le thread principal. Donc, si vous écrivez une application filetée simple, ou créez vos fils en utilisant quelque chose d'autre que TThread, vous n'avez pas besoin de/utiliser SyncEvent à tous.

SIDE-RANT: ceci est un excellent exemple du problème avec l'utilisation de initialisation section. Le simple fait d'inclure une unité peut entraîner des effets secondaires inutiles. Ils sont La Plupart Du Temps Inoffensif, mais pas dans ce cas. Maintenant, vous pouvez argumenter que Classes.pas est gonflée, et je ne discuterai pas. Mais le fait est que si les Classes initialization étaient appelées explicitement d'après le RMR, ce problème aurait été plus facile à cerner et à trouver une solution.


EDIT: New Solution

comme Remy Lebeau l'a noté dans l'autre question que j'ai posée.

La ligne:

    SyncEvent := CreateEvent(nil, True, False, '');

doit être modifié en:

    SyncEvent := CreateEvent(nil, True, False, nil);

Depuis ce la solution implique de recompiler les unités VCL, vous pouvez passer par quelques-uns des questions precedentes sur ce sujet

avec ceci comme seul changement (compilé dans D2009) j'ai réussi à afficher un formulaire vierge à l'écran de connexion. Cependant, gardez à l'esprit que certaines choses que vous pouvez normalement vous attendre à être en mesure de faire seront hors limites en raison des restrictions de sécurité à l'écran de connexion.

5
répondu Disillusioned 2017-05-23 12:20:46

après un petit jeu. Cela doit être connecté à la fenêtre principale cachée de Delphi (real main) vous aurez besoin de regarder sérieusement L'Application.initialiser ou appliquer.HookMainWindow ().

parce qu'étonnamment ce code ne pose pas de problème:

program w7logonsaver;
{$APPTYPE CONSOLE}

var
  i: Integer;
begin
  for i := 1 to 20 do
    writeln;
  write('K ');
  ReadLn;
end.

il suffit de cliquer sur Entrée pour arrêter.

1
répondu Despatcher 2011-04-06 20:50:20