Learn how to launch Windows applications programmatically, handle authentication prompts reliably, and keep sessions active throughout your automation. This lesson takes you from basic app launching through production-grade credential handling and session recovery — the skills every RPA developer needs before anything else.

Picture this: you've built a beautiful automation that pulls sales data from your company's legacy ERP system every morning at 6 AM. It runs unattended, nobody's watching. But at 6:03 AM, the flow fails — not because of bad data or a selector problem, but because the application showed a login dialog, waited for credentials that never came, and eventually timed out. The whole run is wasted.
Authentication is the gatekeeper between your bot and every application it needs to work with. Whether you're automating a decades-old accounting system, an internal HR portal, or a modern CRM installed as a desktop app, the flow has to get through the front door before it can do anything useful. And it's not just about logging in once — sessions expire, apps time out after inactivity, and multi-step authentication prompts can appear at unpredictable moments. Handling all of this reliably is what separates a fragile demo from a production-grade automation.
By the end of this lesson, you'll know exactly how to launch Windows desktop applications programmatically, detect and respond to authentication dialogs, pass credentials safely, verify that login succeeded, and keep sessions alive long enough to complete your work.
What you'll learn:
This lesson assumes you have Power Automate Desktop installed and have successfully run at least one basic flow. If you're completely new to the tool, start with Getting Started with Power Automate Desktop: Installing, Recording, and Running Your First Desktop Flow before continuing here.
A working knowledge of how UI elements and selectors work in Power Automate Desktop will also help significantly. If selectors feel unfamiliar, read UI Elements and Selectors in Power Automate Desktop: Building Automations That Don't Break alongside this lesson.
You'll need access to a Windows application you want to automate — ideally one with a login screen you can test against.
Before you can handle a login prompt, you need to open the application in a way that Power Automate Desktop can work with it. There are two common approaches, and choosing the wrong one creates problems immediately.
The Run Application action (found under System in the action panel) launches an executable by its file path. Open a new flow, find "Run Application" in the action library, drag it into your canvas, and configure it like this:
C:\Program Files\FinanceApp\FinanceApp.exeThe "Wait for application to load" option pauses your flow until Windows reports that the process has finished loading. However, "finished loading" in Windows terms means the process is no longer in a startup state — it does not mean the login dialog is visible and ready for input. You'll almost always need an additional wait step.
After your Run Application action, add a Wait action set to 2–3 seconds as a baseline. Then, follow it with a Wait for UI element action that targets a specific element on the login dialog itself — the username field, for example. This two-stage approach is far more reliable than a fixed timer alone.
Here's how to configure the Wait for UI element action:
This tells the flow: Don't move forward until you can actually see the username field. If the application takes 25 seconds to load on a slow server, your flow will wait patiently rather than crashing into a missing element.
Tip
Use "Wait for UI element to appear" rather than a long fixed Wait. Fixed timers waste time when the app loads fast and fail when it loads slow. A condition-based wait adapts to actual system behavior.
Not all login screens are created equal. You need to recognize what type of prompt you're dealing with before you can handle it correctly.
These are HTML-style or Win32 forms built into the application itself — a window with a text box for username, another for password, and a button labeled "Login" or "Sign In." Power Automate Desktop interacts with these using standard UI automation: click the field, type the value, click the button.
Some applications use Windows-integrated authentication and display an operating system-level credential dialog — the one with the blue Windows security header. These are not part of the application's UI; they're system windows. They still have UI elements you can capture, but you must capture them from the dialog itself, not from the application window.
Some modern desktop applications embed a browser frame for authentication (common with SSO systems like Azure AD or Okta). The login form looks like a webpage inside the application window. In these cases, you may need to treat the embedded browser as a web automation target rather than a native UI automation target.
Warning
Web-based embedded login frames often use the Edge/WebView2 rendering engine. Power Automate Desktop can interact with these, but you may need to use browser-specific actions rather than UI Automation actions. If your selectors aren't working on what looks like a login form, check whether you're dealing with an embedded web view.
Enterprise applications increasingly use multi-step authentication: enter username, click Next, enter password on a second screen, then potentially handle an MFA prompt. Each step requires its own sequence of actions, and each screen transition requires a new wait condition.
This is where many beginners make a critical mistake: they hardcode their username and password directly into "Populate text field" or "Send keys" actions as plain text strings. Don't do this. Anyone who opens your flow can see those credentials.
The safest approach within Power Automate Desktop itself is to use sensitive input variables. When you create a flow variable and mark it as sensitive (the padlock icon in the variable properties), the value is masked in logs and in the flow designer.
Create two input variables at the top of your flow:
AppUsername — Type: Text, Sensitive: No (usernames are generally not secret)AppPassword — Type: Text, Sensitive: Yes (always mask passwords)You can then pass these values in when the flow is triggered, rather than storing them in the flow itself.
For production unattended automations, the gold standard is to retrieve credentials from Azure Key Vault at runtime rather than storing them anywhere in the flow configuration. This is covered thoroughly in Handling Credentials Securely in Desktop Flows: Sensitive Variables and Azure Key Vault — if you're building anything that will run unattended in a business environment, read that lesson carefully before going further.
The pattern looks like this in your flow:
Once you have your credentials in variables, use the Populate text field action (not "Send keys") for form fields. Populate text field interacts with the UI element directly, which is more reliable and doesn't depend on the window having focus. Configure it as:
%AppPassword%For the username field, use the same action with %AppUsername%.
Note
When filling password fields specifically, check whether the field is marked as a password type in the application. If Power Automate Desktop's "Populate text field" action doesn't seem to work on it, try "Set text" or "Send keys" as a fallback — some legacy applications handle password inputs differently.
Clicking the login button is straightforward — use a Click UI element action targeting the Submit or Login button. What's not straightforward is knowing whether the login actually worked.
After submitting credentials, one of two things happens:
Most beginners only code for success. A production flow needs to handle both.
Use an If UI element exists condition to check for the presence of an element that only appears on the main application screen — the main menu bar, a "Welcome" label, a specific navigation panel. If that element exists, login succeeded. If it doesn't exist within your timeout window, something went wrong.
Here's the structure:
Wait for UI element (Main Menu) with timeout 15 seconds
If UI element exists (Main Menu):
# Continue with your automation work
Else:
# Check for error message element
If UI element exists (Error Message Label):
Set variable LoginError = "Invalid credentials - check AppUsername and AppPassword"
Stop flow with error message %LoginError%
Else:
Set variable LoginError = "Login timed out - application may not have responded"
Stop flow with error message %LoginError%
This tells you specifically what went wrong rather than leaving you with a generic timeout error to debug at midnight.
Key insight
Always check for a positive signal (the main screen appeared) rather than just the absence of a negative signal (the error message didn't show up). Error messages might appear in ways you didn't anticipate, but the main menu is definitively either there or it isn't.
You logged in successfully. Your flow starts doing its work — navigating menus, entering data, extracting records. Then, twenty minutes in, a dialog pops up. It might be a session expiry warning, a "do you want to save changes?" prompt, or a software update notification. Your flow halts because it can't find the UI element it expected to click.
This is one of the most common failure modes in production desktop automations.
Power Automate Desktop's error handling mechanism lets you respond to unexpected situations without crashing the flow. The approach is covered in depth in Error Handling in Desktop Flows: On Block Error, Retry Policies, and Recovery Screenshots, but here's the session-specific pattern:
Wrap your main automation work in an On block error section. If any action fails (likely because an unexpected dialog stole focus), the error handler runs. Inside the error handler:
For dialogs you know will appear — like "Your session will expire in 5 minutes, do you want to continue?" — use a parallel check pattern. Build a subflow that looks for that specific dialog and clicks the "Continue" button if it finds it. Call this subflow periodically throughout your main processing loop.
# Main processing loop
Loop through each record in DataTable:
Process Record (subflow)
Check and Dismiss Session Warnings (subflow) # called every iteration
End Loop
This is a lightweight check — if the dialog isn't there, the subflow finds nothing and exits immediately. If it is there, the subflow handles it. Either way, your main loop keeps running. Using Subflows and Reusable Logic in Power Automate Desktop effectively is what makes this pattern practical to maintain.
Some applications log you out after a period of inactivity, even mid-automation. If your flow spends 10 minutes processing data in Excel before coming back to the desktop app, the app may have timed out. You need a keep-alive strategy.
The simplest keep-alive is to interact with the application at regular intervals — even something as minor as moving focus to the application window and pressing a harmless key like F5 (refresh) or moving the mouse over the menu bar.
# Inside a long-running processing loop
Set IterationCount = IterationCount + 1
If IterationCount > 50:
Focus application window
Send key {F5} # or another safe refresh key
Set IterationCount = 0
End If
Test this carefully against your specific application — some apps respond to F5 by refreshing and potentially losing your place in the UI.
Rather than trying to prevent session expiry, detect it before each significant operation. Check whether a key element from the main screen is visible. If it isn't, run the login subflow to re-authenticate, then continue.
# Before each major operation
If UI element does not exist (Main Menu Bar):
Run subflow: Login to Application
End If
# Now perform the operation
This is more robust than keep-alive because it handles any reason for session loss — timeout, application crash, network hiccup — not just inactivity timeout.
Warning
If your application requires you to navigate back to a specific screen after re-authentication, your "login and resume" subflow needs to include that navigation. Don't assume you'll land back in the right place just because you logged in again.
Everything we've built so far should live in a dedicated subflow, not scattered through your main flow. This makes maintenance dramatically easier — when the application's login screen changes (and it will), you update one subflow rather than hunting through 200 actions.
Your Login_to_FinanceApp subflow might look like this:
Subflow: Login_to_FinanceApp
1. Run Application: C:\Program Files\FinanceApp\FinanceApp.exe
2. Wait: 2 seconds
3. Wait for UI element to appear: Username field (timeout: 30s)
4. Populate text field: Username field → %AppUsername%
5. Populate text field: Password field → %AppPassword%
6. Click UI element: Login button
7. Wait for UI element to appear: Main Menu Bar (timeout: 15s)
8. If UI element exists: Main Menu Bar
Set variable: LoginSuccessful = True
Else:
Set variable: LoginSuccessful = False
Set variable: LoginErrorMessage = "Failed to log into FinanceApp"
9. Return variable: LoginSuccessful
Your main flow then simply calls this subflow and checks the output:
Run subflow: Login_to_FinanceApp
If LoginSuccessful = False:
Stop flow with error: %LoginErrorMessage%
# Continue with main work
This separation of concerns is what makes your automation maintainable at scale. When you're building multi-application workflows that touch several different systems, each application gets its own login subflow, and your main flow orchestrates them cleanly.
In this exercise, you'll build a complete login flow for a real application. If you don't have a target application handy, use Windows Notepad as a placeholder for the structural practice, or better yet, download a trial of any software that has a login screen.
Your goal: Build a flow that launches an application, logs in with credentials stored as sensitive variables, verifies the login succeeded, and re-authenticates if the session is found to be invalid when checked 60 seconds later.
Step 1: Create two flow variables — AppUsername (text) and AppPassword (sensitive text). Set their default values to your actual test credentials.
Step 2: Create a subflow called Login_to_App. Inside it, add:
%AppUsername%%AppPassword%LoginResult = "Success", else set LoginResult = "Failed"Step 3: In your main flow, call Login_to_App. Add a conditional that stops the flow if LoginResult = "Failed".
Step 4: After the login subflow, add a Wait action for 60 seconds. After that wait, add an "If UI element exists" check targeting the main screen. If it doesn't exist (session expired), call Login_to_App again.
Step 5: Run the flow. Watch the login happen, wait through the 60-second pause, and verify the session check works.
Once this is working, try manually closing the application during the 60-second wait and observe how the flow responds.
"The flow types into the wrong field" This usually happens when the application has already moved focus by the time your Populate text field action runs. Always capture the UI element explicitly — don't rely on keyboard focus. If using Send keys instead of Populate text field, add a Click action on the field first to set focus intentionally.
"The login button click doesn't seem to do anything" Some applications require the Enter key rather than a button click. Try "Send keys {Return}" after populating the password field. Also check whether the button is only enabled after both fields are filled — if you're filling them too fast, the button might still be disabled when you click it.
"My selectors break after the application updates" Build your selectors using stable attributes like Name, AutomationId, or Class rather than position-based attributes. Read UI Elements and Selectors in Power Automate Desktop: Building Automations That Don't Break for a detailed guide to building resilient selectors.
"The application shows a Windows Security dialog that I can't capture elements from" Windows credential dialogs can sometimes be tricky to capture because they run in a different security context. Try running Power Automate Desktop as the same user context as the dialog, or use the "Send keys" action after clicking on the dialog window title to set focus.
"My unattended flow fails to log in but the same flow works when attended" This is a very common issue. Unattended flows run in a non-interactive Windows session. Some applications check for interactive sessions and behave differently — or their login dialogs simply don't appear the same way. Read Attended vs Unattended RPA: Choosing a Run Mode and Configuring Machines in Power Automate to understand the session differences, and consider whether your application genuinely supports unattended automation.
"The flow crashes mid-process when a session warning appears" Wrap your processing steps in On block error handling. When an action fails, check for known interrupting dialogs before deciding whether to retry or abort. The keep-alive and dialog-check subflow pattern described in Step 5 and Step 6 above is your primary defense against this.
Tip
When debugging login failures, temporarily add a Take screenshot action immediately after the login attempt. This gives you visual evidence of what the screen looked like when things went wrong, which is far more useful than just knowing an action failed. You can remove the screenshots once the flow is stable.
Login and session management is foundational to every desktop automation you'll build. You've learned how to launch applications reliably, wait for them to be ready, handle different types of authentication prompts, pass credentials securely using sensitive variables, verify that login succeeded, handle unexpected interruptions during your automation session, and structure everything as reusable subflows.
The key mindset shift is thinking about both paths — what happens when login succeeds, and what happens when it doesn't. Production automations fail for reasons you didn't anticipate, and the difference between a flow that recovers gracefully and one that crashes and corrupts data is whether you planned for failure.
From here, consider these next steps:
Power Automate Desktop & RPA