Skip to content

Commit 1460373

Browse files
authored
Merge f6a953b into 4e3544f
2 parents 4e3544f + f6a953b commit 1460373

4 files changed

Lines changed: 46 additions & 10 deletions

File tree

appx/sconscript

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ 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',
66+
# TODO should this be excluded?
67+
# 'nvda_dmp.exe',
6768
'nvda_slave.exe',
6869
'nvda_noUIAccess.exe',
6970
'lib/IAccessible2Proxy.dll',
@@ -107,4 +108,3 @@ if signExec and not isStoreSubmission:
107108
env.AddPostAction(appx,signExec)
108109

109110
Return(['appx'])
110-

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: 36 additions & 7 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,10 +567,17 @@ 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:
580+
# TODO: turn into tryCopyFile?
573581
os.rename(path,tempPath)
574582
except (WindowsError,IOError):
575583
raise RetriableFailure("Failed to rename file %s before remove"%path)
@@ -582,6 +590,7 @@ def tryRemoveFile(path,numRetries=6,retryInterval=0.5,rebootOK=False):
582590
return
583591
except OSError:
584592
pass
593+
log.debugWarning(f"Failed to delete file {tempPath}, attempt {count}/{numRetries}")
585594
time.sleep(retryInterval)
586595
if rebootOK:
587596
log.debugWarning("Failed to delete file %s, marking for delete on reboot"%tempPath)
@@ -592,12 +601,14 @@ def tryRemoveFile(path,numRetries=6,retryInterval=0.5,rebootOK=False):
592601
# #9847: Move file to None to delete it.
593602
winKernel.moveFileEx(pathQualifier+tempPath,None,winKernel.MOVEFILE_DELAY_UNTIL_REBOOT)
594603
except WindowsError:
595-
log.debugWarning("Failed to delete file %s, marking for delete on reboot"%tempPath, exc_info=True)
596-
return
604+
log.debugWarning(f"Failed to mark file {tempPath} for delete on reboot", exc_info=True)
605+
else:
606+
return
597607
try:
608+
# TODO: turn into tryCopyFile?
598609
os.rename(tempPath,path)
599610
except:
600-
log.error("Unable to rename back to %s before retriable failier"%path)
611+
log.error(f"Unable to rename back to {path} before retriable failure")
601612
raise RetriableFailure("File %s could not be removed"%path)
602613

603614
def tryCopyFile(sourceFilePath,destFilePath):
@@ -621,9 +632,27 @@ def tryCopyFile(sourceFilePath,destFilePath):
621632
errorCode = ctypes.GetLastError()
622633
raise OSError("Unable to copy file %s to %s, error %d"%(sourceFilePath,destFilePath,errorCode))
623634

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

625652
def install(shouldCreateDesktopShortcut: bool = True, shouldRunAtLogon: bool = True):
626653
prevInstallPath=getInstallPath(noDefault=True)
654+
if _isNVDAAlive(prevInstallPath):
655+
raise RetriableFailure("Cannot install NVDA while it is still running")
627656
unregisterInstallation(keepDesktopShortcut=shouldCreateDesktopShortcut)
628657
installDir=defaultInstallPath
629658
startMenuFolder=defaultStartMenuFolder
@@ -633,7 +662,7 @@ def install(shouldCreateDesktopShortcut: bool = True, shouldRunAtLogon: bool = T
633662
# so we shouldn't proceed.
634663
# 2. The appropriate executable for nvda.exe will be determined by
635664
# 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"):
665+
for f in _nvdaExes:
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)