How can i kill two processes? - c#

I have in my Form1 button click event this line:
Process.Start(Path.GetFullPath(zippedFileDirectory));
Its just openning the location of this directory.
Then I have another line:
Process.Start(Path.GetFullPath(temp));
If I clicked the first button and then the second button I will have two windows opened each of a process.
Now im closing my program so in the Form1 closing event I want to kill this two processes.
In the else part what do I do ?
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("Are you Sure you want to Exit. Click Yes to Confirm and No to continue", "WinForm",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
{
e.Cancel = true;
}
else
{
}
}
Edit:
I did now in my Form1 top added:
private Process zipFileDirectoryProcess;
Then in the bottom inside the method I did:
private void Compress()
{
string zipFileName = "Diagnosis_Files.zip";
string source = contentDirectory;
string output = zippedFileDirectory;
string programFilesX86 = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFilesX86)
+ "\\Diagnostic Tool\\7z.dll";
if (File.Exists(programFilesX86))
{
SevenZipExtractor.SetLibraryPath(programFilesX86);
}
string programFiles = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFiles)
+ "\\Diagnostic Tool\\7z.dll";
if (File.Exists(programFiles))
{
SevenZipExtractor.SetLibraryPath(programFiles);
}
SevenZipCompressor compressor = new SevenZipCompressor();
compressor.ArchiveFormat = OutArchiveFormat.Zip;
compressor.CompressionMode = CompressionMode.Create;
compressor.TempFolderPath = System.IO.Path.GetTempPath();
string t = Path.Combine(output, zipFileName);
compressor.CompressDirectory(source, t);
zipFileDirectoryProcess.Start(Path.GetFullPath(zippedFileDirectory));
this.TopMost = true;
}
I added the line:
zipFileDirectoryProcess.Start(Path.GetFullPath(zippedFileDirectory));
But im getting an error on this line:
Error 1 Member 'System.Diagnostics.Process.Start(string)' cannot be accessed with an instance reference; qualify it with a type name instead
And before I added this line I had this line:
Process.Start(Path.GetFullPath(zippedFileDirectory));
And it worked good so why now I have this error ?

Process p1 = Process.Start(Path.GetFullPath(zippedFileDirectory));
Process p2 = Process.Start(Path.GetFullPath(temp));
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("Are you Sure you want to Exit. Click Yes to Confirm and No to continue", "WinForm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
{
e.Cancel = true;
}
else
{
p1.Kill();
p2.Kill();
}
}
UPDATE
For your added question, you can't call the Start() method on an instance of Process because:
There is no overriding method (instance method) of Start() taking 1 argument of string. There is only 1 method without any argument Start().
The IDE says you should call the Start() on a type name that means you should call Process.Start(string ....) whereas Process is a type name. This Start(string...) is a static method which can only be called on a type name.

Process.Start returns a process object. You can store this somewhere, and then call Kill() on it if they select yes. So, something like:
Process _proc;
_proc = Process.Start("path);
_proc.Kill();

Related

Visual Studio C# Controls not working (sometimes)

I'm really confused so I'm hoping someone can help me out here. I'm working on a programming assignment for uni but there's one part that's really been bugging me and I can't move on until it is fixed. I have created two classes. The problems in each are shown here:
class Login : Form1
{
Form1 f = new Form1();
public void LoginCorrect()
{
Form1.attempts = 3;
MessageBox.Show("Correct Credentials Entered!");
f.loginScreenVar = false;
f.mainScreenVar = true;
f.ChangeScreen();
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void ChangeScreen()
{
//Login Screen
txtUsername.Visible = loginScreenVar;
txtPassword.Visible = loginScreenVar;
btnLogin.Visible = loginScreenVar;
lblLoginCaption.Visible = loginScreenVar;
lblUsername.Visible = loginScreenVar;
lblPassword.Visible = loginScreenVar;
//Main Screen
lblWelcomeUser.Visible = mainScreenVar;
btnViewDetails.Visible = mainScreenVar;
btnViewAccounts.Visible = mainScreenVar;
btnLogout.Visible = mainScreenVar;
MessageBox.Show(loginScreenVar.ToString());
}
}
I have some controls on screen in my design which consist of text boxes, labels, and buttons, and these are meant to show and hide at diffferent times. I have created some booleans which can be set to true and false which will also set the visibility of these controls to true and false.
My problem is when accessing ChangeScreen() from my Login class, for some reason the controls don't hide when they're meant to. I've literally got a message box in the ChangeScreen() method which outputs the result of 'loginScreenVar' and this is false. Please can someone tell me why my 'Login Screen' controls are NOT hiding even though 'loginScreenVar' = false.
Another thing to note is when calling this code from a button in the Form1 class, it does work. However, due to the brief of my assignment I need to use multiple classes.
I really hope this isn't a bug and someone can help me here because I literally can't move on until this is fixed, thanks!
The issue is that, as noted in the comments, you create a new instance of Form1.
A whole new object, with own states.
Why can't I see this new instance? - well, if you did f.show() THEN you'd see it.
As it stands, you're still looking at the old instance.
So, what you need is a publicly accessible instance of Form1 which your two classes access, without creating a new instance.
OR
you could also work with two different windows. For example:
Form1_loaded(object sender, EventArgs e)
{
LoginWindow lw = new LoginWindow();
var result = lw.ShowDialog();
if(result == DialogResult.Cancel)
{
Application.Quit();
}
}
Let's assume you have a button for login. When clicked, it checks whether password and user name are correct. If not, the incorrect count gets increased by one. If the incorrect count is >= 3, then you just close the LoginWindow. (Default DialogResult is DialogResult.Cancel). The code might look like this:
LoginBtn_Click(object sender, EventArgs e)
{
if(UserNameInput.Text == userName && PasswordInput.Text == password)
{
failedAttempts = 0;
this.DialogResult = DialogResult.OK;
this.Close();
}
else
{
failedAttempts++;
if(failedAttempts >= 3)
{
MessageBox.Show("Wrong password. Shutting down the application...");
this.Close();
}
else
{
MessageBox.Show("Wrong password. " + (3-failedAttempts) + " tries left.");
}
}
}
This way, if login isn't successful, app quits. Otherwise the main screen appears.
Note: This is a basic solution. In a more complex app, you'd want more sophisticated output (not hard-coded strings) and comparisions using VariableName.Equals();
Let's keep it simple (and in the style you've started) for now:
public partial class Form1 : Form //Change the default "form1" "Button1" etc names as soon as possible
{
private bool loginScreenVar = true; //when naming booleans, use "truth test" sounding names like isLoginScreenMode
private bool mainScreenVar = true;
public Form1() //this is a constructor, a method that is always called when a new instance of this object is created
{
InitializeComponent();
//use the constructor to set things up
loginScreenVar = true;
mainScreenVar = false;
ChangeScreen();//make sure loginscreen is showing
}
public void ChangeScreen()
{
//Login Screen
txtUsername.Visible = loginScreenVar;
txtPassword.Visible = loginScreenVar;
btnLogin.Visible = loginScreenVar;
lblLoginCaption.Visible = loginScreenVar;
lblUsername.Visible = loginScreenVar;
lblPassword.Visible = loginScreenVar;
//Main Screen
lblWelcomeUser.Visible = mainScreenVar;
btnViewDetails.Visible = mainScreenVar;
btnViewAccounts.Visible = mainScreenVar;
btnLogout.Visible = mainScreenVar;
MessageBox.Show(loginScreenVar.ToString());
}
//call this method when the login is correct
public void LoginCorrect()
{
loginScreenVar = false;
mainScreenVar = true;
ChangeScreen();
}
//double click your login button in the forms designer to add this click event handler
public void LoginButton_Clicked(object sender, ClickEventArgs e){
if(txtUsername.Text == "user" && txtPassword.Text == "pass"){
LoginCorrect();
} else {
MessageBox.Show("Login incorrect");
}
}
}
Forget the class Login:Form stuff unless you're really trying to explore object instantiation and making your own classes for things. Your Form1 will be on show when your app starts, do all the logic inside it
A better way to change screens in winforms is by creating two separate panels each one contains the desired controls to be shown and hide so that you can switch between them
Code example:
Form1_loaded(object sender, EventArgs e)
{
LogInPanel.Visible=true;
}
private void ConnectBtn_Click(object sender, EventArgs e)
{
// Do your checking here
// IF conditions met
MainPanel.Visible=true;
}
private void DisconnectBtn_Click(object sender, EventArgs e)
{
// Do your checking here
// IF conditions met
LogInPanel.Visible=true;
}
If you want to keep you methadologie make sure your program.cs runs Login class instead of Form1 class

How to check if an .exe file is loade to execute it?

This may be a bit of a newbie question. I am loading a executable from a server and then want to execute this program. After execution is finished, I want to delete this file.
Here is part of my code:
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (check == true)
{
if (webBrowser1.DocumentText.Contains("0"))
{
check = false;
// timer1.Stop();
button1.Enabled = true;
MessageBox.Show("Wrong HWID ");
this.Close();
}
else if (webBrowser1.DocumentText.Contains("1"))
{
check = false;
// timer1.Stop();
button1.Enabled = true;
WebClient wc = new WebClient();
Properties.Settings.Default.Serial = textBox1.Text;
Properties.Settings.Default.Installed = true;
Properties.Settings.Default.Save();
MessageBox.Show("All info correct!");
var result = MessageBox.Show("Do you want to start ?", "Application Exit", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
wc.DownloadFileAsync(uri, filename);
}
if (File.Exists(filename))
{
Process.Start(filename);
}
}
else if (webBrowser1.DocumentText.Contains("2"))
{
check = false;
// timer1.Stop();
button1.Enabled = true;
MessageBox.Show("HWID field left empty");
}
else if (webBrowser1.DocumentText.Contains("3"))
{
check = false;
// timer1.Stop();
button1.Enabled = true;
MessageBox.Show("Wrong serial");
}
else if (webBrowser1.DocumentText.Contains("Object not found"))
Other related code:
Uri uri = new Uri("http://link.com/blabla/blabla.exe");
string filename = #"C:\Users\User\blabla.exe";
If you are fine with locking your current process this can be done synchronously. This is not the recommended way to do it but may work in your case depending on your environment.
Change this:
wc.DownloadFileAsync(uri, filename);
To this:
wc.DownloadFile(uri, filename);
After this you can add:
if (File.Exists(filename)) {
Process process = Process.Start(filename);
process.WaitForExit();
File.Delete(filename);
}
Which will check to see if the file exists, starts it, waits for it to finish, and then deletes it. As always when working with FileIO, you should work to handle exceptions.
This is the better apporach
If it needs to be async then another way to do this may be to trigger an event when the download is complete. You would want to add an event handler like the following to your WebClient:
client.DownloadFileCompleted += new AsyncCompletedEventHandler (DownloadFileCallback);
And then add a handler method similar to the following:
private void DownloadFileCallback(object sender, AsyncCompletedEventArgs e) {
if (File.Exists(filename)) {
Process process = Process.Start(filename);
process.WaitForExit();
}
}
Note that in this handler method, filename is instance data to your class so you know where you saved the file. This should get you started in the right direction.
EDIT:
As mentioned in my answer, using wc.DownloadFile() is synchronous, meaning it will lock your current process. (i.e. you will see this when debugging when you step over this line it will not do anything else until it has finished). This can cause problems when the download (or more generally any synchronous process) takes a long, it has the potential to lock up your UI (if this is UI code). The best practice is to do this asynchronously which is what the original code you posted does. In the code you posted you were using wc.DownloadFileAsync(). To keep using this method, add an event handler like shown above and this handler method will be called once the download has completed. This makes the download run in the background so your thread is free to run other things while this is working. (i.e. this can leave your UI responsive on long downloads) Inside your event handler, your download is finished so you can continue on from there.
EDIT 2:
Since you will only be executing the program and then deleting it, it may be worth just saving it to the temp directory (navigate to %temp%). Something that may work to generate your filename would be the following:
string filename = Path.Combine(Path.GetTempPath(), "MyFile.exe");
This should result in something like the following path C:\Users\Username\AppData\Local\Temp\MyFile.exe

Not to execute any further code until the async method is completed its execution

Not to execute any further code until the async method is completed its execution. Please let me know how to achieve it.
Following is sample code :
// Parent Form code
private void btnOpenForm1_Click(object sender, EventArgs e)
{
Form1 form1 = new Form1();
var result = form1.ShowDialog();
if (result == System.Windows.Forms.DialogResult.OK)
{
// do something
}
}
// Child form code
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
DialogResult result = MessageBox.Show(string.Format("Do you want to save changes?", "Confirmation", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (result == System.Windows.Forms.DialogResult.Cancel)
{
e.Cancel = true;
}
else
{
if (result == DialogResult.Yes)
{
e.Cancel = true;
this.DialogResult = System.Windows.Forms.DialogResult.OK;
// HERE I NEED TO WAIT COMPULSARILY TILL THE OPERATION IS COMPLETED, NO NEXT STATEMENT SHOULD BE EXECUTED (NEITHER IN PARENT FORM)
var isSaveCompleted = await HandleSave().ConfigureAwait(false);
if(isSaveCompleted == true)
{
// dispose some objects
}
}
else // if No is clicked
{
this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
// dispose some objects
}
}
}
public async Task<bool> HandleSave()
{
await doWork();
//
// some code here
//
}
public doWork()
{
//
// some code for I/O operation
//
}
In the above code, I don't want to execute the any of the next statements (not even in the Parent Form) until the HandleSave() method is completed its execution.
There's an XY problem here. Trying to force an asynchronous method to run synchronously in order to block closing the form is the wrong solution.
Instead of fighting window lifetimes, you need to figure out how to work with them. One solution for this scenario is to hide the form rather than closing it; and then actually close it when the asynchronous save completes. You can enable your parent form to detect when the child form is actually closed by using a TaskCompletionSource<DialogResult>.

Can't clear listbox

I'm working on a new button that resets the form application when clicked.
However I've run into a problem that I can't seem to solve.
Basically what I want to do is to clear the list boxes when the the button new is clicked.
The New button should initialize the program exactly as at
start-up (but without restarting the application). If data has not
been saved, allow the user (through a MessageBox) to confirm
proceeding without saving current data or go back to the current
session.
Here is how I tried it:
private void mnuNew_Click(object sender, EventArgs e)
{
for (int index = 0; index < animalmgr.Count; index++)
{
Animal animal = animalmgr.GetAt(index);
if (animal != null)
{
// error message
DialogResult dialogResult = MessageBox.Show("The data will be lost. Continue?", "Are you sure?", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
InitializeGUI();
}
else if (dialogResult == DialogResult.No)
{
}
}
else
{
ClearLists(); <--------This does not work!
}
}
}
private void InitializeGUI()
{
animalmgr.DeleteAll();
Resultlst.Items.Clear();
foodItemslst.Items.Clear();
}
public void ClearLists()
{
Gendercmb.DataSource = Enum.GetValues(typeof(GenderType));
Categorylst.DataSource = Enum.GetValues(typeof(Categorytype));
Resultlst.Items.Clear();
foodItemslst.Items.Clear();
}
What does work: It does display a messagebox if the animal object is not null.
What does NOT work: When I load a file and display the object on the listbox, the new button does NOT clear the list. The reason is because the animal object is null after loading a file and displaying, but it should call the else and clear the list, but it doesn't.
UPDATE:
The problem is NOT the the ClearLists() method. The problem is that the if statement, never seem to reach down to call it. The problem is not the ClearLists() method itself. The problem is that it never is called.
I believe the problem lies in your logic comparison of
animal != null
Look at your logic, the line above gives animal a value, even if that value is 0. Therefore animal is never null, because it always has a value.
Try this.
public void ClearLists()
{
Gendercmb.DataSource = Enum.GetValues(typeof(GenderType));
Categorylst.DataSource = Enum.GetValues(typeof(Categorytype));
Resultlst.DataSource = new List<ListItem>();
foodItemslst.DataSource = new List<ListItem>();
}
Remember, if this is an asp.net webforms application, you also need to call DataBind() dunction on foodItemslst and Resultlst both.

Opening text files in C# application

I'm still a beginner when it comes to programming and this is a small application I did following a C# tutorial.
private void viewImagesToolStripMenuItem_Click(object sender, EventArgs e)
{
string openedfile = "";
openfd.Title = "Insert a text file";
openfd.InitialDirectory = "C:";
openfd.FileName = "";
openfd.Filter = "text files|*.txt|word documents|*.doc|allfiles|*.*";
if (openfd.ShowDialog() == DialogResult.Cancel)
{
MessageBox.Show("Operation canceled");
}
if (openfd.ShowDialog() != DialogResult.Cancel)
{
openedfile = openfd.FileName;
richTextBox1.LoadFile(openedfile,RichTextBoxStreamType.PlainText);
}
While doing this I noticed that if I change the same application's code order just 2 lines-
string openedfile = "";
openedfile = openfd.FileName;
like below It will throw me an error like this when debugging - Empty path name is not legal.
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
openfd.Title = "Insert a text file";
openfd.InitialDirectory = "C:";
openfd.FileName = "";
openfd.Filter = "text files|*.txt|word documents|*.doc|allfiles|*.*";
**string openedfile = "";
openedfile = openfd.FileName;**
if (openfd.ShowDialog() == DialogResult.Cancel)
{
MessageBox.Show("Operation canceled");
}
if (openfd.ShowDialog() != DialogResult.Cancel)
{
richTextBox1.LoadFile(openedfile,RichTextBoxStreamType.PlainText);
}
Isn't there a way to understand errors in these type situations. What is the specific order of coding an application like this?
well, the idea is simple you cannot use a variable that has been not initialized.
in your case sm thing same is happening.
In your first code openedfile = openfd.FileName; is being executed after the dialouge has been shown. Thus the file name comes correctly.
But in the second openedfile = openfd.FileName; is getting initialized before the dilogue has been shown. Since there is no dialogue the name is null, hence it gives error.
Note. I have used initialized word not in tecnical manner.
The line openedfile = openfd.FileName; will not bind the two variables, it will copy the value that openfd.FileName has at this moment into openedfile.
In your second example the user has not yet selected a file at that moment, so this value is still empty (""). The value that is selected later in openfd will be ignored.
EDIT which is why you get the error Empty path name is not legal.
I'm going to go ahead and guess that the problem is the openfd.FileName call outside of the if block (and also before its retrieved), while the if block is still being exectuted the openfd is "left open" if you like, so you can retrieve its result.
When you have left, the if block, you are effectively saying you are done with this dialog, please continue.
In your code you are showing multiple dialogs with multiple calls to show dialog also, consider the following.
if (openfd.ShowDialog() == DialogResult.OK)
{
pictureBox1.Image = Image.FromFile(openfd.FileName);
}
else
{
MessageBox.Show("Operation canceled");
}
(Changed to use dialogresult.ok as this is more than likely the result you wish to receive from the dialog)
Update
With respect to your current applcation, each call to ShowDialog() is opening a new dialog. Consider it similar to
MessageBox.Show("woo");
MessageBox.Show("hoo");
in the above, when the first messagebox is closed, it will close the dialog and move onto handling the second message box (the next line of code), with your
if (openfd.ShowDialog() != DialogResult.Cancel)
Your showdialog is still in use by the if statement so it is deemed to be still in use and not disposed of straight away. When the if statement is finished with, your dialog will then be deemed to be ok to dispose
Also, the error in your application is not to do with the filename path, its trying to load in a file that has no name
I generally Prefer this:
private void viewImagesToolStripMenuItem_Click(object sender, EventArgs e)
{
DialogResult dr=openfd.ShowDialog();
if(dr==DialogResult.Ok)
{
richTextBox1.LoadFile(openfd.FileName,RichTextBoxStreamType.PlainText);
}
else
{
MessageBox.Show("No file Selected!!");
}
}

Categories