Search code examples
c#vb.netui-automationmicrosoft-ui-automation

Dispatcher.BeginInvoke Error in VB but not C#


Hey all I am using some UIAutomation code that was written in C#. So I converted it into VB.net so that I could integrate it into my own program I am making.

The code that has the error is this line:

Private Sub LogMessage(message As String)
    Dispatcher.BeginInvoke(DispatcherPriority.Normal, New SetMessageCallback(AddressOf DisplayLogMessage), message)
End Sub

The error is on the Dispatcher.BeginInvoke stating Error 1 Reference to a non-shared member requires an object reference..

The code in C# looks like this:

private void LogMessage(string message)
{
    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new SetMessageCallback(DisplayLogMessage), message);
}

And has no errors and works just fine.

What am I missing from the VB.net version to make it work correctly?

The original C# code can be found HERE.

My converted C# to VB.net code looks like this:

Imports System.Threading
Imports Automation = System.Windows.Automation
Imports System.Windows.Automation
Imports System.Windows.Threading

Public Class Form1
    Public Delegate Sub SetMessageCallback(ByVal [_Msg] As String)

    Private Sub Automate()
        LogMessage("Getting RootElement...")
        Dim rootElement As AutomationElement = AutomationElement.RootElement
        If rootElement IsNot Nothing Then
            LogMessage("OK." + Environment.NewLine)

            Dim condition As Automation.Condition = New PropertyCondition(AutomationElement.NameProperty, "UI Automation Test Window")

            LogMessage("Searching for Test Window...")
            Dim appElement As AutomationElement = rootElement.FindFirst(TreeScope.Children, condition)

            If appElement IsNot Nothing Then
                LogMessage("OK " + Environment.NewLine)
                LogMessage("Searching for TextBox A control...")
                Dim txtElementA As AutomationElement = GetTextElement(appElement, "txtA")
                If txtElementA IsNot Nothing Then
                    LogMessage("OK " + Environment.NewLine)
                    LogMessage("Setting TextBox A value...")
                    Try
                        Dim valuePatternA As ValuePattern = TryCast(txtElementA.GetCurrentPattern(ValuePattern.Pattern), ValuePattern)
                        valuePatternA.SetValue("10")
                        LogMessage("OK " + Environment.NewLine)
                    Catch
                        WriteLogError()
                    End Try
                Else
                    WriteLogError()
                End If

                LogMessage("Searching for TextBox B control...")
                Dim txtElementB As AutomationElement = GetTextElement(appElement, "txtB")
                If txtElementA IsNot Nothing Then
                    LogMessage("OK " + Environment.NewLine)
                    LogMessage("Setting TextBox B value...")
                    Try
                        Dim valuePatternB As ValuePattern = TryCast(txtElementB.GetCurrentPattern(ValuePattern.Pattern), ValuePattern)
                        valuePatternB.SetValue("5")
                        LogMessage("OK " + Environment.NewLine)
                    Catch
                        WriteLogError()
                    End Try
                Else
                    WriteLogError()
                End If
            Else
                WriteLogError()
            End If
        End If
    End Sub

    Private Function GetTextElement(parentElement As AutomationElement, value As String) As AutomationElement
        Dim condition As Automation.Condition = New PropertyCondition(AutomationElement.AutomationIdProperty, value)
        Dim txtElement As AutomationElement = parentElement.FindFirst(TreeScope.Descendants, condition)
        Return txtElement
    End Function

    Private Sub DisplayLogMessage(message As String)
        TextBox1.Text += message
    End Sub

    Private Sub LogMessage(message As String)
        Me.Dispatcher.BeginInvoke(DispatcherPriority.Normal, New SetMessageCallback(AddressOf DisplayLogMessage), message)
    End Sub

    Private Sub WriteLogError()
        LogMessage("ERROR." + Environment.NewLine)
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim automateThread As New Thread(New ThreadStart(AddressOf Automate))
        automateThread.Start()
    End Sub
End Class

Solution

  • Found the correct way of doing it:

    Private Sub LogMessage(message As String)
        Me.BeginInvoke(New SetMessageCallback(AddressOf DisplayLogMessage), message)
    End Sub
    

    Thanks goes to @HansPassant for the help.