Windows 7登录Delphi中的屏幕保护程序

Kai*_*eks 13 delphi authentication screensaver windows-7

我在使用Delphi应用程序作为Windows 7登录屏幕保护程序(对于32位和64位Windows)时遇到问题.即使是空白应用程序(没有任何额外代码的新项目)也会引发错误.

Delphi 7应用程序抛出"内存无法读取"错误,Delphi 2010应用程序抛出"应用程序中发生异常未知软件异常",然后"运行时错误217".在任何表单初始化之前和异常处理程序的任何初始化之前发生此错误.

将notepad.exe设置为登录屏幕保护程序正常.

这里有什么想法吗?

Dis*_*ned 5

正如我在评论中所说,它不是"隐形代码",只是导致问题的某个单元的初始化部分中的代码.我设法追查罪魁祸首(至少其中一个 - 可能还有其他人).

使用本Forms机时,它依赖于本Classes机.

初始化部分调用InitThreadSynchronization,其中包括调用以下内容:

SyncEvent := CreateEvent(nil, True, False, '');
if SyncEvent = 0 then
  RaiseLastOSError;
Run Code Online (Sandbox Code Playgroud)

CreateEvent从登录屏幕中调用时,似乎API调用失败.不幸的是,我不确定登录屏幕是否:(a)CreateEvent完全禁止(b)要求CreateEventEx或(c)使用适当的lpEventAttributes参数.我发布了一个更具体的问题,希望能找到:Windows-7登录屏幕中的CreateEvent

您可以使用以下控制台应用验证问题:

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.
Run Code Online (Sandbox Code Playgroud)

目的SyncEvent是使TThread实例能够同步回主线程.因此,如果您编写单线程应用程序,或使用其他内容创建线程TThread,则实际上根本不需要/使用SyncEvent.

SIDE-RANT:这是使用初始化部分问题的一个主要示例.仅仅包括一个单元可能会引入不必要的副作用.它们主要是无害的,但在这种情况下并非如此.现在你可能会说这Classes.pas是臃肿的,我不会争论.但重点是,如果从DPR中明确调用了类初始化,则此问题将更容易识别并找到解决方法.


编辑:新的解决方案

正如Remy Lebeau在我发布的另一个问题中指出的那样.
这条线:

    SyncEvent := CreateEvent(nil, True, False, '');
Run Code Online (Sandbox Code Playgroud)

必须更改为:

    SyncEvent := CreateEvent(nil, True, False, nil);
Run Code Online (Sandbox Code Playgroud)

由于此解决方案涉及重新编译VCL单元,您可能需要先阅读有关此主题的一些先前问题

这是唯一的变化(在D2009中编译),我能够在登录屏幕上成功显示一个空白表格.但是,请记住,由于Logon屏幕的安全限制,您通常可以预期能够做的一些事情将会被禁止.