1

I created a Selenium Console Bot which now I want to be started with WPF. So I created a simple window and added a button, which is supposed to start my bot, which I've rewritten into WPF. It starts and it works, but it crashes the xaml window and opens a Console (which shouldn't happen or should?). Then it leaves the console empty and writes down what it should in Visual Studio console. It happens when I start method CheckItems(_driver). Any possible solutions? I don't mind starting a console to run in the background, but why does it crash the main window so I can not move it or do anything with it?

private IWebDriver Setup(IWebDriver driver)
    {

        var option = new ChromeOptions();
        option.AddArgument("--headless");
        option.AddArgument("--silent");
        option.AddArgument("--disable-gpu");
        option.AddArgument("--log-level=3");


        var service = ChromeDriverService.CreateDefaultService();
        service.SuppressInitialDiagnosticInformation = true;


        _driver = new ChromeDriver(service, option);


        //driver.Navigate().GoToUrl("");


        _driver.Navigate().GoToUrl("urlofmychoice");
        _driver.Manage().Window.Maximize();

        _driver.Manage().Timeouts().ImplicitWait =
            TimeSpan.FromSeconds(7); // breaks in between actions taken by webDriver
        _driver.FindElement(By.XPath("/html/body/div[2]/div/a")).Click(); // click got it (need to add fake cookie)
        _driver.FindElement(By.Id("header-email"))
            .SendKeys("myemail"); // enters my login (need to make it adjustable)
        _driver.FindElement(By.Id("header-password"))
            .SendKeys("mypassword" + Keys.Enter); // enters my password (need to make it adjustable)

        var username = _driver.FindElement(By.XPath("/html/body/header/section[1]/div/div[2]/div/a/span"))
            .Text; // Get username from the site and saves to username


        tradeUrl = "ulrIneed" + username; // initialize tradeUrl


        //_driver.Navigate().GoToUrl(tradeUrl); // goes to tradeUrl


        return _driver;
    }

 private void CheckItems(IWebDriver driver)
    {

        while (true)
        {

            _driver.Navigate().GoToUrl(tradeUrl);
            var trades = _driver.FindElements(By.ClassName("rlg-trade-display-header")); // add all trades to list

            for (var i = 0; i < trades.Count; i++) // loop to check all trades
            {
                if (i == 0)

                    Console.WriteLine("\n    Active Trades: " + trades.Count);
                var text = _driver
                    .FindElement(By.XPath(
                        "/html/body/main/div/div/div/div[4]/div[" + (i + 1) + "]/div[1]/div/div/span"))
                    .Text.Split(); // reads text from trade and adjust it for the program
                var test = "Trade " + (i + 1) + " was last updated " + text[1] + " " + text[2] + " ago.";
                Console.WriteLine(test);


                var x = int.Parse(text[1]); // convert string to int to check time later

                if (text[2] == "seconds")
                    continue;


                if (text[2] == "hours" || text[2] == "hour" || text[2] == "days" || text[2] == "day" ||
                    text[2] == "month" || text[2] == "months" || x > 15)
                {
                    var element1 =
                        _driver.FindElement(By.XPath("/html/body/main/div/div/div/div[4]/div[" + (i + 1) +
                                                     "]/div[1]/a/div"));
                    var actions1 = new Actions(_driver);
                    actions1.MoveToElement(element1).Click()
                        .Perform(); // scrolls down to choosen element and clicks it


                    _driver.FindElement(By.XPath("/html/body/main/div/div/div/div[2]/a[1]"))
                        .Click(); // click choosen element


                    var element = _driver.FindElement(By.Name("btnSubmit"));
                    var actions = new Actions(_driver);
                    actions.MoveToElement(element).Click()
                        .Perform(); // scrolls down to choosen element and clicks it
                    driver.Navigate().GoToUrl(tradeUrl);
                    Thread.Sleep(2000);
                }
            }
            Thread.Sleep(15000); // wait 15 second before next loop
        }
    }




   private void BtnStart_OnClick(object sender, RoutedEventArgs e)
    {

        Setup(_driver);
        CheckItems(_driver);

    }
}
D.Weltrowski
  • 321
  • 1
  • 4
  • 15
  • If your problem is that your _WPF_ window becomes unresponsive, it's because you're calling `CheckItems(_driver)` synchronously from the UI thread. Thus the `BtnStart_OnClick` handler is waiting until that method returns control, which it never does (it's basically a `while(true)` loop without any `break`). So the thread is "stolen" or "hogged" by this method and UI is not responsive. The solution would be to dispatch this method to another thread. If however your window crashes in some other fashion, you should provide more details, e.g. exception message and/or stack trace. – Grx70 Nov 22 '17 at 07:19
  • As a side note, I'd advise you to abandon your approach with `while(true)` and `Thread.Sleep`. Your goal seems to be to run a procedure repeatedly at some fixed rate, and I think some kind of timer would be a better choice. – Grx70 Nov 22 '17 at 07:31
  • Thanks for advices guys! I will try to dispatch this method from another thread for sure, because this is exactly a reason for the error. What do You mean with timer? Like do the loop for "that" amount of time? I need this method to work until user decides to stop it so I kind of need the infinite loop. Also `Thread.Sleep` is needed for loop to wait a bit before it starts again so user won't be spammed with results every second. – D.Weltrowski Nov 22 '17 at 10:40
  • What I mean is do not use loop at all. Instead, at the end of the procedure, create a timer which will call the procedure again when the time has elapsed. This way you won't block the thread, as opposed to `Thread.Sleep`. [Here](https://stackoverflow.com/questions/12570324/) you'll find some options on how to proceed. Otherwise you should at least consider using `Task.Delay` instead `Thread.Sleep` (see [this question](https://stackoverflow.com/questions/20082221/when-to-use-task-delay-when-to-use-thread-sleep) for details on the difference between the two). – Grx70 Nov 22 '17 at 10:54
  • Also, [this](https://stackoverflow.com/questions/160587/) may be helpful with dealing with the missing output. – Grx70 Nov 22 '17 at 11:00
  • Alright! I will test it all when I come back from university. Btw. I am studying in Gdansk, just next to Your working place if I am correct ^^ – D.Weltrowski Nov 22 '17 at 11:40
  • So I made my code run in a different thread `Thread thread = new Thread(StartChecking);` and now it works well in case of moving the UI while the program is running. But when I close the console that runs the whole program is beeing killed. How can I overcome this? Is it just that I need to add methods for exepctions in my code? – D.Weltrowski Nov 22 '17 at 12:26
  • Alright. I added try and catch to my code and now it works well. When I close the console, it "throw an error" but I made it to now show any message, so basicly the user will just feel like he closed the program and nothing happens. And it is kind of true. Thanks a lot! Now I think about one more thing. Firstly is why the Console is actually even starting? Is it because of me using Selenium? – D.Weltrowski Nov 22 '17 at 12:35
  • I've never used _Selenium_ so I have no idea. Also, I can't do anymore than wild guess without seeing the `Setup` method code... – Grx70 Nov 22 '17 at 12:43
  • I added a setup to my original post. So if You can check if there is a reason for Console showing up. (There should be, because when I start only `setup(_driver)` without `CheckItems(_driver)` then it starts the console anyway. – D.Weltrowski Nov 22 '17 at 13:03
  • I worked it around. What I did is I noticed that the reason for that is chromedriver and added a simple line `service.HideCommandPromptWindow = true;` and now it doesn't open a console window – D.Weltrowski Nov 22 '17 at 13:23

0 Answers0