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?
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.
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.