WinAppDriver icon indicating copy to clipboard operation
WinAppDriver copied to clipboard

Allow to attach the process based on Process ID

Open karthikmsctcs opened this issue 4 years ago • 10 comments

Appium option should allow to attach the currently running process based on the Process ID

karthikmsctcs avatar Mar 05 '20 12:03 karthikmsctcs

This is a feature request.

naeemakram avatar Mar 10 '20 13:03 naeemakram

This will attach the currently running process to session without using Root session

var processes = Process.GetProcesses(); bool exi = false; foreach (var process in processes) {

            string v = "";
            try
            {
                v = process.MainModule.FileName;
            }
            catch { }
            if (v.ToUpper() == ApplicationPath.ToUpper())
            {
                WindowHandle = process.MainWindowHandle.ToString("x");
                exi = true;
                break;
            }
        }

        //////////
        AppiumOptions Prop = new AppiumOptions();
        Prop.AddAdditionalCapability("appTopLevelWindow", WindowHandle);
        Prop.AddAdditionalCapability("deviceName", "WindowsPC");
        Prop.AddAdditionalCapability("platformName", "Windows");

        Session = new WindowsDriver<WindowsElement>(new Uri(@"http://localhost:4723/"), Prop);

karthikmsctcs avatar Mar 11 '20 04:03 karthikmsctcs

Thanks very much for the answer, I didn't know it was a possibility.

naeemakram avatar Mar 15 '20 05:03 naeemakram

@naeemakram you can use next method https://github.com/microsoft/WinAppDriver/issues/534#issuecomment-562030077

Shakevg avatar Mar 15 '20 08:03 Shakevg

@naeemakram you can use next method #534 (comment)

Thanks for the tip

naeemakram avatar Mar 16 '20 12:03 naeemakram

Process.GetProcesses() is working on local machine. how can we get processes in remote machine ? via remote WinAppDriver, I start an application, the application has a separate dialog. from Inspect, it is independent from the main session but has the same pid. my problem is how to get a windows handle for that dialog. windAppDriver.WindowHandles only give me the main windows. thanks and regards

henry1999sg avatar May 27 '20 02:05 henry1999sg

Yes it is not possible to get Window handle from a remote machine. If any one can give suggestion to get WindowsHandle from a remote machine will be very helpful.

karthikmsctcs avatar May 27 '20 03:05 karthikmsctcs

Yes it is not possible to ge

Create new console app, the console app supply grpc or http service on server, response processes to clients,
the console app start with the codes blow:

            var startInfo = new ProcessStartInfo("C:\\Program Files\\Windows Application Driver\\WinAppDriver.exe");
            var winAppDriverProcess = Process.Start(startInfo);

The client can get processes from remote machine.

huster-songtao avatar Dec 26 '21 14:12 huster-songtao

The ability to minimize the application to the Taskbar is a standard behavior of the vast majority of Windows applications. we have an option to minimize (or close) the program to the system tray (officially known as the Notification Area) that is usually located next to the Taskbar in the bottom-right corner.

process.MainWindowHandle is 0x0000000000000000 Session can not created by process.MainWindowHandle

        [DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Unicode)]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll", EntryPoint = "FindWindowEx", CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string? lpszClass, string? lpszWindow);

        public static List<IntPtr> FindAllWindowHandles(IntPtr hParent, string lpszClass, string lpszWindow)
        {
            var windowHandles = new List<IntPtr>();
            IntPtr prevChild = IntPtr.Zero;
            while (true)
            {
                var currChild = FindWindowEx(hParent, prevChild, lpszClass, lpszWindow);
                if (currChild == IntPtr.Zero)
                    break;
                windowHandles.Add(currChild);
                prevChild = currChild;
            }
            return windowHandles;
        }

        // Find one  WindowHandle, other WindowHandles are being ignored 
        var windowHandle = FindWindow("YourClassName", "YourWindowName");
        // Find all WindowHandles
        var windowHandles = FindAllWindowHandles(IntPtr.Zero, "YourClassName", "YourWindowName");

If nativeWindowHandle is not 0x0000000000000000, you can create Session by windowHandle.

                /// <summary>
        /// Create WindowsDriver by WindowHandle
        /// </summary>
        /// <param name="windowHandle">WindowHandle</param>
        /// <param name="implicitWait">Gets or sets the implicit wait timeout, which is the amount of time the driver should wait when searching for an element if it is not immediately present.</param>
        /// <returns>WindowsDriver</returns>
        public static WindowsDriver<WindowsElement>? CreateWindowsDriver(IntPtr windowHandle, double implicitWait = 1500)
        {
            if (windowHandle.ToInt32() == 0) return null;

            var windowHandleHex = windowHandle.ToInt32().ToString("x");
            var options = new OpenQA.Selenium.Appium.AppiumOptions();
            options.AddAdditionalCapability("deviceName", "WindowsPC");
            options.AddAdditionalCapability("appTopLevelWindow", windowHandleHex);
            var session = new WindowsDriver<WindowsElement>(WindowsApplicationDriver.RemoteAddress, options);
            // Set implicit timeout to 1.5 seconds to ensure element search retries every 500 ms for at most three times
            session.Manage().Timeouts().ImplicitWait = TimeSpan.FromMilliseconds(implicitWait);
            return session;
        }

huster-songtao avatar Dec 26 '21 15:12 huster-songtao

I found a workaround, find your desired applications WindowHandle, then directly create session using extracted WindowHandle. Traversing from root is not worthy. I found a lot of people are complaining about how to switch I hope this will help a lot!

import win32gui

def findWindowHandle():
    handleList = []
    def findit(hwnd,ctx):
        if win32gui.GetWindowText(hwnd) == "Microsoft Store": # check the title
            handleList.append(hwnd)

    win32gui.EnumWindows(findit,None)
    return handleList

handle = hex(findWindowHandle()[0])
print(handle)


desired_caps = {}
desired_caps["appTopLevelWindow"] = handle
desired_caps["deviceName"]="WindowsPC"
desired_caps["platformName"]="Windows"
session = webdriver.Remote(command_executor='http://127.0.0.1:4723', desired_capabilities= desired_caps)

sajid36 avatar Jun 09 '22 23:06 sajid36