我花了一些时间,试图重新创建你的问题。根据我的分析(因为我一开始没有正确运行 SideSync 而花费了一些时间;-)),只有一个名为 SideSync.exe 的进程在运行,它托管多个窗口。
我猜你方法中的“漏洞”是你尝试通过 MainWindowTitle
获取进程。但如果你使用以下代码片段,你会发现MainWindowTitle
取决于该进程中当前激活的窗口,因此不稳定。
while (true)
{
var processes = Process.GetProcesses();
foreach (var process in processes)
{
if (process.ProcessName != "SideSync")
continue;
Console.WriteLine($"{process.ProcessName}, {process.MainWindowTitle}, {process.MainWindowHandle.ToString()}");
}
Thread.Sleep(1000);
}
在我的情况下,MainWindowTitle
在不同的标题之间发生了变化,例如:
SideSync, SideSync, 1313728
SideSync, SideSync, 1313728
SideSync, SideSync, 1313728
SideSync, SideSync, 1313728
SideSync, SideSync, 1313728
SideSync, Notifier, 1903168
SideSync, Notifier, 1903168
SideSync, Notifier, 1903168
SideSync, Notifier, 1903168
SideSync, Notifier, 1903168
SideSync, Notifier, 1903168
SideSync, Notifier, 1903168
SideSync, Notifier, 1903168
SideSync, Notifier, 1903168
SideSync, Samsung Galaxy S7, 3082852
SideSync, Samsung Galaxy S7, 3082852
SideSync, Samsung Galaxy S7, 3082852
SideSync, Samsung Galaxy S7, 3082852
SideSync, ToolTip, 3148196
SideSync, Samsung Galaxy S7, 3082852
SideSync, Samsung Galaxy S7, 3082852
SideSync, Samsung Galaxy S7, 3082852
SideSync, Samsung Galaxy S7, 3082852
SideSync, ToolTip, 3148196
SideSync, ToolTip, 3148196
SideSync, Samsung Galaxy S7, 3082852
SideSync, Samsung Galaxy S7, 3082852
SideSync, SideSync, 1313728
SideSync, SideSync, 1313728
SideSync, SideSync, 1313728
SideSync, SideSync, 1313728
SideSync, SideSync, 1313728
SideSync, SideSync, 1313728
SideSync, SideSync, 1313728
SideSync, SideSync, 1313728
如您所见,输出还包括标题,例如 Notifier 或 ToolTip ,当 Notification Window 出现或将鼠标移动到 SideSync 应用中的图标上时会出现。 正如在输出中进一步看到的那样,活动窗口的 MainWindowHandle
当然也会发生变化。
因此,在我看来,您只需要使用Process.GetProcessesByName("SideSync")
获取 SideSync 进程,仅此而已。
希望这可以帮助您;-)
更新:
根据OP的评论,他需要一种打开 SideSync 进程的一个特定窗口的方法,而不受上次打开哪个窗口的影响。 为了实现这一点,第一步是查找属于 SideSync 进程的窗口的相应窗口句柄。
我基于答案cREcker的代码编写了以下代码,他的答案基于资源获取所有打开窗口的列表。
以下类的GetOpenWindowsByProcessId方法允许获取所有属于指定进程ID的窗口的句柄。
public static class OpenWindowGetter
{
public static IDictionary<string, IntPtr> GetOpenWindowsByProcessId(int processId)
{
IntPtr shellWindow = GetShellWindow();
Dictionary<string, IntPtr> windows = new Dictionary<string, IntPtr>();
EnumWindows(delegate (IntPtr hWnd, int lParam)
{
uint ownerProcessId;
GetWindowThreadProcessId(hWnd, out ownerProcessId);
if (ownerProcessId != processId)
return true;
if (hWnd == shellWindow)
return true;
if (!IsWindowVisible(hWnd))
return true;
int length = GetWindowTextLength(hWnd);
if (length == 0)
return true;
StringBuilder builder = new StringBuilder(length);
GetWindowText(hWnd, builder, length + 1);
windows[builder.ToString()] = hWnd;
return true;
}, 0);
return windows;
}
private delegate bool EnumWindowsProc(IntPtr hWnd, int lParam);
[DllImport("USER32.DLL")]
private static extern bool EnumWindows(EnumWindowsProc enumFunc, int lParam);
[DllImport("USER32.DLL")]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("USER32.DLL")]
private static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("USER32.DLL")]
private static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("USER32.DLL")]
private static extern IntPtr GetShellWindow();
[DllImport("user32.dll", SetLastError = true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
}
此外,我们需要一种方法来“显示”一个窗口。
private const int SW_SHOWNORMAL = 1;
private const int SW_SHOWMINIMIZED = 2;
private const int SW_SHOWMAXIMIZED = 3;
[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
有了这个知识,我们现在可以编写以下代码(当然可以优化成成千上万种不同的方式):
private static void ShowPhoneScreenWindow()
{
const string PROCESSNAME = "sidesync";
const string WINDOWTITLE = "samsung";
var process = Process.GetProcessesByName(PROCESSNAME).FirstOrDefault();
if (process == null)
throw new InvalidOperationException($"No process with name {PROCESSNAME} running.");
var windowHandles = OpenWindowGetter.GetOpenWindowsByProcessId(process.Id);
IntPtr windowHandle = IntPtr.Zero;
foreach (var key in windowHandles.Keys)
if (key.ToLower().StartsWith(WINDOWTITLE))
{
windowHandle = windowHandles[key];
break;
}
if (windowHandle == IntPtr.Zero)
throw new InvalidOperationException($"No window with title {WINDOWTITLE} hosted.");
ShowWindowAsync(windowHandle, SW_SHOWNORMAL);
}