Is there a way to distinguish between Shutdown and Restart in Windows 7 and later? [duplicate] - windows

I know that when Windows is shutting down, it sends a WM_QUERYENDSESSION message to each application. This makes it easy to detect when Windows is shutting down. However, is it possible to know if the computer going to power-off or is it going to restart after Windows has shutdown.
I am not particularly hopeful, considering the documentation at MSDN has this to say about WM_QUERYENDSESSION: "...it is not possible to determine which event is occurring," but the cumulative cleverness of stackoverflow never ceases to amaze me.

In Windows 7 (and probably also in Vista / 8 / Server) you could use the system events to track whether Windows is shutting down (and powering off the computer) or just restarting. Every time a shutdown/reboot is initiated (by any means - clicking the button in Start menu, or programmatically), Windows 7 writes one or two events in the System log, source USER32, event ID 1074. You can see these events recorded if you open the Event Viewer from Administrative Tools (filter the System log to see only ID 1074). The description (message) of these events contains the shutdown type. So you could parse the description of the most recent event of this type (after the shutdown was initiated), looking for the necessary word (shutdown, reboot/restart).
I didn't try to see the shutdown type written in the event when using the power button to gracefully shutdown Windows (I usually disable this function), but some site suggests that it states a "power off" type instead of "shutdown" - so check it out, if you need to be sure. Or simply look for a "reboot" type - if it's not found, then a "shutdown" type is assumed.
In Windows XP, from my experience, an event 1074 is recorded only if the shutdown/reboot is done programmatically (e.g. during a program install or using the shutdown.exe utility). So it does not register the shutdowns initiated from the shell (Explorer), but perhaps you could combine this method with reading the value from registry as proposed in another answer. Also, keep in mind that in WinXP the message of event 1074 contains the word "restart" no matter what the real type of shutdown is, so you should look at the "Shutdown Type:" field, which will state either "shutdown" or "reboot".
Related to this, an event ID 1073 is recorded whenever Windows fails to shutdown/reboot for some reason (e.g. if an application doesn't allow to shutdown as a response to WM_QUERYENDSESSION). In that case the message will also contain words as "shutdown", "reboot" or "power off" - in WinXP. For Win7 this type of event is less useful in our case, since it won't make any difference between shutdown and reboot. But for WinXP - if you only need to intercept the shutdown/reboot, perform some actions, then continue the corresponding shutdown or reboot process - it should work as expected.

From here:
You can read the DWORD value from
"HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shutdown
Setting" to determine what the user
last selected from the Shut Down
dialog.
A bit of a roundabout solution, but it should do the trick.

A trick that usually works is to trap WM_ENDSESSION and log it. Now keep track of the time. If the system comes back up within a reasonable peroid (say 5 minutes). Then that was a reboot, not a shutdown.
Idea: If the system comes back up within 5 minutes, does it really matter if the user clicked 'shutdown' or 'reboot'?
If you really need to detect a shutdown (and the only reason I think you'd need to do this is if you're depending upon an obscure behavioral software difference between a shutdown vs a reboot) you could investigate API hooking of ExitWindowsEx and related functions but I don't recommend this approach. Rethink if you really need to detect this directly.

Possible experimental solution for Windows7 could be the following. (I'm not sure if this works well with other localizations, therefore I would call it a workaround)
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();
}
}
}
}
The following is an example of XML which is written to the event log when a PC is restarted:
- <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>

Related

Outlook VSTO Handling SelectionChange correctly (currently doubleclick crashes Addin)

From what I understand you need to track Activation and Deactivation of the Explorers. During activation, you need to add SelectionChange event handlers for the current explorer.
This seems to work perfectly for single clicks on AppointmentItems. But it crashes the Addin when double-clicking on an appointment series and selecting a single Appointment.
Here is the source:
On class level
private Outlook.Explorer currentExplorer = null;
private Outlook.AppointmentItem currentAppointmentItem = null;
within Startup:
currentExplorer = this.Application.ActiveExplorer();
((Outlook.ExplorerEvents_10_Event)currentExplorer).Activate +=
new Outlook.ExplorerEvents_10_ActivateEventHandler(
Explorer_Activate);
currentExplorer.Deactivate += new
Outlook.ExplorerEvents_10_DeactivateEventHandler(
Explorer_Deactivate);
The event handlers:
void Explorer_Activate()
{
currentExplorer.SelectionChange += new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(Selection_Change);
}
void Explorer_Deactivate()
{
currentExplorer.SelectionChange -= new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(Selection_Change); ;
}
private void Close_Explorer()
{
}
private void Selection_Change()
{
Outlook.MAPIFolder selectedFolder = currentExplorer.CurrentFolder;
if (currentExplorer.Selection.Count > 0)
{
Object selObject = currentExplorer.Selection[1];
if (selObject is Outlook.AppointmentItem)
{
currentAppointmentItem = (Outlook.AppointmentItem)selObject;
}
else
{
currentAppointmentItem = null;
}
}
}
What am I overlooking? Is the form of deregistering a problem?
Try to add try/catch blocks to the event handlers. The Outlook object model can give you unpredictable results sometimes. It is worth adding them and find where an exception is thrown.
currentExplorer.Selection.Count
Also, you may subscribe to the SelectionChange event in the NewExplorer event and don't switch between explorers when they are activated or deactivated. The event is fired whenever a new explorer window is opened, either as a result of user action or through program code.
The only thing which I added was a handler for NewInspector and InspectorClose events along with Marshal.ReleaseComObject(). The only thing which I can imagine that double clicking while debugging I got in some kind of race condition (because double clicking also triggers the Selection_Change event). But this is only a guess.
You do not need to add and remove event handlers as an explorer is activated / deactivated. Are you trying to support multiple explorers? In that case, create a wrapper class that hold the Explorer object as it member and uses its methods as event handlers.

Gamepad hot plugging does not work

In OS X my gamepads are recognised correctly in SDL_PollEvent() at application startup. However, when I try hot plugging new gamepads or removing old gamepads, the SDL_PollEvent() does not trigger either SDL_CONTROLLERDEVICEADDED or SDL_CONTROLLERDEVICEREMOVED. The same code works correctly in Windows when I hot plug game controllers.
A more interesting note is that if I resize the window of my application, the hot plugging works. After resize event all the hot plugging events are triggered. It almost seems that the gamepad events are put in a some kind of waiting queue which is purged when the resize event happens. My SDL_PollEvent() code is quite standard as seen below.
case SDL_CONTROLLERDEVICEADDED:
if (SDL_IsGameController(e.cdevice.which))
{
SDL_GameController *pad = SDL_GameControllerOpen(e.cdevice.which);
if (pad)
{
SDL_Joystick *joy = SDL_GameControllerGetJoystick(pad);
int instanceID = SDL_JoystickInstanceID(joy);
if(m_gameControllers.count(instanceID) == 0)
{
m_gameControllers.insert(std::make_pair(instanceID, pad));
}
}
}
break;
case SDL_CONTROLLERDEVICEREMOVED:
{
auto it = m_gameControllers.find(e.cdevice.which);
if (it != m_gameControllers.end())
{
SDL_GameController* pad = m_gameControllers[e.cdevice.which];
SDL_GameControllerClose(pad);
m_gameControllers.erase(it);
}
}
break;
Has anyone else experienced this?
After some struggling I found the solution: Call SDL_PollEvent() from the main thread. Initially I called the gamepad handling method from the CVDisplayLink thread which resulted the described behaviour.
In my case the solution was simply to add dispatch_async call to my gamepad handling function.
dispatch_async(dispatch_get_main_queue(),^ { handleGamePad();});

Handling configuration change for async methods

I have an activity which has an async method in it. This async method is long running. After the async method returns, the UI needs to be updated and some of the controls reference the activity.
At the moment, everything works correctly if you do not have a configuration change (like screen rotation) while the async task is running. However, if a configuration change happens while it is running, then the exception Activity is destroyed is thrown and the UI is not updated. From what reading I have done, this seems to be because the async method captures context and then tries to update the old context which is of course destroyed after the configuration change.
My question is: What are the best ways to solve this problem or at worst case scenario work around it?
I personally think you have only three options
You can disable rotation permanently or temporary, but this is a bad practice
To disable it permanently set ConfigurationChanges
[Activity(Label = "...", ConfigurationChanges = Android.Content.PM.ConfigChanges.KeyboardHidden | Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
To disable it temporary while task working you should disable rotation handling,
disable
this.RequestedOrientation = Android.Content.PM.ScreenOrientation.Nosensor;
enable
this.RequestedOrientation = Android.Content.PM.ScreenOrientation.Sensor;
If you are using fragment you can prevent fragment destroy with RetainInstance = true. That might work, but i never tested it.
You can cancel task with CancelationToken and restart it in OnRestoreInstanceState()
Here is example how to cancel task
{
CancellationTokenSource cts;
...
// If a download process is already underway, cancel it.
if (cts != null)
{
cts.Cancel();
}
// Now set cts to cancel the current process if the button is chosen again.
CancellationTokenSource newCTS = new CancellationTokenSource();
cts = newCTS;
try
{
//Send cts.Token to carry the message if there is a cancellation request.
await AccessTheWebAsync(cts.Token);
}
// Catch cancellations separately.
catch (OperationCanceledException)
{
ResultsTextBox.Text += "\r\nDownloads canceled.\r\n";
}
catch (Exception)
{
ResultsTextBox.Text += "\r\nDownloads failed.\r\n";
}
// When the process is complete, signal that another process can proceed.
if (cts == newCTS)
cts = null;
}
And in the task
async Task AccessTheWebAsync(CancellationToken ct)
{
...
// Retrieve the website contents from the HttpResponseMessage.
byte[] urlContents = await response.Content.ReadAsByteArrayAsync();
// Check for cancellations before displaying information about the
// latest site.
ct.ThrowIfCancellationRequested();
...
}
There are plenty of things you could do, but please don't go and disable the phones ability to turn the screen -- that is just going to ignore your users.
At a highlevel you will have to do two things:
Make sure the async task keeps running and is not restarted if the activity dies.
You can solve that by moving the task either into the application class or (cleaner) into a headless fragment with setRetainInstance set to true.
In the onDestroy method in the activity, remove it from the async task, in the onCreate task give the activity to the async task (if it exist).
This is what prevents the async task from calling the old context and can be done with a simple java setter on the async task. Don't forget to cache the result in the task if the activity is currently not connected.
In the end what I ended up doing was encapsulating the async task in another class which held a reference to the current activity, which implemented and interface which defined a method which handles the async response and updates the UI.
The activity held a static variable of the encapsulated async task, and if it was running during a config change, the encapsulated async's task reference to the activity was updated to the new activity.

Automatic email send/receive in Outlook

Is there a way to set up Outlook (2013) to automatically send/receive emails when it is activated?
What you can do now is to intruct Outlook to periodically check the emails, and of course, it checks the emails at start time. That's fine, I am a fan... but most of the time Outlook runs minimized. Once I restore it (that is, bring Outlook in front), I would like it to perform an automatic sync, equivalent to pressing the Send/Receive Folders.
I agree this is not a critical issue at all, not even close, but for me it would make sense.
You could try using SendKeys and send F9 hotkey which performs the Send/Receive action. I would probably just do this keystroke myself, but you could programmatically attach to the Explorer.Activate event and generate this event as well. You can also add a debounce to control the frequency as to not overwhelm your Exchange server.
DateTime lastRun = DateTime.Now; // debouce control
void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Application.Explorers.NewExplorer += new Outlook.ExplorersEvents_NewExplorerEventHandler(explorers_NewExplorer);
}
void explorers_NewExplorer(Outlook.Explorer explorer)
{
((Outlook.ExplorerEvents_10_Event)explorer).Activate += new Outlook.ExplorerEvents_10_ActivateEventHandler(ExplorerWrapper_Activate);
}
void ExplorerWrapper_Activate()
{
if ((DateTime.Now - lastRun).TotalMilliseconds > 500) // trigger limit 500ms
{
lastRun = DateTime.Now;
System.Windows.Forms.SendKeys.Send("{F9}"); // hotkey to send/receive
}
}

ScheduledActionService.LaunchForTest not calling ScheduledTaskAgent's OnInvoke after initial install

Let me start by saying that I had the PeriodicTask already working a couple of days back, but when I came back to do something else I noticed the PeriodicTask's OnInvoke is not called anymore.
I think I am doing the basics correct: removing existing PeriodTask if found, calling LaunchForTest only in debug build and I've checked that the ScheduledAgent is referenced properly in the project and the WMAppManifest.xml.
This is how I setup the PeriodicTask:
try
{
PeriodicTask backgroundTask = null;
backgroundTask = ScheduledActionService.Find(BGTASK_NEW_EPISODES) as PeriodicTask;
if (backgroundTask != null)
{
ScheduledActionService.Remove(backgroundTask.Name);
}
// Start our background agent.
backgroundTask = new PeriodicTask(BGTASK_NEW_EPISODES);
backgroundTask.Description = "Foobar";
ScheduledActionService.Add(backgroundTask);
#if DEBUG
ScheduledActionService.LaunchForTest(BGTASK_NEW_EPISODES, TimeSpan.FromSeconds(5));
#endif
}
catch (InvalidOperationException e)
{
if (e.Message.Contains("BNS Error: The action is disabled"))
{
App.showNotificationToast("Background tasks have been disabled from\nsystem settings.");
}
}
catch (Exception) { }
}
Here's my WMAppManifest.xml:
<ExtendedTask Name="BackgroundTask">
<BackgroundServiceAgent Specifier="ScheduledTaskAgent" Name="PodcatcherBackgroundService" Source="PodcatcherBackgroundService" Type="PodcatcherBackgroundService.ScheduledAgent" />
</ExtendedTask>
When I install the app for the first time, then the OnInvoke is called. But if I restart the app, it's not called. The same is true for both device and emulator.
I've also verified that the background task is enabled in settings and I have a fully charged battery (device is a WP7 device and it's connected via USB to PC. For the emulator, of course, this doesn't matter).
So what should I check next?
Thanks!
Ok, seems I got it resolved.
In certain cases I forgot to call NotifyComplete() in the background task. In that case Windows Phone seems to just ignore subsequent tries to invoke the background worker.

Resources