UIAutomation throws AccessViolationException on Windows 11

ygosteli 31 Reputation points
2022-07-06T06:20:51.55+00:00

Original post on stackoverflow: https://stackoverflow.com/questions/72872197/uiautomation-throws-accessviolationexception-on-windows-11
Also posting here as there might be more views, maybe from people at MSFT too. If it's considered duplicata, please close topic.

The issue:

We have an application written in C# that uses UIAutomation to get the current text (either selected or the word behind the carret) in other applications (Word, OpenOffice, Notepad, etc.).

All is working great on Windows 10, even up to 21H2, last update check done today. But we had several clients informing us that the application is closing abruptly on Windows 11.

After some debugging I've seen some System.AccessViolationException thrown when trying to use the TextPatternRange.GetText() method:

System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

What we've tried so far:

Reproductible example

In order to be able to isolate the issue (and check it was not something else in our app that was causing the exception) I quickly made the following test (based on : How to get selected text of currently focused window? validated answer)

private void btnRefresh_Click(object sender, RoutedEventArgs e)  
    {  
        var p = Process.GetProcessesByName("notepad").FirstOrDefault();  
        var root = AutomationElement.FromHandle(p.MainWindowHandle);  
  
        var documentControl = new  
                PropertyCondition(AutomationElement.ControlTypeProperty,  
                                  ControlType.Document);  
  
        var textPatternAvailable = new PropertyCondition(AutomationElement.IsTextPatternAvailableProperty, true);  
  
        var findControl = new AndCondition(documentControl, textPatternAvailable);  
  
        var targetDocument = root.FindFirst(TreeScope.Descendants, findControl);  
        var textPattern = targetDocument.GetCurrentPattern(TextPattern.Pattern) as TextPattern;  
  
        string text = "";  
        foreach (var selection in textPattern.GetSelection())  
        {  
            text += selection.GetText(255);  
            Console.WriteLine($"Selection: \"{selection.GetText(255)}\"");  
        }  
  
        lblFocusedProcess.Content = p.ProcessName;  
        lblSelectedText.Content = text;  
    }  

When pressing a button, this method is called and the results displayed in labels. The method uses UIAutomation to get the notepad process and extract the selected text.

This works well in Windows 10 with latest update, crashes immediately on Windows 11 with the AccessViolationException. On Windows 10 it works even without the uiaccess=true setting in the manifest.

Questions/Next steps

Do anyone know/has a clue about what can cause this? Is Windows 11 way more regarding towards UIAutomation?

On my side I'll probably open an issue by Microsoft. And one track we might follow is getting an EV and sign the app itself and the installer as it'll also enhance the installation process, removing the big red warnings. But as this is an app distributed for free we had not done it as it was working without it.

I'll also continue testing with the reproductible code and update this question should anything new appear.

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,681 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,310 questions
Windows 11
Windows 11
A Microsoft operating system designed for productivity, creativity, and ease of use.
8,294 questions
{count} vote

Accepted answer
  1. Castorix31 81,831 Reputation points
    2022-07-06T08:51:12.043+00:00

    Maybe you can test with UIAutomationCore and IUIAutomation :
    (I don't have Windows 11, so only tested on Windows 10)

       // Add reference to : "C:\Windows\system32\UIAutomationCore.dll" (UIAutomationClient : Embed Interop Types = False)  
       // Add : using UIAutomationClient;  
       // Add : using System.Runtime.InteropServices;  
    
            var p = System.Diagnostics.Process.GetProcessesByName("notepad").FirstOrDefault();  
            IntPtr hWndNotepad = p.MainWindowHandle;  
            if (hWndNotepad != IntPtr.Zero)  
            {  
                IUIAutomation pUIAutomation = new CUIAutomation8();  
                if (pUIAutomation != null)  
                {  
                    IUIAutomationTextPattern pTextPattern = null;  
                    IUIAutomationElement pWindowElement = pUIAutomation.ElementFromHandle(hWndNotepad);  
                    IUIAutomationCacheRequest pCacheRequest = pUIAutomation.CreateCacheRequest();  
                    if (pCacheRequest != null)  
                    {  
                        pCacheRequest.AddProperty(UIA_PropertyIds.UIA_IsTextPatternAvailablePropertyId);  
                        pCacheRequest.AddPattern(UIA_PatternIds.UIA_TextPatternId);  
                        IUIAutomationCondition pCondition = pUIAutomation.CreatePropertyCondition(UIA_PropertyIds.UIA_ControlTypePropertyId, UIA_ControlTypeIds.UIA_DocumentControlTypeId);  
                        if (pCondition != null)  
                        {  
                            IUIAutomationElement pElement = pWindowElement.FindFirstBuildCache(TreeScope.TreeScope_Children, pCondition, pCacheRequest);  
                            if (pElement != null)  
                            {  
                                bool bRet = (bool)pElement.GetCachedPropertyValue(UIA_PropertyIds.UIA_IsTextPatternAvailablePropertyId);  
                                if (bRet)  
                                {  
                                    pTextPattern = (IUIAutomationTextPattern)pElement.GetCachedPattern(UIA_PatternIds.UIA_TextPatternId);  
                                    if (pTextPattern != null)  
                                    {  
                                        IUIAutomationTextRangeArray pTextRangeArray = pTextPattern.GetSelection();  
                                        if (pTextRangeArray != null)  
                                        {  
                                            string sText = "";  
                                            int nNbItems = pTextRangeArray.Length;  
                                            for (int nItem = 0; nItem <= nNbItems - 1; nItem++)  
                                            {  
                                                IUIAutomationTextRange element = pTextRangeArray.GetElement(nItem);  
                                                sText += element.GetText(-1);                                                 
                                            }  
                                            Console.WriteLine("Selected text = " + sText);  
                                            Marshal.ReleaseComObject(pTextRangeArray);  
                                        }  
                                        Marshal.ReleaseComObject(pTextPattern);  
                                    }                                      
                                }  
                                Marshal.ReleaseComObject(pElement);  
                            }  
                            Marshal.ReleaseComObject(pCondition);  
                        }  
                        Marshal.ReleaseComObject(pCacheRequest);  
                    }  
                    Marshal.ReleaseComObject(pWindowElement);  
                    Marshal.ReleaseComObject(pUIAutomation);  
                }  
            }
    
    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful