How to dispose IE when form is closed? - c#

I've been looking for an answer to this problem, but couldn't find it anywhere.
I have written an app that utilizes Watin. It works fine, apart from the problem that if I click the "X" button to close the app BEFORE Watin completes all of the actions (before it's disposed, I guess), it doesn't close. My app is still running (although the form is no longer there), as well as all of the IE instances.
I guess I should use FormClosing event handler to kill Watin, but since I'm utilizing the using statement, I've no idea how to achieve that.
Here's a piece of code I'm using:
using (var newBrowser = new IE("http://address.com"))
{
AnalyzeTools FormActions = new AnalyzeTools(progressBar, labelProgress, labelProgressOutOf, richBoxKeywords.Lines.Count());
Analyzer Analytic = new Analyzer(newBrowser, richBoxKeywords.Lines.ToList<string>(), FormActions);
BeingAnalyzed = Analytic;
Analytic.Initialize(textBoxLogin.Text, textBoxPass.Text);
Analytic.HandleAnalysis();
}
EDIT:
OK, I did some more trouble-shooting and this is what I've come up with:
The app is working until all it's finished, simple as that. But it doesn't finish "properly", though -- it crashes, because it can't access the form which no longer exists.
I believe I could fix this by creating a FormClosing or FormClosed event that when triggered, would modify the behaviour of my app. A custom "exit" method. But still, I won't be terminating Watin (something I want to do) and the app would be still running.
The thing is, I don't really need it to accomplish all of the actions it's supposed to.
Is my idea of termination a good one? And is there a way to terminate Watin without dropping the using-statement idea?
EDIT 2:
OK, I tried a few new things.
I created that messagebox which asks for a decision. I tried using Application.Exit() to terminate, but it doesn't work as I hoped it would. The app's vshost is still running (WatiN?).
So I guess my question comes to this: is the only way to terminate WatiN to drop the using statement, make the IE object available everywhere in the class and dispose it when the user chooses to terminate it?

I think what you need to do is create an instance of IE and then just close that instance. When you need it again you can just recreate the instance. I found this on Stackoverflow a long time ago when I had a similiar problem but I couldn't find it again to link to it.
public sealed class BrowserIE
{
static readonly IE _Instance = new IE();
static BrowserIE()
{}
BrowserIE()
{ }
public static IE Instance
{
get { return _Instance; }
}
}
create a class with the code above. use
var browser = BrowserIE.Instance("myUrl");
and when your done with it use:
browser.Close();
hope this helps. If you have any other questions I'll try to help.

Which version of WatIn are you using
Watin has a specific dispose method for this job
browser.Dispose();

Related

Why the Process Exited event raise automatic all the time?

In the top of Form1 i did:
private Process zipFileDirectoryProcess;
In the constructor i did:
zipFileDirectoryProcess = new Process();
zipFileDirectoryProcess.StartInfo.FileName = "explorer.exe";
zipFileDirectoryProcess.StartInfo.CreateNoWindow = true;
zipFileDirectoryProcess.EnableRaisingEvents = true;
zipFileDirectoryProcess.Exited += new EventHandler(zipFileDirectoryProcess_Exited);
Then i have a method i call it from a button click event:
private void Compress()
{
zipFileDirectoryProcess.StartInfo.Arguments = zipFileDirectoryProcess.StartInfo.Arguments = "/select," + Path.GetFullPath(t);
zipFileDirectoryProcess.Start();
zipFileDirectoryProcess.WaitForExit();
this.TopMost = true;
}
And then in the bottom the Exited event:
private void zipFileDirectoryProcess_Exited(object sender, EventArgs e)
{
this.BeginInvoke(new MethodInvoker(delegate()
{
this.TopMost = false;
}));
}
What i wanted to do is only when i close the process window after started it in the method only if closed the window/process then do the Exited event.
The problem is that once the process started after 2-3 seconds its jumping automatic to the Exited event.
How can i fix it ? Tried examples cant figure out.
Tried to add this line:
zipFileDirectoryProcess.WaitForExit();
But no effect.
zipFileDirectoryProcess.StartInfo.FileName = "explorer.exe";
Trying to start Windows Explorer again when it is already running, and it is always running, will have a disappointing outcome. It is a "heavy" process and it intentionally tries the minimize the number of running copies. Otherwise known as a "single-instance app". There are lots like that, the Microsoft Office programs are single instance apps for example.
So what really happens is that explorer.exe actually starts up, but sees that another instance is already running. And uses process interop to ask that first instance to do the job that you asked it to do. Since you didn't ask it to do anything, you just get another window, displayed by the first instance. The one that you started immediately quits, it doesn't have anything else to do.
So, yes, you'll see that the Exited event fires without you doing anything. Accurately telling you that the explorer.exe process you started did in fact quit. Easy to see in the Taskmgr.exe Processes tab btw. Waiting for that window to be closed is never going to work, it is displayed by the original instance of explorer.exe.
This will just not work the way you hope it will work. What you are actually trying to do is not quite obvious but can be guessed at. Creating a ZIP archive is not difficult, there are excellent libraries available for C# to get the job done, no point in asking another program to do it for you. DotNetZip and SharpZipLib are very popular. It got finally added to .NET as well in version 4.5, Microsoft finally getting over the lost Stacker lawsuit, about time. If you really, really want another program to do it for you then use a console mode zipper like 7-zip.
To show output folder in windows explorer to the user, it's simply enough to do this:
Process.Start("explorer.exe", OutputDir);

How do I stop running code from executing?

I'm playing a little bit with some C# Winforms/WPF code and just stumbled upon something strange.
Let's say I have a code like this:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DoSomething();
// something more if everything worked okay
}
}
What puzzles me is that I cannot simply close the application from the method DoSomething before the constructor finishes its job. If anything during the execution of DoSomething fails, I need to close the application immediately; however, it just keeps running, executes the part // something more... and THEN closes, but that's way too late for me.
I have to put the code for closing the form inside the constructor itself with a following return; and then it works, but I don't really find that an acceptable solution. I'm trying to move such validation logic from the constructor to my methods.
I've tried things like:
public void DoSomething()
{
Close();
}
and
public void DoSomething()
{
Application.Current.Shutdown();
}
But it doesn't seem to work. Yes, both codes do close the application, but only after a fully finished constructor code.
Why would I need such a thing? Well, because at startup I need to check for various things, like availability of the connection and hardware, validate the user etc, and if anything fails, there's no point of executing more code.
I tried the same principle with Winforms and WPF (hence the tags) — works the same way.
Can anybody provide an explanation or a solution?
Just try using Environment.Exit(-1) in your situation and all will be good.
ADDED: This is the best reference i can get for you.
Difference between Application.Exit vs Application.Shutdown vs Environment.Exit
Application.Exit() is for exiting a windows forms application in a graceful way. Basically, it stops the message pump, closes all windows and lands you back in the Main() method just after the call to Application.Run(). However, sometimes it doesn't appear to work - this is usually because there are other foreground threads (apart from the UI thread) still running which are preventing the thread from ending.
Application.Shutdown() is (broadly) the equivalent of Application.Exit() in a WPF application. However, you have a bit more control as you can set the ShutDownMode so that the application shuts down when the main window closes, the last window closes or only when this method is called.
Environment.Exit() kills all running threads and the process itself stone dead. This should only be used in WF or WPF as a last resort when the more graceful methods are not working for some reason. It can also be used to make an abrupt exit from a console application.
Another Reference: How to properly exit a C# application?
You can always ignore your fellow developers and just use Environment.FailFast()
But really - don't. If you have critical things to do, S.A verifying the serial port is connected to the nuclear power plant, just do it prior. There's no rule forcing you to Application.Run(...) as soon as Main() is called.
There have already been posted viable solutions for your problem.
Just to answer your follow-up question: the reason why methods like Close() and Shutdown() do not immediately exit your application is that both just push messages into the application's message queue. They are only processed after MainWindow's constructor finished and code execution returns to the message processing loop, maybe even after some other still pending messages in the queue have been handled too.
On the contrary, methods like Environment.Exit() or Environment.FailFast() are kind of hard-core os functions leading to more or less immediately killing the process.
A workaround would be to throw a exception and handle it in application.UnhandledException
Define an Exception class:
public class InitializationException : Exception
{
public InitializationException()
{}
public InitializationException(string msg)
: base(msg)
{}
public InitializationException(string msg, Exception inner)
: base(msg, inner)
{}
}
and change your code like this:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
try
{
DoSomething();
// maybe something more if everything went ok
}
catch( InitializationException ex )
{
// log the exception
Close();
}
}
public void DoSomething()
{
if (notSomethingOK)
throw new InitializationException( "Something is not OK and the applicaiton must shutdown." );
}
}
This is a clean and maintainable solution.
System.Windows.Forms.Application.Exit();
Conceptually such things should not be used in class constructors. Constructor is somewhat made for instance initialization with starting state and not the actual things may happen (like exceptions, message boxes, etc).
Don't forget that you can just return; from constructor, if you need to break its execution. This is better tactic (most times you don't need to just shutdown application on error without displaying some text).
There are "window shown", "visibility changed", "loaded" and many other events in C# on Windows/WPF, that you can override virtually or add as an event handler. Initialize your form/app there.
They're normal methods so all works as expected. You can try throwing exceptions that your application entry point (Main function) will just catch and ignore.
For WPF, check this:
- https://msdn.microsoft.com/en-us/library/system.windows.forms.application.setunhandledexceptionmode(v=vs.110).aspx.

Using WUAPI to quietly install updates in C#

I'm trying to create a program that will handle updates silently. I am using the wuapilib.dll, which comes with a number of classes (c#). My first revision of the program was as follows (ignore typo problems - its on another computer without internet access so i'm typing it by hand):
IUpdateSession mySess = new UpdateSession();
IUpdateSearcher mySear = mySess.CreateUpdateSearcher();
ISearchResult myRes = mySear.Search("Type='Software'");
IUpdateDownloader myDown = mySess.CreateUpdateDownloader();
IUpdateInstaller myInst = mySess.CreateUpdateInstaller();
myDown.Updates = myRes.Updates;
myDown.Download();
myInst.Updates = myRes.Updates;
myInst.Install();
Ignore the case where an update is already downloaded or installed, I'm omitting the logic above. My problem is that IUpdateInstaller doesn't allow you to force a quiet install - a number of updates require that a user click a confirmation box. The IUpdateInstaller2 class does (I got that from the second post down here), but for the life of me I can't find a way to get an IUpdateInstaller2 object. Nothing seems to return one, and Microsoft's documentation doesn't contain any example code. Extensive googling returned nothing of use.
I think I'm really close - the functionality is there, I just can't quite access it.
Thanks for your help.
I checked that (or rather, I think i did - wasn't too clear on getting it to work), and it looks like the CreateUpdateInstaller only returns an IUpdateInstaller, nothing else.
However, I found code (on a chinese website, interestingly enough) that just directly cast the IUpdateInstaller to an IUpdateInstalelr2, which has solved my problems.
Thanks for the help
I have posted in another Question my app to, search, download and then install Windows updates.
See: C# and WUAPI: BeginDownload function
you can easily change the:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.SetCompatibleTextRenderingDefault(false);
Application.EnableVisualStyles();
Thread thread = new Thread(() =>
{
Form1 form1 = new Form1();
form1.Visible = false;
form1.ShowInTaskbar = false;
Application.Run(form1);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
}
then handle
Application.Close();
after the events have done their thing. For example, if no Updates have been found, then close the app. I use the async properties of the interfaces so it can do what it needs to async.
Hope this helps.
I also searched a long time for it.
You just need to cast it
IUpdateInstaller2 installer = new UpdateInstaller();
According to Microsoft documentation there are also version 3 and 4 available. But this must be an error. The functions of version 3 are available also in IUpdateInstaller2 and the functions from version 4 I never found somewhere.

How to run form and console at the same time with c#?

Hey I am fairly new to the c# programming language and have enjoyed my experience so far. I normally develop applications in java but a need for the win32 library has lead me to c# so far the languages seem relatively similar. however a problem I am having at the moment is a simple piece of code that can be best explained in this example
I am trying to print a piece of string to console then display the windows form then print another piece of string to console. however the result i get is first string is printed then the form is displayed, i then have to close the form before the last string is printed. the question i would like to ask is is there anyway to get this working so the second print to console is displayed immediately after the form is displayed. im guessing it has something to do with threading but I am not entirely sure how to implement this
The solution is quite simple:
Just create a Windows Forms Application (when creating the project - which you probably did) and then go to Properties (in context menu "Project", it's the last item) and set "Output type" to "Console Application". The forms will work as before and furthermore the application will now open the console too. You can then freely write to or read from the console.
static class Program
{
[STAThread]
static void Main()
{
Console.WriteLine("first string");
var form = new Form1();
form.Show();
Console.WriteLine("the second string");
Application.Run();
}
}
It sounds like you want to be able to output messages to the console while the form is being displayed, correct? The basic issue is that as long as the form is visible, there must be a message loop running, handling events for the form. The message loop is inside Application.Run, so once you call it, it won't return until the form is closed (as you discovered).
So if you want to write to the console while the form is visible, you have a couple of options. One, as you mentioned, is to use multiple threads. Let your main thread run the message loop, and start up a second thread to write to the console. But that's not necessary--you can also write to the console from within an event handler, directly or indirectly. There's nothing wrong with doing a Console.WriteLine from within a button click handler. Or you can have your button handler call a method in your Program class, and do the writing there.
As for which solution is better, it would help to know more about what you're trying to accomplish. I assume that you don't just want to write stuff to the console--what else is it that you want to do while the form is being displayed?
My suggestion would be to start with a Console application. You can always open a WinForm from a console application...which would give you exactly what you're looking for. (you might want to think about multi-threading as well.
Hey everyone thanks for your answers I made some progress with what im trying to achieve but im not sure how correct or thread safe it is here is the code i got to run
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace Project1
{
class Class2
{
[STAThread]
static void Main()
{
Console.WriteLine("hello");
Class2 t = new Class2();
t.test();
Console.WriteLine("second string");
}
public void test()
{
Thread t = new Thread(new ThreadStart(StartNewStaThrea));
t.Start();
}
private void StartNewStaThrea()
{
Application.Run(new Form1());
}
}
}
pls let me know what you think of this solution
I know this is a super-old question, but I'm going to answer in hopes of karma. One interesting work-around that works well for this comes up if you're using Visual Studio (which is a fairly safe assumption). If you start a forms project in C# in Visual Studio, then make your appropriate forms, but then change the project type to a console application (by right clicking the project-->properties-->Console Application), it will still spawn your forms, but will also keep a Console open, now all you need to do is put one Console.Write statement before your form is created, and the other after, and maybe add a flush statement!
are you using form.showDialog() or form.show()?
form.showDialog() will block until the form is closed, while form.show() will not.
I would either start with a console app, and run the application from the static main function. This is from memory - I haven't had to mess with Winforms for years:
[STAThread]
static void Main()
{
Application.Run(new YourMainForm());
}
or
I would redirect Console.Out and shove that stream into a some sort of control like a text box or list box. This is a lot of code but doable... I have written this before for on-site debugging but don't have the code handy.
Why don't you just create a new windows form with multiline textbox and dock it to the form, set BackColor as Black ForeColor as White and create a public method to send text to that textBox.
If your aim is a one Form application this works pretty much brilliantly.

Return to an already open application when a user tries to open a new instance

This has been a problem that I haven't been able to figure out for sometime. Preventing the second instance is trivial and has many methods, however, bringing back the already running process isn't. I would like to:
Minimized: Undo the minimize and bring the running instance to the front.
Behind other windows: Bring the application to the front.
The language I am using this in is VB.NET and C#.
I found this code to be useful. It does the detection and optional activation of an existing application:
http://www.codeproject.com/KB/cs/cssingprocess.aspx
If you're using .NET, this seems easier and more straightforward using build-in .NET functionality:
The Weekly Source Code 31- Single Instance WinForms and Microsoft.VisualBasic.dll
These link may be of help:
http://www.ai.uga.edu/mc/SingleInstance.html
It has code to detect another instance running, not sure what you can do with it once you've got the instance though.
In
Form_Load this code worked.
If App.PrevInstance = True Then
MsgBox "Already running...."
Unload Me
Exit Sub
End If
Here is a simple and easily understandable method for preventing duplicate concurrent execution (written in c#).
public static void StopProgramOnSecondRun()
{
string
//Get the full filename and path
FullEXEPath = System.Reflection.Assembly.GetEntryAssembly().Location,
//Isolate just the filename with no extension
FilenameWithNoExtension = System.IO.Path.GetFileNameWithoutExtension(FullEXEPath);
//Retrieve a list of processes that have the same name as this one wich is FilenameWithNoExtension
Process[] processes = System.Diagnostics.Process.GetProcessesByName(FilenameWithNoExtension);
//There should always be at least one process returned. If the number is greater than one. Than this is the clone and we must kill it.
if (processes.Length > 1)
System.Diagnostics.Process.GetCurrentProcess().Kill();
}
I used the FileSystemWatcher on the form to solve this. This solution checks for the process, does not start a new instance, and shows the form of the already running process.
Add a FileSystemWatcher to the form that checks for the creation of a file and then shows the form with the created event.
In Program.cs:
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length > 1)
{
File.Create("AlreadyRunning.log").Dispose();
return;
}
For the form's FileSystemWatcher created event:
if (File.Exists("AlreadyRunning.log"))
{
Show();
WindowState = FormWindowState.Normal;
File.Delete("AlreadyRunning.log");
}

Categories