KRogersX
3 months agoContributor
How to Test If Associated PDF Viewer Has Been Opened?
Hey y'all,
We have a PDF user manual that can be accessed from the desktop application under test.
I need to test if the PDF has actually successfully opened in the associated PDF viewer. I don't want to assume the user has a specific PDF viewer like Adobe Reader.
Any ideas on how to determine which PDF viewer is associated to PDF files, and if it's been opened successfully with a specific PDF?
In case it's helpful, here's what I came up with. This only works if the associated PDF app is initially opened with the PDF file; if the app is already open, it gets much harder to check. (Chrome and Edge in particular are difficult to check since it's highly likely they are already open.)
import winreg import shlex class Registry: @staticmethod def ReadValue( root, keyPath, valueName ): try: with winreg.OpenKey( root, keyPath, 0, winreg.KEY_READ ) as key: value, _ = winreg.QueryValueEx( key, valueName ) return value except FileNotFoundError: Log.Error( fr"Registry key or value not found: \{keyPath}\{valueName}" ) except Exception as e: Log.Error( f"Exception: {e}" ) return @staticmethod def DoesProgIdKeyExist( progId ): try: return winreg.OpenKey( winreg.HKEY_CLASSES_ROOT, progId ) != "" except FileNotFoundError: Log.Error( f"ProgId '{progId}' key not found." ) except Exception as e: Log.Error( f"Exception: {e}" ) return @staticmethod def GetAppOpenCommandPath( progIdKey ): try: keyValue = Registry.ReadValue( winreg.HKEY_CLASSES_ROOT, fr"{progIdKey}\shell\open\command", "" ) exePath = shlex.split( keyValue )[0] return exePath except FileNotFoundError: Log.Error( f"App open command key not found for key '{progIdKey}'." ) except Exception as e: Log.Error( f"Exception: {e}" ) return # end Registry class def GetProcessName( exePath ): startIndex = exePath.rindex( '\\' ) + 1 endIndex = exePath.rindex( '.' ) processName = exePath[startIndex:endIndex] return processName def CheckProcessForPdfFile( pdfProcessName, pdfFileName ): result = False processCount = Sys.ChildCount for index in range( 0, processCount - 1 ): process = Sys.Child( index ) if pdfProcessName == process.ProcessName: #Log.Message( f"PDF process '{process.ProcessName}' found..." ) if pdfFileName.lower() in process.CommandLine.lower(): Log.Message( "PDF file in command line.") result = True break return result def Example(): pdfExtPath = r"Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.pdf\UserChoice" pdfExtValue = "ProgId" progId = Registry.ReadValue(winreg.HKEY_CURRENT_USER, pdfExtPath, pdfExtValue) Log.Message(f"Prog ID = {progId}") exePath = Registry.GetAppOpenCommandPath( progId ) if Registry.DoesProgIdKeyExist( progId ) else "" Log.Message( f"App open command path = {exePath}") pdfProcessName = GetProcessName( exePath ) thePdfFileName = "User-Manual.pdf" if Sys.WaitProcess( pdfProcessName, 5000 ).Exists: Log.Checkpoint( f"PDF viewer '{pdfProcessName}' is open." ) if CheckProcessForPdfFile( pdfProcessName, thePdfFileName ): Log.Checkpoint( f"PDF viewer has opened the expected PDF file '{thePdfFileName}'." ) else: Log.Warning( f"The expected PDF file '{thePdfFileName}' might be open, but can't determine for sure." ) else: Log.Error( "PDF viewer is not open." )