c# - 在用户关闭文件后终止打开文件的进程[WPF应用程序]
问题描述
我正在尝试通过单击 WPF 应用程序按钮有效地打开-关闭-重新打开 Power bi 文件 (.pbix)。我的方法首先创建一个打开 pbix 文件的进程,然后在文件关闭时终止该进程,然后在再次单击按钮时创建一个新进程以重新打开文件。
请在下面找到我用来执行上述步骤的代码。
namespace TestApp
{
public class MainWindowViewModel : INotifyPropertyChanged
{
public int CheckFileIsOpen(string filenamepath)
{
try
{
using FileStream fs = new FileStream(filenamepath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
return 0;
}
catch (Exception)
{
WindowEffect = new BlurEffect();
Mouse.OverrideCursor = null;
bool? Result = new CustomMessageBox($"File: {filenamepath.Split(@"\").Last()} in use!\nClose it and try again.", "File used by another process", MessageType.Error, MessageButtons.Ok).ShowDialog(); //this is a MessageBox object
if (Result.Value)
{
WindowEffect = null;
return 1;
}
else
{
WindowEffect = null;
return 2;
}
}
}
private void OpenOnlineLocally(bool open_local)
{
Process p = new Process();
string copy_name = "File_Copy.pbix";
string path = AppDomain.CurrentDomain.BaseDirectory; //the directory the .exe file runs.
try
{
Mouse.OverrideCursor = Cursors.Wait;
if (open_local == true)
{
int IsPBIFileOpen = CheckFileIsOpen($@"{path}{copy_name}");
if (new[] { 1, 2 }.Contains(IsPBIFileOpen))
{
return;
}
//Open the file using the system process
p.StartInfo = new ProcessStartInfo($"{path}{copy_name}")
{
UseShellExecute = true
};
p.Start();
}
else
{
OpenUrl("https://app.powerbi.com/...");
}
}
finally
{
if (p.HasExited) { p.Kill(); } //kill the process if the user closed the .pbix file
}
}
public ICommand ExportPowerBICommand //binded to a button click command in xaml
{
get { return new DelegateCommand<object>(FuncExportPowerBI); }
}
public void FuncExportPowerBI(object parameter)
{
Mouse.OverrideCursor = Cursors.Wait;
try
{
OpenOnlineLocally(true);
}
finally
{
Mouse.OverrideCursor = null;
}
}
}
}
上面的代码在finally statement
:
System.InvalidOperationException:“没有进程与此对象关联。”
实验后的一些注意事项:
当用户关闭 .pbix 文件(即单击桌面应用程序右上角的 X 图标)时,应终止该进程。如果进程没有被杀死并且用户重新单击按钮以重新打开文件,那么我会收到一个错误,即该文件已被另一个进程打开并使用。
我更喜欢避免使用 的解决方案,
process.WaitForExit()
原因有两个。首先,应用程序在用户使用文件时冻结。其次,桌面需要几秒钟才能意识到进程已经退出,所以它可以退出kill()
(不是时间效率)。
解决方案
由于您正在运行 .NET 5,因此有一个异步方法Process.WaitForExitAsync()。异步操作不会阻塞 UI。
我对两种方法进行了更改
private async Task OpenOnlineLocally(bool open_local)
{
Process p = new Process();
string copy_name = "File_Copy.pbix";
string dir = AppDomain.CurrentDomain.BaseDirectory; //the directory the .exe file runs.
string path = Path.Combine(dir, copy_name);
try
{
if (open_local == true)
{
int IsPBIFileOpen = CheckFileIsOpen(path);
if (IsPBIFileOpen != 0)
{
return;
}
//Open the file using the system process
p.StartInfo = new ProcessStartInfo(path)
{
UseShellExecute = true
};
p.Start();
await p.WaitForExitAsync();
}
else
{
OpenUrl("https://app.powerbi.com/...");
}
}
finally
{
if (!p.HasExited) { p.Kill(); } //kill the process if the user closed the .pbix file
}
}
public async void FuncExportPowerBI(object parameter)
{
Mouse.OverrideCursor = Cursors.Wait;
try
{
await OpenOnlineLocally(true);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message); // handle possible exception here
}
Mouse.OverrideCursor = null;
}
推荐阅读
- r - 在多列上执行 fct_lump 的最佳方法
- javascript - 如何为用户体验模拟慢速互联网连接?
- c++ - 交叉编译的基础知识(使用 CMake)
- react-native - React Navigation + React Native Web - 在抽屉导航器中多次导航到同一屏幕不会添加到浏览器历史记录
- c# - 链接按钮上的查询字符串
- pointers - Rust Global.dealloc vs ptr::drop_in_place vs ManuallyDrop
- json - 如何使用 express 添加更多页面并在节点中发送值?
- java - 方法调用可能会产生“NullPointerException”
- linux - 尝试运行我的第一个 cron 任务,它是一个可执行的 shell 文件,但 cron 什么都不做,只是创建一个空的日志文件
- firebase - 找不到 GoogleUtilities/AppDelegateSwizzler/Private/GULApplication.h' 文件是否有任何解决方法