1
0
mirror of https://github.com/winscp/winscp.git synced 2026-10-24 02:28:55 +03:00

Bug 83: MSI installation package

https://winscp.net/tracker/83

Source commit: 599e90f2406250f67542a77f1594218f68a7ac67
This commit is contained in:
Martin Prikryl
2022-11-10 12:13:34 +00:00
parent 0215ebbea9
commit 75dd266823
7 changed files with 78 additions and 6 deletions

View File

@@ -60,6 +60,10 @@ Currency=USD
ImportSites=Looking for sites to import...
AcceptButton=&Accept
IncompleteTranslation=You are about to use an incomplete translation. It is completed by %1%% only.%n%nUntranslated parts of the user interface will be shown in their original English version.%n%nVisit WinSCP website at winscp.net to check, if newer version of the translation is available.
MsiInstallation=WinSCP is already installed on this system using an MSI installer. Please uninstall that before running this standalone executable installer.
; MSI (sic)
InnoSetupInstallation=WinSCP is already installed on this system using a standalone executable installer. Please uninstall that before running this MSI installer.
[CustomOptions]
TranslationCompleteness=100

View File

@@ -809,6 +809,13 @@ begin
end;
end;
if IsMsiProductInstalled('{029F9450-CFEF-4408-A2BB-B69ECE29EB18}', 0) and
(not CmdLineParamExists('/OverrideMsi')) then
begin
MsgBox(CustomMessage('MsiInstallation'), mbError, MB_OK);
Abort;
end;
Result := True;
end;

View File

@@ -49,7 +49,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Base)'!=''">
<_TCHARMapping>wchar_t</_TCHARMapping>
<AllPackageLibs>vcl.lib;rtl.lib;vclx.lib;ws2_32.lib;secur32.lib;My.lib;DriveDir.lib;DragDropP.lib;tb2k.lib;tbxp.lib;bcbie.lib;Crypt32.lib;PngComponents.lib;xmlrtl.lib;vclactnband.lib;vclimg.lib;winhttp.lib;jcl.lib;vclie.lib;urlmon.lib;shlwapi.lib;powrprof.lib;soaprtl.lib;fmx.lib;dbrtl.lib;inet.lib;psapi.lib</AllPackageLibs>
<AllPackageLibs>vcl.lib;rtl.lib;vclx.lib;ws2_32.lib;secur32.lib;My.lib;DriveDir.lib;DragDropP.lib;tb2k.lib;tbxp.lib;bcbie.lib;Crypt32.lib;PngComponents.lib;xmlrtl.lib;vclactnband.lib;vclimg.lib;winhttp.lib;jcl.lib;vclie.lib;urlmon.lib;shlwapi.lib;powrprof.lib;soaprtl.lib;fmx.lib;dbrtl.lib;inet.lib;psapi.lib;msi.lib</AllPackageLibs>
<BCC_AllWarnings>true</BCC_AllWarnings>
<BCC_ExtendedErrorInfo>true</BCC_ExtendedErrorInfo>
<BCC_OptimizeForSpeed>true</BCC_OptimizeForSpeed>

View File

@@ -34,6 +34,7 @@
#include <Soap.HTTPUtil.hpp>
#include <Web.HTTPApp.hpp>
#include <System.IOUtils.hpp>
#include <WinApi.h>
//---------------------------------------------------------------------------
#define KEY _T("SYSTEM\\CurrentControlSet\\Control\\") \
_T("Session Manager\\Environment")
@@ -805,11 +806,12 @@ UnicodeString __fastcall ProgramUrl(UnicodeString URL)
FORMAT(L"%d.%d.%d.%d",
(HIWORD(FileInfo->dwFileVersionMS), LOWORD(FileInfo->dwFileVersionMS),
HIWORD(FileInfo->dwFileVersionLS), LOWORD(FileInfo->dwFileVersionLS)));
int IsInstalledFlag = (IsInstalled() ? 1 : (IsInstalledMsi() ? 2 : 0));
UnicodeString Params =
FORMAT(L"v=%s&lang=%s&isinstalled=%d",
(CurrentVersionStr,
GUIConfiguration->AppliedLocaleHex,
int(IsInstalled())));
IsInstalledFlag));
if (Configuration->IsUnofficial)
{
@@ -1983,6 +1985,12 @@ bool __fastcall AnyOtherInstanceOfSelf()
return Result;
}
//---------------------------------------------------------------------------
static bool DoIsPathToExe(const UnicodeString & Path)
{
UnicodeString ExePath = ExcludeTrailingBackslash(ExtractFilePath(Application->ExeName));
return IsPathToSameFile(ExePath, Path);
}
//---------------------------------------------------------------------------
static bool __fastcall DoIsInstalled(HKEY RootKey)
{
std::unique_ptr<TRegistry> Registry(new TRegistry(KEY_READ));
@@ -1992,21 +2000,52 @@ static bool __fastcall DoIsInstalled(HKEY RootKey)
if (Result)
{
UnicodeString InstallPath = ExcludeTrailingBackslash(Registry->ReadString(L"Inno Setup: App Path"));
UnicodeString ExePath = ExcludeTrailingBackslash(ExtractFilePath(Application->ExeName));
Result =
!InstallPath.IsEmpty() &&
IsPathToSameFile(ExePath, InstallPath);
DoIsPathToExe(InstallPath);
}
return Result;
}
//---------------------------------------------------------------------------
bool __fastcall IsInstalled()
bool IsInstalled()
{
return
DoIsInstalled(HKEY_LOCAL_MACHINE) ||
DoIsInstalled(HKEY_CURRENT_USER);
}
//---------------------------------------------------------------------------
static int GIsInstalledMsi = -1;
bool IsInstalledMsi()
{
if (GIsInstalledMsi < 0)
{
GIsInstalledMsi = 0;
wchar_t ProductCode[MAX_GUID_CHARS + 1];
if (MsiEnumRelatedProducts(L"{029F9450-CFEF-4408-A2BB-B69ECE29EB18}", 0, 0, ProductCode) == ERROR_SUCCESS)
{
UnicodeString InstallPath;
InstallPath.SetLength(MAX_PATH);
unsigned long Size = InstallPath.Length() + 1;
int ErrorCode = MsiGetProductInfo(ProductCode, INSTALLPROPERTY_INSTALLLOCATION, InstallPath.c_str(), &Size);
if (ErrorCode == ERROR_MORE_DATA)
{
InstallPath.SetLength(Size);
Size++;
ErrorCode = MsiGetProductInfo(ProductCode, INSTALLPROPERTY_INSTALLLOCATION, InstallPath.c_str(), &Size);
}
if (ErrorCode == ERROR_SUCCESS)
{
InstallPath.SetLength(Size);
if (DoIsPathToExe(InstallPath))
{
GIsInstalledMsi = 1;
}
}
}
}
return (GIsInstalledMsi > 0);
}
//---------------------------------------------------------------------------
static TStringList * __fastcall TextToTipList(const UnicodeString & Text)
{
std::unique_ptr<TStringList> List(new TStringList());

View File

@@ -25,7 +25,8 @@ void __fastcall StopUpdateThread();
UnicodeString __fastcall CampaignUrl(UnicodeString URL);
void __fastcall UpdateJumpList(TStrings * SessionNames, TStrings * WorkspaceNames);
bool __fastcall AnyOtherInstanceOfSelf();
bool __fastcall IsInstalled();
bool IsInstalled();
bool IsInstalledMsi();
UnicodeString __fastcall ProgramUrl(UnicodeString URL);
void __fastcall AutoShowNewTip();
bool __fastcall AnyTips();

View File

@@ -192,4 +192,24 @@ public:
#define SES_EX_HANDLEFRIENDLYURL (0x100)
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// msi.h (available, but does not compile)
extern "C"
{
#define MAX_GUID_CHARS 38
#define INSTALLPROPERTY_INSTALLLOCATION __TEXT("InstallLocation")
UINT WINAPI MsiEnumRelatedProductsW(
__in LPCWSTR lpUpgradeCode, // upgrade code of products to enumerate
__reserved DWORD dwReserved, // reserved, must be 0
__in DWORD iProductIndex, // 0-based index into registered products
__out_ecount(MAX_GUID_CHARS+1) LPWSTR lpProductBuf); // buffer of char count: 39 (size of string GUID)
#define MsiEnumRelatedProducts MsiEnumRelatedProductsW
//---------------------------------------------------------------------------
UINT WINAPI MsiGetProductInfoW(
__in LPCWSTR szProduct, // product code
__in LPCWSTR szAttribute, // attribute name, case-sensitive
__out_ecount_opt(*pcchValueBuf) LPWSTR lpValueBuf, // returned value, NULL if not desired
__inout_opt LPDWORD pcchValueBuf); // in/out buffer character count
#define MsiGetProductInfo MsiGetProductInfoW
}
//---------------------------------------------------------------------------
#endif // WinApiH

View File

@@ -603,6 +603,7 @@ void __fastcall UpdateStaticUsage()
bool InProgramFiles = AnsiSameText(ExeName.SubString(1, ProgramsFolder.Length()), ProgramsFolder);
Configuration->Usage->Set(L"InProgramFiles", InProgramFiles);
Configuration->Usage->Set(L"IsInstalled", IsInstalled());
Configuration->Usage->Set(L"IsInstalledMsi", IsInstalledMsi());
Configuration->Usage->Set(L"Wine", IsWine());
Configuration->Usage->Set(L"NetFrameworkVersion", GetNetVersionStr());
Configuration->Usage->Set(L"NetCoreVersion", GetNetCoreVersionStr());