Проблема в старых установщиках заключалась в том, что при обновлении ожидается, что ваш установщик найдет в ЖЕ ПАПЕ на компакт-диске от одного установщика к другому.(Также ожидается то же имя файла .MSI.) Когда начальная установка завершена, папка CD записывается в запись реестра MediaPackage.И когда установщик upgrqade ищет эту папку и не находит ее (потому что она изменилась), он открывает диалоговое окно «Вставить диск 1», чтобы вы могли найти его.Раздражает.
Не знаю, было ли это исправлено в более новых версиях установщика Windows, так как мы сохранили наш обходной путь в установщиках и должны были бы вытащить его для повторного тестирования.
Первое решение состоит в том, чтобы сохранить имя папки на компакт-диске одинаковым - установить жесткие требования к носителям.
Если это невозможно (потому что идиоты, которые создают ваши носители, продолжают забывать? - или естьизменения в требованиях к медиафайлам), следующее решение - создать настраиваемое действие, которое изменяет запись в папке MediaPackagePath на текущую папку компакт-диска и помещает это достаточно рано в последовательность действий, чтобы установщик не жаловался (прежде чем он на самом деле ищетЗначение папки MediaPackage).И, создайте действие Rollback Custom, чтобы ВОССТАНОВИТЬ старое значение MediaPackage, если пользователь отменяет установку.
Это непросто, поскольку также включает использование GUID зашифрованного продукта.Поэтому у вас должно быть действие, которое также генерирует зашифрованный идентификатор из стандартного ProductID.
// For XP/2000/NT MediaPackage is set in two places:
// 1. HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\
// Products\<encrypted prod guid>\SourceList\Media
// MediaPackage
// 2. HKEY_CLASSES_ROOT\Installer\Products\
// <encrypted prod guid>\SourceList\Media
// MediaPackage
У меня есть три пользовательских действия:
CalculateCompressedProdGUID () -Размещается после ISSetupFilesExtract в последовательности Execute.Это вычисляет зашифрованный идентификатор и сохраняет его в свойстве.Это также сохраняет старый MediaPackagePath в свойстве для целей отката.Размещение действия здесь, без сомнения, работает, потому что оно происходит до ResolveSource ().
ResetMediaPackagePath () - помещается после SetCompressedProdGUID () в последовательности Execute, поскольку для него требуется зашифрованный идентификатор.
RollbackMediaPackagePath () - Сбрасывает старое значение MediaPackage, если пользователь отменяет установку.Это действие должно происходить после InstallInitialize (), потому что это действие отката (оно включается только во время отката).
Настраиваемые действия выполняются только с незначительным обновлением, так как значительное обновлениеавтоматически удаляет все регистрации и повторяет их, и, следовательно, нет проблем.Фактически, весь этот ригамароле просто СОХРАНИТЬ возможность незначительного обновления при изменении имени папки продукта на компакт-диске.
Код, вероятно, будет выглядеть как мусор, только что скопированный здесь (улучшите егоесли вы думаете, что это нужно улучшить):
***************
function CalculateCompressedProdGUID(hMsi)
STRING svSubStr, svProductGUID;
STRING szCompressedGUID; // return value
NUMBER iCount, nBuffer;
begin
MsiGetProperty(ISMSI_HANDLE, "ProductCode", svProductGUID, nBuffer);
// character 0 of the GUID is {
szCompressedGUID = "";
// first group - reverse order
for iCount = 8 downto 1
StrSub(svSubStr, svProductGUID, iCount, 1);
szCompressedGUID = szCompressedGUID + svSubStr;
endfor;
// second group - reverse order
// character 9 is -
for iCount = 13 downto 10
StrSub(svSubStr, svProductGUID, iCount, 1);
szCompressedGUID = szCompressedGUID + svSubStr;
endfor;
// third group - reverse order
// character 14 is -
for iCount = 18 downto 15
StrSub(svSubStr, svProductGUID, iCount, 1);
szCompressedGUID = szCompressedGUID + svSubStr;
endfor;
// fourth group - swap every other
// character 19 is -
for iCount = 20 to 23 step 2
StrSub(svSubStr, svProductGUID, iCount + 1, 1);
szCompressedGUID = szCompressedGUID + svSubStr;
StrSub(svSubStr, svProductGUID, iCount, 1);
szCompressedGUID = szCompressedGUID + svSubStr;
endfor;
// fifth group - swap every other
// character 24 is -
for iCount = 25 to 36 step 2
StrSub(svSubStr, svProductGUID, iCount + 1, 1);
szCompressedGUID = szCompressedGUID + svSubStr;
StrSub(svSubStr, svProductGUID, iCount, 1);
szCompressedGUID = szCompressedGUID + svSubStr;
endfor;
// character 37 of the GUID is } - so ignore
MsiSetProperty(ISMSI_HANDLE, "COMPRESSED_PROD_GUID", szCompressedGUID);
return ERROR_SUCCESS;
end;
*******************
function SetMediaPackagePathRegistryEntry(hMsi)
STRING svDBMediaPackagePath, szCompressedGUID, szKey;
STRING svIsMinorUpgrade, svPathValue;
NUMBER nBuffer, nReturn, nvPathSize, nvType;
begin
// For XP/2000/NT MediaPackage is set in two places:
// 1. HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\
// Products\<encrypted prod guid>\SourceList\Media
// MediaPackage
// 2. HKEY_CLASSES_ROOT\Installer\Products\
// <encrypted prod guid>\SourceList\Media
// MediaPackage
// precaution against using during non-Minor Upgrade
svIsMinorUpgrade = "0";
nBuffer = 1;
MsiGetProperty (ISMSI_HANDLE, "IS_MINOR_UPGRADE", svIsMinorUpgrade, nBuffer);
if (svIsMinorUpgrade != "1") then
return ERROR_SUCCESS;
endif;
nBuffer = 40;
MsiGetProperty(ISMSI_HANDLE, "COMPRESSED_PROD_GUID", szCompressedGUID, nBuffer);
svPathValue = "\\"; // default
// Save the value for rollback functionality:
if (RegDBGetKeyValueEx ( szKey, "MediaPackage", nvType, svPathValue, nvPathSize ) = 0) then
MsiSetProperty(ISMSI_HANDLE, "MEDIAPACKAGEPATHROLLBACK", svPathValue);
endif;
nBuffer = 130;
MsiGetProperty(ISMSI_HANDLE, "MEDIAPACKAGEPATH", svDBMediaPackagePath, nBuffer);
// This is the main location MediaPackage is stored on 2000/XP/NT
RegDBSetDefaultRoot(HKEY_CLASSES_ROOT);
szKey = "Installer\\Products\\";
szKey = szKey + szCompressedGUID + "\\SourceList\\Media";
RegDBSetKeyValueEx ( szKey, "MediaPackage", REGDB_STRING, svDBMediaPackagePath, -1 );
// This is the secondary location.
RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);
szKey = "SOFTWARE\\Classes\\Installer\\Products\\";
szKey = szKey + szCompressedGUID + "\\SourceList\\Media";
RegDBSetKeyValueEx ( szKey, "MediaPackage", REGDB_STRING, svDBMediaPackagePath, -1 );
return ERROR_SUCCESS;
end;
*************************
function RollbackMediaPackagePathRegistryEntry(hMSI)
STRING svRollbackPackagePath, szCompressedGUID, szKey;
STRING svIsMinorUpgrade, svPathValue;
NUMBER nBuffer, nvPathSize, nReturn;
begin
// For XP/2000/NT MediaPackage is set in two places:
// 1. HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\
// Products\<encrypted prod guid>\SourceList\Media
// MediaPackage
// 2. HKEY_CLASSES_ROOT\Installer\Products\
// <encrypted prod guid>\SourceList\Media
// MediaPackage
// Remember that we no longer support Windows 98.
nBuffer = 1;
svIsMinorUpgrade = "0";
MsiGetProperty (ISMSI_HANDLE, "IS_MINOR_UPGRADE", svIsMinorUpgrade, nBuffer);
// precaution against use during non-Minor Upgrade
if (svIsMinorUpgrade != "1") then
return ERROR_SUCCESS;
endif;
nBuffer = 40;
MsiGetProperty(ISMSI_HANDLE, "COMPRESSED_PROD_GUID", szCompressedGUID, nBuffer);
// Get the rollback path
nBuffer = 130;
MsiGetProperty (ISMSI_HANDLE, "MEDIAPACKAGEPATHROLLBACK", svRollbackPackagePath, nBuffer);
// Primary location
RegDBSetDefaultRoot(HKEY_CLASSES_ROOT);
szKey = "Installer\\Products\\" + szCompressedGUID + "\\SourceList\\Media";
RegDBSetKeyValueEx ( szKey, "MediaPackage", REGDB_STRING, svRollbackPackagePath, -1 );
// Secondary location
RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);
szKey = "SOFTWARE\\Classes\\Installer\\Products\\" + szCompressedGUID + "\\SourceList\\Media";
RegDBSetKeyValueEx ( szKey, "MediaPackage", REGDB_STRING, svRollbackPackagePath, -1 );
return ERROR_SUCCESS;
end;