使用C#启动远程进程时出现问题

3

我正在使用System.Diagnostics.Process.Start来启动另一个域机器上的远程应用程序。

不幸的是,如果远程进程已经在远程机器的桌面背景中运行,Process.Start无法使应用程序获得焦点。

问题1:是否有其他API或机制可以强制远程应用程序获得焦点或闪烁以引起用户的注意?

我注意到的另一个问题是,如果远程进程已经在运行,则可能会执行新实例,而不是重用现有进程资源。这违反了MSDN文档中的规定:

"如果进程已经在运行,则不会启动任何其他进程资源。相反,将重用现有进程资源,并且不会创建新的Process组件。在这种情况下,Start返回null而不是返回新的Process组件。"

问题2:有人找到了一种方法,在这种情况下防止应用程序启动第二个实例吗?对于远程启动应用程序,WMI是否是更好的选择?


你能修改你试图调用的应用程序的代码吗(或者愿意这样做)? - PedroC88
不幸的是,它是一个第三方显微镜控制器/图像记录器。我的设置是一个地质实验室,有2台惠普TouchSmart个人电脑。我的应用程序在左侧显示器上运行,当用户单击/触摸显微镜按钮时,理想情况下会在右侧显示器上启动(或前置)这个第三方应用程序。 - retrodrone
@ChrisB,实际上我没有。这似乎是一个可行的方法...但在那个应用程序中,设置焦点到我的目标应用程序的API是什么?看起来我有同样的问题。 - retrodrone
好的,辅助程序可以检查进程是否已经启动(类似于http://www.vcskicks.com/single-instance.php)。问题的一部分已经解决了。 - Jess
@retrodrone - 使用PInvoke调用Win32 API可以让你对窗口焦点、位置等进行几乎任何操作 - 下面mazzzzz的回答就是一个很好的例子。 - Chris B
显示剩余2条评论
1个回答

2

好的,不知道这对你有多大帮助,但这是一个示例类,你可以在辅助程序中使用它。这只是一个开始,如果你打算使用它,你需要一个网络系统(使用C#并不太麻烦)。告诉我它对你有什么用。

/// <summary>
/// Allows you to start a specified program, or if it is already running, bring it into focus
/// </summary>
static class SFProgram
{
    static public void StartFocus(string FileName, string ProcessName)
    {
        if (!ProcessStarted(ProcessName))
            Process.Start(FileName);
        else
            SFProgram.BringWindowToTop("notepad");
    }

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SetForegroundWindow(IntPtr hWnd);
    [DllImport("user32.dll")]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    /// <summary>
    /// Bring specified process to focus
    /// </summary>
    /// <param name="windowName">Process Name</param>
    /// <returns>If it was successful</returns>
    private static bool BringWindowToTop(string windowName)
    {
        Process[] processes = Process.GetProcessesByName(windowName);
        foreach (Process p in processes)
        {
            int hWnd = (int)p.MainWindowHandle;
            if (hWnd != 0)
            {
                return SetForegroundWindow((IntPtr)hWnd);
            }
            //p.CloseMainWindow();
        }
        return false;
    }

    private static bool ProcessStarted(string ProcessName)
    {
        Process[] processes = Process.GetProcessesByName(ProcessName);
        return (processes.Length > 0);
    }
}

谢谢你的代码,我还没有机会尝试它。也许明天吧。我很感激。 - retrodrone
没问题,我更愿意指导你正确的方向(不喜欢只是为别人写点东西),但这似乎只是辅助程序的一小部分。 - Jess
我的实现非常完美,感谢 @mazzzzz。我加强了 Process.Start 来要求用户凭据。我不需要在目标上运行随机代码。谢谢! - retrodrone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接