Forum Discussion

KRogersX's avatar
KRogersX
Contributor
3 months ago
Solved

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 w...
  • KRogersX's avatar
    3 months ago

    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." )