Я потратил некоторое время и попытался воссоздать вашу проблему.
Согласно моему анализу (который занял некоторое время, потому что сначала я не запустил 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
Как вы можете видеть, выходные данные также включают заголовки, такие как Уведомитель или Подсказка , которые появляются, когда появляется Окно уведомлений или когда вы наводите указатель мыши на значок в приложение SideSync . Как можно видеть на выходе, MainWindowHandle
активного окна тоже меняется.
Так что, по моему мнению, вам просто нужно получить SideSync процесс с Process.GetProcessesByName("SideSync")
, больше ничего.
Надеюсь, это поможет; -)
Обновление:
Согласно комментарию ОП, ему нужен способ открыть одно конкретное окно процесса SideSync , независимого от которого он был открыт в последний раз. Чтобы добиться этого, первым шагом является поиск соответствующих дескрипторов окон, которые принадлежат процессу SideSync .
Я основал следующий код на коде ответа от cREcker , который основал свой ответ на ресурсе Получение списка всех открытых окон .
Метод GetOpenWindowsByProcessId следующего класса позволяет получить дескриптор всех окон, принадлежащих указанному идентификатору процесса.
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);
}