Project:
I currently devellop an application to warn the user if he leaves (lockscreen or shutdown) his workplace and has left his smartcard in the reader.
I was able to detect through the use of the WinAPI (WinSCard.dll
) if the smarcard is currently in the reader.
Problem:
I read (correct me if this is wrong) it is not possible for an application to delay the lockscreen so I currently focus on delaying the shutdown.
The problem I am having now is that I need to delay the ongoing shutdown to warn the user that he left his smartcard.
I try to use ShutdownBlockReasonCreate
to delay the shutdown for at least the 5 seconds Windows so generously lets me. The idea was that if the user removes his smartcard my application calls ShutdownBlockReasonDestroy
to continue the shutdown.
I implemented the two methods like so:
[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);
furthermore I use GetLastError
to check for errors which I implemented this way:
[DllImport("Kernel32.dll", EntryPoint = "GetLastError",
CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern int GetLastError();
Now the strange thing is that if I create the reason
WinAPIMethoden.ShutdownBlockReasonCreate(
new WindowInteropHelper(Application.Current.MainWindow).Handle,
"Smartcard still in reader!");
and then display the error
MessageBox.Show(WinAPIMethoden.GetLastError().ToString("X"));
it shows 0 which stands for ERROR_SUCCESS
.
So far everything seems great. Now if I try to shut the PC down there is no sign whatsoever that my application has requested that the PC should not be shut down right now.
Question:
What am I doing wrong so that ShutdownBlockReasonCreate
does not work as intended?
Or is there maybe a better way to prevent the user from shutting the PC down if his smartcard is still in like preventing him from initiating the shutdown while his card is in or something like that?
tl;dr:
I try to prevent shutdown while user has his smartcard in the reader.
I use ShutdownBlockReasonCreate
but it doesnt seem to work although there is no error.
Solution:
The accepted answer lead me to the solution of the problem.
You have to create the cancle reason AND subscribe a handler to SystemEvents.SessionEnding
.
This handler then has to set e.Cancel
to true
void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
{
if (mgr.state == SmartcardState.Inserted)
{
e.Cancel = true;
}
}
To execute the programm on shutdown I addet it to the shutdown scripts using gpendit.msc
.
The programm then gets executed AFTER all programs have been terminated. Looks really weird but does the job.
Please take a look at these posts that could help you with your situation:
How to abort shutdown in Windows (XP|Vista) programatically?
Aborting computer shutdown from windows service