Automate file save in microsoft edge using selenium - c#

I am using the beta version of selenium webdriver(4.0.0) for microsoft edge. I can't figure out how to save the data as pdf that is in print window, which opens after I click on a button in main window
var found = await driver.WaitForElementToAppear(".//font[contains(text(),'Uploaded')]", 180, token);
if(found)
{
//All buttons , which when clicked opens Print window
var ebrcElements = driver.ElementsByXpath(".//input[#type='submit']");
foreach (var ebrcElement in ebrcElements)
{
ebrcElement.Click();//Opens the new window
Thread.Sleep(2000);
driver.SwitchToNewWindow();//Switches to the last window
//The window has "Print" and "Cancel" button
driver.CloseCurrentWindow();
driver.SwitchToFirstWindow();
}
}

Since the window that opens when print button is clicked, is an os dialog box, it cannot be accessed directly from selenium. The way I solved the problem was using P/Invoke.
Using visual studio's spy++ tool it was easy to find the window handle and its caption.
Next I defined method
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
and Called it like,
var saveHandle = FindWindowByCaption(IntPtr.Zero, "Save Print Output As");
Next step was to bring the window to foreground using the handle. For that I used the method
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
Last step was to simulate the keyboard and mouse operations. For that I used library InputSimulator. It can be downloaded using nuget package manager
var ins = new InputSimulator();
ins.Keyboard.TextEntry($"ebrc{irandom.NextDouble()}");
Thread.Sleep(2000);
ins.Keyboard.KeyPress(WindowsInput.Native.VirtualKeyCode.TAB);
ins.Keyboard.KeyPress(WindowsInput.Native.VirtualKeyCode.TAB);
ins.Keyboard.KeyPress(WindowsInput.Native.VirtualKeyCode.RETURN);

Related

Bring another application into foreground when WPF XAML window is in Maximized

I have a WPF application in which the main window is set to full screen via WindowState="Maximized" in the Window tag. In the application, I'm opening PowerPoint through the Office Interop libraries with the intention that PowerPoint opens in the foreground, on top of the WPF application. However, PowerPoint is not consistently coming to the foreground (particularly on Windows 7 machines). In these cases I have to press the Windows key to bring up the Windows Taskbar and click on the PowerPoint icon.
I've tried a few things, such as using SetForegroundWindow() from the Win32 API, the .Activate() function in the PowerPoint Interop library, and the AutomationElement class (here's some code for the last one):
Process process = System.Diagnostics.Process.GetProcessesByName("POWERPNT").FirstOrDefault();
AutomationElement element = AutomationElement.FromHandle(process.MainWindowHandle);
if (element != null)
{
element.SetFocus();
}
However, none of these seem to consistently bring PowerPoint to the front. Does anyone know why exactly this behavior is occurring and how best to get PowerPoint into the foreground?
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(HandleRef hWnd, int nCmdShow);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr WindowHandle);
public const int SW_RESTORE = 9;
static void Main(string[] args)
{
Process process = System.Diagnostics.Process.GetProcessesByName("POWERPNT").FirstOrDefault();
IntPtr hWnd = IntPtr.Zero;
hWnd = process.MainWindowHandle;
ShowWindowAsync(new HandleRef(null, hWnd), SW_RESTORE);
SetForegroundWindow(process.MainWindowHandle);
}
works fine with me.
This may work in your case:
Microsoft.VisualBasic.Interaction.AppActivate("fullTitleOfWindow_OR_firstLettersOfWindowTitle");

How can I programmatically click a button on a custom MS Office Access Ribbon?

I'm looking for some guidance here, if not an example of how to accomplish what I am looking to do in C-Sharp(C#).
There is a particular button on a MS Access Ribbon that I would like to click. The MS Access window has a custom UI and custom buttons in different groups. When the button in the first group is clicked, it then opens a childform window. I need to automate that particular step and have my C# application programmatically open that child form by clicking the button or any other means to get it open.
I attempted to do this with the SendKeys and FindWindow functions, but this prove to be rather faulty, because the ALT id's kept changing in MS Access and the SendKeys would stop working.
I've tried searching for articles that would help me with this issue, but all I came across are tutorials on how to make a custom add-in for MS ribbon (I do not want this).
There might be a better way to do this and any help with it is greatly appreciated!
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string strClassName, int nptWindowName);
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
Public Void SendTest()
{
IntPtr WinHandle = FindWindow("OMain", 0); // OMain = Window Class --found window by class
if (WinHandle == IntPtr.Zero)
{
MessageBox.Show("Program is not running or could not be detected.");
return;
}
SetForegroundWindow(WinHandle);
SendKeys.SendWait("%"); // ALT
SendKeys.SendWait("Y1"); // Y1
SendKeys.SendWait("Y1"); //Y1
}

Lost focus issue when using WPF and WindowsInteropHelper

I have a problem with hosting a WPF window inside Excel. What we want to achieve is a window similar to Excel 2013 chart icons next to the chart when chart is selected.
The normal logic is already in place, but there was an issue with click on the ribbon or switching to another window and back to Excel. Both of those scenarios resulted in our window getting hidden.
The solution to this is to set the Owner of our WPF window which is not straight forward when combining Excel and WPF windows. The solution for now was this:
// Getting the active window
[DllImport("user32.dll")]
static extern IntPtr GetActiveWindow();
// Using the WindowInteropHelper to bind WPF window to excel
var wpfWindow = new WPFWindow();
var handle = GetActiveWindow();
helper = new WindowInteropHelper(wpfWindow) { Owner = handle };
wpfWindow.Show();
The above code works fine as long as we only stay in Excel. However the following steps produce a problem:
show our wpfWindow from an Excel addin
switch to another program that is currently running (like browser,...)
switchback to Excel
when our form hides the previously selected program becomes activated and is shown on top of Excel
Any solution to this issue? I have read two similar problems here and here, but they don't offer a working solution.
(I realise this is an old question but hopefully will help someone in the future)
This seems to be a known bug with using window.Show() in wpf windows that hasn't been fixed ( here and here )
Forcing focus to the Owner before Closing seems to work for me (Solution posted in the first link):
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
// Getting the active window
[DllImport("user32.dll")]
static extern IntPtr GetActiveWindow();
// Using the WindowInteropHelper to bind WPF window to excel
var wpfWindow = new WPFWindow();
wpfWindow.Closing += (sender, args) => SetForegroundWindow(new WindowInteropHelper(wpfWindow).Owner);
var handle = GetActiveWindow();
helper = new WindowInteropHelper(wpfWindow) { Owner = handle };
wpfWindow.Show();

how to find the window handle, of the control in application where mouse was clicked

I writing a C# application. I am looking a way to find a window handle of the controls in other applications by just giving the coordinates of the mouse click (or for that matter any coordinates).
Example: On my desktop, I have calculator application opened, notepad opened and some other 3rd party application running. Screen is covered partially by each of them. Now if I run my application and if I click at any location on the screen, I want to be able to find out the window handle of the control (button, textbox, label, tab, frame, etc.) under the mouse irrespective if it was clicked on a button in calculator, File menu in notepad, or some other control in the 3rd party application. It is similar to the functionality we get from Spy++.
BTW, this has already been done for you, sounds like all you need is to clone the repo then customize to your hearts content.
I don't think Global Hooks would be necessary.
You should be able to use any number of methods to get cursor position, hooking is just going to complicate things. For example, you can try the following:
using System;
using System.Windows;
using System.Windows.Input;
using System.Runtime.InteropServices;
namespace Namespace1
{
class Class1
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetCursorPos(ref Win32Point pt);
[StructLayout(LayoutKind.Sequential)]
internal struct Win32Point
{
public Int32 X;
public Int32 Y;
};
public static Point GetMousePosition()
{
Win32Point w32Mouse = new Win32Point();
GetCursorPos(ref w32Mouse);
return new Point(w32Mouse.X, w32Mouse.Y);
}
}
}
Then you just need a few Pinvoke signatures.
Namely, WindowFromPoint and EnumChildWindows.
Refer to "Enumerating Windows/Controls of another application from .Net".
Hope that helps.
Good luck.
Use Windows hook for mouse events (like oleksa said) then this PInvoke to get the foreground window : http://www.pinvoke.net/default.aspx/user32.getforegroundwindow
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
void yourFonction(){
[...]
IntPtr handleTopMostWindow = GetForegroundWindow();
}
you just need to call this method in your code to retrieve the window's foreground handle :
you have to set global Windows hook for mouse events. This will cause yours application to get mouse (or keyboard) clicks in foreign windows.
Please find this article on code project as sample C# wrapper on Windows API. Windows API functions are listed in the article too

Open an Application .exe window inside another application

I have an application in WPF running. I would like that, when a button is clicked inside this application, another application opens, with its window maximized. However, I don't want my first application to stop and wait. I want both to be open and running independently.
When the button is clicked again, in case the application is minimized, the application is maximized. In case it is not, it is open again.
How is it possible using C#? I have tried the following:
Process process = Process.GetProcesses().FirstOrDefault(f => f.ProcessName.Contains("Analysis"));
ShowWindow((process ?? Process.Start("..\\..\\..\\MS Analysis\\bin\\Debug\\Chemtech.RT.MS.Analysis.exe")).MainWindowHandle.ToInt32(), SW_MAXIMIZE);
But the window does not open, even though the process does start.
var hwnd = ..;
ShowWindow(hwnd, SW_MAXIMIZE);
BringWindowToTop(hwnd);
[DllImport("user32.dll", SetLastError=true)]
static extern bool BringWindowToTop(IntPtr hWnd)

Categories

Resources