如何检测的Windows是否关闭或重新启动
题
我知道,当Windows正在关闭时,它发送的 WM_QUERYENDSESSION 消息给每个应用程序。这可以很容易地在Windows正在关闭检测。然而,是否有可能知道,如果电脑要关机或正在准备重新启动Windows已经关机。
我不是特别乐观,考虑在MSDN文档有此说关于WM_QUERYENDSESSION
:“......这是不可能的,以确定哪些事件正在发生,”但计算器累计聪明从来没有停止给我带来惊喜<。 / p>
解决方案
从这里:
可以读取来自DWORD值 “HKCU \软件\微软\的Windows \ CurrentVersion \ Explorer中\关机 设置”,以确定用户什么 最后从Shut选择向下 对话框。
迂回溶液的位,但它应该做的伎俩。
其他提示
在Windows 7中(可能也是在Vista / 8 /服务器),你可以使用系统事件跟踪的Windows是否关闭(和计算机电源关闭)或只是重新启动。每次关机/重启开始时间(通过任何方式 - 点击开始菜单按钮,或在程序上),Windows 7中写道:在系统日志中的一个或两个事件,源USER32,事件ID 1074你可以看到,如果记录这些事件您从管理工具(过滤系统日志只看到ID 1074)打开事件查看器。这些事件的说明(消息)包含关断型。所以,你可以分析最近的这种类型的事件的说明(关机开始后),找必要的字(关机,重启/重启)。
我没有尝试看看使用电源按钮正常关闭的Windows(我通常禁用此功能)时,写入事件关机类型,但一些网站的建议,它指出了“断电”型而非“关机” - 所以检查出来,如果你需要确定。或者干脆找一个“重启”型 - 如果它没有找到,那么“关机”型假设
在Windows XP中,从我的经验,事件1074被记录只有在关机/重启编程完成(例如在一个程序安装或使用shutdown.exe的实用程序)。因此,它不注册从壳(资源管理器)开始停产检修,但也许你就可以像在另一个答案建议阅读从注册表中的值,此方法结合起来。另外,请记住,在WinXP事件1074的消息包含单词“重启”不管真正的类型关机的是什么,所以你应该看看“关机类型:”字段,这将说明无论是“关机”或“重新启动”。
与此相关的,事件ID 1073被记录每当Windows无法关机/重启出于某种原因(例如,如果一个应用程序不允许关闭以WM_QUERYENDSESSION的响应)。在这种情况下该消息还将包含词作为“关断”,“重新启动”或“断电” - 在WinXP。对于Win7的这种类型的事件在我们的情况不太有用,因为它不会让关机和重启任何区别。但对于WinXP的 - 如果你只需要拦截关机/重启,执行一些操作,然后继续相应的关机或重启的过程 - 它应该按预期工作
这通常工作甲诀窍是陷阱WM_ENDSESSION
和记录它。现在跟踪的时间。如果系统回来了一个合理的peroid内(如5分钟)。然后,这是重新启动,并不关闭。
创意:如果系统恢复后5分钟内,做它的真正的问题,如果用户点击 '关机' 或 '重启'
?如果你真的需要检测关闭(和唯一的原因,我认为你需要做的是,如果你根据停机之间VS重启一个不起眼的行为差异的软件),你可以调查API hooking
的ExitWindowsEx
和相关的功能,但我不推荐这种方法。重新思考,如果你真的需要直接检测这一点。
有关的Windows7可能的实验方案可以是以下内容。 (我不知道这是否与其他本地化运作良好,因此我把它称为一种变通方法)
using System.Diagnostics.Eventing.Reader;
namespace MyApp
{
public class RestartDetector : IDisposable
{
public delegate void OnShutdownRequsted(bool restart);
public OnShutdownRequsted onShutdownRequsted;
private EventLogWatcher watcher = null;
public RestartDetector()
{
try
{
EventLogQuery subscriptionQuery = new EventLogQuery(
"System", PathType.LogName, "*[System[Provider[@Name='USER32'] and (EventID=1074)]]");
watcher = new EventLogWatcher(subscriptionQuery);
// Make the watcher listen to the EventRecordWritten
// events. When this event happens, the callback method
// (EventLogEventRead) is called.
watcher.EventRecordWritten +=
new EventHandler<EventRecordWrittenEventArgs>(
EventLogEventRead);
// Activate the subscription
watcher.Enabled = true;
}
catch (EventLogReadingException e)
{
}
}
public void EventLogEventRead(object obj, EventRecordWrittenEventArgs arg)
{
bool restart = false;
try
{
// Make sure there was no error reading the event.
if (arg.EventRecord != null)
{
String[] xPathRefs = new String[1];
xPathRefs[0] = "Event/EventData/Data";
IEnumerable<String> xPathEnum = xPathRefs;
EventLogPropertySelector logPropertyContext = new EventLogPropertySelector(xPathEnum);
IList<object> logEventProps = ((EventLogRecord)arg.EventRecord).GetPropertyValues(logPropertyContext);
string[] eventData = (string[])logEventProps[0];
foreach (string attribute in eventData)
{
if (attribute.Contains("restart")) { restart = true; break; }
}
}
}
catch (Exception e)
{
}
finally
{
if (onShutdownRequsted != null) { onShutdownRequsted(restart); }
}
}
public void Dispose()
{
// Stop listening to events
if (watcher != null)
{
watcher.Enabled = false;
watcher.Dispose();
}
}
}
}
下面是当PC重新启动信息被写入到事件日志XML的示例:
- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
<Provider Name="USER32" />
<EventID Qualifiers="32768">1074</EventID>
<Level>4</Level>
<Task>0</Task>
<Keywords>0x80000000000000</Keywords>
<TimeCreated SystemTime="2015-12-15T11:10:43.000000000Z" />
<EventRecordID>90416</EventRecordID>
<Channel>System</Channel>
<Computer>WIN7PC</Computer>
<Security UserID="S-1-5-21-1257383181-1549154685-2724014583-1000" />
</System>
- <EventData>
<Data>C:\Windows\system32\winlogon.exe (WIN7PC)</Data>
<Data>WIN7PC</Data>
<Data>No title for this reason could be found</Data>
<Data>0x500ff</Data>
<Data>restart</Data>
<Data />
<Data>WIN7PC\WIN7PCUser</Data>
<Binary>FF00050000000000000000000000000000000000000000000000000000000000</Binary>
</EventData>
</Event>