Skip to content

Commit c889fbb

Browse files
authored
Merge 3802381 into 4e3544f
2 parents 4e3544f + 3802381 commit c889fbb

5 files changed

Lines changed: 47 additions & 12 deletions

File tree

appx/sconscript

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ signExec=env['signExec'] if env['certFile'] else None
6363
# Files from NVDA's distribution that cannot be included in the appx due to policy or security restrictions
6464
excludedDistFiles=[
6565
'nvda_eoaProxy.exe',
66-
'nvda_service.exe',
6766
'nvda_slave.exe',
6867
'nvda_noUIAccess.exe',
6968
'lib/IAccessible2Proxy.dll',
@@ -107,4 +106,3 @@ if signExec and not isStoreSubmission:
107106
env.AddPostAction(appx,signExec)
108107

109108
Return(['appx'])
110-

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ requests==2.31.0
1212
# This can be removed when upgrading py2exe to 0.13+ and python to 3.8+.
1313
# https://github.com/Ousret/charset_normalizer/issues/253
1414
charset-normalizer==2.1.1
15+
psutil==5.9.8
1516

1617
#NVDA_DMP requires diff-match-patch
1718
diff_match_patch_python==1.0.2

source/buildVersion.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def formatVersionForGUI(year, major, minor):
6767
name = "NVDA"
6868
version_year = 2023
6969
version_major = 3
70-
version_minor = 3
70+
version_minor = 4
7171
version_build = 0 # Should not be set manually. Set in 'sconscript' provided by 'appVeyor.yml'
7272
version=_formatDevVersionString()
7373
publisher="unknown"

source/installer.py

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
# A part of NonVisual Desktop Access (NVDA)
33
# This file is covered by the GNU General Public License.
44
# See the file COPYING for more details.
5-
# Copyright (C) 2011-2023 NV Access Limited, Joseph Lee, Babbage B.V., Łukasz Golonka
5+
# Copyright (C) 2011-2024 NV Access Limited, Joseph Lee, Babbage B.V., Łukasz Golonka
66

77
import ctypes
88
import winreg
99
import time
1010
import os
11+
import psutil
1112
import tempfile
1213
import shutil
1314
import itertools
@@ -22,7 +23,6 @@
2223
import COMRegistrationFixes
2324
import winKernel
2425
from typing import (
25-
Any,
2626
Dict,
2727
Union,
2828
)
@@ -205,6 +205,7 @@ def removeOldProgramFiles(destPath):
205205
for fn in files:
206206
fn = os.path.join(root, fn)
207207
# No need to use tryRemoveFile here because these files should never be locked.
208+
# TODO: should we use tryRemoveFile anyway here?
208209
if os.path.isdir(fn):
209210
shutil.rmtree(fn)
210211
else:
@@ -566,7 +567,13 @@ def _deleteKeyAndSubkeys(key, subkey):
566567
class RetriableFailure(Exception):
567568
pass
568569

569-
def tryRemoveFile(path,numRetries=6,retryInterval=0.5,rebootOK=False):
570+
571+
def tryRemoveFile(
572+
path: str,
573+
numRetries: int = 6,
574+
retryInterval: float = 0.5,
575+
rebootOK: bool = False
576+
):
570577
dirPath=os.path.dirname(path)
571578
tempPath=tempfile.mktemp(dir=dirPath)
572579
try:
@@ -581,7 +588,7 @@ def tryRemoveFile(path,numRetries=6,retryInterval=0.5,rebootOK=False):
581588
os.remove(tempPath)
582589
return
583590
except OSError:
584-
pass
591+
log.debugWarning(f"Failed to delete file {tempPath}, attempt {count}/{numRetries}", exc_info=True)
585592
time.sleep(retryInterval)
586593
if rebootOK:
587594
log.debugWarning("Failed to delete file %s, marking for delete on reboot"%tempPath)
@@ -592,12 +599,13 @@ def tryRemoveFile(path,numRetries=6,retryInterval=0.5,rebootOK=False):
592599
# #9847: Move file to None to delete it.
593600
winKernel.moveFileEx(pathQualifier+tempPath,None,winKernel.MOVEFILE_DELAY_UNTIL_REBOOT)
594601
except WindowsError:
595-
log.debugWarning("Failed to delete file %s, marking for delete on reboot"%tempPath, exc_info=True)
596-
return
602+
log.debugWarning(f"Failed to mark file {tempPath} for delete on reboot", exc_info=True)
603+
else:
604+
return
597605
try:
598606
os.rename(tempPath,path)
599-
except:
600-
log.error("Unable to rename back to %s before retriable failier"%path)
607+
except Exception:
608+
log.exception(f"Unable to rename back to {path} before retriable failure")
601609
raise RetriableFailure("File %s could not be removed"%path)
602610

603611
def tryCopyFile(sourceFilePath,destFilePath):
@@ -621,9 +629,27 @@ def tryCopyFile(sourceFilePath,destFilePath):
621629
errorCode = ctypes.GetLastError()
622630
raise OSError("Unable to copy file %s to %s, error %d"%(sourceFilePath,destFilePath,errorCode))
623631

632+
_nvdaExes = {
633+
"nvda.exe",
634+
"nvda_noUIAccess.exe",
635+
"nvda_uiAccess.exe",
636+
"nvda_dmp.exe",
637+
"nvda_slave.exe"
638+
}
639+
640+
641+
def _isNVDAAlive(installDir: str) -> bool:
642+
fullPathNvdaExes = {os.path.join(installDir, fn) for fn in _nvdaExes}
643+
for process in psutil.process_iter():
644+
if process.exe() in fullPathNvdaExes:
645+
return True
646+
return False
647+
624648

625649
def install(shouldCreateDesktopShortcut: bool = True, shouldRunAtLogon: bool = True):
626650
prevInstallPath=getInstallPath(noDefault=True)
651+
if _isNVDAAlive(prevInstallPath):
652+
raise RetriableFailure("Cannot install NVDA while it is still running")
627653
unregisterInstallation(keepDesktopShortcut=shouldCreateDesktopShortcut)
628654
installDir=defaultInstallPath
629655
startMenuFolder=defaultStartMenuFolder
@@ -633,7 +659,10 @@ def install(shouldCreateDesktopShortcut: bool = True, shouldRunAtLogon: bool = T
633659
# so we shouldn't proceed.
634660
# 2. The appropriate executable for nvda.exe will be determined by
635661
# which executables exist after copying program files.
636-
for f in ("nvda.exe","nvda_noUIAccess.exe","nvda_UIAccess.exe","nvda_service.exe","nvda_slave.exe"):
662+
# Some exes are no longer used, but we remove them anyway from legacy copies.
663+
# nvda_service.exe was removed in 2017.4 (#7625).
664+
# nvda_eoaProxy.exe was removed in 2024.1 (#15544).
665+
for f in _nvdaExes.union({"nvda_service.exe", "nvda_eoaProxy.exe"}):
637666
f=os.path.join(installDir,f)
638667
if os.path.isfile(f):
639668
tryRemoveFile(f)

user_docs/en/changes.t2t

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ What's New in NVDA
44
%!includeconf: ../changes.t2tconf
55
%!includeconf: ./locale.t2tconf
66

7+
= 2023.3.4 =
8+
This is a patch release to fix an installer issue.
9+
10+
== Bug Fixes ==
11+
- Fixes bug which caused NVDA installation to fail to an unrecoverable state. (#16122)
12+
-
13+
714
= 2023.3.3 =
815
This is a patch release to fix a security issue.
916
Please responsibly disclose security issues following NVDA's [security policy https://github.com/nvaccess/nvda/blob/master/security.md].

0 commit comments

Comments
 (0)