Как мне передать свойства msiexec пользовательскому действию WiX C #?
-
08-07-2019 - |
Вопрос
У меня есть MSI-файл, создаваемый с помощью Wxs 3.0.Мой MSI ссылается на пользовательское действие C #, написанное с использованием нового Проект пользовательского действия на C #.
Я хочу передать аргумент msiexec, который перенаправляется на мое пользовательское действие - например:
msiexec /i СРЕДА MyApp.msi=ТЕСТ#
В моем файле .wxs я ссылаюсь на свое пользовательское действие следующим образом:
<Property Id="ENVIRONMENT"/>
<Binary Id="WixCustomAction.dll" SourceFile="$(var.WixCustomAction.Path)" />
<CustomAction Id="WixCustomAction" BinaryKey="WixCustomAction.dll" DllEntry="ConfigureSettings"/>
<InstallExecuteSequence>
<Custom Action="WixCustomAction" After="InstallFiles"></Custom>
</InstallExecuteSequence>
Мое пользовательское действие C # настроено следующим образом:
[CustomAction]
public static ActionResult ConfigureSettings(Session session)
{
}
Я ожидал, что смогу получить доступ к собственности вот так:
строка environmentName = сеанс.Свойство["СРЕДА"];
но, похоже, это не работает.
Как мне получить доступ к свойству, которое я передал msiexec в моем пользовательском действии?
Решение
Если вместо
<CustomAction Id="SetCustomActionDataValue"
Return="check"
Property="Itp.Configurator.WixCustomAction"
Value="[ENVIRONMENT],G2,[CONFIGFILE],[TARGETDIR]ITP_v$(var.VERSION_MAJOR)" />
ты пишешь это
<CustomAction Id="SetCustomActionDataValue"
Return="check"
Property="Itp.Configurator.WixCustomAction"
Value="Environment=[ENVIRONMENT];G=G2;ConfigFile=[CONFIGFILE];TargetDir=[TARGETDIR]ITP_v$(var.VERSION_MAJOR)" />
тогда вы сможете ссылаться на свои переменные следующим образом:
string env=session.CustomActionData["Environment"];
Другие советы
Просто для полноты картины;использование метода, описанного Джереми Лью в блоге выше, позволяет добиться следующего:
Зовущий:
msiexec /i ITP.Platform.2.msi ENVIRONMENT=QA CONFIGFILE=EnvironmentConfig.xml
С этим в файле .wxs:
<Property Id="ENVIRONMENT" Secure="yes" />
<Property Id="CONFIGFILE" Secure="yes" />
<Binary Id="Itp.Configurator.WixCustomAction.dll"
SourceFile="$(var.Itp.Configurator.WixCustomAction.Path)" />
<CustomAction Id="SetCustomActionDataValue"
Return="check"
Property="Itp.Configurator.WixCustomAction"
Value="[ENVIRONMENT],G2,[CONFIGFILE],[TARGETDIR]ITP_v$(var.VERSION_MAJOR)" />
<CustomAction Id="Itp.Configurator.WixCustomAction"
Return="check"
Execute="deferred"
BinaryKey="Itp.Configurator.WixCustomAction.dll"
DllEntry="ConfigureItpBrandSettings" />
<InstallExecuteSequence>
<Custom Action="SetCustomActionDataValue" After="InstallFiles"></Custom>
<Custom Action="Itp.Configurator.WixCustomAction" After="SetCustomActionDataValue"></Custom>
</InstallExecuteSequence>
С помощью пользовательского действия:
/// <summary>
/// CustomAction keys should be Environment,BrandId,ConfigPath,itpBasePath
/// </summary>
/// <param name="session"></param>
/// <returns></returns>
[CustomAction]
public static ActionResult ConfigureItpBrandSettings(Session session)
{
string[] arguments = GetCustomActionDataArguments(session);
string environmentName = arguments[0];
string brandId = arguments[1];
string configPath = arguments[2];
string itpBasePath = arguments[3];
//Do stuff
return ActionResult.Success;
}
private static string[] GetCustomActionDataArguments(Session session)
{
string[] keys = new string[session.CustomActionData.Keys.Count];
session.CustomActionData.Keys.CopyTo(keys,0);
return keys[0].Split(',');
}
работает.
Разбор аргументов CustomActionData довольно уродлив, но это действительно работает.Надеюсь, кто-нибудь знает более элегантный способ сделать это.
Вот мой рабочий код:
<Binary Id="MyCA" SourceFile="..\bin\ChainerRun.CA.exe" />
<CustomAction Id="SetCustomActionDataValue" Return="check" Property="CustomActionData" Value="TARGETDIR=[TARGETDIR];AA=Description;" />
<CustomAction Id="ReadAndSet"
BinaryKey="MyCA"
DllEntry="ReadAndSet"
Execute="immediate"
HideTarget="no"
Return="check" />
<InstallExecuteSequence>
<Custom Action="SetCustomActionDataValue" Before="InstallFiles" />
<Custom Action="ReadAndSet" After="SetCustomActionDataValue" />
</InstallExecuteSequence>
В функции настраиваемых действий C #:
[CustomAction]
public static ActionResult ReadAndSet(Session session)
{
ActionResult retCode = ActionResult.NotExecuted;
System.Diagnostics.Debug.Assert(false);
session.Log("ReadAndSet() begins ...");
string installLocation = session.CustomActionData["TARGETDIR"];
string hostName = session.CustomActionData["AA"];
...
}
Ваше настраиваемое действие должно быть отложенным настраиваемым действием, чтобы запускаться после InstallFiles. Отложенные пользовательские действия не имеют доступа к свойствам, но они имеют доступ к CustomActionData. См. этот пост в блоге для обсуждения того, как узнать, что с этим делать. (Этот пример является настраиваемым действием VBScript, но вы сможете получить значение через коллекцию session.CustomActionData.)
Если мы говорим о Wix Sharp (а не о простом Wix с его XML-компонентами), добавление пользовательского свойства - это просто. Все, что вам нужно сделать, это установить свойство UsesProperties для вашего управляемого действия.
Например, если вы хотите добавить собственное свойство с именем " MYPROP " ;, просто определите свое действие следующим образом:
new ElevatedManagedAction(nameof(CustomActions.MyCustomAction))
{
Condition = Condition.Installed,
When = When.Before,
Step = Step.RemoveFiles,
Return = Return.check,
Execute = Execute.deferred,
UsesProperties = "MYPROP"
}
Установите значение свойства с помощью командной строки msiexec:
msiexec /i my.msi MYPROP=MYVALUE
И тогда вы сможете получить к нему доступ из своего пользовательского действия:
[CustomAction]
public static ActionResult MyCustomAction(Session session)
{
session.Log("MYPROP VALUE: " + session.CustomActionData["MYPROP"]);
return ActionResult.Success;
}
Если свойство не установлено в командной строке, значением по умолчанию будет пустая строка.