2

项目:

我目前正在开发一个应用程序来警告用户如果他离开(锁屏或关机)他的工作场所并将他的智能卡留在阅读器中。

我能够通过使用 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;博士:

当用户将他的智能卡放在读卡器中时,我尝试防止关机。我使用ShutdownBlockReasonCreate但它似乎没有工作,虽然没有错误。

解决方案:

接受的答案引导我解决问题。

您必须创建取消原因并将处理程序订阅到SystemEvents.SessionEnding. 然后这个处理程序必须设置e.Canceltrue

void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
{
    if (mgr.state == SmartcardState.Inserted)
    {
        e.Cancel = true;
    }
}

要在关机时执行程序,我使用gpendit.msc. 然后在所有程序终止后执行程序。看起来很奇怪,但确实有效。

4