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

标签 delphi windows-7 screensaver authentication

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

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

将 notepad.exe 设置为登录屏幕保护程序效果很好。

你知道这里发生了什么吗?

最佳答案

正如我在评论中所说,这不是“隐形代码”,只是导致问题的某些单元的初始化部分中的代码。我已经成功地找到了罪魁祸首(至少是其中一个 - 可能还有其他人)。

当您使用Forms时单位,它依赖于 Classes单位。

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

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

好像是API调用CreateEvent从登录屏幕内调用时失败。不幸的是,我不确定登录屏幕是否:(a) 禁止 CreateEvent (b) 总共需要 CreateEventEx相反,或 (c) 将与适当的 lpEventAttributes 配合使用争论。我发布了一个更具体的问题希望能找到答案:CreateEvent from Windows-7 Logon Screen

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

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.

SyncEvent的目的是启用TThread实例同步回主线程。因此,如果您编写单线程应用程序,或者使用 TThread 以外的其他内容创建线程。 ,您实际上并不需要/使用 SyncEvent完全没有。

SIDE-RANT: This is a prime example of the problem with using the initialization section. Merely including a unit has the potential to introduce unnecessary side-effects. They're Mostly Harmless, but not in this case. Now you may argue that Classes.pas is bloated, and I won't argue. But the point is that if Classes initialization were called explicitly from the DPR, this problem would have been easier to identify and find a workaround for.

<小时/>

编辑:新解决方案

正如 Remy Lebeau 在我发布的另一个问题中指出的那样。
该行:

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

必须更改为:

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

由于此解决方案涉及重新编译 VCL 单元,因此您可能需要查看 previous questions 中的一些内容。关于这个话题

有了这个作为唯一的更改(在 D2009 中编译),我能够成功地在登录屏幕上显示空白表单。但是,请记住,由于登录屏幕上的安全限制,您通常期望能够执行的某些操作将受到限制。

关于delphi - Delphi 中的 Windows 7 登录屏幕保护程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5567775/

相关文章:

c++ - Windows 应用程序以非管理员身份运行时看到文件的旧版本而不是当前版本

java - java中有类似user.home的东西可以获取\Users\Public目录吗?

ubuntu - gltext 屏幕保护程序字体大小

python - 使用 Python3 通过 python-dbus 在 Linux 上显示屏幕保护程序状态

delphi - 是否可以通过 Show() 或 ShowModal() 知道表单的显示

delphi - 为什么 MSHTML_TLB.pas 会产生警告?

delphi - 提高 Crc16 计算速度

delphi - 我如何告诉 Delphi 必须将其自动创建的事件代码放置在哪里?

date - 检查文件在过去 xx 天后是否被修改

.NET:屏幕保护程序配置对话框所有者和预览焦点