项目:
我目前正在开发一个应用程序,如果用户离开(锁屏或关机)他的工作场所并将他的智能卡留在读卡器中,则会发出警告。
我能够通过使用 WinAPI (WinSCard.dll) 检测智能卡当前是否在读卡器中。
问题:
我读到(如果有误,请纠正我)应用程序不可能延迟锁屏,所以我目前专注于延迟关机。
我现在遇到的问题是我需要延迟正在进行的关机以警告用户他离开了他的智能卡。
我尝试使用 ShutdownBlockReasonCreate 将关机延迟至少 5 秒 Windows 如此慷慨地让我这样做。这个想法是,如果用户移除他的智能卡,我的应用程序将调用 ShutdownBlockReasonDestroy 以继续关闭。
我像这样实现了这两种方法:
[DllImport("User32.dll", EntryPoint = "ShutdownBlockReasonCreate",
CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool ShutdownBlockReasonCreate(
[In()]IntPtr wndHandle,
[In()]string reason);
[DllImport("User32.dll", EntryPoint = "ShutdownBlockReasonDestroy",
CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool ShutdownBlockReasonDestroy(
[In()]IntPtr wndHandle);
此外,我使用 GetLastError 来检查我以这种方式实现的错误:
[DllImport("Kernel32.dll", EntryPoint = "GetLastError",
CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern int GetLastError();
现在奇怪的是,如果我创造原因
WinAPIMethoden.ShutdownBlockReasonCreate(
new WindowInteropHelper(Application.Current.MainWindow).Handle,
"Smartcard still in reader!");
然后显示错误
MessageBox.Show(WinAPIMethoden.GetLastError().ToString("X"));
它显示 0,代表 ERROR_SUCCESS。
到目前为止,一切似乎都很好。 现在,如果我尝试关闭 PC,则没有任何迹象表明我的应用程序已请求不应立即关闭 PC。
问题:
我做错了什么导致 ShutdownBlockReasonCreate 无法按预期工作?
或者是否有更好的方法来防止用户在他的智能卡仍然处于关闭状态时关闭 PC,例如阻止他在他的智能卡处于插入状态时启动关机之类的?
tl;dr:
当用户将他的智能卡放在读卡器中时,我试图防止关机。 我使用 ShutdownBlockReasonCreate 但它似乎不起作用,尽管没有错误。
解决方案:
接受的答案引导我解决问题。
您必须创建取消原因并为 SystemEvents.SessionEnding 订阅处理程序。 然后,此处理程序必须将 e.Cancel 设置为 true
void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
{
if (mgr.state == SmartcardState.Inserted)
{
e.Cancel = true;
}
}
为了在关机时执行程序,我使用 gpendit.msc 将其添加到关机脚本中。 然后在所有程序终止后执行该程序。看起来真的很奇怪,但确实有用。
请您参考如下方法:
请查看这些可能对您的情况有所帮助的帖子:
How to abort shutdown in Windows (XP|Vista) programatically?
Aborting computer shutdown from windows service
