Commit 96c6b2b6 authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-19781 fixups

- It is not enough to have  and DeleteSymlinks actions
because within the same installation some exes executables can be both
added and removed, which needs both adding and removing some symlinks.

Instead of CreateSymlinks, there is now FixSymlinks function, which
goes through the list, and adds or removes the symlinks as needed.

- Implemented rollback for symlink custom action.

- Generate list of symlinks in C++ file, using CMake, rather than storing
lists as MSI properties.
parent ed355f59
# Create lists # Create lists
if(COMMAND REGISTER_SYMLINK)
return()
endif()
macro(REGISTER_SYMLINK from to) macro(REGISTER_SYMLINK from to)
list(APPEND MARIADB_SYMLINK_FROMS ${from}) list(APPEND MARIADB_SYMLINK_FROMS ${from})
list(APPEND MARIADB_SYMLINK_TOS ${to}) list(APPEND MARIADB_SYMLINK_TOS ${to})
......
...@@ -14,9 +14,20 @@ ...@@ -14,9 +14,20 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA
INCLUDE_DIRECTORIES(${WIX_DIR}/../SDK/${WIX_MSVC_SUFFIX}/inc) INCLUDE_DIRECTORIES(${WIX_DIR}/../SDK/${WIX_MSVC_SUFFIX}/inc)
SET(WIXCA_SOURCES CustomAction.cpp CustomAction.def) SET(WIXCA_SOURCES CustomAction.cpp CustomAction.def ${CMAKE_CURRENT_BINARY_DIR}/symlinks.cc)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql ${CMAKE_CURRENT_SOURCE_DIR})
INCLUDE(symlinks)
LIST(LENGTH MARIADB_SYMLINK_FROMS LEN)
MATH(EXPR max_index "${LEN}-1")
SET(ALL_SYMLINKS "")
FOREACH(i RANGE 0 ${max_index})
LIST(GET MARIADB_SYMLINK_FROMS ${i} src)
LIST(GET MARIADB_SYMLINK_TOS ${i} dst)
STRING(APPEND ALL_SYMLINKS "{L\"${src}\",L\"${dst}\"},\n")
ENDFOREACH()
CONFIGURE_FILE(symlinks.cc.in symlinks.cc)
# Custom action should not depend on C runtime, since we do not know if CRT is installed. # Custom action should not depend on C runtime, since we do not know if CRT is installed.
FORCE_STATIC_CRT() FORCE_STATIC_CRT()
......
...@@ -746,7 +746,7 @@ extern "C" UINT __stdcall PresetDatabaseProperties(MSIHANDLE hInstall) ...@@ -746,7 +746,7 @@ extern "C" UINT __stdcall PresetDatabaseProperties(MSIHANDLE hInstall)
if (BufferPoolsizeParamLen && buff[0]) if (BufferPoolsizeParamLen && buff[0])
{ {
WcaLog(LOGMSG_STANDARD, "BUFFERPOOLSIZE=%s, len=%u",buff, BufferPoolsizeParamLen); WcaLog(LOGMSG_STANDARD, "BUFFERPOOLSIZE=%S, len=%u",buff, BufferPoolsizeParamLen);
InnodbBufferPoolSize= _wtoi64(buff); InnodbBufferPoolSize= _wtoi64(buff);
} }
else else
...@@ -1013,304 +1013,268 @@ extern "C" BOOL WINAPI DllMain( ...@@ -1013,304 +1013,268 @@ extern "C" BOOL WINAPI DllMain(
return TRUE; return TRUE;
} }
// check if file exists
inline bool checkIfFileExists (wstring& name) {
string sLog = "checkIfFileExists, ";
string sName(name.begin(), name.end() ); static wstring MakeExePath(const wchar_t *installDir, const wchar_t *basename)
{
ifstream f(sName); wstring path(installDir);
if (path.back() != L'\\')
sLog.append(sName); path.append(L"\\");
sLog.append(", result: "); path.append(L"bin\\");
bool fileExists = f.good(); path.append(basename);
path.append(L".exe");
if (f.good()) return path;
sLog.append("true"); }
else
sLog.append("false");
WcaLog(LOGMSG_STANDARD, sLog.c_str());
return f.good(); static wstring MakeExePath(const wchar_t *installDir, string basename)
{
wstring path(installDir);
if (path.back() != L'\\')
path.append(L"\\");
path.append(L"bin\\");
for (auto c : basename)
path+= c;
path.append(L".exe");
return path;
}
static wstring MakeFixSymlinksLogPath()
{
wchar_t buf[MAX_PATH];
if (GetTempPathW(MAX_PATH, buf))
return wstring(buf) + L"\\mariadb_msi_fix_symlinks.log";
return L"";
} }
// string to wstring static string w2s(wstring w)
std::wstring s2ws(const std::string& s)
{ {
int len; string s;
int slength = (int)s.length() + 1; for (auto wc : w)
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0); s += (char)wc;
wchar_t* buf = new wchar_t[len]; return s;
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
} }
/* MDEV-19781 MariaDB symlinks on Windows */ /*
extern "C" UINT __stdcall CreateSymlinks(MSIHANDLE hInstall) Remove symlinks if target file does not exist.
Create symlink if target exists, but symlink is not.
*/
static void fix_symlink(const wchar_t *file, const wchar_t *link,
const wchar_t *installdir,
vector<string> &rollback_actions)
{ {
HRESULT hr = S_OK; WcaLog(LOGMSG_STANDARD, "fix_symlink %S=>%S", link, file);
UINT er = ERROR_SUCCESS;
wchar_t customActionData[10000];
wchar_t installDir[MAX_PATH];
DWORD len = 10000;
wchar_t installerVersion[MAX_VERSION_PROPERTY_SIZE];
DWORD size = MAX_VERSION_PROPERTY_SIZE;
wchar_t binDir[MAX_PATH];
size_t blen = NULL;
hr = WcaInitialize(hInstall, __FUNCTION__); auto tgt= MakeExePath(installdir, file);
WcaLog(LOGMSG_STANDARD, "Initialized."); auto lnk= MakeExePath(installdir, link);
auto target_path= tgt.c_str();
auto link_path= lnk.c_str();
if (MsiGetPropertyW(hInstall, L"CustomActionData", customActionData, &len) != ERROR_SUCCESS) auto target_attr= GetFileAttributesW(target_path);
auto link_attr= GetFileAttributesW(link_path);
WcaLog(LOGMSG_STANDARD, "%S %s", target_path,
target_attr == INVALID_FILE_ATTRIBUTES ? "does not exist" : "exists");
WcaLog(LOGMSG_STANDARD, "%S %s", link_path,
link_attr == INVALID_FILE_ATTRIBUTES ? "does not exist" : "exists");
if (link_attr != INVALID_FILE_ATTRIBUTES &&
((link_attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0))
{ {
hr = HRESULT_FROM_WIN32(GetLastError()); WcaLog(LOGMSG_STANDARD, "%S is not a symlink!", link_path);
MsiProcessMessage(hInstall, INSTALLMESSAGE_INFO, hr); return;
} }
if (MsiGetPropertyW(hInstall, L"ProductVersion", installerVersion, &size) != ERROR_SUCCESS) if (target_attr == INVALID_FILE_ATTRIBUTES)
{ {
hr = HRESULT_FROM_WIN32(GetLastError()); if (link_attr == INVALID_FILE_ATTRIBUTES)
MsiProcessMessage(hInstall, INSTALLMESSAGE_INFO, hr); {
return;
} }
auto ok= DeleteFileW(link_path);
MsiProcessMessage(hInstall, INSTALLMESSAGE_INFO, hr); WcaLog(LOGMSG_STANDARD, "DeleteFileW(L\"%S\") returned %s, last error %lu",
link_path, ok ? "success" : "error", GetLastError());
wstring wsCustomActionData(customActionData); if (ok)
string sCustomActionData(wsCustomActionData.begin(), wsCustomActionData.end());
WcaLog(LOGMSG_STANDARD, sCustomActionData.c_str());
stringstream ss;
ss << sCustomActionData;
vector<string> vCustomActionData;
while( ss.good() )
{ {
string substr; rollback_actions.push_back(string("create_symlink ") + w2s(link) + " " +
getline( ss, substr, '|' ); w2s(file));
WcaLog(LOGMSG_STANDARD, substr.c_str());
vCustomActionData.push_back( substr );
} }
return;
int i = 0;
string sBinPath = "";
string sPathFrom = "";
string sPathTo = "";
for(auto const& value: vCustomActionData) {
if (i == 0) {
sBinPath = value;
sBinPath.append("bin\\");
} else if (i == 1) {
sPathFrom = value;
} else if (i == 2) {
sPathTo = value;
} }
WcaLog(LOGMSG_STANDARD, value.c_str()); if (link_attr != INVALID_FILE_ATTRIBUTES)
return;
i++;
}
WcaLog(LOGMSG_STANDARD, sBinPath.c_str()); auto ok= CreateSymbolicLinkW(link_path, target_path, 0);
WcaLog(LOGMSG_STANDARD, sPathFrom.c_str()); WcaLog(LOGMSG_STANDARD,
WcaLog(LOGMSG_STANDARD, sPathTo.c_str()); "CreateSymbolicLinkW(\"%S\",\"%S\", 0) returned %s, last error %d",
link_path, target_path, ok ? "success" : "error",
(int) GetLastError());
if (ok)
rollback_actions.push_back(string("delete ") + w2s(link));
}
stringstream ssPathFrom, ssPathTo; static string rollback_info_path()
ssPathFrom << sPathFrom; {
ssPathTo << sPathTo; char tmppath[MAX_PATH];
vector<string> vPathFrom; if (!GetTempPathA(MAX_PATH, tmppath))
vector<string> vPathTo; return "";
string filepath(tmppath);
filepath.append("\\mariadb_symlink_rollback_info.tmp");
return filepath;
}
while(ssPathFrom.good()) {
string substr = "";
getline(ssPathFrom, substr, ';');
substr = substr.insert(0, sBinPath);
WcaLog(LOGMSG_STANDARD, substr.c_str());
vPathFrom.push_back(substr);
}
while(ssPathTo.good()) { static void save_symlink_rollback_info(vector<string> rollback_info)
string substr = ""; {
getline(ssPathTo, substr, ';'); std::ofstream ofs;
substr = substr.insert(0, sBinPath); string path = rollback_info_path();
WcaLog(LOGMSG_STANDARD, substr.c_str()); ofs.open(path, std::ofstream::out | std::ofstream::trunc);
vPathTo.push_back(substr); if (!ofs.good())
return;
WcaLog(LOGMSG_STANDARD,
"Storing this rollback script for custom action in %s, in case installation rolls back",
path.c_str());
for (auto line : rollback_info)
{
WcaLog(LOGMSG_STANDARD, "%s", line.c_str());
ofs << line << "\n";
} }
WcaLog(LOGMSG_STANDARD, "End of rollback script");
}
i = 0;
for(auto const& value: vPathTo) {
string &sTmpPathFrom = vPathFrom[i];
string &sTmpPathTo = vPathTo[i];
sTmpPathFrom.append(".exe");
sTmpPathTo.append(".exe");
wstring wsPathFrom = s2ws(sTmpPathFrom);
LPCWSTR lPathFrom = wsPathFrom.c_str();
wstring wsPathTo = s2ws(sTmpPathTo);
LPCWSTR lPathTo = wsPathTo.c_str();
int createdSymlink = -1;
if (checkIfFileExists(wsPathFrom)) #include <symlinks.h>
createdSymlink = CreateSymbolicLinkW(wsPathTo.c_str(), wsPathFrom.c_str(), 0); /* MDEV-19781 MariaDB symlinks on Windows */
extern "C" UINT __stdcall FixSymlinksRollback(MSIHANDLE hInstall)
{
HRESULT hr= S_OK;
UINT er= ERROR_SUCCESS;
wchar_t targetdir[MAX_PATH];
DWORD len= MAX_PATH;
hr= WcaInitialize(hInstall, __FUNCTION__);
WcaLog(LOGMSG_STANDARD, "Initialized.");
std::ifstream ifs;
std::string command;
string created = "Created symlink: "; if (MsiGetPropertyW(hInstall, L"CustomActionData", targetdir, &len) !=
created.append(sTmpPathTo); ERROR_SUCCESS)
created.append(" --> "); {
created.append(sTmpPathFrom); hr= HRESULT_FROM_WIN32(GetLastError());
created.append(", result= "); ExitOnFailure(hr, "MsiGetPropertyW failed");
created.append(to_string(createdSymlink)); }
WcaLog(LOGMSG_STANDARD, created.c_str()); ifs.open(rollback_info_path(), std::ofstream::in);
if (!ifs.good())
goto LExit;
i++; while (ifs >> command)
{
if (command == "create_symlink")
{
string link;
ifs >> link;
auto link_path= MakeExePath(targetdir, link);
string file;
ifs >> file;
auto target_path= MakeExePath(targetdir, file);
bool ok= CreateSymbolicLinkW(link_path.c_str(), target_path.c_str(), 0);
WcaLog(LOGMSG_STANDARD, "CreateSymbolicLinkW(%S,%S) %s, last error %lu",
link_path.c_str(), target_path.c_str(), ok ? "success" : "error",
GetLastError());
}
else if (command == "delete")
{
string link;
ifs >> link;
auto link_path= MakeExePath(targetdir, link);
auto link_attr= GetFileAttributesW(link_path.c_str());
if (link_attr != INVALID_FILE_ATTRIBUTES &&
(link_attr & FILE_ATTRIBUTE_REPARSE_POINT))
{
auto ok= DeleteFileW(link_path.c_str());
WcaLog(LOGMSG_STANDARD, "DeleteFile(%S) %s, last error %lu",
link_path.c_str(), ok ? "success" : "error", GetLastError());
}
}
else
{
WcaLog(LOGMSG_STANDARD, "Unknown command '%s' in rollback script ",
command.c_str());
goto LExit;
}
} }
ReleaseStr(installDir); LExit:
ReleaseStr(installerVersion);
ReleaseStr(binDir);
return WcaFinalize(er); return WcaFinalize(er);
} }
/* MDEV-19781 MariaDB symlinks on Windows */
extern "C" UINT __stdcall DeleteSymlinks(MSIHANDLE hInstall) extern "C" UINT __stdcall SymlinksUninstall(MSIHANDLE hInstall)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS; UINT er = ERROR_SUCCESS;
wchar_t customActionData[10000]; wchar_t targetdir[MAX_PATH];
wchar_t installDir[MAX_PATH]; DWORD len = MAX_PATH;
DWORD len = 10000; int i;
DWORD size = MAX_VERSION_PROPERTY_SIZE;
wchar_t binDir[MAX_PATH];
size_t blen = NULL;
hr = WcaInitialize(hInstall, __FUNCTION__); hr = WcaInitialize(hInstall, __FUNCTION__);
WcaLog(LOGMSG_STANDARD, "DeleteSymlinks initialized."); WcaLog(LOGMSG_STANDARD, "Initialized.");
if (MsiGetPropertyW(hInstall, L"CustomActionData", customActionData, &len) != ERROR_SUCCESS) if (MsiGetPropertyW(hInstall, L"CustomActionData", targetdir, &len) !=
ERROR_SUCCESS)
{ {
hr = HRESULT_FROM_WIN32(GetLastError()); hr = HRESULT_FROM_WIN32(GetLastError());
MsiProcessMessage(hInstall, INSTALLMESSAGE_INFO, hr); ExitOnFailure(hr, "MsiGetPropertyW failed");
} }
wstring wsCustomActionData(customActionData); for (i = 0; all_symlinks[i].file; i++)
string sCustomActionData(wsCustomActionData.begin(), wsCustomActionData.end());
WcaLog(LOGMSG_STANDARD, sCustomActionData.c_str());
stringstream ss;
ss << sCustomActionData;
vector<string> vCustomActionData;
while( ss.good() )
{ {
string substr; auto link_path = MakeExePath(targetdir, all_symlinks[i].link);
getline( ss, substr, '|' ); auto link_attr = GetFileAttributesW(link_path.c_str());
WcaLog(LOGMSG_STANDARD, substr.c_str()); auto filepath = link_path.c_str();
vCustomActionData.push_back( substr );
}
int i = 0;
string sBinPath = "";
string sPathFrom = "";
string sPathTo = "";
for(auto const& value: vCustomActionData) { if (link_attr == INVALID_FILE_ATTRIBUTES)
if (i == 0) { {
sBinPath = value; WcaLog(LOGMSG_STANDARD, " %S does not exist",filepath);
sBinPath.append("bin\\"); continue;
} else if (i == 1) {
sPathFrom = value;
} else if (i == 2) {
sPathTo = value;
}
WcaLog(LOGMSG_STANDARD, value.c_str());
i++;
} }
WcaLog(LOGMSG_STANDARD, sBinPath.c_str()); if(!(link_attr & FILE_ATTRIBUTE_REPARSE_POINT))
WcaLog(LOGMSG_STANDARD, sPathFrom.c_str()); {
WcaLog(LOGMSG_STANDARD, sPathTo.c_str()); WcaLog(LOGMSG_STANDARD, " %S is not a symbolic link!",filepath);
continue;
stringstream ssPathFrom, ssPathTo;
ssPathFrom << sPathFrom;
ssPathTo << sPathTo;
vector<string> vPathFrom;
vector<string> vPathTo;
while(ssPathFrom.good()) {
string substr = "";
getline(ssPathFrom, substr, ';');
substr = substr.insert(0, sBinPath);
WcaLog(LOGMSG_STANDARD, substr.c_str());
vPathFrom.push_back(substr);
} }
BOOL ok = DeleteFileW(filepath);
while(ssPathTo.good()) { WcaLog(LOGMSG_STANDARD, "DeleteFile(%S) %s, last error %lu",
string substr = ""; filepath, ok? "succeeded":"failed", GetLastError());
getline(ssPathTo, substr, ';');
substr = substr.insert(0, sBinPath);
WcaLog(LOGMSG_STANDARD, substr.c_str());
vPathTo.push_back(substr);
} }
i = 0; LExit:
return WcaFinalize(er);
for(auto const& value: vPathTo) { }
string &sTmpPathFrom = vPathFrom[i];
string &sTmpPathTo = vPathTo[i];
sTmpPathFrom.append(".exe");
sTmpPathTo.append(".exe");
wstring wsPathFrom = s2ws(sTmpPathFrom);
LPCWSTR lPathFrom = wsPathFrom.c_str();
wstring wsPathTo = s2ws(sTmpPathTo);
LPCWSTR lPathTo = wsPathTo.c_str();
int deletedSymlink = -1;
if (checkIfFileExists(wsPathTo))
deletedSymlink = DeleteFileW(wsPathTo.c_str());
string deleted = "Deleted symlink: ";
deleted.append(sTmpPathTo);
deleted.append(" --> ");
deleted.append(sTmpPathFrom);
deleted.append(", result= ");
deleted.append(to_string(deletedSymlink));
WcaLog(LOGMSG_STANDARD, deleted.c_str()); /* MDEV-19781 MariaDB symlinks on Windows */
extern "C" UINT __stdcall FixSymlinks(MSIHANDLE hInstall)
{
HRESULT hr= S_OK;
UINT er= ERROR_SUCCESS;
wchar_t targetdir[MAX_PATH];
vector<string> rollback_actions;
DWORD len= MAX_PATH;
int i;
hr= WcaInitialize(hInstall, __FUNCTION__);
WcaLog(LOGMSG_STANDARD, "Initialized.");
i++; if (MsiGetPropertyW(hInstall, L"CustomActionData", targetdir, &len) !=
ERROR_SUCCESS)
{
hr= HRESULT_FROM_WIN32(GetLastError());
ExitOnFailure(hr, "MsiGetPropertyW failed");
} }
/*
for(size_t i = 0; i < std::size(symlink_to); i++) { for (i= 0; all_symlinks[i].file; i++)
wchar_t pathTo[MAX_PATH]; fix_symlink(all_symlinks[i].file, all_symlinks[i].link, targetdir,
rollback_actions);
wcscpy(pathTo, binDir); save_symlink_rollback_info(rollback_actions);
wcscat(pathTo, symlink_to[i].data());
wstring wsPathTo(pathTo); LExit:
if ( checkIfFileExists(wsPathTo) ) {
DeleteFileW(pathTo);
} else {
hr = HRESULT_FROM_WIN32(GetLastError());
ExitOnFailure(hr, "Could not delete symlink");
}
}
*/
ReleaseStr(installDir);
ReleaseStr(binDir);
return WcaFinalize(er); return WcaFinalize(er);
} }
...@@ -8,5 +8,6 @@ CheckDatabaseProperties ...@@ -8,5 +8,6 @@ CheckDatabaseProperties
CheckDataDirectoryEmpty CheckDataDirectoryEmpty
CheckDBInUse CheckDBInUse
CheckServiceUpgrades CheckServiceUpgrades
CreateSymlinks FixSymlinks
DeleteSymlinks FixSymlinksRollback
SymlinksUninstall
#include "symlinks.h"
symlink all_symlinks[]=
{
@ALL_SYMLINKS@
{nullptr, nullptr}
};
#pragma once
struct symlink
{
const wchar_t *file;
const wchar_t *link;
};
extern symlink all_symlinks[];
# get the symlink lists
#INCLUDE(${CMAKE_SOURCE_DIR}/../../cmake/symlinks.cmake)
#INCLUDE(symlinks)
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/../../cmake/symlinks.cmake)
MACRO(MAKE_WIX_IDENTIFIER str varname) MACRO(MAKE_WIX_IDENTIFIER str varname)
STRING(REPLACE "/" "." ${varname} "${str}") STRING(REPLACE "/" "." ${varname} "${str}")
......
...@@ -63,9 +63,6 @@ ...@@ -63,9 +63,6 @@
<Property Id="BUFFERPOOLSIZE" Secure="yes"/> <Property Id="BUFFERPOOLSIZE" Secure="yes"/>
<!-- Innodb page size --> <!-- Innodb page size -->
<Property Id="PAGESIZE" Secure="yes" Value="16K"/> <Property Id="PAGESIZE" Secure="yes" Value="16K"/>
<!-- Symlinks -->
<Property Id="SYMLINK_TOS" Value="@MARIADB_SYMLINK_TOS@" />
<Property Id="SYMLINK_FROMS" Value="@MARIADB_SYMLINK_FROMS@" />
<CustomAction Id="LaunchUrl" BinaryKey="WixCA" DllEntry="WixShellExec" Execute="immediate" Return="check" Impersonate="yes" /> <CustomAction Id="LaunchUrl" BinaryKey="WixCA" DllEntry="WixShellExec" Execute="immediate" Return="check" Impersonate="yes" />
...@@ -665,16 +662,19 @@ ...@@ -665,16 +662,19 @@
<?endif?> <?endif?>
<!-- Custom action, create symlinks --> <!-- Custom action, create symlinks -->
<CustomAction Id="CreateSymlinks.SetProperty" Return="check" Property="CreateSymlinks" Value="[INSTALLDIR]|[SYMLINK_FROMS]|[SYMLINK_TOS]" /> <CustomAction Id="Symlinks.SetProperty" Return="check" Property="Symlinks" Value="[INSTALLDIR]" />
<CustomAction Id="CreateSymlinks" BinaryKey="wixca.dll" DllEntry="CreateSymlinks" Execute="deferred" Impersonate="no" Return="ignore" /> <CustomAction Id="Symlinks" BinaryKey="wixca.dll" DllEntry="FixSymlinks" Execute="deferred" Impersonate="no" Return="ignore"/>
<CustomAction Id="DeleteSymlinks.SetProperty" Return="check" Property="DeleteSymlinks" Value="[INSTALLDIR]|[SYMLINK_FROMS]|[SYMLINK_TOS]" /> <CustomAction Id="SymlinksRollback.SetProperty" Return="check" Property="SymlinksRollback" Value="[INSTALLDIR]" />
<CustomAction Id='DeleteSymlinks' BinaryKey="wixca.dll" DllEntry="DeleteSymlinks" Execute="deferred" Impersonate="no" Return="ignore" /> <CustomAction Id="SymlinksRollback" BinaryKey="wixca.dll" DllEntry="FixSymlinksRollback" Execute="rollback" Impersonate="no" Return="ignore"/>
<CustomAction Id="SymlinksUninstall.SetProperty" Return="check" Property="SymlinksUninstall" Value="[INSTALLDIR]" />
<CustomAction Id="SymlinksUninstall" BinaryKey="wixca.dll" DllEntry="SymlinksUninstall" Execute="deferred" Impersonate="no" Return="ignore"/>
<InstallExecuteSequence> <InstallExecuteSequence>
<Custom Action="CreateSymlinks.SetProperty" Before="CreateSymlinks">NOT Installed</Custom> <Custom Action="Symlinks.SetProperty" Before="Symlinks">NOT Installed OR UPGRADINGPRODUCTCODE</Custom>
<Custom Action="CreateSymlinks" Before="InstallFinalize">NOT Installed</Custom> <Custom Action="Symlinks" After="SymlinksRollback">NOT Installed OR UPGRADINGPRODUCTCODE</Custom>
<Custom Action="DeleteSymlinks.SetProperty" Before="DeleteSymlinks">Installed AND NOT REINSTALL</Custom> <Custom Action="SymlinksRollback.SetProperty" Before="SymlinksRollback">NOT Installed OR UPGRADINGPRODUCTCODE</Custom>
<Custom Action="DeleteSymlinks" Before="RemoveFiles">Installed AND NOT REINSTALL</Custom> <Custom Action="SymlinksRollback" After="InstallFiles">NOT Installed OR UPGRADINGPRODUCTCODE</Custom>
<Custom Action="SymlinksUninstall.SetProperty" Before="SymlinksUninstall">Installed AND NOT UPGRADINGPRODUCTCODE</Custom>
<Custom Action="SymlinksUninstall" Before="RemoveFiles">Installed AND NOT UPGRADINGPRODUCTCODE</Custom>
</InstallExecuteSequence> </InstallExecuteSequence>
<!-- Custom action, call mysql_install_db --> <!-- Custom action, call mysql_install_db -->
...@@ -897,10 +897,10 @@ ...@@ -897,10 +897,10 @@
> >
<![CDATA[ NOT(NSISINSTALLKEY << "MariaDB @MAJOR_VERSION@.@MINOR_VERSION@.") OR Installed]]> <![CDATA[ NOT(NSISINSTALLKEY << "MariaDB @MAJOR_VERSION@.@MINOR_VERSION@.") OR Installed]]>
</Condition> </Condition>
<!-- Condition Message= <Condition Message=
'Setting the ALLUSERS property is not allowed because [ProductName] is a per-machine application. Setup will now exit.'> 'Setting the ALLUSERS property is not allowed because [ProductName] is a per-machine application. Setup will now exit.'>
<![CDATA[ALLUSERS = "1"]]> <![CDATA[ALLUSERS = "1"]]>
</Condition --> </Condition>
<Condition Message='This application is only supported on Windows Vista, Windows Server 2008, or higher.'> <Condition Message='This application is only supported on Windows Vista, Windows Server 2008, or higher.'>
<![CDATA[Installed OR (VersionNT >= 600)]]> <![CDATA[Installed OR (VersionNT >= 600)]]>
</Condition> </Condition>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment