Get item names from a .NET applications list control using winapi or mfc

c++, mfc, winapi

Solution

Spy++ is an excellent tool, but it's not .Net aware. I suggest trying UISpy.exe on the application as well to see it is able to find more elements than Spy++. UISpy.exe can be found at http://msdn.microsoft.com/en-us/library/ms727247.aspx and there is ManagedSpy.exe as well http://msdn.microsoft.com/en-us/magazine/cc163617.aspx

You can be certain if the application is a .Net application or not by attaching a debugger to it (either Visual Studio or WinDBG; I'd recommend the free version of VC++ if you don't have Visual Studio already as I'm not sure that the C# version has native debugging support). Another option is to utilize depends.exe from the Windows Platform SDK or even just ProcessExplorer.exe from http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx to see what DLLs are loaded into the process (i.e. a .Net app will have the core .Net DLLs loaded).

If the list is actually a Windows Presentation Forms (WPF) list you will likely have to utilize the .Net UIAutomation classes to access the list's contents. UIAutomation is documented here: http://msdn.microsoft.com/en-us/library/ms747327.aspx

Edit: UISpy.exe is now obsolete according to MSDN docs:

Note The Accessible Explorer and UI Spy tools are obsolete and no longer available. Developers should use Inspect or AccScope instead.

Problem

So basically i have this software which outputs data in a list form. Thanks to the comments here we have understood that it is most likely written in .NET. I want to scan the list so i can do some algorithms on the data. Using Spy++ i found that what holds this list is titled "Panel2" and i can get the handle to this (its class is "WindowsForms10.Window.8.app") using EnumChildWindows. However i don't know how to get to the list itself so i can read its items. I have tried EnumChildWindows on the "Panel2" handle and outputting the caption of all those windows but they are all empty. Can panel2 be the actuall list? If so could i just cast it to (CListCtrl*) ? Axilles mentions in the comments that it probably is written in .NET, wold it be possible to get the controlID / handle to the list using something like http://reflector.red-gate.com/download.aspx?TreatAsUpdate=1 ? ``` CWnd* mainWindow; CWnd* panel; CListCtrl* list; BOOL CALLBACK findWindow( HWND hwnd,LPARAM lParam) { char text[8]; GetWindowText(hwnd,text,8); if(strcmp(text,"Fetcher") == 0) { mainWindow= CWnd::FromHandle(hwnd); return false; } return true; } BOOL CALLBACK findPanel(HWND hwnd,LPARAM lParam) { char text[7]; GetWindowText(hwnd,text,7); if(strcmp(text,"Panel2") == 0) { panel = CWnd::FromHandle(hwnd); return false; } return true; } void CAnalyzeDlg::OnBnClickedButton1() { mainWindow = 0; while(mainWindow == 0) { ::EnumWindows(findWindow,0); } mainWindow ->ActivateTopParent(); while(panel == 0) ::EnumChildWindows(mainWindow ->m_hWnd,findPanel,0); CWnd* pointTest = NULL; CString text = ""; int xx = 337; int yy = 95; while(yy < 1024 && (pointTest == NULL || strcmp(text,"") == 0 || strcmp(text,"Panel2") == 0)) { pointTest = mainWindow->ChildWindowFromPoint(CPoint(xx,yy)); yy++; if(pointTest != 0) pointTest->GetWindowTextA(text); } if(strcmp(text,"") != 0) MessageBox(0,text,0); // This never shows } ```

Original source