Pocket PC Power Management Series 6: Request the Device to Run: a Gentle Way
====>SiteMap of this Blog<===
Pocket PC Power Management Series 6: Request the Device to Run: a Gentle Way
In Pocket PC Power Management Series 5, I showed how to use API SystemIdleTimerReset to force the device not to sleep. However, this technique is an overkill and a waste if used for case-2 programs (which need to run periodically, not continuously). Further, some utilities are known to disrupt SystemIdleTimerReset, for example, Keyguard.
A more gentle way is to request the device to run at certain time, by using the omnipotent CeSetUserNotificationEx (see my Pocket PC Power Management Series 4 for a brief introduction to this API). Hereby I present three ready-to-use functions.
1. How to Use?
If you want to run Pocket IE to browse a URL 10 minutes later, simply call:
ScheduleRunApp(TEXT("\\Windows\\iexplore.exe"), TEXT("URLXXX""), 600);
And remember to clear it after some time:
ClearRunApp(TEXT("\\Windows\\iexplore.exe"));
2. Walkthrough of the functions
- SecondsAfter: It takes a pointer to SYSTEMTIME and a number of seconds,;
upon returning, the SYSTEMTIME is modified to be exactly that number of
seconds after the original time. For example, if original time is 10:00AM
now, and you want to a time 10:05AM, just pass 300 as the second parameter.
The function converts SYSTEMTTIME to FILETIME for easy arithmetic operation.
static HRESULT SecondsAfter(SYSTEMTIME* pst, int numSeconds)
{
FILETIME ft;
// convert to FILETIME then ULONGLONG for calculation
if (!SystemTimeToFileTime(pst, &ft)) return E_FAIL;
ULONGLONG ulLongFt = *(ULONGLONG*)&ft;
ulLongFt += (ULONGLONG)numSeconds * 10000000;
// 10000000: how many nano seconds per second, divided by 100
// convert back to FILETIMEand SYSTEMTIME
ft = *(FILETIME*)&ulLongFt;
if (!FileTimeToSystemTime(&ft, pst)) return E_FAIL;
return S_OK;
}
- ScheduleRunApp: It takes an Executable name, arguments and a number of
seconds. All parameters are self-explanatory. For example, if you pass 300
as dwAfterSeconds, the program is scheduled to run 5 minutes after the
function is called.
static HRESULT ScheduleRunApp(
LPCTSTR szExeName,
LPCTSTR szArgs,
DWORD dwAfterSeconds)
{
HRESULT hr = S_OK;
HANDLE hNotify = NULL;
// set a CE_NOTIFICATION_TRIGGER
CE_NOTIFICATION_TRIGGER notifTrigger;
memset(¬ifTrigger, 0, sizeof(CE_NOTIFICATION_TRIGGER));
notifTrigger.dwSize = sizeof(CE_NOTIFICATION_TRIGGER);
// calculate time
SYSTEMTIME st = {0};
GetLocalTime(&st);
hr = SecondsAfter(&st, dwAfterSeconds);
if (FAILED(hr)) {
return hr;
}
notifTrigger.dwType = CNT_TIME;
notifTrigger.stStartTime = st;
// timer: execute an exe at specified time
notifTrigger.lpszApplication = (LPTSTR)szExeName;
notifTrigger.lpszArguments = (LPTSTR)szArgs;
hNotify = CeSetUserNotificationEx(0, ¬ifTrigger, NULL);
// NULL because we do not care the action
if (!hNotify) {
hr = E_FAIL;
} else {
// close the handle as we do not need to use it further
CloseHandle(hNotify);
}
return hr;
}
- ClearRunApp: I want to emphasize and repeat what I said in Pocket
PC Power Management Series 4 regarding CeSetUserNotificationEx. One
notorious side-effect of CeSetUserNotificationEx is that the notification
will be persisted in a central repository, unless the creator remembers to
remove it. I've seen a couple of novice developers forgot to clear the
notifications and subject his/her testing device to some really weird
behaviors. So I also present ClearRunApp, which is used to clear previously
scheduled tasks. Remember: Even if the task already ran, the notification is
still persisted, unless cleared programmatically.
static HRESULT ClearRunApp(LPCTSTR szExeName)
{
HRESULT hr = S_OK;
// hold a notification
PBYTE pBuff = (PBYTE)LocalAlloc(LPTR, 8192);
if (!pBuff) {
return E_OUTOFMEMORY;
}
// at most 256 notification handles
HANDLE hNotifHandlers[256];
DWORD nNumHandlers, nNumClearedHandlers = 0;
DWORD i = 0;
int rc = CeGetUserNotificationHandles(hNotifHandlers,
dim(hNotifHandlers), &nNumHandlers);
if (!rc) {
hr = E_FAIL;
goto FuncExit;
}
// iterate all notifications
// Notice: We do not care about the status of the notification.
// Just clear it even if it is not filed??
for (; i<nNumHandlers; i++) {
// query info for this specific handler
BOOL bClearThis = FALSE;
DWORD dwSize = 0;
rc = CeGetUserNotification(
hNotifHandlers[i], 8192, &dwSize, pBuff);
if (!rc) continue;
PCE_NOTIFICATION_INFO_HEADER pnih =
(PCE_NOTIFICATION_INFO_HEADER)pBuff;
PCE_NOTIFICATION_TRIGGER pNotifTrigger = pnih->pcent;
// Notice some events with NULL lpszApplication might be inserted!
if (pNotifTrigger && pNotifTrigger->lpszApplication
&& !_tcsicmp(pNotifTrigger->lpszApplication, szToCompare)) {
CeClearUserNotification(pnih->hNotification)
}
}
FuncExit:
if (pBuff) {
LocalFree(pBuff);
}
return hr;
}
3. Further thoughts
If you do not need the style of "running a program AFTER some time", rather, what you want is "running a program AT certain time", you can simply modify ScheduleRunApp as needed.
Category: [Power Management]
20 Comments:
Hi,
Great series - well done!!
Just one note - your ScheduleRunApp() is leaking a handle each time it is called!
CeSetUserNotificationEx returns a handle if successful and you aren't closing it!
Thanks for pointing out! I've modified the source code (also in Series 4) to close the handle.
I complete agree that it is a good habit to always close any handle *so long as* it is not used. However, I am not sure whether the handle returned by CeSetUserNotificationEx is really that critical like a handle to a Kernel Object. For example, if you forget to close a handle to a Thread kernel object, the handle won't be released until the process dies. Those kernel objects are tracked in the process' handle table. So my question is whether the handle returned by CeSetUserNotificationEx is such an object being tracked in the handle table, and pointing to to a data structure maintained only by the kernel; or the handle returned by CeSetUserNotificationEx is just a pseudo number, which does not carry much significance (if you do not need to call CeClearUserNotification to clear it in the same process). My sample code actually clears the notification in a separate process.
Looks like at least one other people had such concern, and Peter Foot said that there is no need to close the handle since it is not a real one.
I posted a question to Microsoft Smart Device Development forum, hoping to get an authoritative answer from within Microsoft.
(http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=321876&SiteID=1)
Hi, I posted a question about
series 6 on
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=324621&SiteID=1
it's about how to use the unmanaged code. I'm still learning ;)
thank you.
I saw a new interesting blog about SSL. I'll take a look at it
Can you tell me more exactly how to use it with c#, I haven't a clue
thus like : make new file, which kind?
...
sorry, me again, but I'm running out off time...
I want to call it from c# or another way, but how??
Davy.timmermans a t kahosl.be
Is there any posibility to enable the "View Item" menu item when notification arrives?
I want to use it to launch my application.
This comment has been removed by the author.
AMAZING CODE i must say !!
just 1 help.. I wanted to do the reverse of u r doing up here .. as in .. DETECT an APP which is running..
I mean .. when i click the IE icon from the today screen, i want to get a notification, & so on for every Exe under windows like tasks.exe, tcalc.exe, etc .. PLEASE HELP !!
Thanks so much for sharing your knowledge. I have one question.
int the line
" int rc = CeGetUserNotificationHandles(hNotifHandlers,
dim(hNotifHandlers), &nNumHandlers); "
of "ClearRunApp(...)"
I've got an error while compiling.
The error point is at "dim(hNotifHandlers)".
Do you have any suggestion?
Thanks in advance.
I like play online game, I also gw gold and GuildWars Gold, the Guild Wars Gold is very cheap, and use the GuildWars money can buy many things, I like cheap gw gold, thanks, it is very good.
I like play online game, I also buy habbo gold and habbo credits, the habbo gold is very cheap, and use the habbo coins can buy many things, I like cheap habbo credits, thanks, it is very good.
I like play online game, I also buy hero gold and hero gold, the hero online gold is very cheap, and use the hero online money can buy many things, I like hero money, thanks, it is very good.
I like play online game, I also buy kal geons and kal gold, the kal online geons is very cheap, and use the kal online gold can buy many things, I like kalonline Geons, thanks, it is very good.
Now do you worried about that in the game do not had enough Sword of the New World Vis to play the game, now you can not worried, my friend told me a website, in here you can buy a lot Sword of the New World Gold and only spend a little money, do not hesitate, it was really, in here we had much cheap snw vis, we can sure that you will get the Sword of the New World money, quick to come here to buy vis.
great post!
I like the Tales Of Pirates gold, in the game Tales Of Pirates money is very important, if you have cheap Tales Of Pirates gold, you will become stronger. You can buy weapons with the buy Tales Of Pirates Gold, so when you have many buy Tales Of Pirates Gold, you will improve your level quickly.
Hi,
The ScheduleRunApp runs in principle like a charm, but I have one major problem. For some reason, the PDA does not wake up after setting a notification with ScheduleRunApp("JustAProgram").
ScheduleRunApp("JustAProgram") only works fine when the device stays on, or is in sleep mode with the external power connected.
Please help,
Huub
I just figured it out!
When the notification hits, the application is started but the device goes into suspend mode almost immediately. I use SetSystemPowerState() to force the device to go into power on mode.
Cheers,
Huub
Hi Lao K,
Firstly, I'd like to thank you for an awesome series on power management!
I've been battling with Motorola(Symbol) over a major power saving issue. What they have done is whenever a TCP or UDP data packet is sent or received, they force a reset of the system idle timer. So, as you can imagine if the device were set to sleep after 5 minutes and a mail client checked for mail every 4 minutes the device would never sleep.
Please correct me if I'm wrong but doesn't that go against the design of the OS & Power Manager?
This is causing major problems with our application that retains an open connection for pushing data from our servers to our mobile devices. The application sends a keep alive packet every 45 seconds to let the server know the device is within GPRS range and online.
Motorola seem very reluctant to change this stating it's "the desired and better behavior for MOST customers".
They also state that it would be "impossible to transfer big file since the terminals will suspend before finishing". Surely this is why an application transfering a large file should call SystemIdleTimerReset function.
Please note, this feature is only implemented on 2 devices (the MC70 & MC9090). Motorola claim that these two devices are "focused in different environments where the user needs and preferences are different".
Personally, I can't think of any scenario in which you'd want to force this functionality. Regardless of environment.
I don't really know where to go next on this issue. Motorola are not listening.
Any help or comments would be greatly appreciated.
Thanks in advance
Tom Bradley
I am grateful to you for this great content.aöf thanks radyo dinle cool hikaye very nice sskonlycinsellik very nice ehliyet turhoq home free kadın last go korku jomax med olsaoy hikaye lesto go mp3 indir free only film izle
Post a Comment
<< Home