[Python-checkins] cpython: Closes #23253: Delay-load ShellExecute

steve.dower python-checkins at python.org
Sat Jan 24 17:54:06 CET 2015


https://hg.python.org/cpython/rev/5bff604a864e
changeset:   94267:5bff604a864e
user:        Steve Dower <steve.dower at microsoft.com>
date:        Sat Jan 24 08:18:24 2015 -0800
summary:
  Closes #23253: Delay-load ShellExecute

files:
  Doc/library/os.rst    |   4 ++
  Misc/NEWS             |   3 +
  Modules/posixmodule.c |  47 ++++++++++++++++++++++++++++--
  3 files changed, 50 insertions(+), 4 deletions(-)


diff --git a/Doc/library/os.rst b/Doc/library/os.rst
--- a/Doc/library/os.rst
+++ b/Doc/library/os.rst
@@ -3024,6 +3024,10 @@
    doesn't work if it is.  Use the :func:`os.path.normpath` function to ensure that
    the path is properly encoded for Win32.
 
+   To reduce interpreter startup overhead, the Win32 :c:func:`ShellExecute`
+   function is not resolved until this function is first called.  If the function
+   cannot be resolved, :exc:`NotImplementedError` will be raised.
+
    Availability: Windows.
 
 
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
 Core and Builtins
 -----------------
 
+- Issue #23253: Delay-load ShellExecute[AW] in os.startfile for reduced
+  startup overhead on Windows.
+
 - Issue #22038: pyatomic.h now uses stdatomic.h or GCC built-in functions for
   atomic memory access if available. Patch written by Vitor de Lima and Gustavo
   Temple.
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -15128,6 +15128,37 @@
 an absolute path, make sure the first character is not a slash (\"/\");\n\
 the underlying Win32 ShellExecute function doesn't work if it is.");
 
+/* Grab ShellExecute dynamically from shell32 */
+static int has_ShellExecute = -1;
+static HINSTANCE (CALLBACK *Py_ShellExecuteA)(HWND, LPCSTR, LPCSTR, LPCSTR,
+                                              LPCSTR, INT);
+static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
+                                              LPCWSTR, INT);
+static int
+check_ShellExecute()
+{
+    HINSTANCE hShell32;
+
+    /* only recheck */
+    if (-1 == has_ShellExecute) {
+        Py_BEGIN_ALLOW_THREADS
+        hShell32 = LoadLibraryW(L"SHELL32");
+        Py_END_ALLOW_THREADS
+        if (hShell32) {
+            *(FARPROC*)&Py_ShellExecuteA = GetProcAddress(hShell32,
+                                            "ShellExecuteA");
+            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
+                                            "ShellExecuteW");
+            has_ShellExecute = Py_ShellExecuteA &&
+                               Py_ShellExecuteW;
+        } else {
+            has_ShellExecute = 0;
+        }
+    }
+    return has_ShellExecute;
+}
+
+
 static PyObject *
 win32_startfile(PyObject *self, PyObject *args)
 {
@@ -15138,6 +15169,14 @@
     HINSTANCE rc;
 
     PyObject *unipath, *uoperation = NULL;
+
+    if(!check_ShellExecute()) {
+        /* If the OS doesn't have ShellExecute, return a
+           NotImplementedError. */
+        return PyErr_Format(PyExc_NotImplementedError,
+            "startfile not available on this platform");
+    }
+
     if (!PyArg_ParseTuple(args, "U|s:startfile",
                           &unipath, &operation)) {
         PyErr_Clear();
@@ -15166,8 +15205,8 @@
         woperation = NULL;
 
     Py_BEGIN_ALLOW_THREADS
-    rc = ShellExecuteW((HWND)0, woperation, wpath,
-                       NULL, NULL, SW_SHOWNORMAL);
+    rc = Py_ShellExecuteW((HWND)0, woperation, wpath,
+                          NULL, NULL, SW_SHOWNORMAL);
     Py_END_ALLOW_THREADS
 
     Py_XDECREF(uoperation);
@@ -15189,8 +15228,8 @@
     }
     filepath = PyBytes_AsString(ofilepath);
     Py_BEGIN_ALLOW_THREADS
-    rc = ShellExecute((HWND)0, operation, filepath,
-                      NULL, NULL, SW_SHOWNORMAL);
+    rc = Py_ShellExecuteA((HWND)0, operation, filepath,
+                          NULL, NULL, SW_SHOWNORMAL);
     Py_END_ALLOW_THREADS
     if (rc <= (HINSTANCE)32) {
         PyObject *errval = win32_error("startfile", filepath);

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list