gpt4 book ai didi

C# 最小化窗口未通过调用 System.Diagnostics.Process.GetProcesses() 返回

转载 作者:可可西里 更新时间:2023-11-01 12:45:47 24 4
gpt4 key购买 nike

我试图找到一个最小化的窗口并显示它。

该程序可以从三星下载,名称为“SideSync”。要完全复制我的问题,您需要安装它并且还需要将三星手机插入您的计算机。

这是它完全配置和运行的屏幕截图:

enter image description here

观察到有两个窗口,A和B。我用一个名为Microsoft Inspect的工具确定这两个程序窗口是正常窗口。他们没有父子关系。但是,当我启动 SideSync 时,只出现窗口 A。然后我必须单击“电话屏幕”,然后出现窗口 B(除了窗口 A)。这可能是解决此问题的线索?我们拭目以待。

这是在 Microsoft Inspect 中显示的两个窗口:

enter image description here

两个窗口都有窗口标题。使用下面的代码,我可以检索窗口的 Process(这是我的目标)。

服务器代码:

public static Process GetProcessByWindowTitle(string windowTitleContains)
{
foreach (var windowProcess in GetWindowProcesses())
if (windowProcess.MainWindowTitle.Contains(windowTitleContains))
return windowProcess;

return null;
}

但是,一些奇怪的行为正在发生。 GetProcessByWindowTitle() 将返回一个而不是两个进程。我假设因为有两个窗口,所以必须有两个进程。

它返回哪个 Process 取决于我用鼠标单击的最后一个窗口。

例如,如果我上次单击窗口 A;然后 GetProcessByWindowTitle("SideSync") 将返回一个 Process,然后 GetProcessByWindowTitle("SAMSUNG") 将返回 void.

...反之亦然,如果我最后一次单击窗口 B,GetProcessByWindowTitle("SideSync") 将返回一个 void,但随后 GetProcessByWindowTitle("SAMSUNG ") 将返回 Process

客户端代码:

[Ignore("Requires starting SideSync and clicking one of the windows. Only the last clicked will return a Process.")]
[Test]
public void NonMinimizedWindowProcessIsDetected()
{

Process p1 = Windows.GetProcessByWindowTitle("SAMSUNG");

if(p1==null) { Console.WriteLine("SAMSUNG process is null.");}
else { Console.WriteLine("SAMSUNG process detected.");}

Process p2 = Windows.GetProcessByWindowTitle("SideSync");

if (p2 == null) { Console.WriteLine("SideSync process is null."); }
else { Console.WriteLine("SideSync process detected."); }
}

我的目标是显示窗口 B。我的问题是,这只有在我最后单击它时才有可能,这会产生不需要的依赖性。我希望能够独立于任何点击顺序显示窗口 B。

最佳答案

我花了一些时间尝试重现您的问题。根据我的分析(这花了一些时间,因为一开始我没有正确运行 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

如您所见,输出还包括诸如 NotifierToolTip 之类的标题,它们会在 Notification Window 出现或您将鼠标移到上方时出现SideSync 应用程序中的图标。从输出中可以进一步看出,事件窗口的 MainWindowHandle 当然也发生了变化。

所以在我看来,您只需要使用 Process.GetProcessesByName("SideSync") 获取 SideSync 进程,没有别的。

希望对您有所帮助 ;-)

更新:

根据 OP 的评论,他需要一种方法来打开独立于上次打开的 SideSync 进程的一个特定窗口。为了实现这一点,第一步是找到属于 SideSync 进程的窗口的相应窗口句柄。

我根据 cREcker 的答案代码编写了以下代码,他的答案基于资源 Getting a list of all the open windows .

以下类的方法 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);
}

关于C# 最小化窗口未通过调用 System.Diagnostics.Process.GetProcesses() 返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53052163/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com