C# 使最小化/系统托盘应用程序gui从c可见#
我有一个windows窗体应用程序,可以打开其他供应商的应用程序。如果供应商的应用程序未运行,“我的代码”将打开它,它将按预期显示。但是,如果供应商的应用程序已经在运行或在系统托盘中,则在调用C# 使最小化/系统托盘应用程序gui从c可见#,c#,.net,winforms,process,C#,.net,Winforms,Process,我有一个windows窗体应用程序,可以打开其他供应商的应用程序。如果供应商的应用程序未运行,“我的代码”将打开它,它将按预期显示。但是,如果供应商的应用程序已经在运行或在系统托盘中,则在调用Process.Start()时,无法使其可见。是否有办法使当前运行的应用程序可见/显示,无论是最小化还是在系统托盘中 这是我打开另一个应用程序的代码,该应用程序只有在VendorProgram.exe未运行时才能工作。如果VendorProgram.exe正在运行,但最小化了,则不会使其可见/显示,这就是
Process.Start()
时,无法使其可见。是否有办法使当前运行的应用程序可见/显示,无论是最小化还是在系统托盘中
这是我打开另一个应用程序的代码,该应用程序只有在VendorProgram.exe
未运行时才能工作。如果VendorProgram.exe
正在运行,但最小化了,则不会使其可见/显示,这就是我需要的
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "C:\\Program Files (x86)\\VendorProgram.exe";
startInfo.WindowStyle = ProcessWindowStyle.Normal;
Process p = Process.Start(startInfo);
编辑:如果不清楚,我不是想让一个应用程序自己打开,我是想从我的应用程序中打开一个独立供应商的应用程序。首先,你有点想重新发明轮子。正如Steve在评论中指出的那样,已经有了实现单实例应用程序的内置方法,例如使用 然而,“当它最小化到托盘时显示它”部分是一个棘手的部分 您可以循环运行的进程来查找您的进程,然后可以选择启动一个新进程,或者调用已经运行的进程。这需要一点p/invoke魔法:
[DllImport("user32.dll")]
private static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
[DllImport("user32.dll")]
private static extern Boolean SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow);
var bFound = false;
foreach (var proc in Process.GetProcesses())
{
if (proc.ProcessName.Equals("YourProcessName"))
{
var window = FindWindow(null, proc.MainWindowTitle);
if (!window.Equals(IntPtr.Zero))
{
//Mixed results...this might be redundant
SetForegroundWindow(window);
ShowWindow(window, 1); //SW_NORMAL
bFound =true;
}
}
}
if (!bFound)
{
var startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "C:\\Program Files (x86)\\Program.exe";
startInfo.WindowStyle = ProcessWindowStyle.Normal;
Process.Start(startInfo);
}
我找到了,它帮助我做了我需要的事情
诀窍是在FindWindow()
而不是process.MainWindowTitle
中使用正确的窗口名。显然,process.MainWindowTitle
会返回应用程序创建的第一个窗口。这有时可能有效,但并不总是有效。我需要将最小化的实际窗口的名称放在系统托盘中。例如,使用记事本,如果标题是my file-notepad
,则需要将其放入FindWindow
。这看起来很笨拙,但每次对我都有效。记事本不是我要打开的应用程序,但它就是一个例子
这不管用
foreach (var proc in Process.GetProcesses()) {
if (proc.ProcessName.Equals("Notepad"))
{
IntPtr window = FindWindow(null, proc.MainWindowTitle);
ShowWindow(hWnd, 1);
break;
}
}
确实如此
IntPtr window = FindWindow(null, "my file - Notepad");
ShowWindow(hWnd, 1);
你试过使用
[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
与“ShowWindow(IntPtr hWnd,int nCmdShow)”不同?请仔细阅读,当外部应用程序在任务栏(而不是任务栏)中时,没有标准的方法让它“显示自己”.@Idle\u Mind的“无标准方法”是指它不可能从
.net/c
中实现吗?不……在Windows中,没有简单或万无一失的方法从托盘“恢复”应用程序。使用托盘图标时显示的窗口/表单可能与最初启动应用程序时显示的表单相同,也可能不同;应用程序可能会创建表单的新实例。换句话说,主窗体和托盘图标不一定相互绑定。据我所知,也没有windows消息可以发送到任务栏图标以使其“还原”…我只是试图从c#打开正在运行的应用程序的gui,而不是重新发明轮子。您的示例看起来很有希望,但无论是最小化还是在系统托盘中,它都没有打开正在运行的进程的形式SetForeground
和ShowWindow
没有执行任何操作。您可以尝试不使用window
变量,而是将其用法替换为proc.MainWindowHandle
FindWindow
将找到第一个匹配项,可能它返回了错误的句柄。MainWindowHandle
也没有这样做。