如何使用 C++ WinAPI 功能强制打开文件 "silently"(最小化,不活动)?
How to force open file "silently" (minimized, not active) using c++ WinAPI functional?
在我的 WinAPI C++ 应用程序中,我尝试使用 ShellExecuteEx:
使用默认系统播放器打开音频文件
int OpenFileWithDefaultProgram(const std::wstring& path, int showMode, HANDLE* hProc) {
SHELLEXECUTEINFO shInfo;
::ZeroMemory(&shInfo, sizeof(SHELLEXECUTEINFO));
shInfo.cbSize = sizeof(SHELLEXECUTEINFO);
shInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shInfo.hwnd = NULL;
shInfo.lpVerb = L"open";
shInfo.lpFile = path.c_str();
shInfo.nShow = showMode;
::ShellExecuteEx(&shInfo);
*hProc = shInfo.hProcess;
return (int)shInfo.hInstApp;
}
OpenFileWithDefaultProgram函数是这样调用的:
HANDLE hProc;
int error = OpenFileWithDefaultProgram(path, SW_SHOWMINNOACTIVE, &hProc);
if (error <= 32) {
// Process error
} else {
// Some actions
}
然而 SW_SHOWMINNOACTIVE 参数被某些播放器忽略(例如 MediaPlayerClassic HomeCinema - MPC HC),这导致打开播放器时更改前景 window 甚至显示播放器 window 在某些 PC 上未最小化。
第一个问题是:是否可以在"silent"模式下强制打开播放器(最小化且不激活)?
我也尝试过使用 GetForegroundWindow 和 SetForegroundWindow,直到我添加 Sleep 在 OpenFileWithDefaultProgram 之后(据我了解,播放器需要一些时间来初始化,在此期间前景 window 不会改变):
HWND hWndForeground = GetForegroundWindow();
HANDLE hProc;
int error = OpenFileWithDefaultProgram(path, SW_SHOWMINNOACTIVE, &hProc);
if (error <= 32) {
// Process error
} else {
Sleep(100);
SetForegroundWindow(hWndForeground);
// Some actions
}
这段代码完美地恢复了前景window,但我不喜欢我需要用作Sleep函数参数的常量。
因此,第二个问题是:是否可以在播放器初始化的那一刻"wake up"线程?或者,我应该如何确定播放器初始化所需的时间(考虑到默认播放器可以是任何东西并且启动时间完全不同)?
注:
- 我试过调用 WaitForSingleObject(hProc, INFINITE),它没有完成等待,因为播放器在播放后没有终止;
- 我尝试调用 WaitForInputIdle(hProc, INFINITE),它立即 returns 没有等待(可能是因为播放器没有消息队列)。
The first question is: is it possible to force opening player in "silent" mode (minimized and not becoming active)?
不,你能做的最好的就是请求它,请求可以被忽略。你已经发现了那个部分。
The second question: is it possible to "wake up" the thread at the exact moment when the player is initialized?
不,没有定义进程完全初始化的时刻。您已经发现 WaitForInputIdle
及其限制。但是想象一个媒体播放器在后台获取 CD 封面图像(不是那么牵强,不需要为此延迟音频)——它什么时候完成初始化?
此外,请记住 ShellExecute
甚至可能不会启动新进程。如果有一个现有的,它可能会用它来打开文件。
在我的 WinAPI C++ 应用程序中,我尝试使用 ShellExecuteEx:
使用默认系统播放器打开音频文件int OpenFileWithDefaultProgram(const std::wstring& path, int showMode, HANDLE* hProc) {
SHELLEXECUTEINFO shInfo;
::ZeroMemory(&shInfo, sizeof(SHELLEXECUTEINFO));
shInfo.cbSize = sizeof(SHELLEXECUTEINFO);
shInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shInfo.hwnd = NULL;
shInfo.lpVerb = L"open";
shInfo.lpFile = path.c_str();
shInfo.nShow = showMode;
::ShellExecuteEx(&shInfo);
*hProc = shInfo.hProcess;
return (int)shInfo.hInstApp;
}
OpenFileWithDefaultProgram函数是这样调用的:
HANDLE hProc;
int error = OpenFileWithDefaultProgram(path, SW_SHOWMINNOACTIVE, &hProc);
if (error <= 32) {
// Process error
} else {
// Some actions
}
然而 SW_SHOWMINNOACTIVE 参数被某些播放器忽略(例如 MediaPlayerClassic HomeCinema - MPC HC),这导致打开播放器时更改前景 window 甚至显示播放器 window 在某些 PC 上未最小化。
第一个问题是:是否可以在"silent"模式下强制打开播放器(最小化且不激活)?
我也尝试过使用 GetForegroundWindow 和 SetForegroundWindow,直到我添加 Sleep 在 OpenFileWithDefaultProgram 之后(据我了解,播放器需要一些时间来初始化,在此期间前景 window 不会改变):
HWND hWndForeground = GetForegroundWindow();
HANDLE hProc;
int error = OpenFileWithDefaultProgram(path, SW_SHOWMINNOACTIVE, &hProc);
if (error <= 32) {
// Process error
} else {
Sleep(100);
SetForegroundWindow(hWndForeground);
// Some actions
}
这段代码完美地恢复了前景window,但我不喜欢我需要用作Sleep函数参数的常量。
因此,第二个问题是:是否可以在播放器初始化的那一刻"wake up"线程?或者,我应该如何确定播放器初始化所需的时间(考虑到默认播放器可以是任何东西并且启动时间完全不同)?
注:
- 我试过调用 WaitForSingleObject(hProc, INFINITE),它没有完成等待,因为播放器在播放后没有终止;
- 我尝试调用 WaitForInputIdle(hProc, INFINITE),它立即 returns 没有等待(可能是因为播放器没有消息队列)。
The first question is: is it possible to force opening player in "silent" mode (minimized and not becoming active)?
不,你能做的最好的就是请求它,请求可以被忽略。你已经发现了那个部分。
The second question: is it possible to "wake up" the thread at the exact moment when the player is initialized?
不,没有定义进程完全初始化的时刻。您已经发现 WaitForInputIdle
及其限制。但是想象一个媒体播放器在后台获取 CD 封面图像(不是那么牵强,不需要为此延迟音频)——它什么时候完成初始化?
此外,请记住 ShellExecute
甚至可能不会启动新进程。如果有一个现有的,它可能会用它来打开文件。