0

对于一个项目,我必须在 C# 中启动一个应用程序,撕掉与流程相关的 AutomationElement 树,然后关闭应用程序并输出树。我通过使用 Process.Start 打开应用程序来做到这一点。然后,我找到了与生成的进程相关的 AutomationElement,并结合使用 TreeWalker 和 AutomationElement 的 FindFirst 和 FindAll 方法来遍历树。

这在我的计算机上运行良好,并在本地使用 NUnit 正确运行。它也可以在我组计算机中的其他人上运行。问题是它永远不会在我们运行 Hudson 的中央测试服务器上运行。经过几个小时的调试,我在 Hudson 上进行了测试,启动应用程序,然后打印第一级 AutomationTree。在我的电脑上,这会打印我桌面上的所有窗口。在 Hudson 上,这仅打印桌面。

考虑到可能有多个桌面,我尝试在 RootElement 上使用 TreeWalker 的 GetNextSibling 函数。它仍然只报告了一个桌面。

这是我用来启动进程的代码。

public bool connect(string[] args)
{
    if (this.process != null) {
        Console.WriteLine("ERROR: Process already connected");
        return false;
    }

    if (!File.Exists(sApplicationPath)) {
        Console.WriteLine(sApplicationPath + " does not exist");
        return false;
    }

    // Turn the command arguments into a single string
    string arguments = "";
    foreach (string arg in args) {
        arguments += arg + " ";
    }

    try {
        // Start the application
        ProcessStartInfo processStartInfo =
            new ProcessStartInfo(sApplicationPath);
        processStartInfo.Arguments = arguments;
        this.process = Process.Start(processStartInfo);

        // Must be a positive integer (non-zero)
        if ( !( iInitialDelay > 0 )  ) {
            Console.WriteLine("Invalid initial delay. " +
                              "Defaulting to 5 seconds.");
            this.iInitialDelay = 5000;
        }

        Thread.Sleep(this.iInitialDelay);
    } catch (Exception ex) {
        Console.WriteLine("WGApplication.connect: " + ex.Message);
        return false;
    }

    // Check if the process still exists
    try {
        /** This part does not return an error, so I think that means the process exists and is started */
        Process check = Process.GetProcessById(process.Id);
    } catch (ArgumentException ex) {
        Console.WriteLine("The process expired before connection was complete");
        Console.WriteLine("Make sure the process is not open anywhere else");
        Console.WriteLine("and that it is able to execute on the host machine.");
        return false;
    }

    // Check if the base automation element exists to verify open
    AutomationElement rootWindow =
        AutomationElement.RootElement.FindChildProcessById(process.Id);
    /** This part returns null, so it can't find the window associated with this process id */

    if (this.process == null) {
        return false;
    } else if (rootWindow == null) {
        // A root window with this process id has not been found
        Console.WriteLine("Cannot find the root window of the created " +
                          "process. Unknown error.");
        return false;
    } else {
        // Everything is good to go
        return true;
    }
}

sApplicationPath 设置为可执行文件的绝对路径。iInitialDelay 是确保应用程序有时间启动的延迟。我在 Windows Vista SP2 上的“C:\Windows\System32\notepad.exe”上运行它,并使用 v3.5 C# 编译器对其进行编译。

FindChildProcessById 定义如下:

public static AutomationElement FindChildProcessById(
    this AutomationElement element, int processId)
{
    var result = element.FindChildByCondition(
        new PropertyCondition(AutomationElement.ProcessIdProperty,
                              processId));

    return result;
}

请记住,这可以在我的计算机上编译并运行。我在 Hudson 上的测试程序说 RootElement 根本没有孩子。

所以我启动应用程序,确认它存在,然后我找不到与该进程关联的任何窗口。除了桌面,我找不到任何与任何东西相关联的窗口。

这是哈德森的问题吗?Hudson 是否以某种特定方式工作,而该代码无法在其上工作?我的代码有问题吗?Hudson 服务器在 Windows Server 2003 计算机上运行。任何帮助,将不胜感激。我知道这是一个非常具体的问题,这就是我在网上找不到任何解决方案的原因。

4

1 回答 1

1

Hudson 是否作为服务运行?如果是这样,它可能没有显示窗口的必要权限。

于 2010-04-26T19:02:22.670 回答