1+ # Example of embedding CEF browser using the PyWin32 extension.
2+ # Tested with pywin32 version 218.
3+
4+ import os , sys
5+ libcef_dll = os .path .join (os .path .dirname (os .path .abspath (__file__ )),
6+ 'libcef.dll' )
7+ if os .path .exists (libcef_dll ):
8+ # Import a local module
9+ if (2 ,7 ) <= sys .version_info < (2 ,8 ):
10+ import cefpython_py27 as cefpython
11+ elif (3 ,4 ) <= sys .version_info < (3 ,4 ):
12+ import cefpython_py34 as cefpython
13+ else :
14+ raise Exception ("Unsupported python version: %s" % sys .version )
15+ else :
16+ # Import an installed package
17+ from cefpython3 import cefpython
18+
19+ import cefwindow
20+ import win32con
21+ import win32gui
22+ import win32api
23+ import time
24+
25+ DEBUG = True
26+
27+ # -----------------------------------------------------------------------------
28+ # Helper functions.
29+
30+ def Log (msg ):
31+ print ("[pywin32.py] %s" % str (msg ))
32+
33+ def GetApplicationPath (file = None ):
34+ import re , os , platform
35+ # On Windows after downloading file and calling Browser.GoForward(),
36+ # current working directory is set to %UserProfile%.
37+ # Calling os.path.dirname(os.path.realpath(__file__))
38+ # returns for eg. "C:\Users\user\Downloads". A solution
39+ # is to cache path on first call.
40+ if not hasattr (GetApplicationPath , "dir" ):
41+ if hasattr (sys , "frozen" ):
42+ dir = os .path .dirname (sys .executable )
43+ elif "__file__" in globals ():
44+ dir = os .path .dirname (os .path .realpath (__file__ ))
45+ else :
46+ dir = os .getcwd ()
47+ GetApplicationPath .dir = dir
48+ # If file is None return current directory without trailing slash.
49+ if file is None :
50+ file = ""
51+ # Only when relative path.
52+ if not file .startswith ("/" ) and not file .startswith ("\\ " ) and (
53+ not re .search (r"^[\w-]+:" , file )):
54+ path = GetApplicationPath .dir + os .sep + file
55+ if platform .system () == "Windows" :
56+ path = re .sub (r"[/\\]+" , re .escape (os .sep ), path )
57+ path = re .sub (r"[/\\]+$" , "" , path )
58+ return path
59+ return str (file )
60+
61+ def ExceptHook (excType , excValue , traceObject ):
62+ import traceback , os , time , codecs
63+ # This hook does the following: in case of exception write it to
64+ # the "error.log" file, display it to the console, shutdown CEF
65+ # and exit application immediately by ignoring "finally" (os._exit()).
66+ errorMsg = "\n " .join (traceback .format_exception (excType , excValue ,
67+ traceObject ))
68+ errorFile = GetApplicationPath ("error.log" )
69+ try :
70+ appEncoding = cefpython .g_applicationSettings ["string_encoding" ]
71+ except :
72+ appEncoding = "utf-8"
73+ if type (errorMsg ) == bytes :
74+ errorMsg = errorMsg .decode (encoding = appEncoding , errors = "replace" )
75+ try :
76+ with codecs .open (errorFile , mode = "a" , encoding = appEncoding ) as fp :
77+ fp .write ("\n [%s] %s\n " % (
78+ time .strftime ("%Y-%m-%d %H:%M:%S" ), errorMsg ))
79+ except :
80+ print ("[pywin32.py] WARNING: failed writing to error file: %s" % (
81+ errorFile ))
82+ # Convert error message to ascii before printing, otherwise
83+ # you may get error like this:
84+ # | UnicodeEncodeError: 'charmap' codec can't encode characters
85+ errorMsg = errorMsg .encode ("ascii" , errors = "replace" )
86+ errorMsg = errorMsg .decode ("ascii" , errors = "replace" )
87+ print ("\n " + errorMsg + "\n " )
88+ cefpython .QuitMessageLoop ()
89+ cefpython .Shutdown ()
90+ os ._exit (1 )
91+
92+ # -----------------------------------------------------------------------------
93+
94+ def CefAdvanced ():
95+ sys .excepthook = ExceptHook
96+
97+ appSettings = dict ()
98+ # appSettings["cache_path"] = "webcache/" # Disk cache
99+ if DEBUG :
100+ # cefpython debug messages in console and in log_file
101+ appSettings ["debug" ] = True
102+ cefwindow .g_debug = True
103+ appSettings ["log_file" ] = GetApplicationPath ("debug.log" )
104+ appSettings ["log_severity" ] = cefpython .LOGSEVERITY_INFO
105+ appSettings ["release_dcheck_enabled" ] = True # Enable only when debugging
106+ appSettings ["browser_subprocess_path" ] = "%s/%s" % (
107+ cefpython .GetModuleDirectory (), "subprocess" )
108+ cefpython .Initialize (appSettings )
109+
110+ wndproc = {
111+ win32con .WM_CLOSE : CloseWindow ,
112+ win32con .WM_DESTROY : QuitApplication ,
113+ win32con .WM_SIZE : cefpython .WindowUtils .OnSize ,
114+ win32con .WM_SETFOCUS : cefpython .WindowUtils .OnSetFocus ,
115+ win32con .WM_ERASEBKGND : cefpython .WindowUtils .OnEraseBackground
116+ }
117+
118+ browserSettings = dict ()
119+ browserSettings ["universal_access_from_file_urls_allowed" ] = True
120+ browserSettings ["file_access_from_file_urls_allowed" ] = True
121+
122+ if os .path .exists ("icon.ico" ):
123+ icon = os .path .abspath ("icon.ico" )
124+ else :
125+ icon = ""
126+
127+ windowHandle = cefwindow .CreateWindow (title = "pywin32 example" ,
128+ className = "cefpython3_example" , width = 1024 , height = 768 ,
129+ icon = icon , windowProc = wndproc )
130+ windowInfo = cefpython .WindowInfo ()
131+ windowInfo .SetAsChild (windowHandle )
132+ browser = cefpython .CreateBrowserSync (windowInfo , browserSettings ,
133+ navigateUrl = GetApplicationPath ("example.html" ))
134+ cefpython .MessageLoop ()
135+ cefpython .Shutdown ()
136+
137+ def CloseWindow (windowHandle , message , wparam , lparam ):
138+ browser = cefpython .GetBrowserByWindowHandle (windowHandle )
139+ browser .CloseBrowser ()
140+ return win32gui .DefWindowProc (windowHandle , message , wparam , lparam )
141+
142+ def QuitApplication (windowHandle , message , wparam , lparam ):
143+ win32gui .PostQuitMessage (0 )
144+ return 0
145+
146+ def GetPywin32Version ():
147+ fixed_file_info = win32api .GetFileVersionInfo (win32api .__file__ , '\\ ' )
148+ return fixed_file_info ['FileVersionLS' ] >> 16
149+
150+ if __name__ == "__main__" :
151+ Log ("pywin32 version = %s" % GetPywin32Version ())
152+ CefAdvanced ()
0 commit comments