从 C# 启动远程进程的问题

Posted

技术标签:

【中文标题】从 C# 启动远程进程的问题【英文标题】:Issues with launching a remote process from C# 【发布时间】:2011-06-25 01:51:37 【问题描述】:

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

不幸的是,如果远程进程已经在运行,但在远程计算机桌面的后台,应用程序不会使用 Process.Start 获得焦点。

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

我注意到的另一个问题是,如果远程进程已经在运行,除了原始实例之外,还可能会执行一个新实例。这违反了 MSDN 的文档,该文档说:

"如果进程已经在运行,则不启动额外的进程资源。而是重用现有的进程资源,并且不创建新的Process组件。在这种情况下,Start不是返回新的Process组件,而是返回null到调用过程。”

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

【问题讨论】:

您可以修改您尝试调用(或愿意)的应用程序的代码吗? 不,不幸的是,它是第 3 方显微镜控制器/图像记录器。我的设置是一个带有 2 台 HP TouchSmart PC 的地质实验室。我的应用程序在左侧显示器上运行,当用户点击/触摸显微镜按钮时,理想情况下它会在右侧显示器上启动(或启动)这个第 3 方应用程序。 哦,好吧,我正要建议使用 Mutex 类,以确保一次运行不超过 1 个应用程序实例。但如果你不能修改它,那我的手就束手无策了。 我假设您已经考虑在第二台机器上安装一个小型辅助应用程序? @ChrisB,实际上我没有。这似乎是一种可行的方法......但在那个应用程序中,将焦点设置到我想要的目标应用程序的 API 是什么?看来我也有同样的问题。 【参考方案1】:

好吧,不知道这对你有多大的帮助,但它是一个你可以在帮助程序中使用的示例类。这只是一个开始,如果您打算使用它,您将需要一个网络系统(虽然 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);
    

【讨论】:

感谢代码,我还没有机会尝试。明天吧。我很感激。 没问题,我更愿意为您指明正确的方向(讨厌只是为某人写东西),但这似乎只是帮助程序的一小部分。 我的实现很漂亮,谢谢@mazzzzz。我加强了 Process.Start 以要求用户凭据。我不需要在目标上运行随机代码。谢谢!

以上是关于从 C# 启动远程进程的问题的主要内容,如果未能解决你的问题,请参考以下文章

远程启动应用程序时无法从 psexec 接收异步输出

如何从 C# 应用程序远程调用另一个进程方法

如何从 C# 启动进程?

直接在机器上启动进程和从远程桌面连接启动进程之间的区别

无法使用 WMI 和 C# 远程终止进程

如何在不提供 C# 管理员凭据的情况下从标准用户启动进程