Установщик имеет пользовательский интерфейс, который просит пользователя скопировать и вставить строку подключения, данную ему из отдела поддержки.Установщик редактирует файл JSON в папке приложения, используя отложенное действие CustomAction.Это отложено, потому что это должно было быть после того, как файлы записаны на диск, и это также должно было иметь повышенные разрешения.Все это прекрасно работало, пока я не решил, чтобы служба запускалась сама по себе в конце установки.Моей первой попыткой было использование
<ServiceControl Id="StartService" Start="install" ...>
Но это заняло 4 минуты, чтобы потерпеть неудачу.Устранение неполадок показало, что служба запускается ПЕРЕД пользовательским действием, которое записывает строку подключения в файл JSON.Мне нужно было отложить запуск сервиса до окончания действия.Я смотрел на добавление второй записи ServiceControl в свой собственный компонент, который можно было запланировать намного позже, но это дало мне неприятное ощущение, что я собираюсь прервать деинсталляцию и восстановить установки.Итак, я только что добавил другое отложенное настраиваемое действие, упорядоченное сразу после редактирования файла JSON.Это новое действие выполняет «SC.EXE start MyServiceName».SC.EXE - это неблокирующий способ запуска служб, поэтому успешно или неудачно он завершится быстро.
Мое окончательное решение:
<Component Id="MyCloudSync.exe" Guid="{generate-your-own-guid}">
<File Id="MyCloudSync.exe.file" KeyPath="yes" Source="$(var.RELEASEBINARIES)\MyCloudSync.exe" />
<ServiceInstall Id="MyCloudSync.exe"
Type="ownProcess"
Name="MyGateway"
DisplayName="My Gateway"
Description="Synchronizes laboratory data with Cloud"
Start="auto"
ErrorControl="normal" />
<!--Start is performed by a customer action that calls SC.EXE so it can be delayed after the custom action that writes the JSON file -->
<ServiceControl Id="StartService" Stop="both" Remove="uninstall" Name="MyGateway" Wait="yes" />
</Component>
Следует отметить, что приведенная выше запись ServiceControl делаетне иметь "start =" DLL, которую вызывают GetConnectionString и SetConnectionString, является моей собственной разработкой.Wix имеет свое собственное настраиваемое действие для тихого запуска командной строки ... WixQuietExec
<CustomAction Id= "GetConnectionString"
BinaryKey="MyCustomActions"
DllEntry="GetConnectionString"
Execute="immediate"/>
<CustomAction Id= "SetConnectionString"
BinaryKey="MyCustomActions"
Impersonate="no"
DllEntry="SetConnectionString"
Execute="deferred"/>
<CustomAction Id="SetConnectionStringDeferredParams"
Property="SetConnectionString"
Value=""[INSTALLFOLDER]""[CONNECTIONSTRING]"" />
<Property Id="QtExecStartService" Value=""SC.EXE" start MyGateway"/>
<CustomAction Id="QtExecStartService"
BinaryKey="WixCA"
DllEntry="WixQuietExec"
Impersonate="no"
Execute="deferred"
Return="ignore"/>
Запуск службы - это просто удобство, поэтому установщик может запретить переход к Services.msc для выполненияначало или требуется перезагрузка.Поэтому я использовал Return = "ignore".Кроме того, SC.EXE просто переводит службу в «Ожидание запуска», поэтому он, вероятно, не сможет вернуть большую часть ошибки, если ваша служба не существует.
ПРИМЕЧАНИЕ: WixQuietExec задокументирован здесь .Обязательно укажите в EXE-файле и присвойте свойству тот же идентификатор, что и CustomAction, который использует WixQuietExec.Эта информация находится в разделе «Отложенное выполнение», но я все равно ошибся при первой попытке.