Skip to content

Commit b854d4a

Browse files
committed
Made sure all our pattern calls are now try/catch safe to avoid crashing
1 parent 1c9639a commit b854d4a

3 files changed

Lines changed: 44 additions & 9 deletions

File tree

src/FlaUInspect/ViewModels/ElementViewModel.cs

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77
using System.Collections.ObjectModel;
88
using System.Windows.Input;
99
using MenuItem = System.Windows.Controls.MenuItem;
10+
using User32=FlaUI.Core.WindowsAPI.User32;
1011
namespace FlaUInspect.ViewModels;
1112

1213
public class ElementViewModel(AutomationElement? automationElement, ILogger? logger) : ObservableObject {
1314
private readonly object _lockObject = new ();
1415
public AutomationElement? AutomationElement { get; } = automationElement;
1516
private RelayCommand? _refreshItemCommand;
1617
private RelayCommand? _focusCommand;
18+
private RelayCommand? _focusNativeCommand;
1719

1820
public bool IsExpanded {
1921
get => GetProperty<bool>();
@@ -47,24 +49,55 @@ public bool IsSelected {
4749
});
4850

4951
public ICommand FocusCommand =>
50-
_focusCommand ??= new((_) => {
52+
_focusCommand ??= CreateDelayedSafeCommand(AutomationElement.Focus);
53+
54+
public ICommand FocusNativeCommand =>
55+
_focusNativeCommand ??= CreateDelayedSafeCommand(DoNativeFocus);
56+
57+
private async void DoNativeFocus() {
58+
try{
59+
//await Task.Delay(250);
60+
if (AutomationElement.Properties.ProcessId.TryGetValue(out int processId)){
61+
var proc = System.Diagnostics.Process.GetProcessById(processId);
62+
var res = User32.SetForegroundWindow(proc.MainWindowHandle);
63+
await Task.Delay(100);
64+
}
65+
AutomationElement.FocusNative();
66+
}catch(Exception ex){
67+
System.Diagnostics.Debug.WriteLine(ex.ToString());
68+
}
69+
}
70+
71+
private static RelayCommand CreateDelayedSafeCommand(Action action, int delayMs=250){
72+
var delayedAction = CreateDelayedSafeAction(action,delayMs);
73+
return new RelayCommand(_ => delayedAction());
74+
}
75+
/// <summary>
76+
/// Mouse/focus related commands need a delay to allow our mosue action t obe handled first or we resteal the mouse
77+
/// </summary>
78+
/// <param name="action"></param>
79+
/// <param name="delayMs"></param>
80+
/// <returns></returns>
81+
public static Action CreateDelayedSafeAction(Action action, int delayMs=250) {
82+
return async () => {
5183
try {
52-
AutomationElement.Focus();
84+
await Task.Delay(delayMs);
85+
action();
5386
} catch { }
54-
});
55-
87+
};
88+
}
5689

5790
private ObservableCollection<MenuItem>? _mouseActions;
5891
public ObservableCollection<MenuItem> MouseActions { get => _mouseActions ??= BuildMouseActions(); }
5992

6093
private ObservableCollection<MenuItem> BuildMouseActions() {
6194
return [
62-
CreateMenuItem("Left Click", () => AutomationElement?.Click()),
63-
CreateMenuItem("Right Click", () => AutomationElement?.RightClick()),
64-
CreateMenuItem("Double Click", () => AutomationElement?.DoubleClick()),
95+
CreateMenuItem("Left Click", CreateDelayedSafeAction(() => AutomationElement?.Click())),
96+
CreateMenuItem("Right Click", CreateDelayedSafeAction(() => AutomationElement?.RightClick())),
97+
CreateMenuItem("Double Click", CreateDelayedSafeAction(() => AutomationElement?.DoubleClick())),
6598
];
6699
}
67-
100+
private MenuItem CreateMenuItem(string header, Action<object> value) => CreateMenuItem(header,()=>value(default));
68101
private MenuItem CreateMenuItem(string header, Action value) {
69102
return new MenuItem {
70103
Header = header,

src/FlaUInspect/ViewModels/MainViewModel.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,8 @@ private void ReadPatternsForSelectedItem(AutomationElement? selectedItemAutomati
216216
System.Windows.Controls.MenuItem actionMenuItem = new() {
217217
Header = $"{patternItem.Key}"
218218
};
219-
actionMenuItem.Click += (_, _) => patternItem.Action?.Invoke();
219+
var safeAction = ElementViewModel.CreateDelayedSafeAction(patternItem.Action);
220+
actionMenuItem.Click += (_, _) => safeAction();
220221
PatternActionContextItems.Add(actionMenuItem);
221222
}
222223
}

src/FlaUInspect/Views/MainWindow.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@
320320
<ContextMenu>
321321
<MenuItem Header="Refresh Children" Command="{Binding RefreshItemCommand}" />
322322
<MenuItem Header="Focus" Command="{Binding FocusCommand}" IsCheckable="False" />
323+
<MenuItem Header="Native Front &amp; Focus" Command="{Binding FocusNativeCommand}" IsCheckable="False" />
323324
<MenuItem Header="Pattern Actions" ItemsSource="{Binding PlacementTarget.Tag.PatternActionContextItems, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}" Visibility="{Binding PlacementTarget.Tag.PatternActionContextItems.Count, Converter={StaticResource CountToVisibilityConverter}, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}" />
324325
<MenuItem Header="Mouse Actions" ItemsSource="{Binding MouseActions}" />
325326
</ContextMenu>

0 commit comments

Comments
 (0)