// TARGET:winword.exe /t // START_IN: ///////////// // Word 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; using System.Threading; public class Word_Run_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; // Maximum seconds to wait for windows/controls int globalWaitInSeconds = 3; // Standard pause between actions int waitMessageboxInSeconds = 2; // Duration to show on-screen wait messages int documentScrollDownCount = 40; // Number of wheel notches to scroll down in the document int documentScrollUpCount = 40; // Number of wheel notches to scroll up in the document int saveDialogRetryCount = 2; // Attempts to locate the Save As dialog int typingCpm = 600; // Characters-per-minute speed for typing file paths int startMenuWaitInSeconds = 5; // Seconds to wait around Start menu interactions int keyboardShortcutsCPM = 15; // Typing speed for keyboard shortcuts int waitInBetweenKeyboardShortcuts = 3; // Wait time between keyboard shortcuts int maxFileSizeChecks = 10; // Max poll loops before giving up on PDF size stabilization int fileSizeCheckInterval = 1000; // Milliseconds between each file‐size check // ===================================================== // Execute Method // ===================================================== private void Execute() { // Ensure TEMP\LoginEnterprise exists var temp = GetEnvironmentVariable("TEMP"); var lEDir = Path.Combine(temp, "LoginEnterprise"); if (!Directory.Exists(lEDir)) Directory.CreateDirectory(lEDir); // Simulate Start Menu interaction Log("Simulating Start Menu interaction."); Wait(startMenuWaitInSeconds); Type("{LWIN}", hideInLogging: false); Wait(startMenuWaitInSeconds); Type("{LWIN}", hideInLogging: false); Wait(1); Type("{ESC}", hideInLogging: false); Wait(startMenuWaitInSeconds); // Focus the already-open LoginVSI Word document Log("Focusing existing LoginVSI Word document."); var wordWin = FindWindow( className: "Win32 Window:OpusApp", title: "*loginvsi*", processName: "WINWORD", timeout: globalTimeoutInSeconds ); if (wordWin == null) ABORT("LoginVSI Word window not found."); wordWin.Focus(); wordWin.Maximize(); Wait(globalWaitInSeconds); // Resizing canvas and scrolling through the document wordWin.Type("{ALT}wi", cpm: keyboardShortcutsCPM, hideInLogging: false); Wait(waitInBetweenKeyboardShortcuts); wordWin.Type("{ALT}w1", cpm: keyboardShortcutsCPM, hideInLogging: false); Wait(globalWaitInSeconds); var editorPane = wordWin.FindControl(className: "Pane:_WwB", title: "loginvsi*",timeout: globalTimeoutInSeconds); // Clicking the editor pane to ensure the document is ready for scrolling Wait(globalWaitInSeconds); editorPane.Click(); Wait(waitMessageboxInSeconds, showOnScreen: true, onScreenText: "Scrolling through Word document"); Log("Scrolling down."); Scroll("Down", documentScrollDownCount, 1, 0.1); Log("Scrolling up."); Scroll("Up", documentScrollUpCount, 1, 0.1); Wait(globalWaitInSeconds); // PDF-print the document Log("Printing document to PDF"); wordWin.Type("{CTRL+P}", hideInLogging: false); // Find and click the Print button var printBtn = wordWin.FindControl( className: "Button:NetUISimpleButton", title: "Print", timeout: globalTimeoutInSeconds, continueOnError: true ); if (printBtn == null) ABORT("Print button not found"); Wait(globalWaitInSeconds); wordWin.FindControl(className: "ComboBox:NetUIDropdownAnchor", title: "Which Printer", text: "Microsoft Print to PDF", timeout: globalTimeoutInSeconds); Wait(globalWaitInSeconds); printBtn.Click(); // Time Save As dialog appearance StartTimer("SaveAsDialog"); for (int i = 0; i < saveDialogRetryCount; i++) { var saveAs = FindWindow( className: "Win32 Window:#32770", title: "Save Print Output As", processName: "WINWORD", timeout: 3, continueOnError: true ); if (saveAs == null) continue; StopTimer("SaveAsDialog"); Log("Save dialog opened."); var filenameBox = saveAs.FindControl( className: "Edit:Edit", title: "File name:", timeout: globalTimeoutInSeconds ); var pdfPath = Path.Combine(lEDir, "loginvsiWordPrint.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); // Wait up to globalTimeoutInSeconds for the PDF to appear (size > 0) var start = DateTime.UtcNow; while ((DateTime.UtcNow - start).TotalSeconds < globalTimeoutInSeconds) { if (File.Exists(pdfPath) && new FileInfo(pdfPath).Length > 0) { Log("PDF file created, size is now > 0 bytes."); break; } Thread.Sleep(500); } // Poll until its size stops growing (or until maxFileSizeChecks) long lastSize = new FileInfo(pdfPath).Length; for (int loop = 0; loop < maxFileSizeChecks; loop++) { Thread.Sleep(fileSizeCheckInterval); if (File.Exists(pdfPath)) { var fi = new FileInfo(pdfPath); if (fi.Length == lastSize) { Log($"PDF size stabilized at {fi.Length} bytes after {loop + 1} checks."); break; } lastSize = fi.Length; } } break; } Log("Word Run complete; document remains open."); } // ===================================================== // 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); void Scroll(string direction, int scrollCount, int notches, double waitTime) { if (waitTime <= 0) throw new ArgumentException("Scroll waitTime must be > 0 seconds."); int sign = direction.Equals("Down", StringComparison.OrdinalIgnoreCase) ? -1 : 1; int delta = sign * 120 * notches; Log($"Scrolling {direction} {scrollCount} times, {notches} notch(es) each, {waitTime}s between."); for (int i = 0; i < scrollCount; i++) { mouse_event(MOUSEEVENTF_WHEEL, 0, 0, delta, UIntPtr.Zero); Wait(seconds: waitTime); } } } // ===================================================== // 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 = null; 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 '{text}', got '{current}' after {attempts} attempts."); } }