Установщик Windows: ошибка 1001, CustomAction _xxxxx.install вернул фактический код ошибки 1603
Вопрос:
Я создал установщик для службы Windows с Visual Studio 2012 и InstallShield.
Сервис работает нормально.
Установщик отлично работает на моей машине для разработки (Windows 8 64 бит) и моей виртуальной машине XP (32 бит).
Но на Windows Server 2008 R2 тот же установщик получает "Ошибка 10001".
Никакой дополнительной информации.
Следующая информация была включена в журнал событий:
Product: DbBackupServiceSetup -- Error 1001.
(NULL)
(NULL)
(NULL)
(NULL)
(NULL)
the message resource is present but the message is not found in the string/message table
Если я устанавливаю вручную с:
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\InstallUtil.exe "D:\Program Files\Test\DbBackupService.exe"
Тогда он отлично работает даже на Windows Server 2008 R2...
Я создал один установщик с 32-разрядными исполняемыми файлами и один с 64-разрядными исполняемыми файлами, но я получаю эту ошибку на обоих...
Я попытался выполнить MSI с включенным ведением журнала
msiexec /i "D:\Install\DISK1\DbBackupServiceSetup.msi" /Lv "D:\example.log"
Первое указание на ошибку в файле журнала здесь:
Created Custom Action Server with PID 3932 (0xF5C).
MSI (s) (C0:74) [14:26:28:065]: Running as a service.
MSI (s) (C0:74) [14:26:28:080]: Hello, I'm your 32bit Elevated custom action server.
MSI (s) (C0!14) [14:26:33:681]:
MSI (s) (C0:E8) [14:26:33:681]: Leaked MSIHANDLE (16) of type 790531 for thread 3348
MSI (s) (C0:E8) [14:26:33:681]: Note: 1: 2769 2: _B384C869AD7BC0C39F5780609620645B.install 3: 1
Info 2769. Custom Action _B384C869AD7BC0C39F5780609620645B.install did not close 1 MSIHANDLEs.
CustomAction _B384C869AD7BC0C39F5780609620645B.install returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
Action ended 14:26:33: InstallFinalize. Return value 3.
MSI (s) (C0:F0) [14:26:33:697]: User policy value 'DisableRollback' is 0
MSI (s) (C0:F0) [14:26:33:697]: Machine policy value 'DisableRollback' is 0
Я не понимаю
Тот же установщик отлично работает на других машинах.
Все пользовательские действия обернуты в try-catch, системная учетная запись имеет полный доступ к файловой системе, и это не сетевой ресурс.
И установка службы с помощью installutil работает, поэтому она должна быть ошибкой в самом установщике.
Мне кажется, это зовет
C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe "D:\Program Files\test\DbBackupService.exe"
вместо
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\InstallUtil.exe "D:\Program Files\test\DbBackupService.exe"
и, следовательно, получает плохое изображение исключения.
Однако, если это так, то я не понимаю, почему я получаю эту ошибку, используя 32- и 64-разрядные исполняемые файлы...
Само собой разумеется, что проблема заключается в самом InstallShield...
О, я использую удаленный рабочий стол (mstsc.exe) для подключения к серверу, в случае, если это имеет значение, и у меня нет прямого доступа к серверу, поэтому я не могу попробовать, если это проблема mstsc.
3 ответа
Решено написанием моего собственного установщика.
Все, что я делаю, это встраиваю выходные данные проекта службы в качестве ресурсов в проект установщика и записываю их в указанную папку.
Затем я запускаю installutil программным способом, который просто устанавливает службу, и затем она работает.
Единственный недостаток по сравнению с настоящим инсталлятором - это то, что нет деинсталлятора, но мне уже все равно. Когда на днях быстрее накатить свой собственный установщик, чем с помощью InstallShield, тогда что-то не так с InstallShield.
Повторное изобретение колеса может привести к ошибкам, но, по крайней мере, они мои и могут быть решены.
Вот решение, на случай, если оно пригодится кому-либо еще.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace SimpleInstaller
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static int Main(string[] args)
{
if (false)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
//for (int i = 0; i < args.Length; ++i)
//{
// Console.WriteLine("args[{0}] = {1}", i, args[i]);
//}
string strPath = @"C:\pro\DbBackupService\DbBackupService\bin\Debug\DbBackupService.exe";
string[] callArgs = null;
string[] argInstall = new string[] { strPath };
string[] argUnInstall = new string[] { "/u", strPath };
bool bIsInstallation = true;
bIsInstallation = false;
callArgs = bIsInstallation ? argInstall : argUnInstall;
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.CurrentUICulture.GetConsoleFallbackUICulture();
//if(Console.OutputEncoding.CodePage != 65001 && Console.OutputEncoding.CodePage !=
if (Console.OutputEncoding.CodePage != 65001
&& Console.OutputEncoding.CodePage != System.Threading.Thread.CurrentThread.CurrentUICulture.TextInfo.OEMCodePage
&& Console.OutputEncoding.CodePage != System.Threading.Thread.CurrentThread.CurrentUICulture.TextInfo.ANSICodePage)
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
}
try
{
System.Configuration.Install.ManagedInstallerClass.InstallHelper(callArgs);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
//return -1;
}
Console.WriteLine(Environment.NewLine);
Console.WriteLine(" --- Press any key to continue --- ");
Console.ReadKey();
return 0;
} // End Sub Main
} // End Class Program
} // End Namespace SimpleInstaller
Код ошибки 1001 ВСЕГДА означает сбой в настраиваемом действии класса Installer. InstallShield просто потребляет / размещает его, как вы указали. Пользовательские действия класса установщика общеизвестно хрупки и не работают, поэтому вы получаете очень мало регистрации.
Вместо использования настраиваемого действия следует использовать собственные таблицы установщика Windows ServiceInstall и ServiceConfigure, предоставляемые InstallShield в дополнительных настройках компонента. Создайте компонент, добавьте в него свой EXE-файл службы в качестве ключевого файла, а затем определите мета-службу.
Сначала я предлагаю просто создать установку, а затем запустить ее вручную после установки. Как только это сработает, добавьте информацию ServiceControl, чтобы установщик сделал это автоматически. Сполосните и повторите на ВМ.
Если вы получаете ошибку 1920, когда установщик пытается запустить сервис, это всегда проблема сервиса. Профилируйте его, чтобы понять проблему, а затем либо исправьте код, либо исправьте установщик, если в нем отсутствует зависимость.
Решено путем переопределения всех методов пользовательских действий в моем классе установщика. После много попыток, наконец, это работает как шарм.
public override void Install(IDictionary savedState)
{
base.Install(savedState);
}
public override void Commit(IDictionary savedState)
{
base.Commit(savedState);
}
public override void Rollback(IDictionary savedState)
{
base.Rollback(savedState);
}
public override void Uninstall(IDictionary savedState)
{
base.Uninstall(savedState);
}