From a73733b146e937be196fe64e31c8dd5d52944e55 Mon Sep 17 00:00:00 2001 From: Matthieu Gallien Date: Mon, 7 Apr 2025 17:57:21 +0200 Subject: [PATCH 1/6] fix(msi): use standard replace mode for MSI installer shoudl enable replacing files during install happen only when needed instead of always will need to take care of migration from older releases Signed-off-by: Matthieu Gallien Signed-off-by: Jyrki Gadinger --- admin/win/msi/Nextcloud.wxs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/win/msi/Nextcloud.wxs b/admin/win/msi/Nextcloud.wxs index b8ef1514ded05..b83c462d6c3ba 100644 --- a/admin/win/msi/Nextcloud.wxs +++ b/admin/win/msi/Nextcloud.wxs @@ -34,7 +34,7 @@ https://www.joyofsetup.com/2010/01/16/major-upgrades-now-easier-than-ever/ --> - + From 532c5dfdeb040258190743066a98c36832eb871b Mon Sep 17 00:00:00 2001 From: Jyrki Gadinger Date: Wed, 7 May 2025 16:07:37 +0200 Subject: [PATCH 2/6] fix(msi): do not completely remove the previous installation when updating The MSIs we distribute perform so-called "major upgrades". From the Microsoft docs, we learn that... > A typical major upgrade **removes a previous version** of an > application and installs a new version. Indeed that was the case -- the previous version is uninstalled completely before the new version gets installed. Since we install an extension that's loaded by explorer, the installer will ask the user to restart Windows Explorer during the uninstallation of the previous version (and restarting that might not always work as expected). There is a way to change this behaviour though, using Wix3's `MajorUpgrade` element. Through its `Schedule` property it's possible to define when the removal of the previous version should occur. The previous value `afterInstallInitialize` is one of two values that perform a complete uninstall/install sequence. The new value `afterInstallExecute` will install new files on top of the previous installation (depending on the `REINSTALLMODE` I guess) and remove older files that are not present. In the case of the extensions this means that the .dlls from the previous installation will not be touched, as long as the version embedded in the DLL info didn't change. This results in the installer no longer requesting Windows Explorer to restart, which is a big plus :D I also changed the REINSTALLMODE to `dmus` to allow downgrades as well. With this change, the request to restart Windows Explorer should hopefully happen only once an installation was made using an MSI that contains this change. Further updates will only request a restart if the DLL version of these extensions change... See also: - https://learn.microsoft.com/en-us/windows/win32/msi/major-upgrades - https://docs.firegiant.com/wix/schema/wxs/majorupgrade/#attributes:~:text=Schedule Signed-off-by: Jyrki Gadinger --- admin/win/msi/Nextcloud.wxs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/win/msi/Nextcloud.wxs b/admin/win/msi/Nextcloud.wxs index b83c462d6c3ba..30939cd877a22 100644 --- a/admin/win/msi/Nextcloud.wxs +++ b/admin/win/msi/Nextcloud.wxs @@ -33,8 +33,8 @@ https://www.firegiant.com/wix/tutorial/upgrades-and-modularization/replacing-ourselves/ https://www.joyofsetup.com/2010/01/16/major-upgrades-now-easier-than-ever/ --> - - + + From 59f3e774ad359fe5c83edd322e4eb40b369b08f5 Mon Sep 17 00:00:00 2001 From: Jyrki Gadinger Date: Thu, 8 May 2025 14:23:40 +0200 Subject: [PATCH 3/6] fix(msi): force termination of stuck processes Stopping the Windows Explorer process does not always work. Per default the MSI Restart Manager will display a warning message after a timeout, and not attempt to restart Explorer afterwards -- resulting in a black screen if no other window is open. Setting the property `MSIRMSHUTDOWN` to `1` will force the termination of the process when the timeout is reached, which finally allows the Explorer to be restarted. Signed-off-by: Jyrki Gadinger --- admin/win/msi/Nextcloud.wxs | 1 + 1 file changed, 1 insertion(+) diff --git a/admin/win/msi/Nextcloud.wxs b/admin/win/msi/Nextcloud.wxs index 30939cd877a22..9e6a8c70f88a3 100644 --- a/admin/win/msi/Nextcloud.wxs +++ b/admin/win/msi/Nextcloud.wxs @@ -35,6 +35,7 @@ --> + From 92d5c473f5dde50e76fcd867dcfe28f49eff645d Mon Sep 17 00:00:00 2001 From: Matthieu Gallien Date: Fri, 9 May 2025 15:07:25 +0200 Subject: [PATCH 4/6] feat(windows): use cmake to configure windows integration DLL version Signed-off-by: Matthieu Gallien --- VERSION.cmake | 2 ++ shell_integration/windows/NCUtil/CMakeLists.txt | 5 ++++- shell_integration/windows/NCUtil/{Version.h => Version.h.in} | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) rename shell_integration/windows/NCUtil/{Version.h => Version.h.in} (81%) diff --git a/VERSION.cmake b/VERSION.cmake index 1623810ab798a..e7ff4215f9e47 100644 --- a/VERSION.cmake +++ b/VERSION.cmake @@ -11,6 +11,8 @@ set(MIRALL_VERSION_PATCH 50) set(MIRALL_VERSION_YEAR 2025) set(MIRALL_SOVERSION 0) set(MIRALL_PREVERSION_HUMAN "3.17.0 alpha") # For preversions where PATCH>=50. Use version + alpha, rc1, rc2, etc. +set(NCEXT_BUILD_NUM 47) +set(NCEXT_VERSION 3,0,0,${NCEXT_BUILD_NUM}) # ------------------------------------ # Minimum supported server versions diff --git a/shell_integration/windows/NCUtil/CMakeLists.txt b/shell_integration/windows/NCUtil/CMakeLists.txt index 234e1e775bc2e..75972307f6957 100644 --- a/shell_integration/windows/NCUtil/CMakeLists.txt +++ b/shell_integration/windows/NCUtil/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-FileCopyrightText: 2018 ownCloud GmbH # SPDX-License-Identifier: LGPL-2.1-or-later +configure_file(Version.h.in ${CMAKE_CURRENT_BINARY_DIR}/Version.h) + add_library(NCUtil STATIC CommunicationSocket.cpp RemotePathChecker.cpp @@ -9,5 +11,6 @@ add_library(NCUtil STATIC target_include_directories(NCUtil PUBLIC - "${CMAKE_CURRENT_SOURCE_DIR}" + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} ) diff --git a/shell_integration/windows/NCUtil/Version.h b/shell_integration/windows/NCUtil/Version.h.in similarity index 81% rename from shell_integration/windows/NCUtil/Version.h rename to shell_integration/windows/NCUtil/Version.h.in index 92f6600cc2bd7..30ce150ce4e11 100644 --- a/shell_integration/windows/NCUtil/Version.h +++ b/shell_integration/windows/NCUtil/Version.h.in @@ -5,10 +5,10 @@ // This is the number that will end up in the version window of the DLLs. // Increment this version before committing a new build if you are today's shell_integration build master. -#define NCEXT_BUILD_NUM 47 +#cmakedefine NCEXT_BUILD_NUM @NCEXT_BUILD_NUM@ #define STRINGIZE2(s) #s #define STRINGIZE(s) STRINGIZE2(s) -#define NCEXT_VERSION 3,0,0,NCEXT_BUILD_NUM +#cmakedefine NCEXT_VERSION @NCEXT_VERSION@ #define NCEXT_VERSION_STRING STRINGIZE(NCEXT_VERSION) From 96df5cb0a6039b12b34d3a06f5e2744cc026ebb5 Mon Sep 17 00:00:00 2001 From: Matthieu Gallien Date: Fri, 9 May 2025 17:10:48 +0200 Subject: [PATCH 5/6] fix(windows): add missing version to cfapi shell integration DLL Signed-off-by: Matthieu Gallien --- src/libsync/vfs/cfapi/shellext/CMakeLists.txt | 3 + .../cfapi/shellext/CfApiShellIntegration.rc | 64 +++++++++++++++++++ .../CfApiShellIntegrationVersion.h.in | 14 ++++ 3 files changed, 81 insertions(+) create mode 100644 src/libsync/vfs/cfapi/shellext/CfApiShellIntegration.rc create mode 100644 src/libsync/vfs/cfapi/shellext/CfApiShellIntegrationVersion.h.in diff --git a/src/libsync/vfs/cfapi/shellext/CMakeLists.txt b/src/libsync/vfs/cfapi/shellext/CMakeLists.txt index 8d391c7c74fcf..b4c9d404e62d6 100644 --- a/src/libsync/vfs/cfapi/shellext/CMakeLists.txt +++ b/src/libsync/vfs/cfapi/shellext/CMakeLists.txt @@ -155,6 +155,8 @@ set(cppWinRtExe "${WindowsSDKBinPathForTools}\\cppwinrt.exe") message("cppWinRtExe: ${cppWinRtExe}") message("midlExe: ${midlExe}") +configure_file(CfApiShellIntegrationVersion.h.in ${CMAKE_CURRENT_BINARY_DIR}/CfApiShellIntegrationVersion.h) + # use midl.exe and cppwinrt.exe to generate files for CustomStateProvider (WinRT class) add_custom_command(OUTPUT ${MidlOutputPathHeader} COMMAND ${midlExe} /winrt /h nul /tlb ${MidlOutputPathTlb} /winmd ${MidlOutputPathWinmd} /metadata_dir "${WindowsSDKReferencesPath}\\Windows.Foundation.FoundationContract\\${WindowsFoundationContractVersion}" /nomidl /reference "${WindowsSDKReferencesPath}\\Windows.Foundation.FoundationContract\\${WindowsFoundationContractVersion}\\Windows.Foundation.FoundationContract.winmd" /reference "${WindowsSDKReferencesPath}\\Windows.Storage.Provider.CloudFilesContract\\${WindowsStorageProviderCloudFilesContractVersion}\\Windows.Storage.Provider.CloudFilesContract.winmd" /I ${MidleFileFolder} customstateprovider.idl @@ -172,6 +174,7 @@ add_library(CfApiShellExtensions MODULE ${CMAKE_SOURCE_DIR}/src/common/shellextensionutils.cpp customstateprovider.cpp CfApiShellIntegration.def + CfApiShellIntegration.rc ) message("CUSTOM_STATE_ICON_LOCKED_OUT: ${CUSTOM_STATE_ICON_LOCKED_OUT}") diff --git a/src/libsync/vfs/cfapi/shellext/CfApiShellIntegration.rc b/src/libsync/vfs/cfapi/shellext/CfApiShellIntegration.rc new file mode 100644 index 0000000000000..b6a3777370a08 --- /dev/null +++ b/src/libsync/vfs/cfapi/shellext/CfApiShellIntegration.rc @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: GPL-2.0-or-later + */ +// Microsoft Visual C++ generated resource script. +// +#include "CfApiShellIntegrationVersion.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "windows.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION NCEXT_VERSION + PRODUCTVERSION NCEXT_VERSION + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Nextcloud GmbH" + VALUE "FileDescription", "Nextcloud CfApi shell extension" + VALUE "FileVersion", NCEXT_VERSION_STRING + VALUE "InternalName", "NCOverlays" + VALUE "LegalCopyright", "Copyright (C) 2023 Nextcloud GmbH" + VALUE "ProductName", "Nextcloud shell extension" + VALUE "ProductVersion", NCEXT_VERSION_STRING + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/libsync/vfs/cfapi/shellext/CfApiShellIntegrationVersion.h.in b/src/libsync/vfs/cfapi/shellext/CfApiShellIntegrationVersion.h.in new file mode 100644 index 0000000000000..30ce150ce4e11 --- /dev/null +++ b/src/libsync/vfs/cfapi/shellext/CfApiShellIntegrationVersion.h.in @@ -0,0 +1,14 @@ +#pragma once + +// SPDX-FileCopyrightText: 2016 ownCloud GmbH +// SPDX-License-Identifier: LGPL-2.1-or-later + +// This is the number that will end up in the version window of the DLLs. +// Increment this version before committing a new build if you are today's shell_integration build master. +#cmakedefine NCEXT_BUILD_NUM @NCEXT_BUILD_NUM@ + +#define STRINGIZE2(s) #s +#define STRINGIZE(s) STRINGIZE2(s) + +#cmakedefine NCEXT_VERSION @NCEXT_VERSION@ +#define NCEXT_VERSION_STRING STRINGIZE(NCEXT_VERSION) From d28b8e325dbf4e4bc4c2515727f14ae51f7b650d Mon Sep 17 00:00:00 2001 From: Jyrki Gadinger Date: Mon, 12 May 2025 12:39:48 +0200 Subject: [PATCH 6/6] feat(msi): do not schedule reboots ourselves let's have the MSI RestartManager take care of that Signed-off-by: Jyrki Gadinger --- admin/win/msi/Nextcloud.wxs | 3 --- 1 file changed, 3 deletions(-) diff --git a/admin/win/msi/Nextcloud.wxs b/admin/win/msi/Nextcloud.wxs index 9e6a8c70f88a3..22354a2bdee59 100644 --- a/admin/win/msi/Nextcloud.wxs +++ b/admin/win/msi/Nextcloud.wxs @@ -78,9 +78,6 @@ (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL") - - - (SCHEDULE_REBOOT=1) OR NOT (UILevel=2)