Prevent Windows Screen Locking using SessionSwitch event - c#

I am just wondering if it is possible to stop a windows workstation from locking using the SessionSwitch event in a Windows Form.
I am working on a (very simple) time and attendance system, and I want to prevent a user locking their screen unless they have set their status to away/lunch.
Current code is like this.
protected override void OnLoad(EventArgs e)
{
SystemEvents.SessionSwitch += new SessionSwitchEventHandler(SystemEvents_SessionSwitch);
}
void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
if (e.Reason == SessionSwitchReason.SessionLock)
{
MessageBox.Show("Logout reason " + e.Reason);
// Check if status is valid for logout, if not then prevent lock
}
}
Is there a way to prevent the screen locking from within a windows form? Or should I look for a different solution?
Thanks.

I don't believe you can stop the user from locking the screen. But, even if you can, what good would it be? They can still go away without locking their screen, can't they?
To me, it comes across as if you need to attribute time to a valid category like Lunch, Work, Meeting, etc. If that's the case, you need to realize that you can't force the user to do it. But, you can incentivize the user to do so or punish the user for not doing so.
I might suggest, hooking up to relevant event (SessionSwitch, Applications.Idle) and using a heuristics to guess the category (say if computer is idle for more than 20 minutes then categorize it as Lunch break). Provide the user with the ability to change the categorization. This way folks who have 3 lunch breaks in their timesheet, might start setting the system with the correct category before leaving for a break.

Related

C# Event not detecting suspend state

I'm working on a Windows forms application that needs to perform some logic before the PC goes to sleep. I've looked through many threads and found this which should work perfectly: Link. I can detect when the power is plugged/unplugged just fine, but I've run into serious problems when trying to detect a sleep/suspend event.
Using the logic mentioned, I have this section of code in my program:
public void powerModeChanged(object sender, PowerModeChangedEventArgs args)
{
if (args.Mode == PowerModes.Suspend)
{
Trace.WriteLine("Sleeping.....");
}
else if (args.Mode == PowerModes.StatusChange)
{
Trace.WriteLine("Other Status Change:");
}
}
public MainPage()
{
InitializeComponent();
SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(powerModeChanged);
Per this documentation page - Link, there are 3 types of power modes. The statusChange is detected as expected when I unplug and replug the power adapter into my laptop, and prints to the debug Window just fine. However, it will not detect when I put the computer to sleep. After going over this for hours, my conclusion is that what the version of Windows 10 I'm running defines as "sleep" doesn't match up with the event that I'm checking for.
There is a comment on that initial thread in the first link that says the solution I tried doesn't seem to work with the "new Connected/Modern Standby modes" and provides a link to this thread: Link where it describes using the session switch event handler instead. This works on my laptop as my laptop locks upon sleep, but when testing on a Surface tablet (which is our target device for operation), it doesn't work due to the surface not locking upon sleep.
Of course, I could just set the device to lock on sleep, and that may end up being the only solution, but I wanted to see if there was something I was overlooking or any other way to check for sleep in modern versions of Windows. As it stands, I would hate for this important feature of the application depend on the system having to be setup to lock when sleeping. Thanks!
You could use the SystemEvents.PowerModeChanged event to detect when the computer is about to go to sleep. Within the event handler, you can perform any logic that needs to be done before the computer goes to sleep. For example, you could write commands to the windows registry or perform some other related tasks.
Below is an example of how this could be done:
// Register the SystemEvents.PowerModeChanged event handler
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
// Event handler for SystemEvents.PowerModeChanged
private void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
// Check if the computer is about to go to sleep
if (e.Mode == PowerModes.Suspend)
{
// Perform the logic that needs to be done before the computer goes to sleep
// ...
}
}
I ended up finding this thread, the answer on that thread solves this issue.
Link to Solution

C# threading and polling

I have a tray icon that needs to display two icons:
If there is network connectivity, display a green circle with a check mark
If there isn't network connectivity, display a red circle with an X
So what I have is:
using System.Net.NetworkInformation;
bool isConnected = NetworkInterface.GetIsNetworkAvailable()
So I'm thinking of starting a new thread or using the background worker progress because the tray icon is a NotifyIcon which is a component so I can't use:
Form.Invoke(delegate, object[])
to update the icon property of the NotifyIcon class.
My big concern is the polling process: I could write some logic that does:
while (true)
{
System.Threading.Thread.Sleep(1000);
isConnected = NetworkInterface.GetIsNetworkAvailable();
if (isConnected)
notifyIcon.Icon = "ConnectedIcon.ico";
else
notifyIcon.Icon = "DisconnectedIcon.ico";
}
but I've seen a couple of articles that tell me to stay away from Sleep(1000). I can't seem to find those articles since I didn't bookmark them. I'm just curious to know why that isn't a good idea for polling in a thread.
You can register an Event on NetworkChange so you are being notified when the status changes:
NetworkChange.NetworkAvailabilityChanged += new NetworkAvailabilityChangedEventHandler(NetworkChange_NetworkAvailabilityChanged);
void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
{
if (e.IsAvailable) {
Console.WriteLine("Network Available");
} else {
Console.WriteLine("Network Unavailable");
}
}
In you situation its totally fine to use the Sleep method.
What you saw was probably saying so its better to use a Reset Event - from looping etc...
Polling isn't always evil, but it's best avoided if possible. If I run your application that's polling once per second, that means that once per second your program is getting scheduled to do work on a CPU core that is 99.9999% going to be a no-op. On a desktop that's not too terrible, but imagine a laptop. CPUs there try run in very low power modes whenever possible, so additional CPU work means less battery life! This is the reason why many mobile platforms (iOS, Windows Phone 7, etc) ban arbitrary background threads because they know people will abuse them.
In your case, there's an easier way: just use System.Net.NetworkInformation.NetworkChange which provides events for when the network connectivity changes. No polling required!

How can I lag a computer in c#? CREATE lag!

This is an odd question, I understand. I also assumed it would be simple, because lord knows I have created my share of infinite loops.
I'm trying to cause a slight PC lag in C# - specifically I need to create a 'choppy mouse' situation system wide (not just the sandboxed exe).
The little app can't crash the computer! The lag should be able to run for 2-10 seconds ish - then stop.
What I have tried so far:
-Spawning numerous threads that save data (filled up memory and cause PF usage, no real lag).
-Spawning TONS of threads (lag at first, but then none when treads are re-spawned again - as if the second time the OS is ready).
-Spawning threads that take several screenshots (the screenshots don't seem to lag).
None of these have worked - any ideas?
Optional back story (optional):
The reason for the application, without divulging any company information, is to cover up a laggy background process in a production environment. We have tried to speed the app up, or improve the computers with no results. There is an abuse case that is present when production workers associate a lag with this background application running. The goal is to disassociate this lag ... by creating a similar one at random times sparingly.
Clarification:
The original background app is not home grown (fyi) the only real solution would to be purchase 1000s of new boxes. The company is going with the cheaper 'hide the background app' ... 'solution'. I know...
You can just create a background app that randomly calls the Windows BlockInput API at a desired interval. This allows your app to have as small a footprint as possible preventing it from taking up CPU cycles and memory.
More information here:
http://msdn.microsoft.com/en-us/library/ms646290.aspx
That said, I agree with the other posts / comments that this is addressing the symptoms and not the problem.
EDIT: code example
using System.Runtime.InteropServices;
using System.Threading;
namespace LagTimer
{
class Program
{
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool BlockInput([In, MarshalAs(UnmanagedType.Bool)] bool fBlockIt);
static void Main(string[] args)
{
Thread t = new Thread(LagTick);
t.Start();
while (true) { } // Prevent the app from exiting
}
static void LagTick()
{
while (true)
{
BlockInput(true);
System.Threading.Thread.Sleep(250);
BlockInput(false);
// TODO: Randomize time in between ticks
Thread.Sleep(100);
// TODO: Add logic for when to "sputter" the mouse
}
}
}
}
You could make a thread that has an infinite loop, and every X seconds raises an event that the UI Thread catches. The UI thread could then call Thread.Sleep for however long you want.
PLEASE DON'T DO THIS
That said, it could be accomplished by creating a number of threads that matches the number of logical processor cores in the system, set the processor affinity of each thread so that there's one per core, and then just have each thread run code like this:
int i = rand();
while (!timeLimitExpired())
{
i += rand() % i;
}
The purpose of the rand() call is to keep a compiler optimization from realizing that your loop doesn't actually do anything and optimizing it away, and the purpose of the modulo operation is to prevent creating an overflow (exception) (you could use simple division as well).
Because I don't think you should do, I won't share the code on how to determine the number of processor core or detect thread affinity. Instead, please please please fix your app. It's probably as simple as adding a sleep() call in the middle of a tight loop somewhere.
It sounds like you are trying to make a timed busy-loop. The simplest way to do that is just a tight loop that checks the clock and exits when a certian delta of time has passed.
Now, on a typical PC you might not see any "lag" when this happens. Why? Well there are a couple of reasons.
Multiple CPUs. If you don't do this on every CPU, then there's a free CPU for the OS to use and you might not notice the difference. To make sure you are using every CPU, I'd suggest creating a process to run your "cpu eater" with the CPU affinity set or CPU 0, and then another for each other CPU the system has.
Task priorities. Generally things like the desktop are given a higher priority than background tasks. If you want to keep your program from being pre-empted by that, you need to make it a very high priority.
Note: if you make your task high-priority, and then somehow set it up to run on startup or login, I am not responsible for any damage you do to your machine or OS reinstalls you are forced to perform. Also, chewing up large amounts of CPU for extended periods can cause PCs with stock cooling setups to overheat. This causes crashes and sometimes permanent damage.
I would like to add that, while we developers don't have to sign onto any code of ethics to get professional licenses like Doctors, Lawyers, and some engineers must do, there are still times when we have an obligation to refuse to carry out unethical requests.
Since you say these are your company's own machines that they are looking to slow down, that's stoopid, but not unethical. However, if these were customer machines then I'd have to put my foot down. Your boss won't thank you (and may even fire you), but your company would get absolutely roasted if/when a customer finds out what is really going on. Doing the right thing for both your company and its customers, against supervisor wishes, is what ethics is all about.
You bind a
Form2 Form = new Form2();
// open form2
Form.Show();
to a
private void timer1_Tick(object sender, EventArgs e)
//spam form2. Maybe set timer Interval to 10 or 5.
{
}
And it will lag intense within 4 min or so. atleast I can't access the task manager.
form2 properties, put opacity 0%, windowsstate = Minimized and don't show in taskbar.
this is an example:
private void timer1_Tick(object sender, EventArgs e)
//spam form2. Maybe set timer Interval to 10 or 5.
{
Form2 Form = new Form2();
// open form2
Form.Show();
}

How to programmatically detect when the OS (Windows) is waking up or going to sleep

Background
My son likes to use his laptop when he's not supposed to and I just thought it would be handy if I could write an application that would email me whenever he opened / closed his laptop.
(I'd even settle for something that notified me when there was network traffic on the machine)
Question
How do you programmatically detect when an OS is waking up or going to sleep? I found this link from this related post. But that covers OS X. I'm looking for the same thing for Windows 7.
(I'd like to do this in Java, if possible, but I'd settle for C#/C++)
Easiest way is not to write any code at all, even though this is stack overflow. Click Start, type Schedule and choose Scheduled Tasks. Set one up (click Create Task) and set a Trigger when the machine is unlocked. For the Action, have it send you an email.
Repeat for startup and when a user logs in, if you want. Done.
You're going to want to create a window and watch for the WM_POWERBROADCAST message (http://msdn.microsoft.com/en-us/library/aa373248%28v=vs.85%29.aspx) and check the wParam for your desired action. For example, your window should receive a WM_POWERBROADCAST with PBT_APMSUSPEND as the wParam when the system is about to enter a suspended state (i.e. closing a laptop). Resuming seems to have a few different wParam values: PBT_APMRESUMESUSPEND, PBT_APMRESUMECRITICAL and PBT_APMRESUMEAUTOMATIC
I search for a long time and found that this was the best way, the 'Sleep'-event was never working before:
private ManagementEventWatcher managementEventWatcher;
private readonly Dictionary<string, string> powerValues = new Dictionary<string, string>
{
{"4", "Entering Suspend"},
{"7", "Resume from Suspend"},
{"10", "Power Status Change"},
{"11", "OEM Event"},
{"18", "Resume Automatic"}
};
public void InitPowerEvents()
{
var q = new WqlEventQuery();
var scope = new ManagementScope("root\\CIMV2");
q.EventClassName = "Win32_PowerManagementEvent";
managementEventWatcher = new ManagementEventWatcher(scope, q);
managementEventWatcher.EventArrived += PowerEventArrive;
managementEventWatcher.Start();
}
private void PowerEventArrive(object sender, EventArrivedEventArgs e)
{
foreach (PropertyData pd in e.NewEvent.Properties)
{
if (pd == null || pd.Value == null) continue;
var name = powerValues.ContainsKey(pd.Value.ToString())
? powerValues[pd.Value.ToString()]
: pd.Value.ToString();
Console.WriteLine("PowerEvent:"+name);
}
}
public void Stop()
{
managementEventWatcher.Stop();
}
A very simple, perhaps crude, but effective way may be to have a program with a timer firing every minute. If the timer fires and it's been, say, 5 minutes of real time since its last execution then you can likely assume that the computer was sleeping since it's unlikely that your thread was unable to be scheduled for so long.
The other reason for the difference may be a clock adjustment, like DST or a manual change, but that kind of "noise" should be very low, in your scenario.
You could write a simple app and register it as a Windows service, to be started automatically at system startup. This app could then do whatever you want when it starts. And if it's a proper Windows app, it can register to get notification about impending system shutdown too (I don't remember the details but I implemented this in a C++ MFC app many years ago).
If you prefer Java, you could register your app as a service via a suitable service wrapper like Tanuki (it seems they have a free Community License option). Although this might be overkill. And it may be possible to get notification about the JVM shutting down when the system is closing (but I have no concrete experience with this).
http://www.pinvoke.net/default.aspx/powrprof.CallNtPowerInformation - Check out the link. It has almost all win32api for all windows function. You can call power management feature directly in your windows 7 laptop. For that create a Windows Service , that will use these specific api to notify the machine state.

What is the proper way of handling logoff / shutdown / restart when the application has unsaved data?

In WPF App.Current.SessionEnding must return in a few seconds, otherwise the "application does not respond" window appears. So the user can't be asked in this event handler to save his data, because the user's response takes longer than a few seconds.
I thought a solution would be to cancel the logoff / shutdown / restart, and resume it when the user answered to the file save dialog.
ReasonSessionEnding _reasonSessionEnding;
App.Current.SessionEnding +=
new SessionEndingCancelEventHandler(Current_SessionEnding);
void Current_SessionEnding(object sender, SessionEndingCancelEventArgs e)
{
if (_dataModified)
{
e.Cancel = true;
_reasonSessionEnding = e.ReasonSessionEnding;
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(EndSession));
}
}
void EndSession()
{
if (SaveWithConfirmation()) // if the user didn't press Cancel
//if (_reasonSessionEnding = ReasonSessionEnding.Logoff)
// logoff
//else
// shutdown or restart ?
}
The problem is that ReasonSessionEnding does not tell me if Windows was shutting down or restarting (it does not differentiate between the two).
So, what should my program do on the session ending event ?
Should it even do anything, or doing nothing on this event is the standard ?
The user is asked to save his changes in my main form's OnClosing method, so he does not lose data, but I think that the "application does not respond" window does not suggest a normal workflow.
Canceling the shutdown is not desired I guess, because some of the other programs have been shut down already.
What seems to be the accepted way is to display the save as dialog regardless.
Cancelling the shutdown, then resuming it later is most certainly not an option, for the reason you state and various others.
Since simply discarding the data is unacceptable, there really is no other options.
Well, except to save the data to a temporary file, then automatically restoring them the next time the program is run. Rather like MS Word after it has crashed. Actually, the more I consider it, the better it sounds.
Edit: There's yet another avenue, namely to save continously, the way eg. MS OneNote does. What has struck me before is that, provided you implement decent multilevel undo in your application, the whole manual saving business is actually somewhat dated - an anachronism from the days when disk operations were expensive and error-prone, nowadays mostly old habit.
But I'm digressing. Anyway, it's probably not applicable to your application, since I imagine it needs to be implemented from the beginning.

Categories

Resources