Unable to call this system event in Windows service, how can we call it in Windows service?
Microsoft.Win32.SystemEvents.TimeChanged += SystemEvents_TimeChanged;
void SystemEvents_TimeChanged(object sender, EventArgs e)
{
AnyMethodExample();
}
This event is only raised if the message pump is running. In a Windows
service, unless a hidden form is used or the message pump has been
started manually, this event will not be raised.
https://msdn.microsoft.com/en-us/library/microsoft.win32.systemevents.timechanged(v=vs.110).aspx
It depends where you are calling within windows service. You can post complete code for further support. Simply,
class Program
{
static void Main(string[] args)
{
SystemEvents.TimeChanged += new EventHandler(SystemEvents_TimeChanged);
Console.ReadKey();
}
static void SystemEvents_TimeChanged(object sender, EventArgs e)
{
Console.WriteLine("TimeChanged: {0}", DateTime.Now);
}
}
Caution: Because this is a static event, you must detach your event handlers when your application is disposed, or memory leaks will result.
Related
here's what I've done in my universal windows app:
public MainPage()
{
InitializeComponent();
private LockApplicationHost lol=LockApplicationHost.GetForCurrentView();
}
private async void Lol_Unlocking(LockApplicationHost sender, LockScreenUnlockingEventArgs args)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
alarm.Pause();
Status.Text = "lolwtf";
});
}
I'm trying to know when the user unlocks his computer.
EDIT: also the error I keep getting is:
Delegate to an instance method cannot have null 'this'. and it highlights:
lol.Unlocking += Lol_Unlocking;
I'm trying to know when the user unlocks his computer.
You can hookup a SessionSwitchEventHandler. Obviously your application will need to be running. SessionSwitchEventHandler delegate, you identify the method that will handle the event. To associate the event with your event handler, add an instance of the delegate to the event.
Microsoft.Win32.SystemEvents.SessionSwitch += new Microsoft.Win32.SessionSwitchEventHandler(SystemEvents_SessionSwitch);
void SystemEvents_SessionSwitch(object sender, Microsoft.Win32.SessionSwitchEventArgs e)
{
if (e.Reason == SessionSwitchReason.SessionLock)
{
//I left my desk
}
else if (e.Reason == SessionSwitchReason.SessionUnlock)
{
//I returned to my desk
}
}
You can have a look on the SessionSwitchReason Enumeration to find more about the uses the SessionSwitchReason class to represent the type of a session switch event.
lol.Unlocking += Lol_Unlocking;
should be lol.Unlocking += Lol_Unlocking(EventHandler_Unlocking); and EventHandler_Unlocking has to be defined in the program.
my understanding for LockApplicationHost.Unlocking is that it helps to unlock and lock the device whereas to determine if the device is unlocked and unlocked SessionSwitchEventHandler will be better approach. For more understanding on the LockApplicationHost.Unlocking check this
I want to handle when windows service is killed by task manager or by system restart.
I tried using below handler inside Timer_Elapsed method of the service timer
public void Start()
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
_myTimer= new Timer(10000);
_myTimer.Elapsed += OnElapsed;
_myTimer.AutoReset = false;
_myTimer.Start();
}
private void OnElapsed(object sender, ElapsedEventArgs e)
{
try
{
_myTimer.Stop();
//Work
}
finally
{
_myTimer.Start();
}
}
and even I have placed the same into Main() method of the console as I am using Topshelf for windows service.
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
var exitCode = HostFactory.Run(hostConfigurator =>
{
hostConfigurator.Service<MyService>(serviceConfigurator =>
{
serviceConfigurator.ConstructUsing(() => new MyService());
serviceConfigurator.WhenStarted(MyService => MyService.Start());
serviceConfigurator.WhenStopped(MyService=> MyService.Stop());
});
hostConfigurator.RunAsLocalSystem();
hostConfigurator.SetDisplayName("MyService");
hostConfigurator.SetDescription("MyService");
hostConfigurator.SetServiceName("MyService");
hostConfigurator.UseLog4Net();
});
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
File.AppendAllText(#"C:\Crash.txt", "Main Termination");
}
In either scenario the handler is not getting called when I kill the windows service process from task manager or system restart. Even TopShelf is not logging "UnhandledServiceException" exit code.
I have searched Google for all possible ways but no luck. Could any one please help me in this.
Thanks
I want to detect and close any program (for example: Notepad.exe) by using a windows service. Below code is good choose in a console application.
class Program
{
private static SessionSwitchEventHandler sseh;
static void Main(string[] args)
{
sseh = new SessionSwitchEventHandler(SystemEvents_SessionSwitch);
SystemEvents.SessionSwitch += sseh;
while (true) { }
}
static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
Console.WriteLine(e.Reason.ToString());
}
}
But Above code is not working in a windows service windows 7. look this link :
http://social.msdn.microsoft.com/Forums/eu/netfxcompact/thread/04b16fac-043a-41c3-add9-482c912e95be
I have written below code in the windows service which does not run on win 7, it is working every time on windows 7 in console application.
protected override void OnStart(string[] args)
{
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
Console.ReadLine();
SystemEvents.SessionSwitch -= SystemEvents_SessionSwitch;
}
static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
WriteToLogFile( e.Reason.ToString());
if (e.Reason == SessionSwitchReason.SessionLock)
{
WriteToLogFile("SessionLock ");
}
if (e.Reason == SessionSwitchReason.SessionUnlock)
{
WriteToLogFile("SessionUnlock ");
}
if (e.Reason == SessionSwitchReason.SessionLogon)
{
WriteToLogFile("SessionLogon ");
}
}
I have been read this article (http://rhauert.wordpress.com/category/ucc/) but I can not use
protected override void OnStart(string[] args)
{
WriteToText("Windows Service is started");
SessionChangeHandler x = new SessionChangeHandler();
}
MSDN:
SystemEvents.SessionSwitch Event:
This event is only raised if the message pump is running. In a Windows service, unless a hidden form is used or the message pump has been started manually, this event will not be raised. For a code example that shows how to handle system events by using a hidden form in a Windows service, see the SystemEvents class.
The code sample is on this page, which also notes:
Services do not have message loops, unless they are allowed to interact with the desktop. If the message loop is not provided by a hidden form, as in this example, the service must be run under the local system account, and manual intervention is required to enable interaction with the desktop. That is, the administrator must manually check the Allow service to interact with desktop check box on the Log On tab of the service properties dialog box. In that case, a message loop is automatically provided. This option is available only when the service is run under the local system account. Interaction with the desktop cannot be enabled programmatically.
I have an object that uses a timer to occasionally poll for a resource and then raises an event whenever the poll finds something of note. I have looked at several other examples but can't seem to find a method to marshall the event back to the UI thread without extra code on the event handler on the UI thread. So my question is:
Is there any way to hide this extra effort from the users of my object?
For the purpose of discussion I will include a trivial example:
Imagine I have a form with 1 richtextbox:
private void Form1_Load(object sender, EventArgs e)
{
var listener = new PollingListener();
listener.Polled += new EventHandler<EventArgs>(listener_Polled);
}
void listener_Polled(object sender, EventArgs e)
{
richTextBox1.Text += "Polled " + DateTime.Now.Second.ToString();
}
Also I have this object:
public class PollingListener
{
System.Timers.Timer timer = new System.Timers.Timer(1000);
public event EventHandler<EventArgs> Polled;
public PollingListener()
{
timer.Elapsed +=new System.Timers.ElapsedEventHandler(PollNow);
timer.Start();
}
void PollNow(object sender, EventArgs e)
{
var temp = Polled;
if (temp != null) Polled(this, new EventArgs());
}
}
If I run this, as expected it yields the exception
"Cross-thread operation not valid: Control 'richTextBox1' accessed
from a thread other than the thread it was created on"
This makes sense to me, and I can wrap the event handler method differently as so:
void listener_Polled(object sender, EventArgs e)
{
this.BeginInvoke(new Action(() => { UpdateText() }));
}
void UpdateText()
{
richTextBox1.Text += "Polled " + DateTime.Now.Second.ToString();
}
But now the user of my object has to do this for any event that is raised from the timer event in my control. So, is there anything I can add to my PollingListener class that doesn't change the signature of it's methods to pass in extra references that would allow the user of my object to be oblivious of the marshaling event in the background to the UI thread?
Thanks for any input you may have.
Added after comment:
You would need to pickup some latent detail that you can exploit to be able to accomplish that goal.
One thing that comes to mind is creating your own Forms/WPF timer at construction time and then use this and some synchronization to hide the details of coordination across threads. We can infer from your sample that construction of your poller should always happen in context of your consumer's thread.
This is a rather hack-ish way to accomplish what you want, but it can accomplish the deed because the construction of your poll-listener happens from the consumer's thread (which has a windows message pump to fuel the dispatches of Forms/WPF timers), and the rest of the operation of the class could occur from any thread as the forms Timer's tick will heartbeat from the original thread. As other comments and answers have noted, it would be best to reassess and fix the operating relationship between your polling operations and the consumer.
Here is an updated version of the class, PollingListener2 that uses a ManualResetEvent and a concealed System.Windows.Forms.Timer to ferry the polling notice across threads. Cleanup code is omitted for the sake of brevity. Requiring the use of IDisposable for explicit cleanup would be recommended in a production version of this class.
ManualResetEvent # MSDN
public class PollingListener2
{
System.Timers.Timer timer = new System.Timers.Timer(1000);
public event EventHandler<EventArgs> Polled;
System.Windows.Forms.Timer formsTimer;
public System.Threading.ManualResetEvent pollNotice;
public PollingListener2()
{
pollNotice = new System.Threading.ManualResetEvent(false);
formsTimer = new System.Windows.Forms.Timer();
formsTimer.Interval = 100;
formsTimer.Tick += new EventHandler(formsTimer_Tick);
formsTimer.Start();
timer.Elapsed += new System.Timers.ElapsedEventHandler(PollNow);
timer.Start();
}
void formsTimer_Tick(object sender, EventArgs e)
{
if (pollNotice.WaitOne(0))
{
pollNotice.Reset();
var temp = Polled;
if (temp != null)
{
Polled(this, new EventArgs());
}
}
}
void PollNow(object sender, EventArgs e)
{
pollNotice.Set();
}
}
This has some precedent in the distant Win32 past where some people would use hidden windows and the like to maintain one foot in the other thread without requiring the consumer to make any significant changes to their code (sometimes no changes are necessary).
Original:
You could add a member variable on your helper class of type Control or Form and use that as the scope for a BeginInvoke() / Invoke() call on your event dispatch.
Here's a copy of your sample class, modified to behave in this manner.
public class PollingListener
{
System.Timers.Timer timer = new System.Timers.Timer(1000);
public event EventHandler<EventArgs> Polled;
public PollingListener(System.Windows.Forms.Control consumer)
{
timer.Elapsed += new System.Timers.ElapsedEventHandler(PollNow);
timer.Start();
consumerContext = consumer;
}
System.Windows.Forms.Control consumerContext;
void PollNow(object sender, EventArgs e)
{
var temp = Polled;
if ((temp != null) && (null != consumerContext))
{
consumerContext.BeginInvoke(new Action(() =>
{
Polled(this, new EventArgs());
}));
}
}
}
Here's a sample that shows this in action. Run this in debug mode and look at your output to verify that it is working as expected.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
listener = new PollingListener(this);
}
PollingListener listener;
private void Form1_Load(object sender, EventArgs e)
{
listener.Polled += new EventHandler<EventArgs>(listener_Poll);
}
void listener_Poll(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine("ding.");
}
}
If the processing work inside your PollNow is fairly small then you do not need to perform it on a separate thread. If WinForms use Timer, in WPF you use DispatchTimer and then you are performing the test on the same thread as the UI and there is no cross-thread issue.
This SO question prompted this comment:
I think this excerpt is enlightening: "Unlike the
System.Windows.Forms.Timer, the System.Timers.Timer class will, by
default, call your timer event handler on a worker thread obtained
from the common language runtime (CLR) thread pool. [...] The
System.Timers.Timer class provides an easy way to deal with this
dilemma—it exposes a public SynchronizingObject property. Setting this
property to an instance of a Windows Form (or a control on a Windows
Form) will ensure that the code in your Elapsed event handler runs on
the same thread on which the SynchronizingObject was instantiated."
And System.Times.Timer doc says of SynchronizingObject:
Gets or sets the object used to marshal event-handler calls that are
issued when an interval has elapsed.
Both of which implie that if you pass a control created on the UI thread as the sync object then the timer will effectively marshal the timer event calls to the UI thread.
Not sure if the title covers the question well, but here it comes.
I have a project with:
A website: webforms (Aps.net 4,c#) where the user can upload files, interact with them and manually trigger some batch processing
A classlib with all the business logic for the processing
An app that runs on a machine at the customers location and is scheduled to upload files by SFTP to our server.
A console app that is scheduled on the server and does the batch processing for the files that are uploaded by SFTP.
'heavy use customers' use the SFTP app, the others use the website.
The console app and the website both use the same classlib.
What mechanism can I use to send logging/progress information to the website or the console app without implementing two classlibs? I do not want the classlib to be aware that it is called by the console app or the website. For example they also share the same settings. etc.
Any ideas?
Events.
You could add events to the classes that perform the actual business logic in your shared lib. When something happens that requires feedback, you can raise that event in the class.
The consuming application (either the console app or the web-app) can subscribe to those events, and take the appropriate action that is specific to their platform.
A very simplyfied example:
public class SomeLogicClass
{
public event EventHandler SomethingDone;
protected virtual void OnSomethingDone()
{
if( SomethingDone != null )
{
SomethingDone(this, EventArgs.Empty);
}
}
public void DoSomething()
{
// Do some work.
OnSomethingDone();
}
}
In your console-app you can do this, for instance:
var x = new SomeLogicClass();
x.SomethingDone += (s,e) => Console.WriteLine ("Work done.");
x.DoSomething();
The Events idea solves nothing as it will block the main thread and e.g. not be useful for reporting progress in a responsive UI.
Use BackgroundWorker:
public static void Main(string[] args)
{
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.ProgressChanged += ReportProgress;
worker.RunWorkerCompleted += ProgressComplete;
worker.DoWork += DoWork;
worker.RunWorkerAsync();
}
private static void DoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
//Runs on seperate thread
//Do stuff
//(sender as BackgroundWorker).ReportProgress... reports back to main thread
//Do other stuff
}
private static void ProgressComplete(object sender, RunWorkerCompletedEventArgs e)
{
//Executed on main thread
Console.Out.WriteLine("All Done");
}
private static void ReportProgress(object sender, ProgressChangedEventArgs e)
{
//Can be used to asynchronously send status updates or update UI elements on the main thread
Console.Out.WriteLine("{0:P} done", e.ProgressPercentage/100.0);
}