Form is not responding after event - c#

I am having this problem that my form would show up but not responding after it detects an event.
Here's my code for listening the event and what it does after it detects the event.
private void checkPrintJobs()
{
EventLogQuery logQuery = new EventLogQuery("Microsoft-Windows-PrintService/Operational", PathType.LogName, "*[System[(EventID = 800)]]");
EventLogWatcher logWatcher = new EventLogWatcher(logQuery);
logWatcher.EventRecordWritten += new EventHandler<EventRecordWrittenEventArgs>(EventWritten);
logWatcher.Enabled = true;
}
private void EventWritten(Object obj, EventRecordWrittenEventArgs arg)
{
PrintQueue myPrintQueue = new PrintQueue(ps, printer, PrintSystemDesiredAccess.AdministratePrinter);
myPrintQueue.Pause();
foreach (var job in myPrintQueue.GetPrintJobInfoCollection())
{
job.Pause();
}
MessageBox.Show("WAIT!");
frmPromptPIN frm = new frmPromptPIN(printer);
frm.Show();
}
If i removed the MessageBox.Show("WAIT!"), the form won't show up at all.
Anyone experiencing this one?

As TnTinMn says you have to invoke your UI code in the UI thread, eg.
private void EventWritten(Object obj, EventRecordWrittenEventArgs arg)
{
PrintQueue myPrintQueue = new PrintQueue(ps, printer, PrintSystemDesiredAccess.AdministratePrinter);
myPrintQueue.Pause();
foreach (var job in myPrintQueue.GetPrintJobInfoCollection())
{
job.Pause();
}
Invoke((MethodInvoker) delegate {
frmPromptPIN frm = new frmPromptPIN(printer);
frm.Show();
});
}

Related

FinishLoadingFrameEvent event is called once when loading multiple urls

I have a list of urls in a for loop, loading a url one at a time but FinishLoadingFrameEvent event is called only once.
My complete code is like this
private List<string> urls = //fetch from db;
ManualResetEvent waitEvent = new ManualResetEvent(false);
BrowserView webView = new WPFBrowserView();
string path = //my local path;
public MainWindow()
{
InitializeComponent();
mainLayout.Children.Add((UIElement)webView.GetComponent());
webView.Browser.FinishLoadingFrameEvent += delegate (object sender, FinishLoadingEventArgs e)
{
System.Threading.Thread.Sleep(5000);
if (e.IsMainFrame)
{
DOMDocument document = e.Browser.GetDocument();
var html = document.DocumentElement.InnerHTML;
System.IO.File.WriteAllText(path, html);
waitEvent.Set();
}
};
foreach (var url in urls)
{
webView.Browser.LoadURL(url);
waitEvent.WaitOne();
waitEvent.Reset();
}
}
Am i missing something?
Your code seems to work as expected for my set of URLs.
Here is the complete sample code with all the modifications:
public partial class MainWindow : Window
{
private List<string> urls = new List<string>
{ "google.com", "microsoft.com", "teamdev.com", "teamdev.com/dotnetbrowser" };
ManualResetEvent waitEvent = new ManualResetEvent(false);
BrowserView webView = new WPFBrowserView();
string path = "html.txt";
public MainWindow()
{
InitializeComponent();
mainLayout.Children.Add((UIElement)webView.GetComponent());
webView.Browser.FinishLoadingFrameEvent += delegate (object sender,
FinishLoadingEventArgs e)
{
//System.Threading.Thread.Sleep(5000);
if (e.IsMainFrame)
{
DOMDocument document = e.Browser.GetDocument();
var html = document.DocumentElement.InnerHTML;
System.IO.File.WriteAllText(path, html);
waitEvent.Set();
}
};
foreach (var url in urls)
{
Debug.WriteLine($"Loading {url}");
webView.Browser.LoadURL(url);
waitEvent.WaitOne();
Debug.WriteLine($"{url} loaded");
waitEvent.Reset();
}
}
}
You can notice that I have commented out the Thread.Sleep call in the event handler. Uncommenting it simply makes everything run much slower, but it still works.

systemevents.sessionended is not being caught or fired

Please in my code i try to catch win32.systemevents.sessionended event to procede with saving of my app data by the end of session in case the app is not closed manually .. some time ago this has been workin and now that i had my project grown a lil it is not any more..? i have tried to find something meaningfull for few days but found nothing really.. when i try to catch another systemevent like MonitorResolutionChanged it works well but this one not. I have also tried to register within the mainWindow (app form ..), nothing :-( Please any idea?
I think all the relevant information should be in the beginning till void Main but i put it all in case you would need or want to see more .. Thanx a lot Tomas
My code:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Threading;
using MovablePython; // my own class within this project
using Avn; //my own referenced assembly
namespace DirDist
{
class Program
{
private static string appGuid = "Cddbserviceman";
private static System.Windows.Forms.ContextMenu nIMenu;
internal static System.Windows.Forms.NotifyIcon notifyIcon1;
private static MenuItem showItem;
public static MenuItem justCDsItem;
private static MenuItem searchItem;
private static MenuItem settingsItem;
private static MenuItem quitItem;
internal static Form1 mainWindow;
private static Hotkey hk;
internal static Registration.LicenceState mode; // app mode - registered/trial/blocked/demaged ..
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
using (Mutex mutex = new Mutex(false, appGuid))
{
if (!mutex.WaitOne(0, false))
{
MessageBox.Show("CDDB is already running on your machine \n (Check status bar for access ..)");
return;
}
GC.Collect();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
mode = Registration.Startup();
Program.mainWindow = new Form1();
mainWindow.Activate();
//mainWindow.Validate();
//mainWindow.Update();
mainWindow.Visible = false;
PutIcon();
//Microsoft.Win32.SystemEvents.SessionEnded += SystemEvents_SessionEnded;
Microsoft.Win32.SystemEvents.SessionEnded += new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);//**zkousime zda funguje pro hibernaci ..
RegisterHotKey(true);
Application.Run();
}
}
static void SystemEvents_SessionEnded(object sender, Microsoft.Win32.SessionEndedEventArgs e)
{
//MessageBox.Show("SessionEnded fired");
RegisterHotKey(false);
notifyIcon1.Visible = false;
notifyIcon1.Dispose();
notifyIcon1 = null;
if (!mainWindow.dBSaved) mainWindow.SaveDb(Form1.settings.dBPath);
if (mainWindow.index != null) mainWindow.SaveIndex(Form1.settings.indexPath);
Microsoft.Win32.SystemEvents.SessionEnded -= new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
mainWindow.Close();
}
// zaregistruje globalni hotkey ctrl+shift+F Pro hledani
private static void RegisterHotKey(bool active)
{
if (!active)
{
if (hk != null) hk.Unregister();
}
else
{
if(hk ==null) hk = new Hotkey();
hk.KeyCode = Keys.F;
//hk.Windows = true;
hk.Shift = true;
hk.Control = true;
//hk.Pressed += delegate { Console.WriteLine("Windows+1 pressed!"); };
hk.Pressed += delegate { searchItemClick(new object(), new EventArgs()); };
if (hk.GetCanRegister(mainWindow)) hk.Register(mainWindow);
else ; // just do nothing
}
}
private static void PutIcon()
{
if (notifyIcon1 == null)
{
showItem = new MenuItem ("&Show interface", new System.EventHandler (showInfaceClick));
justCDsItem = new MenuItem ("&Jus'CDs",new System.EventHandler ( justCDsClick));
justCDsItem.Checked = Form1.settings.justCDs;
searchItem = new MenuItem("Search CDDB",new System.EventHandler (searchItemClick));
searchItem.Shortcut = Shortcut.CtrlShiftF;
searchItem.ShowShortcut = true;
settingsItem = new MenuItem("Settings", new System.EventHandler(settingsItemClick));
quitItem = new MenuItem("&Quit", new System.EventHandler(quitItemClick));
nIMenu = new System.Windows.Forms.ContextMenu(new MenuItem[5] { showItem, justCDsItem, searchItem,settingsItem, quitItem });
notifyIcon1 = new System.Windows.Forms.NotifyIcon();
notifyIcon1.ContextMenu = nIMenu;
notifyIcon1.Icon = new System.Drawing.Icon(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\Icon1.ico");
//notifyIcon1.Icon = new System.Drawing.Icon(System.IO.Path.GetDirectoryName(
//System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase ) + "Icon1.ico");
//notifyIcon1.Icon = new System.Drawing.Icon("Icon1.ico");
notifyIcon1.DoubleClick += new EventHandler(notifyIcon1_DoubleClick);
notifyIcon1.Visible = true;
}
}
/* private static void notifyIcon1_MouseMove(object sender, MouseEventArgs mea)
* aby to fungovalo je treba upravit contextmenu na contextmenustrip a taky ty items .. az nakonec
* je tu kolem uz rozdelana priprava ..
{
notifyIcon1.ShowBalloonTip(2000,AppName,"Active",ToolTipIcon.None);
} */
// clicks on NotificationIcon context menu ..
private static void showInfaceClick(object sender, EventArgs e)
{
mainWindow.tabControl1.SelectedIndex = 0;
mainWindow.Show();
}
private static void justCDsClick(object sender, EventArgs e)
{
Form1.settings.justCDs = mainWindow.checkBox1.Checked = justCDsItem.Checked = !Form1.settings.justCDs;
if (mainWindow.Visible) mainWindow.Update();
}
private static void searchItemClick(object sender, EventArgs e)
{
mainWindow.tabControl1.SelectedIndex = 1 ;
//this.Size = new Size(this.Width, SystemInformation.PrimaryMonitorSize.Height);
mainWindow.Location = new System.Drawing.Point(SystemInformation.PrimaryMonitorSize.Width - mainWindow.Width, SystemInformation.PrimaryMonitorSize.Height - mainWindow.Height);
//mainWindow.Location = new System.Drawing.Point(880, 500);
mainWindow.Show();
}
private static void settingsItemClick(object sender, EventArgs e)
{
mainWindow.tabPage3_GotFocus(new Object(), new EventArgs());
mainWindow.tabControl1.SelectedIndex = 2;
mainWindow.Show();
}
public static void quitItemClick(object sender, EventArgs e)
{
if (DialogResult.Cancel == MessageBox.Show("Really exit application and stop scanning?",Form1.AppName,MessageBoxButtons.OKCancel,MessageBoxIcon.Question)) return;
if (!mainWindow.dBSaved) mainWindow.SaveDb(Form1.settings.dBPath);
//if (mainWindow.index != null) mainWindow.SaveIndex(Form1.settings.indexPath);
if (Form1.settings.fileIndex) mainWindow.SaveIndex(Form1.settings.indexPath);
mainWindow.Close();
mainWindow = null;
notifyIcon1.Visible = false;
Application.Exit();
}
static void notifyIcon1_DoubleClick(object sender, EventArgs e)
{
//throw new NotImplementedException();
//if (!mainWindow.Visible) mainWindow.WindowState = FormWindowState.Normal; else mainWindow.WindowState = FormWindowState.Minimized;
//if (!mainWindow.Visible) mainWindow.Show(); else mainWindow.Hide();
if (!mainWindow.Visible) mainWindow.Visible = true; else mainWindow.Visible = false;
}
}
}
OK. So here is the catch and solution . In Windows it is not determined whether win32.systemevents.sessionended shall be risen or form.close() will be called first by operating system. moreover it seems that if form.close() is called first then sessionended is omited even though form is not closed and disposed due to canceling closing process. in my system this behaviour changed after i ran some registry cleaning software. anyway understanding this we have to take care of both possible scenarios.
1. catch win32.systemevents.sessionended (or sessionending) event whatever suits our needs better and be
.
.
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Microsoft.Win32.SystemEvents.SessionEnded += new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
Program.mainWindow = new Form1();
mainWindow.Activate();
mainWindow.Visible = false;
PutIcon();
RegisterHotKey(true);
Application.Run();
}
}
public static void SystemEvents_SessionEnded(object sender, Microsoft.Win32.SessionEndedEventArgs e)
{
// do whatever needed and exit application ..
RegisterHotKey(false);
notifyIcon1.Visible = false;
notifyIcon1.Dispose();
notifyIcon1 = null;
if (!mainWindow.dBSaved) mainWindow.SaveDb(Form1.settings.dBPath);
if (mainWindow.index != null) mainWindow.SaveIndex(Form1.settings.indexPath);
Microsoft.Win32.SystemEvents.SessionEnded -= new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
if (mainWindow != null)
{
mainWindow.Dispose();
mainWindow = null;
}
Application.Exit();
}
2. properly override form.OnClosing() because this is being called when form is closing either manually by user or by system when shuting down, loging off etc. or create hanler for main form.Closing:
public Form1()
{
this.Closing += new CancelEventHandler(this.Form1_Closing);
InitializeComponent();
}
private void Form1_Closing(Object sender, CancelEventArgs e)
{
if (systemShutdown) Program.SystemEvents_SessionEnded(this, new Microsoft.Win32.SessionEndedEventArgs(Microsoft.Win32.SessionEndReasons.SystemShutdown));
else
{
e.Cancel = true;
this.Hide();
}
}
just want to mention that message pump must be runnig in order to sessionended be risen. Application.run() accomplishes that.
in my case as you can see i had to dig even deeper as i had closing redirected just to hide the app not to close it ( i just hide the app to notification irea icon and close it manually when i need .. ) and so i had to use some kind of way to specify the situation when this is called because sender is unfortunatelly and unexpectedly always this ..?
this is done by overring WndProc and catching propper message .here you can listen pretty much to everything inside windows ( like disc inserted / removed )but it is hooked only to a form and implementation gets often not so simple as you have to manully define various values and structs and compare against those values .. other then that its pretty simple:
private static int WM_QUERYENDSESSION = 0x11;
private static bool systemShutdown = false;
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg==WM_QUERYENDSESSION)
{
systemShutdown = true;
}
base.WndProc(ref m);
}
this was found here:
http://msdn.microsoft.com/en-us/library/microsoft.win32.systemevents.sessionending.aspx
Thinking a bit further we can possibly omit point 1 as system shall probably always try to call mainForm.close() but i keep it as i can not be certain about windows behaviour once it runs those things in different order again .. and also it is the mainly suggested solution for reacting to system shut down ..
hope this is helpfull for someone. greets from prague tomas
Here is something that you could try
For a shutdown, override the OnShutdown method:
protected override void OnShutdown()
{
//your code here
base.OnShutdown();
}
For a logoff:
First, add an event handler to Microsoft.Win32.SystemEvents.SessionEnded in the Service Constructor:
public MyService()
{
InitializeComponent;
Microsoft.Win32.SystemEvents.SessionEnded += new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
}
Then add the handler:
void SystemEvents_SessionEnded(object sender, Microsoft.Win32.SessionEndedEventArgs e)
{
//your code here
}
This should catch any ended session, including the console itself (the one running the services).

cross-thread calls?

This is mt first time trying to write a not web based program, and my first time writing anything in C#.
I need a program that monitors folders, but I can't get it to work.
I have used the example from this post Using FileSystemWatcher with multiple files but is trying to make it a form.
My current problem comes in the ProcessQueue function where fileList apparently is defined in another thread.
Whenever a file is actually submitted to the watched folder I get an error that using fileList is a cross thread call
Can anyone explain this error to me, and how to fix it?
namespace matasWatch
{
public partial class Form1 : Form
{
private int n = 1;
private bool isWatching = false;
private List<string> filePaths;
private System.Timers.Timer processTimer;
private string watchedPath;
private FileSystemWatcher watcher;
public Form1()
{
filePaths = new List<string>();
watchedPath = "C:\\Users\\username\\Desktop\\test";
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (!isWatching)
{
button1.Text = "Stop";
isWatching = true;
watcher = new FileSystemWatcher();
watcher.Filter = "*.*";
watcher.Created += Watcher_FileCreated;
watcher.Error += Watcher_Error;
watcher.Path = watchedPath;
watcher.IncludeSubdirectories = true;
watcher.EnableRaisingEvents = true;
}
else {
button1.Text = "Watch";
isWatching = false;
watcher.EnableRaisingEvents = false;
watcher.Dispose();
watcher = null;
}
}
private void Watcher_Error(object sender, ErrorEventArgs e)
{
// Watcher crashed. Re-init.
isWatching = false;
button1_Click(sender, e);
}
private void Watcher_FileCreated(object sender, FileSystemEventArgs e)
{
filePaths.Add(e.FullPath);
if (processTimer == null)
{
// First file, start timer.
processTimer = new System.Timers.Timer(2000);
processTimer.Elapsed += ProcessQueue;
processTimer.Start();
}
else{
// Subsequent file, reset timer.
processTimer.Stop();
processTimer.Start();
}
}
private void ProcessQueue(object sender, ElapsedEventArgs args)
{
try
{
fileList.BeginUpdate();
foreach (string filePath in filePaths)
{
fileList.Items.Add("Blaa");
}
fileList.EndUpdate();
filePaths.Clear();
}
finally
{
if (processTimer != null)
{
processTimer.Stop();
processTimer.Dispose();
processTimer = null;
}
}
}
}
}
I assume that fileList is a windows forms control. The ProcessQueue method is called from a timer thread which is by default a background thread. The fileList control resides in the UI thread. You need to use the Invoke() method of the form passing it in a delegate the updates the fileList control.
Invoke(new Action(() =>
{
fileList.BeginUpdate();
foreach (string filePath in filePaths)
{
fileList.Items.Add("Blaa");
}
fileList.EndUpdate();
filePaths.Clear();
}));
Try using System.Windows.Forms.Timer instead of System.Timers.Timer so the timer tick event is executed on the UI thread.
See here for more details.

BackgroundWorker ShowDialog causes app to stop

I have been trying to implement a BackgroundWorker into my application, and so far, it has not gone well. On a new thread, I want to open up a new Form that will have a progressbar and a label to report progress, however, this is not working well. When I call ShowDialog, the application does not respond any more. Is this because my code is running from my Form1, and I am showing WorkingForm? Also, can this be implemented cleaner?
private void button14_Click(object sender, EventArgs e)
{
List<object> param = new List<object>();
object[] objectparams = new object[1];
objectparams[0] = null;
Opera opera = new Opera();
System.Reflection.MethodInfo clearOpera = opera.GetType().GetMethod("ClearOpera");
param.Add(clearOpera);
param.Add(opera);
param.Add(objectparams);
backgroundWorker1.RunWorkerAsync(param);
}
private void button2_Click_1(object sender, EventArgs e)
{
Browser.cancelPending = true;
}
private delegate void getnewform();
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
mainForm main = new mainForm();
TestURLGUI4.Form1 form = (TestURLGUI4.Form1)Application.OpenForms[0];
var variab = (bool)form.Invoke(new getnewform(main.AskForConfirmation));
List<object> param = e.Argument as List<object>;
List<object> result = new List<object>();
var method = param[0] as MethodInfo;
object[] parameters = param[2] as object[];
if (parameters[0] == null)
{
result.Add(method.Invoke(param[1], null));
result.Add(false);
}
else
{
result.Add(method.Invoke(param[1], parameters));
if (parameters.Contains(true))
result.Add(true);
}
int progress = (100 * Browser.progressValue) / Browser.progressMax;
backgroundWorker1.ReportProgress(progress);
// If the BackgroundWorker.CancellationPending property is true, cancel
if (backgroundWorker1.CancellationPending)
{
Console.WriteLine("Cancelled");
Browser.cancelPending = true;
}
e.Result = result;
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
TestURLGUI4.WorkingForm form = (TestURLGUI4.WorkingForm)Application.OpenForms[1];
form.progressBar1.Value = e.ProgressPercentage;
form.label1.Text = Browser.progressValue + "/" + Browser.progressMax;
Application.DoEvents();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
List<object> param = e.Result as List<object>;
if (e.Cancelled == false && param.Contains(true))
{
Display.DisplayURLs(param[0] as SortableBindingList<URL>);
TestURLGUI4.WorkingForm form = (TestURLGUI4.WorkingForm)Application.OpenForms[1];
MessageBox.Show("Done");
}
else if (e.Cancelled == false && param.Contains(false))
{
TestURLGUI4.WorkingForm form = (TestURLGUI4.WorkingForm)Application.OpenForms[1];
MessageBox.Show("Done");
}
}
public class mainForm
{
public void AskForConfirmation()
{
TestURLGUI4.Form1 form = (TestURLGUI4.Form1)Application.OpenForms[0];
var workingForm = new TestURLGUI4.WorkingForm();
workingForm.ShowDialog(form);
workingForm.DialogResult = DialogResult.None;
}
}
Edit:
Ok, I have updated my code according to the suggestions, and now, this produces a stackoverflowexception in System.Windows.Forms.dll:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
mainForm main = new mainForm();
TestURLGUI4.Form1 form = (TestURLGUI4.Form1)Application.OpenForms[0];
List<object> param = e.Argument as List<object>;
List<object> result = new List<object>();
var method = param[0] as MethodInfo;
object[] parameters = param[2] as object[];
if (parameters[0] == null)
{
result.Add(method.Invoke(param[1], null));
result.Add(false);
}
else
{
result.Add(method.Invoke(param[1], parameters));
if (parameters.Contains(true))
result.Add(true);
}
int progress = (100 * Browser.progressValue) / Browser.progressMax;
backgroundWorker1.ReportProgress(progress);
// If the BackgroundWorker.CancellationPending property is true, cancel
if (backgroundWorker1.CancellationPending)
{
Console.WriteLine("Cancelled");
Browser.cancelPending = true;
}
e.Result = result;
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
TestURLGUI4.Form1 form1 = (TestURLGUI4.Form1)Application.OpenForms[0];
if (Application.OpenForms.Count >= 2)
{
TestURLGUI4.WorkingForm form2 = (TestURLGUI4.WorkingForm)Application.OpenForms[1];
form2.progressBar1.Value = e.ProgressPercentage;
form2.label1.Text = Browser.progressValue + "/" + Browser.progressMax;
Application.DoEvents();
}
else if(Application.OpenForms.Count == 1)
{
var workingForm = new TestURLGUI4.WorkingForm();
workingForm.ShowDialog(form1);
}
}
The purpose of a BackgroundWorker is to invoke code on another thread (not the UI thread). By calling Invoke in the DoWork method, you're completely circumventing the purpose of BackgroundWorker. Do all your UI work before you start the worker. If you need to interact with the user while the worker is working, do it in the ProgressChanged handler--it runs on the UI thread and you don't need to use Invoke in ProgressChanged.
By invoking UI work in DoWork, you run the risk of a deadlock, which will hang your program
you cant run UI on other threads. Has to be on the main thread.
Instantiate the UI before you start the new thread. In the new thread use cross thread invoke methods on the controls you want to work with. Look here for example http://msdn.microsoft.com/en-us/library/ms171728.aspx

c# EventArrivedEventHandler stuck in infinite loop, can't reference watcher

I've googled this problem for the past week, it's killing my peace! Please help... EventArrivedEventHandler is stuck in a loop, and if I stop it, then it won't catch events. But when I use a handler method, the thread is still concentrating on the loop, and won't give attention to the new form I'm trying to make in the handler! Strange thing is, if I just use something small, like a MessageBox, it doesn't cause an issue, just trying to instantiate a form causes the buttons to NOT draw. Then shortly after the program stops responding. In case you're wondering where the form code is, it's just a standard form made by .NET, that works everywhere else in the code except for in the event handler.
Thanks!
class MainClass
{
public static void Main()
{
TaskIcon taskbarIcon;
EventWatch myWatcher;
taskbarIcon = new TaskIcon();
taskbarIcon.Show();
myWatcher = new EventWatch();
myWatcher.Start();
Application.Run();
}
}
public class TaskIcon
{
public void Show()
{
NotifyIcon notifyIcon1 = new NotifyIcon();
ContextMenu contextMenu1 = new ContextMenu();
MenuItem menuItem1 = new MenuItem();
MenuItem menuItem2 = new MenuItem();
contextMenu1.MenuItems.AddRange(new MenuItem[] { menuItem1, menuItem2 });
menuItem1.Index = 0;
menuItem1.Text = "Settings";
menuItem1.Click += new EventHandler(notifyIconClickSettings);
menuItem2.Index = 1;
menuItem2.Text = "Exit";
menuItem2.Click += new EventHandler(notifyIconClickExit);
notifyIcon1.Icon = new Icon("app.ico");
notifyIcon1.Text = "Print Andy";
notifyIcon1.ContextMenu = contextMenu1;
notifyIcon1.Visible = true;
}
private static void notifyIconClickSettings(object Sender, EventArgs e)
{
MessageBox.Show("Settings Here");
}
private static void notifyIconClickExit(object Sender, EventArgs e)
{
//taskbarIcon.Visible = false; // BONUS QUESTION: Why can't I hide the tray icon before exiting?
Application.Exit();
}
}
public class EventWatch
{
public void Start()
{
string thisUser = WindowsIdentity.GetCurrent().Name.Split('\\')[1];
WqlEventQuery query = new WqlEventQuery();
query.EventClassName = "__InstanceCreationEvent";
query.Condition = #"TargetInstance ISA 'Win32_PrintJob'";
query.WithinInterval = new TimeSpan(0, 0, 0, 0, 1);
ManagementScope scope = new ManagementScope("root\\CIMV2");
scope.Options.EnablePrivileges = true;
ManagementEventWatcher watcher = new ManagementEventWatcher(scope, query);
watcher.EventArrived += new EventArrivedEventHandler(showPrintingForm);
watcher.Start();
}
void showPrintingForm(object sender, EventArrivedEventArgs e)
{
// MessageBox.Show("This will draw just fine");
Form1 myForm;
myForm = new Form1();
myForm.Show(); // This causes a hangup
}
}
My guess would be that the ManagementEventWatcher calls the EventArrived handler from a different thread than the UI thread. Then your showPrintingForm is executed on that thread and accessing UI from a different thread than the UI thread is bad. You need to marshal your code back onto the UI thread.

Categories