LighthouseMike
Member
- Joined
- Jul 20, 2020
- Messages
- 11
- Programming Experience
- 5-10
Hey there,
I've been working on a project that automates the "Save As" dialog as part of an automated download process, and I thought it would be best to use UIA (a.k.a. "Microsoft UI Automation", in the System.Windows.Automation namespace) as opposed to simulating keystrokes AutoHotKey-style. I had done it that way before (in C/Win32) and it worked, but I thought UIA might be more reliable; at the same time, the requirements changed so I'm using C# now (lol). Anyway, I've been fighting hard against a bizarre bug that has no logical explanation (based on my little mortal brain's limited understanding of the inner workings of .NET, lol). My program works perfectly when run from Visual Studio (VS 2017, on Windows 10), and works well part of the way when run from PowerShell/CMD. But when not using VS, the program crashes with no stack trace. Debug vs. release mode doesn't seem to matter., but it only works (in both modes) in Visual Studio. When it crashes (in either mode), there is no "the program has stopped working", no text is printed to stdout or stderr, and there is absolutely no indication whatsoever as to what causes the problem. Try/catch blocks don't catch it, piping the output to a file doesn't show any new info, and I haven't been able to dig up any usable info on the interwebz.
But the random doesn't stop there. When I run it from PowerShell, then bring up the Save As dialog in Notepad, it not only crashes my program, but also PowerShell and Notepad! Returning to Visual Studio, if I try to re-compile my code, I get an error:
Severity: Error
Description: Unable to copy file "obj\Debug\download.exe" to "bin\Debug\download.exe". Access to the path 'bin\Debug\download.exe' is denied.
Project: download
All other fields are blank/empty.
Here's the code, with all my comments as I've tried different ways out of this nightmare:
Any info, ideas, questions, suggestions, or other thoughts on the subject would be greatly appreciated. For now, I can go back to simulating keystrokes and get this project done; but UIA is something I may need to use again, so if this is a super-common recurring problem or something I'll eventually need to understand it. My best guess is that Visual Studio jumps through some unknown hoops, dynamically inserting some mysterious missing component that doesn't get packaged with the EXEs... I'm 99.99999% sure it's not my code, cuz my code works in Visual Studio. lol idk.
I've been working on a project that automates the "Save As" dialog as part of an automated download process, and I thought it would be best to use UIA (a.k.a. "Microsoft UI Automation", in the System.Windows.Automation namespace) as opposed to simulating keystrokes AutoHotKey-style. I had done it that way before (in C/Win32) and it worked, but I thought UIA might be more reliable; at the same time, the requirements changed so I'm using C# now (lol). Anyway, I've been fighting hard against a bizarre bug that has no logical explanation (based on my little mortal brain's limited understanding of the inner workings of .NET, lol). My program works perfectly when run from Visual Studio (VS 2017, on Windows 10), and works well part of the way when run from PowerShell/CMD. But when not using VS, the program crashes with no stack trace. Debug vs. release mode doesn't seem to matter., but it only works (in both modes) in Visual Studio. When it crashes (in either mode), there is no "the program has stopped working", no text is printed to stdout or stderr, and there is absolutely no indication whatsoever as to what causes the problem. Try/catch blocks don't catch it, piping the output to a file doesn't show any new info, and I haven't been able to dig up any usable info on the interwebz.
But the random doesn't stop there. When I run it from PowerShell, then bring up the Save As dialog in Notepad, it not only crashes my program, but also PowerShell and Notepad! Returning to Visual Studio, if I try to re-compile my code, I get an error:
Severity: Error
Description: Unable to copy file "obj\Debug\download.exe" to "bin\Debug\download.exe". Access to the path 'bin\Debug\download.exe' is denied.
Project: download
All other fields are blank/empty.
Here's the code, with all my comments as I've tried different ways out of this nightmare:
Makes me love Linux that much more lol:
/// <summary>
/// Automates the "Save As" dialog
/// </summary>
/// <param name="path">The path</param>
/// <param name="file">The file name</param>
static void AutomateSaveAsDialog(string path, string file)
{
// Wait for the "Save As" dialog to appear
AutomationElement start;
while (true)
{
start = AutomationElement.FocusedElement;
if (start.Current.Name.Equals("File name:")) break;
Thread.Sleep(100);
}
// Set the file name
ValuePattern textBox = start.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
if (textBox == null)
{
Console.WriteLine("Error: Can't set the name");
return;
}
textBox.SetValue(path + "\\" + file);
// Get a reference to the dialog.
// "Luke TreeWalker" lol
TreeWalker luke = TreeWalker.ControlViewWalker;
AutomationElement dialog = luke.GetParent(luke.GetParent(luke.GetParent(start)));
// Use that to find the "Save" button
Condition[] conditions = {
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button),
new PropertyCondition(AutomationElement.NameProperty, "Save")
};
// Using this "cave man debugging" (as one Stack Overflow post cleverly put it)
// I found that the cause of the crashing is something somewhere after this line:
Console.WriteLine("Conditions set");
AutomationElement button = dialog.FindFirst(TreeScope.Descendants, new AndCondition(conditions));
// And this line doesn't run, so I think it IS line 123... but why?
Console.WriteLine("It's not line 123");
/*
// Gonna try commenting out this block - maybe something in here causes it??????
if (button == null)
{
Console.WriteLine("Error: couldn't find the save button");
return;
}
*/
Console.WriteLine("button is not null");
// Push the button
InvokePattern save = button.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
Console.WriteLine("It's not line 138");
/*
// We know it won't be null, so Lord willing we can comment this out safely.
if (save == null)
{
Console.WriteLine("Error: Can't set the name");
Console.ReadKey();
return;
}
*/
save.Invoke();
Console.WriteLine("It's not line 151");
// Check to make sure it worked
Thread.Sleep(1000); // just to play it safe
if (!FileExistsAnyExtension(path, file))
Console.WriteLine("Error: File not saved");
}
Any info, ideas, questions, suggestions, or other thoughts on the subject would be greatly appreciated. For now, I can go back to simulating keystrokes and get this project done; but UIA is something I may need to use again, so if this is a super-common recurring problem or something I'll eventually need to understand it. My best guess is that Visual Studio jumps through some unknown hoops, dynamically inserting some mysterious missing component that doesn't get packaged with the EXEs... I'm 99.99999% sure it's not my code, cuz my code works in Visual Studio. lol idk.