GeckoFx
을 사용하여 특정 웹 사이트에 로그인합니다. 이 웹 사이트는 로그인이 실패한 경우 (또는 ReCaptcha와 같은 추가 인증이 필요한 경우) 새 정보로 페이지를 편집합니다. 불행히도, 페이지가 업데이트 될 때 이벤트에 액세스해야합니다. 나는 display: none
속성이 변경된 경우 주로C#에서 GeckoFx의 MutationObserver 사용?
uri
여전히 각 로그인 시도 및 문제의 특정 요소에 대한 후속 체크인시 동일한 경우 계속 검사 (보고 다양한 방법을 시도했습니다. (이 결과 무한 루프로 보이는 것처럼GeckoFx
은 페이지를 비 차단 방식으로 업데이트하여 프로그램이 무한 루프가되도록합니다.- 로그인 요청 사이에 약 5 초 동안 잠자기 상태이고 전술 한
uri
검사를 사용하여 잠자기합니다. 빨대를 쥐고 있었다) 브라우저가 5 초 동결 되어도 여전히 페이지를 업데이트하지 못했습니다. DocumentCompleted
이벤트와 비슷한 페이지가 업데이트 될 때 특정 이벤트에 대해GeckoFx
코드베이스를 검색합니다 (그러한 행운은 없습니다).
내가 읽은 가장 일반적인 접근 방식은 가장 적합합니다 (MutationObserver
). 인터넷을 통한 모든 대답에는 필요한 작업을 수행하기 위해 Javascript
을 주입하는 것이 포함 된 것으로 보입니다. 내 모든 프로그래밍 배경이 웹 개발에 전혀 영향을 미치지 않았 음을 알고, 나는 내가 아는 것에 충실하려고 노력하고있다.
여기 내 접근 방식은 지금까지 불행히도 그리 많지 않습니다. 코멘트에 위의 코드에 명시된 바와 같이
public class GeckoTestWebLogin
{
private readonly string _user;
private readonly string _pass;
public GeckoWebBrowser Gweb;
public Uri LoginUri { get; } = new Uri("https://website.com/login/");
public bool LoginCompleted { get; private set; } = false;
public bool Loaded { get; private set; } = false;
public GeckoTestWebLogin(string user, string pass)
{
_user = user;
_pass = pass;
Xpcom.EnableProfileMonitoring = false;
Xpcom.Initialize("Firefox");
//this code is for testing purposes, it will be removed upon project completion
CookieManager.RemoveAll();
Gweb = new GeckoWebBrowser();
Gweb.DocumentCompleted += DocLoaded;
//right about here is where I get lost, where can I set a callback method for the observer to report back to? Is this even how it works?
MutationObserver mutationObserver = new MutationObserver(Gweb.Window.DomWindow, (nsISupports)Gweb.Document.DomObject);
}
private void TestObservedEvent(string parms, object[] objs)
{
MessageBox.Show("The page was changed @ " + DateTime.Now);
}
public void DocLoaded(object obj, GeckoDocumentCompletedEventArgs e)
{
Loaded = true;
if (Gweb.Url != LoginUri) return;
AttemptLogin();
}
private void AttemptLogin()
{
GeckoElementCollection elements = Gweb.Document.GetElementsByTagName("input");
foreach (GeckoHtmlElement element in elements)
{
switch (element.Id)
{
case "username":
element.SetAttribute("value", _user);
break;
case "password":
element.SetAttribute("value", _pass);
break;
case "importantchangedinfo":
GeckoHtmlElement authcodeModal =
(GeckoHtmlElement)
Gweb.Document.GetElementsByClassName("login_modal").First();
if (authcodeModal.Attributes["style"].NodeValue != "display: none")
{
InputForm form = new InputForm { InputDescription = "Captcha Required!" };
form.ShowDialog();
elements.FirstOrDefault(x => x.Id == "captchabox")?.SetAttribute("value", form.Input);
}
break;
}
}
elements.FirstOrDefault(x => x.Id == "Login")?.Click();
}
public void Login()
{
//this will cause the DocLoaded event to fire after completion
Gweb.Navigate(LoginUri.ToString());
}
}
는, 나는 완전히 내가 나를 설정할 수 있습니다 것 MutationObserver
에 대한 GeckoFx
의 소스에서 아무것도 찾을 수 없습니다
MutationObserver mutationObserver = new MutationObserver(Gweb.Window.DomWindow, (nsISupports)Gweb.Document.DomObject);
에서 손실입니다 콜백/이벤트/whathaveyou. 나의 접근 방식은 일을하는 올바른 방법인가 아니면 Javascript
을 페이지에 삽입하는 것 이외의 다른 옵션으로 남지 않았습니까?
많은 의견 부탁드립니다.
이(GeckoTestWebLogin 현황)
public void DocLoaded(object obj, GeckoDocumentCompletedEventArgs e)
{
Loaded = true;
if (Gweb.Url != LoginUri) return;
MutationEventListener mutationListener = new MutationEventListener();
mutationListener.OnDomMutation += TestObservedEvent;
nsIDOMEventTarget target = Xpcom.QueryInterface<nsIDOMEventTarget>(/*Lost here*/);
using (nsAString modified = new nsAString("DOMSubtreeModified"))
target.AddEventListener(modified, mutationListener, true, false, 0);
AttemptLogin();
}
MutationEventListener.cs :
public delegate void OnDomMutation(/*DomMutationArgs args*/);
public class MutationEventListener : nsIDOMEventListener
{
public event OnDomMutation OnDomMutation;
public void HandleEvent(nsIDOMEvent domEvent)
{
OnDomMutation?.Invoke(/*new DomMutationArgs(domEvent, this)*/);
}
}
안녕하세요, 옵션 2를 시도했습니다, 그러나, 유일한 적절한 참조 내가 찾을 수있는 다음과 같은 뭔가를 주입 'var target = Xpcom.QueryInterface (X);에 대해'WindowRoot'는'Window.cs'에서'WindowRoot'였습니다. 그러나'GeckoWindow.cs'가'Window.cs'를 확장하는 동안 앞에서 언급 한'WindowRoot' 속성을 드러내지 않는 것처럼 보일 것입니다. 내가 잘못된 방향으로가는거야? 내 원래의 질문에 내 시도의 관련 부분을 포함 시켰습니다. –
var body = browser.Document? .Body? .DOMHtmlElement; – Tom
아, 지금 어리 석다. .. Tom에 감사한다! –