C# HtmlElement Как программно выбрать файл (из HtmlElement, к которому обращается веб-браузер) с компьютера без условия гонки
Я довольно новичок, когда дело доходит до класса htmlelement!
Сейчас я пытаюсь заполнить очень скучную внешнюю веб-страницу множеством данных, которые уже существуют на компьютере (программа выполняется локально на указанном компьютере). одна из тех раздражающих и отнимающих много времени вещей, которую нужно делать вручную, - это выбрать изображение установки оборудования на вашем компьютере, а затем отправить его в эту форму, сделать это можно с помощью класса HTMLElement и элемента управления webBrowser, но я ненавижу небезопасное кодирование требуется сделать это, я называю это небезопасным, потому что у него есть проблемы с состоянием гонки, вот посмотрите:
Следующий код не был создан мной
async Task PopulateInputFile(HtmlElement file)
{
file.Focus();
// delay the execution of SendKey to let the Choose File dialog show up
var sendKeyTask = Task.Delay(500).ContinueWith((_) =>
{
// this gets executed when the dialog is visible
SendKeys.Send("C:\\Images\\CCPhotoID.jpg" + "{ENTER}");
}, TaskScheduler.FromCurrentSynchronizationContext());
file.InvokeMember("Click"); // this shows up the dialog
await sendKeyTask;
// delay continuation to let the Choose File dialog hide
await Task.Delay(500);
}
async Task Populate()
{
var elements = webBrowser.Document.GetElementsByTagName("input");
foreach (HtmlElement file in elements)
{
if (file.GetAttribute("name") == "file")
{
file.Focus();
await PopulateInputFile(file);
}
}
}
Хорошо, теперь изображение на вашем компьютере находится в режиме ожидания жесткого диска, или в нем очень стрессовое антивирусное сканирование + одновременное обновление окон, естественно, что появление модального окна может занять даже до 10 секунд. что это означает, что вы вводите путь к файлу и нажимаете клавишу ввода до того, как отобразится показанное диалоговое окно, что приведет к зависанию программы, никогда не выходящей из строя, не выполнившей строку кода, и не предоставив пользователю или кодеру какую-либо ошибку (что ожидается).
То, что я пытаюсь сделать, это именно это, но в то же время избегая этого очень очевидного состояния гонки, я рассматривал возможность проверять каждые 500 мс в цикле, чтобы увидеть, открыто ли окно, и только затем выполнить sendkeys, что-то вроде этого:
AutoUploadPicture(string path)
{
fileUploadDialogElement.Focus();//HTMLElement Taken from webBrowser1.Document
Task.Run(()=>PerformAsyncCheckup());
fileUploadDialogElement.InvokeMember("click");
CancelTask = true;
//successfully continue coding as it avoided that ugly race condition
}
bool CancelTask = false;
PerformAsyncCheckup()
{
while (webBrowser1.AnyDialogFormShowing==false && CancelTask == false)
{
Thread.Sleep(200);
}
if (CancelTask ==false)
SendKeys.Send("C:\\Images\\CCPhotoID.jpg" + "{ENTER}");
То, что я хочу, возможно? Я искал Google и Stackru, и все решения были основаны на случайном таймере, который всегда рискует ошибками состояния гонки.
С уважением!
1 ответ
Я исправил проблему, проигнорировав метод sendkeys и используя комбинацию потоков и внутренней системы обмена сообщениями Windows для обнаружения и настройки модальных окон поверх моего приложения, что устраняет проблемы с надежностью этого текущего кодирования.
А именно FindWindowEx(), SendMessage(), GetParent() и Task.Run()