如何唯一标识从其他应用程序检索的文本框控件?

时间:2016-10-21 06:26:22

标签: winapi

我在C#中编写应用程序来远程控制另一个应用程序。我还没有访问该应用程序,但它最有可能用Visual C ++或VB6编写。我目前正在远程控制我创建的一个简单的C#winforms程序。到目前为止,我可以使用PInvoke以类似于Spy ++的方式获取所有控件。我也可以做一些事情,比如在文本框中设置文本。我遇到的问题是,我无法在我控制的应用程序的执行之间唯一地标识特定的文本框。例如,我不能使用hWnd,因为每次运行应用程序时都会有所不同。 GetWindowLong返回任何hWnd,这样就没有帮助了。互联网谈到了这个名为WM_GETCONTROLNAME的消息。下面的可怕代码试图使用该消息来获取开发人员用于唯一标识控件的名称。 SendMessage似乎正在返回名称中的字节数。但是包含该名称的缓冲区全部返回零。

所以这就是问题所在。如何修复下面的代码,以便正确返回该名称? (希望它是一个容易修复的愚蠢的错误)或者,同样好的,每次运行程序时是否还会保证其他ID相同?如果没有唯一标识文本框控件的内容,我的代码就无法区分它们。

我确实有一个黑客攻击。在我看来,使用文本框的位置来区分它们会起作用。但我更喜欢让下面的代码工作。

    public static string GetWindowText(IntPtr Handle)
    {
        int BufferSize = 256;
        uint Message = RegisterWindowMessage("WM_GETCONTROLNAME");
        StringBuilder sb = new StringBuilder(BufferSize);
        byte[] ControlName = new byte[BufferSize];
        long BytesRead = 0;
        IntPtr BytesReadPointer = new IntPtr(BytesRead);
        IntPtr OtherMem = IntPtr.Zero;

        try
        {
            OtherMem = VirtualAllocEx(Handle, IntPtr.Zero, new IntPtr(sb.Capacity), AllocationType.Commit, MemoryProtection.ExecuteReadWrite);
            var Result = SendMessage(Handle, Message, new IntPtr(sb.Capacity), OtherMem);
            //Result contains different numbers which seem like the correct lengths
            var Result2 = ReadProcessMemory(Handle, OtherMem, ControlName, BufferSize, out BytesReadPointer);
            //ControlName always comes back blank.
        }
        finally
        {
            var Result3 = VirtualFreeEx(Handle, OtherMem, BufferSize, FreeType.Release);
        }

        return ""; // Convert ControlName to a string

    }

1 个答案:

答案 0 :(得分:-2)

所以经过一夜安眠和一点点的修修补补后,我设法自己解决了这个问题。有两个问题。首先,我将控件的句柄传递给VirtualAllocEx。但是在该函数的文档中,它表示它需要处理该过程。所以开始提供它。然后VirtualAllocEx告诉我,我的句柄无效。所以事实证明,传递给VirualAllocEx的句柄必须设置PROCESS_VM_OPERATION。所以我调用了OpenProcess来获取该句柄,然后将其传递给VirtualAllocEx。之后,一切正常。我只需将字节数组转换回字符串,并修剪一堆空值。这将返回控件上的Name属性。我会在这里发布代码,以防其他人需要这样的东西。

eg_id