I took some time and tried to recreate your problem.
According to my analysis (which took some time because I did not get SideSync correctly running at first ;-)) there exists only one process running under the name SideSync.exe which hosts multiple windows.
I guess the "flaw" in your approach is that you are trying to fetch the process by the MainWindowTitle
. But if you use the following code snippet you will see, that the MainWindowTitle
changes depending on the currently active window in that process.
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);
}
In my case the MainWindowTitle
changed between different titles like:
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
As you can see the output also includes titles like Notifier or ToolTip which appear when a Notification Window appears or you move the mouse over an Icon in the SideSync application. As can further be seen in the output the MainWindowHandle
of the active window changes too of course.
So in my opinion you just need to fetch the SideSync process with Process.GetProcessesByName("SideSync")
, nothing else.
I hope this helps ;-)
Update:
According to the OPs comment he needs a way to open one specific window of the SideSync process indipendent on which was opened the last time. In order to achieve this, the first step is to find the corresponding window handles of the windows that belong to the SideSync process.
I have based the following code on the code of the answer from cREcker, who has based his answer on the resource Getting a list of all the open windows.
The method GetOpenWindowsByProcessId of the following class allows to get the handle of all windows which belong to the specified process 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);
}
In addition we will need a way to "show" a window.
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);
With this knowledge we can now write code like the following one (which can for sure be optimized in thousand different ways):
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);
}