AutomationElement.FromHandle(IntPtr Handle) stops the application - c#

private string GetCurrentChromeUrl()
{
try
{
string url = null;
int handle = GetForegroundWindow();
AutomationElement elm = AutomationElement.FromHandle((IntPtr)handle);
AutomationElement elmUrlBar = elm.FindFirst(TreeScope.Descendants,
new PropertyCondition(AutomationElement.NameProperty, "Address and search bar"));
if (elmUrlBar != null)
{
AutomationPattern[] patterns = elmUrlBar.GetSupportedPatterns();
if (patterns.Length > 0)
{
ValuePattern val = (ValuePattern)elmUrlBar.GetCurrentPattern(patterns[0]);
url = val.Current.Value;
//break;
}
}
return url;
}
catch (Exception e1)
{
return "";
}
}
I'm trying to find the URL from google chrome browser.
And I'm using above code. It is work good in other application but in my case it stops my application.
But the main issue is that it will work fine when I'm debugging it, so what wrong when no debugging.
please give your solutions.
thanx in advance

I'm passing through this, it happen cause of the intptr type, it depends of the build of the machine, sometime the windowhandle is too big for an intptr of a 32bits machine.

Related

How to close tabs on Microsoft Edge programmatically

I am trying to close all of the opened tabs on Microsoft Edge from c# code but can't get it working.
tried:
Process[] edgeProcessList = Process.GetProcessesByName("MicrosoftEdgeCP");
foreach (Process theprocess in edgeProcessList)
{
if (theprocess.MainWindowHandle != IntPtr.Zero)
{
SetForegroundWindow(theprocess.MainWindowHandle);
SendKeys.SendWait("^{W}");
Thread.Sleep(3000);
}
}
as well as:
foreach(Process proc in edgeProcessList.ToList())
{
proc.Kill();
}
but neither work. The processes do get killed But new ones re-appear at once.
Shows both in debug after:
Process[] newProcessList = Process.GetProcessesByName("MicrosoftEdgeCP");
as well as in the task manager.
Is there a way to do this that works?
the process is named "msedge"
Process[] Edge = Process.GetProcessesByName("msedge");
foreach (Process Item in Edge)
{
try
{
Item.Kill();
Item.WaitForExit(30000);
}
catch (Exception)
{
}
}
See WebDriver
That appears to be what "driver" in the incomplete answer is referencing.
Code to kill Edge browser instance
Process[] Edge = Process.GetProcessesByName("MicrosoftEdge");
foreach (Process Item in Edge)
{
try
{
Item.Kill();
Item.WaitForExit(3000);
}
catch (Exception)
{
}
}
using System.Windows.Automation and Keyboard Hook
Process[] procsEdge = Process.GetProcessesByName("msedge");
foreach (Process Edge in procsEdge)
{
if (Edge.MainWindowHandle != IntPtr.Zero)
{
AutomationElement root = AutomationElement.FromHandle(Edge.MainWindowHandle);
var tabs = root.FindAll(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.TabItem));
var elmUrl = root.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Address and search bar"));
foreach (AutomationElement tabitem in tabs)
{
if (elmUrl != null)
{
AutomationPattern[] patterns = elmUrl.GetSupportedPatterns();
if (patterns.Length > 0)
{
ValuePattern val = (ValuePattern)elmUrl.GetCurrentPattern(patterns[0]);
string url = val.Current.Value;
Console.WriteLine(url.Contains("bing.com"));
}
}
tabitem.SetFocus();
SendKeys.SendWait("{ALT+W}");
}
}
}
Figured it out and wrote some code that I got to work:
var tabs = driver.WindowHandles;
var x = Enumerable.Range(1, tabs.Count - 1).Reverse();
foreach(var i in Enumerable.Range(1, tabs.Count-1).Reverse())
{
Console.WriteLine(i);
driver.SwitchTo().Window(tabs[i]);
driver.Close();
driver.SwitchTo().Window(tabs[i - 1]);
}

selenium web scraping in c#

I am doing web scraping by using selenium dll's.But i face the problem when scrape the list of records. If I use the debugger it extract all the records, but if disable debugger and run the application it sometime display less records or sometime display no record.I want to know is there is any way to know that yet the page is fully loaded or not.
driver.FindElementsByClassName("search-result-gridview-item").ToList()
vary the record count.
driver.FindElementsByClassName("search-result-gridview-item").ToList().ForEach(x =>
{
objUPCProcess = new UPCProcessingModel();
try
{
objUPCProcess.Description = x.FindElement(By.ClassName("prod-ProductTitle")).Text;
objUPCProcess.Price = x.FindElement(By.ClassName("Price")).Text;
listOfProductDetails.Add(objUPCProcess);
if (i == 0)
{
log.Item = objUPCProcess.Description;
i++;
}
}
catch (OpenQA.Selenium.NoSuchElementException ex)
{
try
{
objUPCProcess.Description = x.FindElement(By.ClassName("prod-ProductTitle")).Text;
objUPCProcess.Price = ex.Message;
listOfProductDetails.Add(objUPCProcess);
}
catch
{
try
{
objUPCProcess.Price = x.FindElement(By.ClassName("Price")).Text;
objUPCProcess.Description = ex.Message;
listOfProductDetails.Add(objUPCProcess);
}
catch
{
objUPCProcess.Description = ex.Message;
objUPCProcess.Price = ex.Message;
log.Message = ex.Message;
listOfProductDetails.Add(objUPCProcess);
log.Status = "Error";
}
}
}
});
}
Looking at this case, I'm pretty sure this is caused by a synchronization issue (webdriver and page work at a different speed) with AJAX requests that actually populate the records. That's why
if disable debugger and run the application it sometime display less records or sometime display no record
I also don't see any explicit waits in your code. But you can implement a helper Utils method that will check
that yet the page is fully loaded or not
I've used the IScriptExecutor like so:
public void WaitSecondsForNewPageToLoad(int maxWaitTimeInSeconds)
{
string state = string.Empty;
bool jQueryActive = true;
try
{
WebDriverWait wait = new WebDriverWait(TestCaseContext.Driver,
TimeSpan.FromSeconds(maxWaitTimeInSeconds));
//Checks every 500 ms whether predicate returns true if returns exit otherwise keep trying till it returns true
wait.Until(d =>
{
try
{
state =
((IJavaScriptExecutor) TestCaseContext.Driver).ExecuteScript(
#"return document.readyState").ToString();
jQueryActive =
(bool)((IJavaScriptExecutor) TestCaseContext.Driver).ExecuteScript(
#"return jQuery.active == 0");
WindowsWhenSteps.WhenIFocusTheCurrentBrowserWindow();
}
catch (InvalidOperationException)
{
//Ignore
}
return (state.Equals("complete", StringComparison.InvariantCultureIgnoreCase) ||
state.Equals("loaded", StringComparison.InvariantCultureIgnoreCase)) &&
jQueryActive;
});
}
catch (TimeoutException)
{
//sometimes Page remains in Interactive mode and never becomes Complete, then we can still try to access the controls
if (!state.Equals("interactive", StringComparison.InvariantCultureIgnoreCase))
Assert.IsTrue(false);
}
catch (NullReferenceException)
{
//sometimes Page remains in Interactive mode and never becomes Complete, then we can still try to access the controls
if (!state.Equals("interactive", StringComparison.InvariantCultureIgnoreCase))
Assert.IsTrue(false);
}
catch (WebDriverException)
{
if (TestCaseContext.Driver.WindowHandles.Count == 1)
{
TestCaseContext.Driver.SwitchTo().Window(TestCaseContext.Driver.WindowHandles[0]);
}
state =
((IJavaScriptExecutor) TestCaseContext.Driver).ExecuteScript(
#"return document.readyState").ToString();
if (
!(state.Equals("complete", StringComparison.InvariantCultureIgnoreCase) ||
state.Equals("loaded", StringComparison.InvariantCultureIgnoreCase)))
Assert.IsTrue(false);
}
}
NOTE: You can lose some of the exception handling if it seems like an overhead, but I'm aiming at full answer in favor of the future readers too.
use the following code to check whether selenium is trigerred
/* * Created by SharpDevelop.
* User: sravanth
* Date: 2/2/2018
* Time: 1:33 AM *
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.IE;
using OpenQA.Selenium.Support.UI;
using System.Diagnostics;
using Microsoft.VisualBasic;
using System.Windows.Forms;
using System.Runtime.InteropServices;
//using System.Collections;
using System.Collections.Generic;
namespace sele
{
class Program
{
public static void Main(string[] args)
{
//Console.WriteLine("Hello World!");
// TODO: Implement Functionality Here
//Console.Write("Press any key to continue . . . ");
//Console.ReadKey(true);
//System.setProperty("webdriver.ie.driver", "C:\\Users/sravanth/Downloads/IEDriverServer_x64_3.8.0/IEdriver.exe");
// C:\Users\sravanth\Downloads\IEDriverServer_x64_3.8.0
IWebDriver driver;
// = new InternetExplorerDriver(#"C:\\Users/sravanth/Downloads/IEDriverServer_x64_3.8.0");
var service = InternetExplorerDriverService.CreateDefaultService(#"C:\\Users/sravanth/Downloads/IEDriverServer_x64_3.8.0");
//var service = InternetExplorerDriverService.CreateDefaultService(#"C:\\Users/sravanth/Downloads/chromedriver_win32");
// properties on the service can be used to e.g. hide the command prompt
var options = new InternetExplorerOptions { IgnoreZoomLevel = true, InitialBrowserUrl = "file:///C:/Users/sravanth/Desktop/a.html", IntroduceInstabilityByIgnoringProtectedModeSettings = true };
driver = new InternetExplorerDriver(service, options);
//driver = new ChromeDriver(#"C:\\Users/sravanth/Downloads/chromedriver_win32");
//driver.Navigate().GoToUrl("https://www.w3schools.com/js/tryit.asp?filename=tryjs_prompt");
driver.Url="file:///C:/Users/sravanth/Desktop/a.html";
//driver.Navigate().GoToUrl("file:///C:/Users/sravanth/Desktop/a.html");
driver.Navigate();
//IList links = driver.FindElements(By.TagName("button"));
// Console.WriteLine(links.Count);
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
//IWebElement btn = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("btn")));
IWebElement btn=driver.FindElement(By.Id("btn"));
btn.Click();
// System.Threading.Thread.Sleep(5000);
Process[] processes = Process.GetProcessesByName("iexplore");
Console.WriteLine(processes.Length);
int i=0;
IntPtr windowHandle;
foreach (Process p in processes)
{
i=i+1;
Console.WriteLine(i);
windowHandle = p.MainWindowHandle;
Console.Write("iexplore");
Console.WriteLine(windowHandle.ToString());
// do something with windowHandle
if(i.Equals(1))
{
//Console.WriteLine("Reached If Loop");
SetForegroundWindow(windowHandle);
}
}
//System.Windows.Forms.SendKeys.SendWait("%{F4}");
Console.WriteLine(processes.Length);
Process.Start("notepad.exe");
var prc = Process.GetProcessesByName("notepad");
if (prc.Length > 0)
{
SetForegroundWindow(prc[0].MainWindowHandle);
}
//System.Windows.Forms.SendKeys.SendWait("%{F4}");
}
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
}
}

C# Arguments for a specific process, open browser with url

I am writing an application that is supposed to open a certain process on the click of a button. However, the user has the ability to add new buttons. I'm using the following code for the action that occurs that starts the process on button click:
private void StartProcess(string path)
{
ProcessStartInfo StartInformation = new ProcessStartInfo();
StartInformation.FileName = path;
Process process = Process.Start(StartInformation);
process.EnableRaisingEvents = true;
}
private void ClickFunc(object sender, RoutedEventArgs e)
{
if (File.Exists(ProgramPath))
{
StartProcess(ProgramPath);
}
else
{
MessageBox.Show("Specified path does not exist, please try again.", "Bad File Path Error", MessageBoxButton.OK);
}
}
What I'm trying to accomplish is, when the user creates a button for a webpage, it opens the browser, then the webpage. Any ideas?
Thank you in advance!
To start a process to open the browser with a specific url you can try this:
string url = "http://www.stackoverflow.com";
var process = System.Diagnostics.Process.Start(url);
But sometimes if you have problems with the path of your browser, it cannot work properly. The function bellow gives you the path of the browser in the machine.
public static string GetDefaultBrowserPath()
{
string urlAssociation = #"Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http";
string browserPathKey = #"$BROWSER$\shell\open\command";
RegistryKey userChoiceKey = null;
string browserPath = “”;
try
{
//Read default browser path from userChoiceLKey
userChoiceKey = Registry.CurrentUser.OpenSubKey(urlAssociation + #"\UserChoice", false);
//If user choice was not found, try machine default
if (userChoiceKey == null)
{
//Read default browser path from Win XP registry key
var browserKey = Registry.ClassesRoot.OpenSubKey(#"HTTP\shell\open\command", false);
//If browser path wasn’t found, try Win Vista (and newer) registry key
if (browserKey == null)
{
browserKey =
Registry.CurrentUser.OpenSubKey(
urlAssociation, false);
}
var path = CleanifyBrowserPath(browserKey.GetValue(null) as string);
browserKey.Close();
return path;
}
else
{
// user defined browser choice was found
string progId = (userChoiceKey.GetValue("ProgId").ToString());
userChoiceKey.Close();
// now look up the path of the executable
string concreteBrowserKey = browserPathKey.Replace(“$BROWSER$”, progId);
var kp = Registry.ClassesRoot.OpenSubKey(concreteBrowserKey, false);
browserPath = CleanifyBrowserPath(kp.GetValue(null) as string);
kp.Close();
return browserPath;
}
}
catch(Exception ex)
{
return "";
}
}
And you can use the path of the browser and the url of website, for sample:
string url = "http://www.stackoverflow.com";
var process = System.Diagnostics.Process.Start(GetDefaultBrowserPath(), url);
In the url string you can pass the webpage link. It will open the browser with the url.
See more:
http://www.seirer.net/blog/2014/6/10/solved-how-to-open-a-url-in-the-default-browser-in-csharp

Get path of current active window using window handle

I'd like to know how to grab the Path of the current active window using C#.
i get handle of currnet active window
const int nChars = 256;
int handle = 0;
StringBuilder Buff = new StringBuilder(nChars);
handle = GetForegroundWindow();
now how do i get path of this window?
i.e: Path of "my document" window is
C:\Users\User\Documents
-=-=-==-=-=edit-=-=-=-=-=-
i want to wirte program to monitor "windows explorer" and see Where the user goes?
(i.e:user go to c:\ and then go to program files and then go to Internet Explorer and i want to get this path:C:\Program Files\Internet Explorer.
Add a reference (COM) to "Microsoft Internet Controls"
var explorer = new SHDocVw.ShellWindowsClass().Cast<SHDocVw.InternetExplorer>().Where(hwnd => hwnd.HWND == handle).FirstOrDefault();
if (explorer != null) {
string path = new Uri(explorer.LocationURL).LocalPath;
Console.WriteLine("name={0}, path={1}", explorer.LocationName, path);
}
Prints the title/path of the explorer.exe instance with the main window handle in handle.
use a thread...
Exception threadEccezione = null;
System.Threading.Thread staThread = new System.Threading.Thread(
delegate()
{
try
{
//SHDocVw.ShellWindows shellWindows = new SHDocVw.ShellWindows();
var explorer = new SHDocVw.ShellWindowsClass().Cast<SHDocVw.InternetExplorer>().Where(hwnd => hwnd.HWND == handle).FirstOrDefault();
if (explorer != null)
{
string path = new Uri(explorer.LocationURL).LocalPath;
MessageBox.Show(path);
}
}
catch (Exception ex)
{
threadEccezione = ex;
}
}
);
;
staThread.Start();
staThread.Join();

Launching MS Office from WPF application

As part of an application, I've added a shortcut bar for relevantly used programs. I have it set up to check if the application is open already, and if it is to switch to it instead of opening another instance. This works fine for programs like calc and notepad, but all the MS Office programs open another instance no matter what, and I'd like them not to.
Office Button
private void wordButton_Click(object sender, RoutedEventArgs e)
{
try
{
SwitchToProcess("winword.exe", "C:\\Program Files (x86)\\Microsoft Office\\Office14\\winword.exe");
}
catch (Win32Exception)
{
try
{
SwitchToProcess("winword.exe", "C:\\Program Files\\Microsoft Office\\Office14\\winword.exe");
}
catch (Win32Exception)
{
}
}
}
Notepad Button
private void notepadLink_Click(object sender, RoutedEventArgs e)
{
SwitchToProcess("notepad.exe");
}
Methods
private void SwitchToProcess(string name)
{
Process[] procs = Process.GetProcesses();
if (procs.Length != 0)
{
for (int i = 0; i < procs.Length; i++)
{
try
{
if (procs[i].MainModule.ModuleName == name)
{
IntPtr hwnd = procs[i].MainWindowHandle;
ShowWindowAsync(hwnd, SW_RESTORE);
SetForegroundWindow(hwnd);
return;
}
}
catch
{
}
}
}
else
{
MessageBox.Show("No process running");
return;
}
launchApp.StartInfo.FileName = name;
launchApp.Start();
}
private void SwitchToProcess(string name, string path)
{
Process[] procs = Process.GetProcesses();
if (procs.Length != 0)
{
for (int i = 0; i < procs.Length; i++)
{
try
{
if (procs[i].MainModule.ModuleName == name)
{
IntPtr hwnd = procs[i].MainWindowHandle;
ShowWindowAsync(hwnd, SW_RESTORE);
SetForegroundWindow(hwnd);
return;
}
}
catch
{
}
}
}
else
{
MessageBox.Show("No process running");
return;
}
launchApp.StartInfo.FileName = path;
launchApp.Start();
}
The reason for the two different directories in the Office button is a simple way of ensuring that x86/x64 install locations don't cause a problem. The computers I'm developing this for have the registry locked out, so I can't check which one is correct.
In your SwitchToProcess method you need to change the following line:
if (procs[i].MainModule.ModuleName == name)
To this:
if (procs[i].MainModule.ModuleName.ToLower() == name.ToLower())
Reason being that the process name for Word is WINWORD.EXE and you are passing the parameter value in lowercase.
As an aside you could change your wordButton_Click event to this:
private void wordButton_Click(object sender, EventArgs e)
{
if (Environment.Is64BitOperatingSystem)
{
SwitchToProcess("winword.exe", "C:\\Program Files (x86)\\Microsoft Office\\Office14\\winword.exe");
}
else
{
SwitchToProcess("winword.exe", "C:\\Program Files\\Microsoft Office\\Office14\\winword.exe");
}
}
Ok, so after digging a little deeper into Google, I finally figured out the problem. I had the program targeted for an x86 processor, and am running it on x64. Switched the target to AnyCPU and it works perfectly. Apparently it was catching an error of Only part of a ReadProcessMemory or WriteProcessMemory request was completed, but since I had the try-catch block in there it wasn't displaying the error until I used StepInto repeatedly on the 77-item processor array. Thanks everyone for the help though.

Categories