Ответ 1
РЕДАКТИРОВАТЬ 1 - Уточнение: Для меня контроль не отображается в API автоматизации - если нет возможности однозначно идентифицировать их для автоматизации. Коэффициент идентификации может быть любым из имени, id, родного брата или родителя.
Как и ожидалось, отсутствие идентификаторов автоматизации привело к тому, что элементы управления не были видны в API дерева дерева UI.
Чтобы обойти это и зная, что они видны в приложении Snoop, вы можете использовать базовую логику (которую использует Snoop), чтобы программно автоматизировать эти элементы управления.
Действия
-
Загрузите двоичные файлы для SnoopUI и добавьте их в свой проект. Обязательно сохраните параметр компиляции как "Нет" и скопируйте его в выходной каталог.
-
Следующим шагом будет добавление вспомогательного метода, который использует эти двоичные файлы для ввода вашей DLL с помощью логики автоматизации в целевое приложение (которое является NordVPN) в этом случае. После того, как dll будет введена в целевой процесс,
ManagedInjector
также вызывает метод, который отправляется как параметр.public class Helper { public static void Inject(IntPtr windowHandle, Assembly assembly, string className, string methodName) { var location = Assembly.GetEntryAssembly().Location; var directory = Path.GetDirectoryName(location); var file = Path.Combine(directory, "HelperDlls", "ManagedInjectorLauncher" + "64-4.0" + ".exe"); Debug.WriteLine(file + " " + windowHandle + " \"" + assembly.Location + "\" \"" + className + "\" \"" + methodName + "\""); Process.Start(file, windowHandle + " \"" + assembly.Location + "\" \"" + className + "\" \"" + methodName + "\""); } }
-
После того, как в приложение была введена dll автоматизации, доступ к
Visual Tree
довольно прост, используяDispatcher
иPresentationSources
.public class Setup { public static bool Start() { Dispatcher dispatcher; if (Application.Current == null) dispatcher = Dispatcher.CurrentDispatcher; else dispatcher = Application.Current.Dispatcher; dispatcher.Invoke(AutomateApp); return true; } public static void AutomateApp() { Window root = null; foreach (PresentationSource presentationSource in PresentationSource.CurrentSources) { root = presentationSource.RootVisual as Window; if (root == null) continue; if ("NordVPN ".Equals(root.Title)) break; }
-
Получение доступа к
VisualTree
является простым, но определение элементов управления не так просто, поскольку нет идентификаторов автоматизации или имен (имен), которые могут однозначно идентифицировать эти элементы управления. Но, к счастью, поскольку они используют MVVM, их можно идентифицировать с помощью привязки (ов), прикрепленных к ним.public static T GetChildWithPath<T>(this DependencyObject depObj, DependencyProperty property = null, string pathName = null) where T : DependencyObject { T toReturn = null; for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) { var child = VisualTreeHelper.GetChild(depObj, i); bool pathNameMatch = (child is T) && child.IsPathNameMatch<T>(property, pathName); if (pathNameMatch) { toReturn = child as T; break; } else toReturn = GetChildWithPath<T>(child, property, pathName); if (toReturn != null) break; } return toReturn; }
-
После того, как вы получили доступ к элементам управления, теперь можно либо напрямую манипулировать их свойствами, либо обращаться к их соответствующим партнерам по автоматизации и поставщикам для автоматизации этих элементов управления.
var checkBoxNames = new[] { "CyberSec", "AutomaticUpdates", "AutoConnect", "StartOnStartup", "KillSwitch", "ShowNotifications", "StartMinimized", "ShowServerList", "ShowMap", "UseCustomDns", "ObfuscatedServersOnly" }; foreach(var path in checkBoxNames) { var chkBox = settingsView.GetChildWithPath<CheckBox>(CheckBox.IsCheckedProperty, path); if(chkBox != null && chkBox.IsEnabled) chkBox.SimulateClick(); }
Полный рабочий образец загружен в репозиторий Github.