【问题标题】:Disable C# Form until external Excel application is closed禁用 C# 表单,直到外部 Excel 应用程序关闭
【发布时间】:2020-11-30 03:30:37
【问题描述】:

我在运行以下代码的 C# Windows 窗体应用程序上有一个按钮:

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

基本上,用户需要能够对 CSV 文件进行更改。用户最愿意在 Microsoft Excel 中进行这些更改。我从一个有多年使用 MS Office 产品和 C# 经验的人那里找到了上面的代码。这家伙解释说,下面的代码可以工作,但比使用上面显示的“Process.Start()”更容易出错。

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

ExcelApp.Visible = true;

这个人解释说“Process.Start()”之所以有效,是因为 Windows 设置为使用 Excel 作为打开 CSV 文件的默认程序。

无论如何,当用户单击上面的按钮 (btnAddDataToCSV) 时,我需要禁用我的 C# 表单(所有按钮变灰),直到用户关闭显示 CSV 文件的 Excel 工作簿。潜在地,我可能需要 C# 程序在用户关闭 Excel 后立即读取 CSV 文件。

我该怎么做?

我假设...我需要执行类似...“禁用 C# 表单...然后等待 Excel 关闭事件...然后一旦 excel 关闭事件发生...启用 C# 表单并读取 CSV 文件。 "

以下是我用于读取 CSV 文件的代码:

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]);
}

【问题讨论】:

标签: c# excel csv


【解决方案1】:

我认为您需要为退出的进程使用事件处理程序。

类似这样的:

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 示例:https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.exited?view=netcore-3.1

【讨论】:

  • 试图效仿你的例子,但我一直遇到问题......一个问题是:“无法通过实例引用访问成员;使用类型名称来限定它”在“myProcess.Start”上(path);" 行...我不确定该错误是什么意思?
  • 所以我把它改成了:myProcess.StartInfo.FileName = "D:\\MyCsvFile.csv";和 myProcess.Start(path);它消除了所有错误......但没有“灰色”掉我的 C# 表单上的按钮......这是我最初发布的关于试图完成的内容。另外,在上面写着“//enableForm”的地方我放了代码来显示一个消息框......但是当我关闭excel工作簿时没有显示消息框。我确实有其他 Excel 工作簿已经打开,但我从未关闭过。不知道是不是这个原因?今晚我将进行更多测试...但我们将不胜感激。
  • 对于“灰色”按钮的问题,您必须将我的评论(//禁用表单)替换为禁用所有要变灰的元素。我想你可以把 yourbuttonName.Enable = False (或类似的东西)。对于结束事件,您必须关闭所有 excel 选项卡,因为您的代码将打开它。所以你可以尝试:1)关闭所有的excel选项卡,2)启动程序3)单击按钮(检查excel打开)4)检查禁用的元素5)关闭exce 6)检查元素是否再次启用(同样在这里,您必须将我的 //enableForm 替换为启用的元素)
【解决方案2】:

即使该解决方案类似于 Microsoft 的解决方案,我也无法使上述解决方案发挥作用。

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

我发现了这个:

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

上面写着:

“我遇到过将 new Process() 放在 using 子句中的示例。如果您想使用 Exited 功能,请不要这样做。using 子句会破坏实例以及 Exited 上的任何事件句柄。”

上面写着:

using(var process = new Process())

应该是:

var process = new Process();

这是没有意义的,因为我为 Microsoft 提供的上述链接是如何使用“Process.Exited Event”的示例,它使用“using(var process = new Process())”

但果然……由于某种原因,当我尝试“var process = new Process();”时它起作用了...这是起作用的代码:

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!!");
}

这是不起作用的代码...但我不明白为什么,因为它类似于微软的示例。

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!!");
}

当您关闭 excel 时...该事件永远不会触发...有人可以解释一下吗?微软的例子肯定没有错。

【讨论】:

  • 无法使用已处置的对象。在 using 指令的末尾, myProcess 被释放,因此当进程终止时,它不再“可用”。顺便说一句,在您的问题中,您没有问过如何使用 Excel Interop 做到这一点吗?
  • 不,我是说我在某处发现“Process.Start()”比“Excel Interop”问题少。我看到您对已处置对象的评论,它们与我在网上其他地方看到的类似...但是...特别是我的问题是...如果您单击我在上面提供的 Microsoft 链接... Microsoft 使用的示例对于“Process.Exited”有“using (myProcess = new Process())”...微软的例子错了吗?
  • 在微软提供的示例中,在 using 语句结束前有如下一行:await Task.WhenAny(eventHandled.Task,Task.Delay(30000)); 将等待进程退出最多 30 秒,然后再处理进程跨度>
  • 我想我现在明白了……谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-09
  • 2016-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多