我正在编写一个程序,在 s 目录中启动一个随机文件。文件可以是任何类型,但主要是视频或图像文件。 每次启动一个文件时,我都想关闭之前打开的文件。
代码:
string FolderSelected = "";
string FileName = "";
Process proc;
List<string> FilesDisplayed = new List<string>();
private void button2_Click(object sender, EventArgs e)
{
if (FolderSelected == string.Empty)
FolderSelected = Properties.Settings.Default.FilesDefaultFolder;
if (proc != null)
{
proc.CloseMainWindow();
proc.Close();
}
FileName = FetchRandomFile();
proc = Process.Start(FileName);
}
问题是,我不断收到
proc = null
(文件已正确启动),并且我无法获取以前打开的进程以关闭它。我知道 .NET 重用进程,这就是它返回 Null 的原因,但我需要重写此行为。
编辑:感谢leppie的评论,我怀疑我知道答案:我的猜测是你正在“启动”类似图像的东西,并且它正在重用现有的进程来打开文档而不是创建新的进程。
我用这个简单的测试应用程序重现了这个:
using System;
using System.Diagnostics;
public class Test
{
static void Main()
{
Process proc = Process.Start("image.tif");
Console.WriteLine(proc == null);
}
}
这会打印“true”,因为它使用
dllhost.exe
来托管 Windows 图像查看器,而不是创建新进程。
要解决此问题,您必须将
UseShellExecute
设置为 false 以绕过 shell。
而不是
Process.Start("filename", "args")
使用
Process.Start(new ProcessStartInfo() {
FileName = "filename",
Arguments = "args",
UseShellExecute = false
});
您在方法范围内声明“proc”,因此当在该方法的顶部检查时,它当然会始终为空。如果您希望引用存在于函数之外,请将其声明为类级别变量。
您每次(可能)都会生成一个进程,Process.Start 不会返回 null,但当 i 超出范围时,您只是丢失了对它的引用。
这甚至无法编译(明确的分配)。作为一个 方法变量 ,
proc
仅对于声明方法(/作用域)是本地的 - 即 button2_Click
,这解释了为什么你不能保留值。如果 proc
旨在在调用之间持续存在,请将其提升为 field(每个实例变量):
Process proc;
private void button2_Click(object sender, EventArgs e)
{
if (proc != null)
...
到目前为止这对我有用。已经尝试过图像和视频。不知道检查文件名的方法是否适用于每个实例,因此我在拥有进程 ID 时使用它。
就我而言,如果 GetProcess 错过了正在运行的进程,那也没什么大不了的,所以对我来说没关系。
public class ProcessFinder
{
public virtual Process GetProcess(int processId)
{
return Process.GetProcesses().FirstOrDefault(p => p.Id == processId);
}
public virtual Process GetProcess(string fileName)
{
return Process.GetProcesses().FirstOrDefault(p => p.MainWindowTitle.StartsWith(fileName));
}
}