1

I have a button on a C# Windows forms application that runs the code below:

private void btnAddDataToCSV_Click(object sender, EventArgs e)
    {
    string path = "D:\MyCsvFile.csv";
    Process.Start(path);
    }

Basically, the user needs to be able to make changes to a CSV file. The user is most comfortable making these changes in Microsoft Excel. I found the above code online from someone who has many years of experience working with MS Office products and C#. This guy explained that the code below works but is more error prone than using "Process.Start()" as shown above.

string path = "D:\MyCsvFile.csv";
var ExcelApp = new Excel.Application();
ExcelApp.Workbooks.OpenText(path, Comma: true);

ExcelApp.Visible = true;

This guy explains that "Process.Start()" works because Windows is set up to use Excel as the default program for opening CSV files.

Anyways, when the user clicks the button above (btnAddDataToCSV), I need my C# form to become disabled (all the buttons grayed out) until the user closes the Excel workbook that is displaying the CSV file. Potentially, I may need the C# program to read the CSV file immediately after the user closes Excel.

Ho do I do this?

I assume... I need to do something like... "disable C# form... then Wait for Excel close event... then once excel close event happens... enable C# form and read CSV file."

Below is the code I have for reading the CSV file:

string path = "D:\MyCsvFile.csv";

var reader = new StreamReader(File.OpenRead(path));

List<string> listA = new List<string>();
List<string> listB = new List<string>();
List<string> listC = new List<string>();

while (!reader.EndOfStream)
{
    var line = reader.ReadLine();
    var values = line.Split(',');

    listA.Add(values[0]);
    listB.Add(values[1]);
    listC.Add(values[2]);
}
XCELLGUY
  • 179
  • 2
  • 12
  • https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.process.exited?view=netcore-3.1 – T.S. Aug 10 '20 at 14:01

2 Answers2

0

I think that you need to use an event handler for process that exits.

Something like this:

private void btnAddDataToCSV_Click(object sender, EventArgs e)
{
//disable form

string path = "D:\MyCsvFile.csv";

using (myProcess = new Process())
 {
   myProcess.EnableRaisingEvents = true;
   myProcess.Exited += new EventHandler(Excel_Exit);
   myProcess.Start(path);   
 }

}


public void Excel_Exit(object sender, System.EventArgs e){
//enableForm
}

Process.Exited example in documentation: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.process.exited?view=netcore-3.1

GCiandro
  • 66
  • 9
  • Trying to follow your example but I keep running into issues... One issue is: "Member cannot be accessed with an instance reference; qualify it with a type name instead' on the "myProcess.Start(path);" line... I am not sure what that error means? – XCELLGUY Aug 10 '20 at 18:26
  • 1
    So I changed it to: myProcess.StartInfo.FileName = "D:\\MyCsvFile.csv"; and myProcess.Start(path); which got rid of all the errors... but doesn't "gray" out the buttons on my C# form... Which was what I originally posted about trying to accomplish. Also, above where it says "//enableForm" I put code to display a message box... but no message box displayed when I closed the excel workbook. I did have other excel workbooks already open, which I never did close. I don't know if that was the reason? I will do some more testing this evening... but additional guidance would be appreciated. – XCELLGUY Aug 10 '20 at 19:42
  • For what concerns "graying" buttons you have to replace my comment (//disable form) with the disabling of all the elements you want to grayed. I guess that you can put yourbuttonName.Enable = False (or something like that). For the closing event, you have to close all of your excel tab because your code will opens it. So you can try: 1) close all of your excel tabs, 2) start the program 3) click the button (check the excel opening) 4)check the disabled elements 5) close exce 6) check if the elements are enabled again (also here, you have to replace my //enableForm with your elements enabling) – GCiandro Aug 11 '20 at 07:40
0

I was unable to get the solution above to work even though the solution is similar to Microsoft's solution.

https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.process.exited?view=netcore-3.1

I found this:

Why is my process's Exited method not being called?

It says:

"I've come across examples that place new Process() in a using clause. Do not do that if you want to use the Exited feature. The using clause destroys the instance along with any event handles on Exited."

It says:

using(var process = new Process())

Should be:

var process = new Process();

This makes no since because the link above that I provided for Microsoft is an example of how to use the "Process.Exited Event" and it uses "using(var process = new Process())"

But sure enough... for some reason when I tried "var process = new Process();" it worked... This is the code that worked:

private void btnAddDataToCSV_Click(object sender, EventArgs e)
{
    var myProcess = new Process();
       
    myProcess.EnableRaisingEvents = true;
    myProcess.Exited += new EventHandler(Excel_Exit);
    myProcess.StartInfo.FileName = "D:\\MyCsvFile.csv";
    myProcess.Start();        
}

public void Excel_Exit(object sender, System.EventArgs e)
{
    MessageBox.Show("Success!!");
}

Here is the code that does not work... But I don't understand why because it is similar to Microsoft's example.

private Process myProcess;
private void btnAddDataToCSV_Click(object sender, EventArgs e)
{
    using (myProcess = new Process())
    {
        myProcess.EnableRaisingEvents = true;
        myProcess.Exited += new EventHandler(Excel_Exit);
        myProcess.StartInfo.FileName = "D:\\MyCsvFile.csv";
        myProcess.Start();
    }          
}

public void Excel_Exit(object sender, System.EventArgs e)
{
    MessageBox.Show("Success!!");
}

When you close excel... the event never fires... Can someone explain this? Surely Microsoft's example isn't wrong.

XCELLGUY
  • 179
  • 2
  • 12
  • A disposed object cannot be used. At the end of the `using` directive, myProcess is disposed, so when the process terminates it is no more "usable". Btw in your question didn't you ask how to do this with Excel Interop? – Matteo Umili Aug 11 '20 at 07:18
  • No I was saying that I found somewhere that "Process.Start()" is less problematic than "Excel Interop." I see your comment about disposed objects and they are similar to what I have seen other places online... But... Specifically my question is... If you click on the Microsoft link I provided above... The example Microsoft uses for "Process.Exited" has "using (myProcess = new Process())"... Is the Microsoft example wrong? – XCELLGUY Aug 11 '20 at 11:33
  • 1
    In the example provided by Microsoft, before the end of the using statement there is the following line: `await Task.WhenAny(eventHandled.Task,Task.Delay(30000));` that will wait the process to exit for a maximum of 30 seconds before disposing the process – Matteo Umili Aug 11 '20 at 13:23
  • I think I understand now... Thank you. – XCELLGUY Aug 11 '20 at 13:33