Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Installation 如何最好地在WiX中定义自定义操作?_Installation_Wix - Fatal编程技术网

Installation 如何最好地在WiX中定义自定义操作?

Installation 如何最好地在WiX中定义自定义操作?,installation,wix,Installation,Wix,我有一个安装程序和一个自定义操作(加上撤消和回滚),它使用安装程序中的一个属性。自定义操作必须在所有文件都位于硬盘上之后进行。在WXS文件中,似乎需要16个条目来完成此操作;根中有八个,如下所示: <CustomAction Id="SetForRollbackDo" Execute="immediate" Property="RollbackDo" Value="[MYPROP]"/> <CustomAction Id="RollbackDo" Execute="rollba

我有一个安装程序和一个自定义操作(加上撤消和回滚),它使用安装程序中的一个属性。自定义操作必须在所有文件都位于硬盘上之后进行。在WXS文件中,似乎需要16个条目来完成此操作;根中有八个,如下所示:

<CustomAction Id="SetForRollbackDo" Execute="immediate" Property="RollbackDo" Value="[MYPROP]"/>
<CustomAction Id="RollbackDo" Execute="rollback" BinaryKey="MyDLL" DllEntry="UndoThing" Return="ignore"/>
<CustomAction Id="SetForDo" Execute="immediate" Property="Do" Value="[MYPROP]"/>
<CustomAction Id="Do" Execute="deferred" BinaryKey="MyDLL" DllEntry="DoThing" Return="check"/>
<CustomAction Id="SetForRollbackUndo" Execute="immediate" Property="RollbackUndo" Value="[MYPROP]"/>
<CustomAction Id="RollbackUndo" Execute="rollback" BinaryKey="MyDLL" DllEntry="DoThing" Return="ignore"/>
<CustomAction Id="SetForUndo" Execute="immediate" Property="Undo" Value="[MYPROP]"/>
<CustomAction Id="Undo" Execute="deferred" BinaryKey="MyDLL" DllEntry="UndoThing" Return="check"/>
<Custom Action="SetForRollbackDo" After="InstallFiles">REMOVE&lt;>"ALL"</Custom>
<Custom Action="RollbackDo" After="SetForRollbackDo">REMOVE&lt;>"ALL"</Custom>
<Custom Action="SetForDo" After="RollbackDo">REMOVE&lt;>"ALL"</Custom>
<Custom Action="Do" After="SetForDo">REMOVE&lt;>"ALL"</Custom>
<Custom Action="SetForRollbackUndo" After="InstallInitialize">REMOVE="ALL"</Custom>
<Custom Action="RollbackUndo" After="SetForRollbackUndo">REMOVE="ALL"</Custom>
<Custom Action="SetForUndo" After="RollbackUndo">REMOVE="ALL"</Custom>
<Custom Action="Undo" After="SetForUndo">REMOVE="ALL"</Custom>

有更好的方法吗?

< P>如果你有复杂的自定义动作需要支持回滚,你可以考虑写一个Wix扩展。扩展通常提供创作支持(即映射到MSI表项的新XML标记),以及自定义操作的自动调度


这不仅仅是编写自定义操作的工作,但是一旦您的CA达到一定的复杂程度,扩展提供的轻松创作就值得了。

WiX自定义操作是一个很好的模型。在这种情况下,您只能使用
CustomAction
声明立即操作、延迟操作和回滚操作。您只能使用
Custom
计划立即操作,其中立即操作作为本机DLL中的代码实现

然后,在即时操作的code中,调用
MsiDoAction
来计划回滚和延迟操作:当它们被延迟时,它们会在调用
MsiDoAction
时写入脚本,而不是立即执行。您还需要调用
MsiSetProperty
来设置自定义操作数据


例如,下载WiX源代码并研究
IISExtension
的工作原理。WiX操作通常解析自定义表,并基于该表生成延迟操作属性的数据。

我在编写WiX安装程序时遇到了相同的问题。我对这个问题的处理方法与迈克的建议基本相同,我有一篇博文

简而言之,您可以为数据定义自定义表:


创建组
SeIncreaseQuotaPrivilege
然后编写一个即时自定义操作来计划延迟、回滚和提交自定义操作:

extern“C”UINT\u stdcall ScheduleLocalGroupCreation(MSIHANDLE hInstall)
{
试一试{
ScheduleAction(hInstall,L“从CreateLocalGroupTable中选择*”,L“CA.LocalGroupCustomAction.deferred”,L“create”);
ScheduleAction(hInstall,L“从CreateLocalGroupTable中选择*”,L“CA.LocalGroupCustomAction.rollback”,L“create”);
}
捕获(CMsiException&){
返回错误\u安装\u失败;
}
返回错误\成功;
}
下面的代码显示了如何计划单个自定义操作。基本上,您只需打开自定义表,读取所需的属性(您可以通过调用MsiViewGetColumnInfo()获得任何自定义表的架构),然后将所需的属性格式化为CustomActionData属性(我使用
/propname:value
格式,尽管您可以使用任何需要的内容)

void ScheduleAction(MSI),
const wchar_t*szQueryString,
const wchar_t*szCustomActionName,
const wchar_t*szAction)
{
CTableView视图(hInstall、szQueryString);
项目管理信息处理记录;
//对于自定义操作表中的每条记录
while(view.Fetch(record)){
//获取“GroupName”属性
wchar_t recordBuf[2048]={0};
DWORD dwBufSize(_countof(recordBuf));
msicrecordgetstring(record、view.GetPropIdx(L“GroupName”)、recordBuf和dwBufSize;
//将两个属性“GroupName”和“Operation”格式化为
//自定义操作数据字符串。
ccutomationdatautil格式化程序;
addProp(L“GroupName”,recordBuf);
addProp(L“操作”,szAction);
//设置“CustomActionData”属性。
MsiSetProperty(hInstall,szCustomActionName,formatter.GetCustomActionData());
//将自定义操作添加到安装脚本中。每个
//MsidAction将一个独特的自定义操作添加到
//脚本,因此如果自定义
//操作表中,将调用延迟的自定义操作
//多次。
nRet=msidAction(hInstall,szCustomActionName);
}
}
至于实现延迟、回滚和提交自定义操作,我更喜欢只使用一个函数,并使用MsiGetMode()来区分应该做什么:

extern“C”UINT\u stdcall LocalGroupCustomAction(MSIHANDLE hInstall)
{
试一试{
//从“CustomActionData”属性解析属性
std::mapProps;
{
wchar_t szBuf[2048]={0};
DWORD dwBufSize=_countof(szBuf);MsiGetProperty(hInstall,L“CustomActionData”、szBuf和dwBufSize);
ccutomationdatautil::ParseCustomActionData(szBuf,mapProps);
}
//查找“GroupName”和“Operation”属性
std::wstring sGroupName;
boolbcreate=false;
std::map::const_迭代器it;
it=mapProps.find(L“GroupName”);
如果(mapProps.end()!=it)sGroupName=it->second;
it=mapProps.find(L“操作”);
if(mapProps.end()!=it)
bCreate=wcscmp(it->second.c_str(),L“create”)==0?真:假;
//因为我们知道该执行什么操作,我们知道是否
//通过MsiGetMode运行回滚、提交或延迟脚本
//实施是直接的
if(MsiGetMode(hInstall、MSIRUNMODE_计划)){
如果(b创建)
CreateLocalGroup(sGroupName.c_str());
其他的
DeleteLocalGroup(sGroupName.c_str());
}
else if(MsiGetMode(hInstall、MSIRUNMODE_ROLLBACK)){
如果(b创建)
DeleteLocalGroup(sGroupName.c_str());
其他的
CreateLocalGroup(sGroupName.c_str());
}
}
捕获(CMsiException&){
返回错误
<CustomAction Id="CA.ScheduleLocalGroupCreation"
              Return="check"
              Execute="immediate"
              BinaryKey="CustomActionDLL"
              DllEntry="ScheduleLocalGroupCreation"
              HideTarget="yes"/>
<CustomAction Id="CA.ScheduleLocalGroupDeletion"
              Return="check"
              Execute="immediate"
              BinaryKey="CustomActionDLL"
              DllEntry="ScheduleLocalGroupDeletion"
              HideTarget="yes"/>
<CustomAction Id="CA.LocalGroupCustomAction.deferred"
              Return="check"
              Execute="deferred"
              BinaryKey="CustomActionDLL"
              DllEntry="LocalGroupCustomAction"
              HideTarget="yes"/>
<CustomAction Id="CA.LocalGroupCustomAction.commit"
              Return="check"
              Execute="commit"
              BinaryKey="CustomActionDLL"
              DllEntry="LocalGroupCustomAction"
              HideTarget="yes"/>
<CustomAction Id="CA.LocalGroupCustomAction.rollback"
              Return="check"
              Execute="rollback"
              BinaryKey="CustomActionDLL"
              DllEntry="LocalGroupCustomAction"
              HideTarget="yes"/>
<InstallExecuteSequence>
    <Custom Action="CA.ScheduleLocalGroupCreation" 
            After="InstallFiles">
        Not Installed
    </Custom>
    <Custom Action="CA.ScheduleLocalGroupDeletion" 
            After="InstallFiles">
        Installed
    </Custom>
</InstallExecuteSequence>