#!/usr/bin/env python3 """ QuickBooks Desktop Connection Test Script Run this directly on your Windows machine to test the connection. Usage: python test_qbd_connection.py """ import sys import time print("=" * 60) print("QuickBooks Desktop Connection Test") print("=" * 60) # Check platform print(f"\n1. Platform: {sys.platform}") if sys.platform != 'win32': print(" ERROR: This script must be run on Windows!") sys.exit(1) print(" OK: Running on Windows") # Check pywin32 print("\n2. Checking pywin32...") try: import pythoncom from win32com.client import Dispatch print(" OK: pywin32 is installed") except ImportError as e: print(f" ERROR: pywin32 not installed: {e}") print(" Run: pip install pywin32") sys.exit(1) # Initialize COM print("\n3. Initializing COM...") try: pythoncom.CoInitialize() print(" OK: COM initialized") except Exception as e: print(f" ERROR: Failed to initialize COM: {e}") sys.exit(1) # Create RequestProcessor print("\n4. Creating QBXMLRP2.RequestProcessor...") try: rp = Dispatch("QBXMLRP2.RequestProcessor") print(" OK: RequestProcessor created") except Exception as e: print(f" ERROR: Failed to create RequestProcessor: {e}") print("\n This usually means:") print(" - QuickBooks Desktop is not installed") print(" - QuickBooks SDK components are not registered") print(" - Try: regsvr32 \"C:\\Program Files (x86)\\Common Files\\Intuit\\QuickBooks\\qbxmlrp2.dll\"") pythoncom.CoUninitialize() sys.exit(1) # Open Connection print("\n5. Opening connection (OpenConnection2)...") try: # Connection types: # 1 = localQBD (local QuickBooks Desktop) # 2 = remoteQBD (remote QuickBooks Desktop) # 3 = localQBDLaunchUI (launch QB if not running) rp.OpenConnection2("", "QBD Test Script", 1) print(" OK: Connection opened") except Exception as e: print(f" ERROR: OpenConnection2 failed: {e}") pythoncom.CoUninitialize() sys.exit(1) # Begin Session - THIS IS WHERE IT USUALLY HANGS print("\n6. Beginning session (BeginSession)...") print(" NOTE: If this hangs, check QuickBooks for an authorization dialog!") print(" Also check: Edit > Preferences > Integrated Applications > Company Preferences") print(" Make sure 'Don't allow any applications...' is UNCHECKED") print("") print(" Attempting BeginSession with timeout indicator...") print(" (If you see dots appearing, the call is hanging)") # Start time start_time = time.time() # We can't easily timeout a COM call, but we can show progress import threading stop_dots = False def print_dots(): count = 0 while not stop_dots: time.sleep(1) count += 1 print(f" ... waiting {count}s", end='\r') if count > 30: print("\n WARNING: BeginSession is taking too long (>30s)") print(" This usually means QuickBooks is waiting for user input") print(" CHECK QUICKBOOKS FOR A DIALOG BOX!") dot_thread = threading.Thread(target=print_dots) dot_thread.daemon = True dot_thread.start() try: # File modes: # 0 = qbFileOpenDoNotCare # 1 = qbFileOpenSingleUser # 2 = qbFileOpenMultiUser ticket = rp.BeginSession("", 0) # Empty string = currently open file stop_dots = True elapsed = time.time() - start_time print(f"\n OK: Session started in {elapsed:.2f}s") print(f" Session ticket: {ticket[:30]}...") except Exception as e: stop_dots = True elapsed = time.time() - start_time print(f"\n ERROR: BeginSession failed after {elapsed:.2f}s: {e}") error_msg = str(e) if "80040408" in error_msg: print("\n DIAGNOSIS: QuickBooks is not running or no company file is open") elif "80040416" in error_msg or "80040417" in error_msg: print("\n DIAGNOSIS: Access denied - need to authorize in QuickBooks") elif "80040422" in error_msg: print("\n DIAGNOSIS: No company file is open") elif "80040423" in error_msg: print("\n DIAGNOSIS: Company file is in single-user mode by another user") try: rp.CloseConnection() except: pass pythoncom.CoUninitialize() sys.exit(1) # If we got here, try a simple query print("\n7. Testing with a simple Company query...") try: # Build a simple QBXML request request = ''' ''' response = rp.ProcessRequest(ticket, request) print(" OK: Query executed successfully") # Parse response to get company name import xml.etree.ElementTree as ET root = ET.fromstring(response) company_name = root.find(".//CompanyName") if company_name is not None: print(f" Company Name: {company_name.text}") except Exception as e: print(f" ERROR: Query failed: {e}") # End session print("\n8. Ending session...") try: rp.EndSession(ticket) print(" OK: Session ended") except Exception as e: print(f" WARNING: EndSession failed: {e}") # Close connection print("\n9. Closing connection...") try: rp.CloseConnection() print(" OK: Connection closed") except Exception as e: print(f" WARNING: CloseConnection failed: {e}") # Uninitialize COM try: pythoncom.CoUninitialize() except: pass print("\n" + "=" * 60) print("TEST COMPLETED SUCCESSFULLY!") print("=" * 60) print("\nQuickBooks Desktop connection is working properly.") print("If the web app still doesn't work, the issue may be with") print("Flask session handling or threading.")