在默认图像查看器中打开和关闭图像
Open and close image in default image viewer
我正在尝试创建一种在默认图像查看器中打开图像并在 time
毫秒后关闭它的简短方法。
现在看起来像这样:
public static async void OpenImage(string path, int time)
{
var process = new Process();
process.StartInfo.FileName = path;
process.Start();
await Task.Delay(time);
process.Kill()
process.Close()
}
我可以看到图像,但是 process.Kill()
抛出 InvalidOperationException
、"No process is associated with this object."
我是不是遗漏了什么或者有其他方法可以做到吗?
更新:
现在也测试了这个:
public static async void OpenImage(string path, int time)
{
var process = Process.Start(path)
await Task.Delay(time);
process.Kill()
process.Close()
}
但是后来Process.Start()
returnsnull
。所以也许我必须像 faljbour 评论的那样直接调用 .exe
?
这里的问题是你并没有真正启动一个进程,而是将文件路径传递给 Windows Shell (explorer.exe
) 来处理。 shell 计算出如何打开文件,它 开始这个过程。
发生这种情况时,您的代码不会取回进程 ID,因此它不知道要终止哪个进程。
您应该做的是找到该文件的默认应用程序,然后显式启动该应用程序(而不是让 shell 弄明白)。
我能想到的查找文件默认应用程序的最简洁方法是使用 Win32 API FindExecutable()
.
当默认应用程序包含在 dll 中时,事情会有点复杂。默认的 Windows 照片查看器 (C:\Program Files (x86)\Windows Photo Viewer\PhotoViewer.dll
) 就是这种情况。由于它不是 exe
,您不能直接启动它,但是可以使用 rundll32
.
启动应用程序
这应该适合你:
[DllImport("shell32.dll")]
static extern int FindExecutable(string lpFile, string lpDirectory, [Out] StringBuilder lpResult);
public static async void OpenImage(string imagePath, int time)
{
var exePathReturnValue = new StringBuilder();
FindExecutable(Path.GetFileName(imagePath), Path.GetDirectoryName(imagePath), exePathReturnValue);
var exePath = exePathReturnValue.ToString();
var arguments = "\"" + imagePath + "\"";
// Handle cases where the default application is photoviewer.dll.
if (Path.GetFileName(exePath).Equals("photoviewer.dll", StringComparison.InvariantCultureIgnoreCase))
{
arguments = "\"" + exePath + "\", ImageView_Fullscreen " + imagePath;
exePath = "rundll32";
}
var process = new Process();
process.StartInfo.FileName = exePath;
process.StartInfo.Arguments = arguments;
process.Start();
await Task.Delay(time);
process.Kill();
process.Close();
}
这段代码演示了这个概念,但如果你想满足更多具有不寻常参数格式(如 photoviewer.dll
所示)的默认应用程序,你应该搜索 registry yourself 或使用第三方库找到要使用的正确命令行。
例如,
我正在尝试创建一种在默认图像查看器中打开图像并在 time
毫秒后关闭它的简短方法。
现在看起来像这样:
public static async void OpenImage(string path, int time)
{
var process = new Process();
process.StartInfo.FileName = path;
process.Start();
await Task.Delay(time);
process.Kill()
process.Close()
}
我可以看到图像,但是 process.Kill()
抛出 InvalidOperationException
、"No process is associated with this object."
我是不是遗漏了什么或者有其他方法可以做到吗?
更新:
现在也测试了这个:
public static async void OpenImage(string path, int time)
{
var process = Process.Start(path)
await Task.Delay(time);
process.Kill()
process.Close()
}
但是后来Process.Start()
returnsnull
。所以也许我必须像 faljbour 评论的那样直接调用 .exe
?
这里的问题是你并没有真正启动一个进程,而是将文件路径传递给 Windows Shell (explorer.exe
) 来处理。 shell 计算出如何打开文件,它 开始这个过程。
发生这种情况时,您的代码不会取回进程 ID,因此它不知道要终止哪个进程。
您应该做的是找到该文件的默认应用程序,然后显式启动该应用程序(而不是让 shell 弄明白)。
我能想到的查找文件默认应用程序的最简洁方法是使用 Win32 API FindExecutable()
.
当默认应用程序包含在 dll 中时,事情会有点复杂。默认的 Windows 照片查看器 (C:\Program Files (x86)\Windows Photo Viewer\PhotoViewer.dll
) 就是这种情况。由于它不是 exe
,您不能直接启动它,但是可以使用 rundll32
.
这应该适合你:
[DllImport("shell32.dll")]
static extern int FindExecutable(string lpFile, string lpDirectory, [Out] StringBuilder lpResult);
public static async void OpenImage(string imagePath, int time)
{
var exePathReturnValue = new StringBuilder();
FindExecutable(Path.GetFileName(imagePath), Path.GetDirectoryName(imagePath), exePathReturnValue);
var exePath = exePathReturnValue.ToString();
var arguments = "\"" + imagePath + "\"";
// Handle cases where the default application is photoviewer.dll.
if (Path.GetFileName(exePath).Equals("photoviewer.dll", StringComparison.InvariantCultureIgnoreCase))
{
arguments = "\"" + exePath + "\", ImageView_Fullscreen " + imagePath;
exePath = "rundll32";
}
var process = new Process();
process.StartInfo.FileName = exePath;
process.StartInfo.Arguments = arguments;
process.Start();
await Task.Delay(time);
process.Kill();
process.Close();
}
这段代码演示了这个概念,但如果你想满足更多具有不寻常参数格式(如 photoviewer.dll
所示)的默认应用程序,你应该搜索 registry yourself 或使用第三方库找到要使用的正确命令行。
例如,