// TARGET:outlook.exe /importprf %TEMP%\LoginPI\Outlook.prf // START_IN: ///////////// // Outlook Run // Workload: Activation-less Office Workloads // Version: 1.0.0 ///////////// using LoginPI.Engine.ScriptBase; using LoginPI.Engine.ScriptBase.Components; using System; using System.IO; using System.Runtime.InteropServices; public class Run_Outlook_Office_Activation_less : ScriptBase { // ===================================================== // Imports & Constants // ===================================================== [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern void mouse_event(uint dwFlags, uint dx, uint dy, int dwData, UIntPtr dwExtraInfo); public const uint MOUSEEVENTF_WHEEL = 0x0800; // ===================================================== // Configurable Variables // ===================================================== int globalTimeoutInSeconds = 60; int globalWaitInSeconds = 3; int waitMessageboxInSeconds = 2; int inboxDownRepeat = 5; int inboxUpRepeat = 5; int existingEmailScrollDownCount = 10; int existingEmailScrollUpCount = 10; int activationDialogRetryCount = 2; int saveDialogRetryCount = 2; int typingCpm = 600; // ===================================================== // Execute Method // ===================================================== private void Execute() { // Ensure TEMP\LoginPI directory exists var temp = GetEnvironmentVariable("TEMP"); var piDir = Path.Combine(temp, "LoginPI"); if (!Directory.Exists(piDir)) Directory.CreateDirectory(piDir); // Simulate Start Menu to reset focus Wait(waitMessageboxInSeconds); Type("{LWIN}", hideInLogging: false); Wait(waitMessageboxInSeconds); Type("{ESC}", hideInLogging: false); Wait(globalWaitInSeconds); // Focus Outlook main window and dismiss popups var mainWin = FindWindow(title: "Inbox -*", processName: "OUTLOOK", timeout: globalTimeoutInSeconds); mainWin.Focus(); mainWin.Maximize(); DismissOutlookClosedItemsDialog(); DismissReminderPopup(mainWin, globalWaitInSeconds); // Scroll inbox and open one email Wait(waitMessageboxInSeconds, showOnScreen: true, onScreenText: "Navigating inbox"); var inbox = mainWin.FindControlWithXPath("Table:SuperGrid", timeout: globalTimeoutInSeconds); inbox.Focus(); inbox.Type("{DOWN}".Repeat(inboxDownRepeat), cpm: typingCpm, hideInLogging: false); inbox.Type("{UP}".Repeat(inboxUpRepeat), cpm: typingCpm, hideInLogging: false); Wait(globalWaitInSeconds); inbox.Type("{ENTER}", cpm: typingCpm, hideInLogging: false); // Measure open time and scroll within the email StartTimer("Open_Existing_Email"); var openEmail = FindWindow(className: "Win32 Window:rctrl_renwnd32", processName: "OUTLOOK", timeout: globalTimeoutInSeconds); StopTimer("Open_Existing_Email"); openEmail.Focus(); openEmail.Maximize(); // InlineScroll helper simulates a real mouse wheel event InlineScroll("Down", existingEmailScrollDownCount, 1, 0.1); InlineScroll("Up", existingEmailScrollUpCount, 1, 0.1); // PDF-print the opened email Log("Printing email to PDF"); openEmail.Type("{CTRL+P}", hideInLogging: false); var printBtn = openEmail.FindControl( className: "Button:NetUISimpleButton", title: "Print", timeout: globalTimeoutInSeconds, continueOnError: true ); if (printBtn == null) ABORT("Print button not found"); Wait(globalWaitInSeconds); // Time Save As dialog appearance printBtn.Click(); StartTimer("SaveAsDialog"); // Handle Save Print Output As dialog for (int i = 0; i < saveDialogRetryCount; i++) { var saveAs = FindWindow( className: "Win32 Window:#32770", title: "Save Print Output As", processName: "OUTLOOK", timeout: 3, continueOnError: true ); if (saveAs == null) continue; StopTimer("SaveAsDialog"); var filenameBox = saveAs.FindControl( className: "Edit:Edit", title: "File name:", timeout: globalTimeoutInSeconds ); var pdfPath = Path.Combine(piDir, "outlookPDFPrint.pdf"); if (File.Exists(pdfPath)) RemoveFile(pdfPath); Wait(globalWaitInSeconds, showOnScreen: true, onScreenText: "Typing PDF file path"); ScriptHelpers.SetTextBoxText(this, filenameBox, pdfPath, cpm: typingCpm); saveAs.Type("{ENTER}", hideInLogging: false); Wait(globalWaitInSeconds); break; } // Close the email window openEmail.Close(); Log("Outlook Run complete"); } // ===================================================== // Helper: Scroll Function // ===================================================== // Usage of Scroll(): // - direction: "Down" to scroll down or "Up" to scroll up. // - scrollCount: Number of scroll events to send. // - notches: Number of notches per event (1 notch is typically 120). // - waitTime: Time in seconds to wait between each scroll event. // Example: // Scroll("Down", 20, 1, 0.2); // Scroll("Up", 10, 2, 0.3); private void InlineScroll(string direction, int scrollCount, int notches, double waitTime) { // Simulate a real mouse wheel event with specified notches int sign = direction.Equals("Down", StringComparison.OrdinalIgnoreCase) ? -1 : 1; int delta = sign * 120 * notches; Log($"Scrolling {direction}: {scrollCount} times, {notches} notches each"); for (int i = 0; i < scrollCount; i++) { mouse_event(MOUSEEVENTF_WHEEL, 0, 0, delta, UIntPtr.Zero); Wait(seconds: waitTime, showOnScreen: false); } } // ===================================================== // Helper: Dismiss Reminder Popup // ===================================================== private void DismissReminderPopup(IWindow mainWindow, int waitTime) { var reminderWindow = FindWindow( className: "Win32 Window:#32770", title: "*Reminder(s)", processName: "OUTLOOK", timeout: 3, continueOnError: true ); if (reminderWindow != null) { Wait(seconds: waitTime, showOnScreen: true, onScreenText: "Dismissing Reminder"); var dismissAllBtn = reminderWindow.FindControl(className: "Button:Button", title: "Dismiss &All", continueOnError: true, timeout: 3); if (dismissAllBtn != null) dismissAllBtn.Click(); var yesBtn = reminderWindow.FindControl(className: "Button:Button", title: "&Yes", continueOnError: true, timeout: 2); if (yesBtn != null) { yesBtn.Click(); mainWindow.Focus(); mainWindow.Maximize(); } } } // ===================================================== // Helper: Dismiss Closed Items Dialog // ===================================================== private void DismissOutlookClosedItemsDialog() { var dialog = FindWindow( className: "Win32 Window:NUIDialog", title: "Microsoft Outlook", processName: "OUTLOOK", timeout: 2, continueOnError: true ); if (dialog != null) { dialog.Type("{ESC}", hideInLogging: false); Wait(globalWaitInSeconds); } } } // ===================================================== // Helper Class for TextBox Operations // ===================================================== public static class ScriptHelpers { public static void SetTextBoxText(ScriptBase script, IWindow textBox, string text, int cpm = 600) { int attempts = 0; string current = ""; do { textBox.Type("{CTRL+A}", hideInLogging: false); script.Wait(1); textBox.Type(text, cpm: cpm, hideInLogging: false); script.Wait(1); current = textBox.GetText(); attempts++; } while (attempts < 5 && current != text); if (current != text) script.ABORT($"Unable to set text to '{text}', got '{current}' after {attempts} attempts."); } }