【发布时间】:2013-07-31 15:05:44
【问题描述】:
项目:
我目前正在开发一个应用程序,用于在用户离开(锁屏或关机)工作场所并将智能卡留在读卡器中时警告用户。
我能够通过使用 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 无法按预期工作?
或者有没有更好的方法来防止用户在他的智能卡还在的情况下关闭电脑,就像在他的卡还在时防止他启动关机或类似的东西?
tl;博士:
当用户将他的智能卡放在读卡器中时,我会尝试防止关机。
我使用ShutdownBlockReasonCreate,但它似乎不起作用,虽然没有错误。
解决方案:
接受的答案引导我解决问题。
您必须创建取消原因并将处理程序订阅到SystemEvents.SessionEnding。
然后这个处理程序必须将e.Cancel 设置为true
void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
{
if (mgr.state == SmartcardState.Inserted)
{
e.Cancel = true;
}
}
为了在关机时执行程序,我使用gpendit.msc 将它添加到关机脚本中。
然后在所有程序终止后执行程序。看起来很奇怪,但确实有效。
【问题讨论】:
-
ShutdownBlockReasonCreate 的文档指出“如果调用成功,则返回值非零”。请不要只调用函数,而是立即分配返回值,看看会发生什么。
-
@Alexander 返回非零,所以这不是问题
标签: c# wpf winapi windows-7 shutdown