Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Installer: try to clean up old library files at the end of installation with out affecting the rest of a successful install #7649

Merged
merged 14 commits into from
Oct 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 32 additions & 8 deletions source/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,36 @@ def copyUserConfig(destPath):
destFilePath=os.path.join(destPath,os.path.relpath(sourceFilePath,sourcePath))
tryCopyFile(sourceFilePath,destFilePath)

def removeOldLibFiles(destPath,rebootOK=False):
"""
Removes library files from previous versions of NVDA.
@param destPath: The path where NVDA is installed.
@ type destPath: string
@param rebootOK: If true then files can be removed on next reboot if trying to do so now fails.
@type rebootOK: boolean
"""
for topDir in ('lib','lib64'):
currentLibPath=os.path.join(destPath,topDir,versionInfo.version)
for parent,subdirs,files in os.walk(os.path.join(destPath,topDir),topdown=False):
if parent==currentLibPath:
# Lib dir for current installation. Don't touch this!
log.debug("Skipping current install lib path: %r"%parent)
continue
for d in subdirs:
path=os.path.join(parent,d)
log.debug("Removing old lib directory: %r"%path)
try:
os.rmdir(path)
except OSError:
log.warning("Failed to remove a directory no longer needed. This can be manually removed after a reboot or the installer will try removing it again next time. Directory: %r"%path)
for f in files:
path=os.path.join(parent,f)
log.debug("Removing old lib file: %r"%path)
try:
tryRemoveFile(path,numRetries=2,rebootOK=rebootOK)
except RetriableFailure:
log.warning("A file no longer needed could not be removed. This can be manually removed after a reboot, or the installer will try again next time. File: %r"%path)

def removeOldProgramFiles(destPath):
# #3181: Remove espeak-ng-data\voices except for variants.
# Otherwise, there will be duplicates if voices have been moved in this new eSpeak version.
Expand All @@ -154,14 +184,6 @@ def removeOldProgramFiles(destPath):
else:
os.remove(fn)

# #7546: Remove old version-specific libs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this issue number still relevant? If so we should probably include it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This issue number was totally wrong. Not sure why it was there in the first place. It was pointing to the one about not supporting XP anymore.

for topDir in ('lib','lib64'):
for parent,subdirs,files in os.walk(os.path.join(destPath,topDir),topdown=False):
for d in subdirs:
tryRemoveFile(os.path.join(parent,d),numRetries=1,rebootOK=True)
for f in files:
tryRemoveFile(os.path.join(parent,f),numRetries=1,rebootOK=True)

# #4235: mpr.dll is a Windows system dll accidentally included with
# earlier versions of NVDA. Its presence causes problems in Windows Vista.
fn = os.path.join(destPath, "mpr.dll")
Expand Down Expand Up @@ -404,6 +426,7 @@ def install(shouldCreateDesktopShortcut=True,shouldRunAtLogon=True):
else:
raise RuntimeError("No available executable to use as nvda.exe")
registerInstallation(installDir,startMenuFolder,shouldCreateDesktopShortcut,shouldRunAtLogon,configInLocalAppData)
removeOldLibFiles(installDir,rebootOK=True)

def removeOldLoggedFiles(installPath):
datPath=os.path.join(installPath,"uninstall.dat")
Expand Down Expand Up @@ -432,6 +455,7 @@ def createPortableCopy(destPath,shouldCopyUserConfig=True):
tryCopyFile(os.path.join(destPath,"nvda_noUIAccess.exe"),os.path.join(destPath,"nvda.exe"))
if shouldCopyUserConfig:
copyUserConfig(os.path.join(destPath,'userConfig'))
removeOldLibFiles(destPath,rebootOK=True)

def registerEaseOfAccess(installDir):
with _winreg.CreateKeyEx(_winreg.HKEY_LOCAL_MACHINE, easeOfAccess.APP_KEY_PATH, 0,
Expand Down
18 changes: 11 additions & 7 deletions source/logHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import traceback
from types import MethodType, FunctionType
import globalVars
import versionInfo

ERROR_INVALID_WINDOW_HANDLE = 1400
ERROR_TIMEOUT = 1460
Expand All @@ -29,6 +30,7 @@
EVENT_E_ALL_SUBSCRIBERS_FAILED = -2147220991
RPC_E_CALL_REJECTED = -2147418111
RPC_E_DISCONNECTED = -2147417848
LOAD_WITH_ALTERED_SEARCH_PATH=0x8

def getCodePath(f):
"""Using a frame object, gets its module path (relative to the current directory).[className.[funcName]]
Expand Down Expand Up @@ -188,17 +190,19 @@ class RemoteHandler(logging.Handler):

def __init__(self):
#Load nvdaHelperRemote.dll but with an altered search path so it can pick up other dlls in lib
h=ctypes.windll.kernel32.LoadLibraryExW(os.path.abspath(ur"lib\nvdaHelperRemote.dll"),0,0x8)
self._remoteLib=ctypes.WinDLL("nvdaHelperRemote",handle=h) if h else None
path=os.path.abspath(os.path.join(u"lib",versionInfo.version,u"nvdaHelperRemote.dll"))
h=ctypes.windll.kernel32.LoadLibraryExW(path,0,LOAD_WITH_ALTERED_SEARCH_PATH)
if not h:
raise OSError("Could not load %s"%path)
self._remoteLib=ctypes.WinDLL("nvdaHelperRemote",handle=h)
logging.Handler.__init__(self)

def emit(self, record):
msg = self.format(record)
if self._remoteLib:
try:
self._remoteLib.nvdaControllerInternal_logMessage(record.levelno, ctypes.windll.kernel32.GetCurrentProcessId(), msg)
except WindowsError:
pass
try:
self._remoteLib.nvdaControllerInternal_logMessage(record.levelno, ctypes.windll.kernel32.GetCurrentProcessId(), msg)
except WindowsError:
pass

class FileHandler(logging.StreamHandler):

Expand Down
15 changes: 8 additions & 7 deletions source/nvda.pyw
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ import pythonMonkeyPatches
import ctypes
import locale
import gettext

#Localization settings
locale.setlocale(locale.LC_ALL,'')
try:
gettext.translation('nvda',localedir='locale',languages=[locale.getlocale()[0]]).install(True)
except:
gettext.install('nvda',unicode=True)

import time
import argparse
import win32con
Expand Down Expand Up @@ -51,13 +59,6 @@ class NoConsoleOptionParser(argparse.ArgumentParser):

globalVars.startTime=time.time()

#Localization settings
locale.setlocale(locale.LC_ALL,'')
try:
gettext.translation('nvda',localedir='locale',languages=[locale.getlocale()[0]]).install(True)
except:
gettext.install('nvda',unicode=True)

# Check OS version requirements
import winVersion
if not winVersion.isSupportedOS():
Expand Down
6 changes: 6 additions & 0 deletions tests/unit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
import os
import sys

import locale
import gettext
#Localization settings
locale.setlocale(locale.LC_ALL,'')
gettext.install('nvda',unicode=True)

# The path to the unit tests.
UNIT_DIR = os.path.dirname(os.path.abspath(__file__))
# The path to the top of the repo.
Expand Down