Allow calibre to be run simultaneously in two different user accounts on windows. Fixes #919856 (Python function terminated unexpectedly [Error 5] Access is denied (Error Code: 1))

This commit is contained in:
Kovid Goyal 2012-01-25 10:15:18 +05:30
parent 83c9501637
commit b271c5ea72
3 changed files with 56 additions and 18 deletions

View File

@ -161,4 +161,27 @@ def get_version():
v += '*'
return v
def get_unicode_windows_env_var(name):
import ctypes
name = unicode(name)
n = ctypes.windll.kernel32.GetEnvironmentVariableW(name, None, 0)
if n == 0:
return None
buf = ctypes.create_unicode_buffer(u'\0'*n)
ctypes.windll.kernel32.GetEnvironmentVariableW(name, buf, n)
return buf.value
def get_windows_username():
import ctypes
try:
advapi32 = ctypes.windll.advapi32
GetUserName = getattr(advapi32, u'GetUserNameW')
except AttributeError:
pass
else:
buf = ctypes.create_unicode_buffer(257)
n = ctypes.c_int(257)
if GetUserName(buf, ctypes.byref(n)):
return buf.value
return get_unicode_windows_env_var(u'USERNAME')

View File

@ -10,7 +10,7 @@ from PyQt4.Qt import (QCoreApplication, QIcon, QObject, QTimer,
from calibre import prints, plugins, force_unicode
from calibre.constants import (iswindows, __appname__, isosx, DEBUG,
filesystem_encoding)
from calibre.utils.ipc import ADDRESS, RC
from calibre.utils.ipc import gui_socket_address, RC
from calibre.gui2 import (ORG_NAME, APP_UID, initialize_file_icon_provider,
Application, choose_dir, error_dialog, question_dialog, gprefs)
from calibre.gui2.main_window import option_parser as _option_parser
@ -304,7 +304,7 @@ def cant_start(msg=_('If you are sure it is not running')+', ',
if iswindows:
what = _('try rebooting your computer.')
else:
what = _('try deleting the file')+': '+ADDRESS
what = _('try deleting the file')+': '+ gui_socket_address()
info = base%(where, msg, what)
error_dialog(None, _('Cannot Start ')+__appname__,
@ -345,14 +345,14 @@ def main(args=sys.argv):
return 0
if si:
try:
listener = Listener(address=ADDRESS)
listener = Listener(address=gui_socket_address())
except socket.error:
if iswindows:
cant_start()
if os.path.exists(ADDRESS):
os.remove(ADDRESS)
if os.path.exists(gui_socket_address()):
os.remove(gui_socket_address())
try:
listener = Listener(address=ADDRESS)
listener = Listener(address=gui_socket_address())
except socket.error:
cant_start()
else:
@ -363,7 +363,7 @@ def main(args=sys.argv):
gui_debug=gui_debug)
otherinstance = False
try:
listener = Listener(address=ADDRESS)
listener = Listener(address=gui_socket_address())
except socket.error: # Good si is correct (on UNIX)
otherinstance = True
else:

View File

@ -9,17 +9,32 @@ __docformat__ = 'restructuredtext en'
import os
from threading import Thread
from calibre.constants import iswindows
from calibre.constants import iswindows, get_windows_username
if iswindows:
ADDRESS = r'\\.\pipe\CalibreGUI'
else:
from tempfile import gettempdir
tmp = gettempdir()
user = os.environ.get('USER', '')
if not user:
user = os.path.basename(os.path.expanduser('~'))
ADDRESS = os.path.join(tmp, user+'-calibre-gui.socket')
ADDRESS = None
def gui_socket_address():
global ADDRESS
if ADDRESS is None:
if iswindows:
ADDRESS = r'\\.\pipe\CalibreGUI'
try:
user = get_windows_username()
except:
user = None
if user:
from calibre.utils.filenames import ascii_filename
user = ascii_filename(user).replace(' ', '_')
if user:
ADDRESS += '-' + user[:100] + 'x'
else:
from tempfile import gettempdir
tmp = gettempdir()
user = os.environ.get('USER', '')
if not user:
user = os.path.basename(os.path.expanduser('~'))
ADDRESS = os.path.join(tmp, user+'-calibre-gui.socket')
return ADDRESS
class RC(Thread):
@ -32,7 +47,7 @@ class RC(Thread):
from multiprocessing.connection import Client
self.done = False
try:
self.conn = Client(ADDRESS)
self.conn = Client(gui_socket_address())
self.done = True
except:
if self.print_error: