I'm trying to do a away timer style thing like Skype. If the user is 'away' for a period of time I'll trigger something. I have been using SetWindowsHookEx() with WM_KEYBOARD_LL which works fine. That is until you open a RDC connection and have it full screen. Then I never get the keyboard events.
Anyone come across this? Or know of a better way to achieve this? I have actually tested skype and with a full screen RDC it will correctly go from Away to Online if I type in the RDC.
Thanks
EDIT: After Raymond Chen's comment I did some testing, and he is right. Can not believe I never found this method after all my searching. It also solved an issue I was having with a WPF app not triggering the LL_Mouse/KEYBOARD events.
Thanks Again. Update my accepted answer based on this. The other answer is still good if you need to do LL_MOUSE/KWYBOARD.
Have a look at GetLastInputInfo(). Try calling that periodically.
Yes. You'll not get keys pressed in remote desktop. I had this problem and only solution I found was this:
Using FindWindow API always look to find RDP window, if you've detected that full-screen RDP window has been created you should do this:
a) Unhook all hooks.
b) Reset all hooks.
So create a function which makes SetWindowHookEx API calls and call it SetHook and another one as UnHook function. Then re-call both of them anytime you find out user get into remote desktop.
Now you can get keys pressed even inside remote desktop connection.
I found my old code, I did something like this:
Created a timer with 1 sec.
Then
std::string tmp;
HWND hParent = ::FindWindow(TEXT("TSHELLHWND"), NULL);
GetWindowString(hParent, tmp);
ix = za.find(" - Remote Desktop");
if (hParent != NULL && ix != string::npos)
RestartHook();
You also should have a global variable to set when you've restarted hook, otherwise all the time it will restart the hook. When window closed, you can reset that global variable.
Related
I'm writting remote login app and I want to include the possibility to start new GUI session for different user. Goal is similar to what is done on Screen Sharing.app when user (different than already logged in) is connected - he can create new desktop without messing with session currently displayed. Is there an API for this? Maybe could You give me some useful links? I can't find anything to point me to the right direction so far.
Edit:
I am already able to connect to running "background" GUI sessions. Now I want to have a possibility to create session for user which is not logged in yet.
Edit: Spawning loginwindow under WindowServer process will also do the trick. When only one user is logged in, loginwindow process is terminated. Additionally - maybe there's a possibility to prevent loginwindow termination?
Edit:
I've tracked down function from private API which executes new loginwindow process under WindowServer and it works OK. Function is called CGSCreateLoginSessionWithDataAndVisibility, the problem is - this is private function I don't know what parameters it takes. Now I call it like this:
CGSSessionID outSession = 1;
CGSCreateLoginSessionWithDataAndVisibility(&outSession, NULL, false);
Does anyone know what arguments are used in CGSCreateLoginSessionWithDataAndVisibility or is there another way to achieve what I want?
Short of reverse engineering fast user switching and some hackage, I'm not too sure this could be accomplished. AFAIK there are not any public APIs other than some notifications and session states that can be observed for when the user switches users. Some info here on how to observe those notifications (you can do it through Cocoa or Carbon) and how to fetch the current sessions information.
Hope this helps, sorry for not being more helpful!
In my app I need to schedule notification to user on specified date and time (for example 1st May at 10:00). At this moment notification must be shown and when user clicks on this notification, my app should be open. I see two ways to do it:
1. Scheduled notifications. But if I use the Alarm class, I can not change the title of the notification (which is "Alarm" in English version of SDK).
Reminder class mostly suits me, but when it appears atop the lock screen and user clicks it, my app doesn't open. May be is there a way around these moments? Also I would like to get rid of listpicker with time (5 min, 10 min, 1 hour, etc.) and the "snooze" button, but it's not critical.
2. Toast (or tile) notifications from background agent. But I'm not sure that my background agent runs at the right time. As I understand the background agents runs by the system, and their launch is limited by several factors (phone battery charge, the presence of the running applications or other background agents). It may not even start. There is a way to force the agent at a specific time by using the LaunchForTest, but everywhere write that this method can be used only for debugging purposes, and before the publication of the application it must be removed.
If I do not delete this method, will my application be certified? Also I don't like that the toast notification is only opens for 10 seconds and then disappears without a trace. Something can be done about it?
I need to notification was guaranteed shown at the right time, and when you click on it my application was open. What is the best way to do this?
If this is not possible in Windows Phone 7, is there a way to do this in Windows Phone 8?
Thanks.
I think you should use the Reminders for this. When you click them your application will open.
Something like:
var reminder = ScheduledActionService.Find("MyAppReminder");
if (reminder != null)
{
ScheduledActionService.Remove("MyAppReminder");
}
reminder = new Reminder("MyAppReminder")
{
Title = "Bla",
BeginTime = DateTime.Now.AddDays(2),
Content = message,
NavigationUri = new Uri("/Start.xaml", UriKind.Relative),
RecurrenceType = RecurrenceInterval.None
};
ScheduledActionService.Add(reminder);
As for the application not opening when the notification appears on the lock screen, it makes sense. Would be a big security hole if you could open apps directly from the lock screen! Hope it helps.
I'm now writing a Bonjour service listener class, according to the document here:
Currently, it seems working, I can receive "netServiceBrowserWillSearch:" and "didFindService:moreComing:" correctly. However, after a long wait, I cannot receive " netServiceBrowserDidStopSearch:" or "netServiceBrowser:didNotSearch:". Therefore I don't know that is the proper time for my delegate class to stop showing some UI.
Could anyone have an idea for this? Thanks.
NSNetServiceBrowser doesn't stop browsing (and call the -netServiceBrowserDidStopSearch: delegate method) until you explicitly tell it to by calling -stop. After it's found the initial services, it continues informing you as new matching services are added or old ones disappear.
How you handle this depends on how you want your app to behave. If you have a window that continuously shows the available services (e.g. like the Bonjour window in iChat), then it's best to let it continue, and contiuously update the list in response to delegate messages. If you've got more like a dialog that gets populated and then goes away once the user makes a selection (e.g like the system Add Printer... dialog), then you want to keep the browser running while it's displayed, then call -stop once the user dismisses it. If you're waiting to find just one specific service, then you can call -stop once you've found and resolved it.
I'm trying to catch WM_QUERYENDSESSION to save some data in the app, but it seems that I'm not receiving this message on User logoff/system restart when the app is minimized to the system tray. How can I catch it?
Thanks.
Relevant code (nothing magic in there, hopefully :)):
ON_WM_QUERYENDSESSION()
BOOL CMainFrame::OnQueryEndSession()
{
AfxMessageBox(L"Are we hitting this?");
return FALSE;
}
For the tray icon I'm using a third-party lib (CodeJock), which I probably can't post here, but generally, it creates a hidden window to process messages, but the main window is simply ShowWindow(SW_HIDE) when needed. Maybe I need to intercept that message in that hidden window and pass it up, I'll need to try that.
This is basically eaten by a third-party class that I'll need to fix up.
Vista puts out a new security preventing Session 0 from accessing hardware like the video card, and the user no longer logs into session 0. I know this means that I cannot show the user a GUI, however, does that also mean I can't show one at all? The way my code is set up right now, it would be more work to make it command line only, however if I can use my existing code and just programmatically manage the GUI it would take a lot less code.
Is this possible?
The article from MSDN says this:
• A service attempts to create a user interface (UI), such as a dialog box, in Session 0. Because the user is not running in Session 0, he or she never sees the UI and therefore cannot provide the input that the service is looking for. The service appears to stop functioning because it is waiting for a user response that does not occur.
Which makes me think it is possible to have an automated UI, but someone told me that you couldn't use SendKeys with a service because it was disabled in Session 0.
EDIT: I don't actually need to show the user the GUI
You can show one; it just doesn't show up.
There is a little notification in the taskbar about there being a GUI window and a way to switch to it.
Anyway, there actually is a TerminalServices API command to switch active session that you could call if you really needed it to show up.
You can write a separate process which provides the UI for your service process. The communication between your UI and service process can be done in various ways (search the web for "inter process communication" or "IPC").
Your service can have a GUI. It's simply that no human will ever see it. As the MSDN quote suggests, a service can display a dialog box. The call to MessageBox won't fail; it just won't ever return — there won't be anyone to press its buttons.
I'm not sure what you mean by wanting to "manage the GUI." Do you actually mean pretending to send input to the controls, as with SendInput? I see no reason that it wouldn't be possible; you'd be injecting input into your own program's queue, after all, and SendInput's Vista-specific warnings don't say anything about that. But I think you'd be making things much more complicated than they need to be. Revisit the idea to alter your program to have no UI at all. (That's not the same as having a console program. Consoles are UI.)
Instead of simulating the mouse messages necessary to click a button, for instance, eliminate the middle-man and simply call directly the function that the button-click event would have called.