वाईएक्स इंस्टॉलर्स लिखते समय मुझे एक ही समस्या आई। समस्या का मेरा दृष्टिकोण ज्यादातर माइक ने सुझाव दिया है और मेरे पास ब्लॉग पोस्ट Implementing WiX custom actions part 2: using custom tables है।
संक्षेप में, आप अपने डेटा के लिए एक कस्टम तालिका को परिभाषित कर सकते हैं:
<CustomTable Id="LocalGroupPermissionTable">
<Column Id="GroupName" Category="Text" PrimaryKey="yes" Type="string"/>
<Column Id="ACL" Category="Text" PrimaryKey="no" Type="string"/>
<Row>
<Data Column="GroupName">GroupToCreate</Data>
<Data Column="ACL">SeIncreaseQuotaPrivilege</Data>
</Row>
</CustomTable>
फिर टाल, रोलबैक शेड्यूल करने के लिए एक भी तत्काल कस्टम क्रिया लिखते हैं, और प्रतिबद्ध कस्टम कार्रवाई:
extern "C" UINT __stdcall ScheduleLocalGroupCreation(MSIHANDLE hInstall)
{
try {
ScheduleAction(hInstall,L"SELECT * FROM CreateLocalGroupTable", L"CA.LocalGroupCustomAction.deferred", L"create");
ScheduleAction(hInstall,L"SELECT * FROM CreateLocalGroupTable", L"CA.LocalGroupCustomAction.rollback", L"create");
}
catch(CMsiException &) {
return ERROR_INSTALL_FAILURE;
}
return ERROR_SUCCESS;
}
निम्न कोड दिखाता है कि एक कस्टम कार्रवाई को शेड्यूल कैसे करें। असल में आप केवल कस्टम टेबल खोलते हैं, अपनी इच्छित संपत्ति को पढ़ते हैं (आप MsiViewGetColumnInfo() पर कॉल करके किसी भी कस्टम तालिका की स्कीमा प्राप्त कर सकते हैं), फिर कस्टमएक्शनडाटा प्रॉपर्टी में आवश्यक गुणों को प्रारूपित करें (मैं फॉर्म /propname:value
का उपयोग करता हूं, हालांकि आप जो कुछ भी चाहते हैं उसका उपयोग कर सकते हैं)।
extern "C" UINT __stdcall LocalGroupCustomAction(MSIHANDLE hInstall)
{
try {
//Parse the properties from the "CustomActionData" property
std::map<std::wstring,std::wstring> mapProps;
{
wchar_t szBuf[2048]={0};
DWORD dwBufSize = _countof(szBuf); MsiGetProperty(hInstall,L"CustomActionData",szBuf,&dwBufSize);
CCustomActionDataUtil::ParseCustomActionData(szBuf,mapProps);
}
//Find the "GroupName" and "Operation" property
std::wstring sGroupName;
bool bCreate = false;
std::map<std::wstring,std::wstring>::const_iterator it;
it = mapProps.find(L"GroupName");
if(mapProps.end() != it) sGroupName = it->second;
it = mapProps.find(L"Operation");
if(mapProps.end() != it)
bCreate = wcscmp(it->second.c_str(),L"create") == 0 ? true : false ;
//Since we know what opeartion to perform, and we know whether it is
//running rollback, commit or deferred script by MsiGetMode, the
//implementation is straight forward
if(MsiGetMode(hInstall,MSIRUNMODE_SCHEDULED)) {
if(bCreate)
CreateLocalGroup(sGroupName.c_str());
else
DeleteLocalGroup(sGroupName.c_str());
}
else if(MsiGetMode(hInstall,MSIRUNMODE_ROLLBACK)) {
if(bCreate)
DeleteLocalGroup(sGroupName.c_str());
else
CreateLocalGroup(sGroupName.c_str());
}
}
catch(CMsiException &) {
return ERROR_INSTALL_FAILURE;
}
return ERROR_SUCCESS;
}
का उपयोग करके:
void ScheduleAction(MSIHANDLE hInstall,
const wchar_t *szQueryString,
const wchar_t *szCustomActionName,
const wchar_t *szAction)
{
CTableView view(hInstall,szQueryString);
PMSIHANDLE record;
//For each record in the custom action table
while(view.Fetch(record)) {
//get the "GroupName" property
wchar_t recordBuf[2048] = {0};
DWORD dwBufSize(_countof(recordBuf));
MsiRecordGetString(record, view.GetPropIdx(L"GroupName"), recordBuf, &dwBufSize);
//Format two properties "GroupName" and "Operation" into
//the custom action data string.
CCustomActionDataUtil formatter;
formatter.addProp(L"GroupName", recordBuf);
formatter.addProp(L"Operation", szAction);
//Set the "CustomActionData" property".
MsiSetProperty(hInstall,szCustomActionName,formatter.GetCustomActionData());
//Add the custom action into installation script. Each
//MsiDoAction adds a distinct custom action into the
//script, so if we have multiple entries in the custom
//action table, the deferred custom action will be called
//multiple times.
nRet = MsiDoAction(hInstall,szCustomActionName);
}
}
आस्थगित, रोलबैक को लागू करने और कस्टम कार्यों के लिए प्रतिबद्ध के लिए के रूप में, मैं अलग करने के लिए क्या किया जाना चाहिए केवल एक ही समारोह का उपयोग करें और MsiGetMode()का उपयोग करना पसंद तकनीक के ऊपर, एक सामान्य कस्टम एक्शन सेट के लिए आप कस्टम एक्शन टेबल को पांच प्रविष्टियों में कम कर सकते हैं:
<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"/>
और इंस्टॉलस्क्यू केवल दो प्रविष्टियों के लिए nce तालिका:
<InstallExecuteSequence>
<Custom Action="CA.ScheduleLocalGroupCreation"
After="InstallFiles">
Not Installed
</Custom>
<Custom Action="CA.ScheduleLocalGroupDeletion"
After="InstallFiles">
Installed
</Custom>
</InstallExecuteSequence>
इसके अलावा, एक छोटे से प्रयास कोड के सबसे पुन: उपयोग किया जा करने के लिए लिखा जा सकता है (जैसे कस्टम तालिका का पढ़ना, गुण हो रही, जरूरत गुण स्वरूपण और करने के लिए सेट के रूप में कस्टमएक्शनडेटा गुण), और कस्टम एक्शन टेबल में प्रविष्टियां अब एप्लिकेशन विशिष्ट नहीं हैं (एप्लिकेशन विशिष्ट डेटा कस्टम तालिका में लिखा गया है), हम कस्टम एक्शन टेबल को अपनी फाइल में डाल सकते हैं और इसे प्रत्येक वाईएक्स प्रोजेक्ट में शामिल कर सकते हैं ।
कस्टम कार्रवाई डीएलएल फ़ाइल के लिए, क्योंकि कस्टम डेटा से एप्लिकेशन डेटा पढ़ा जाता है, इसलिए हम डीएलएल कार्यान्वयन से एप्लिकेशन विशिष्ट विवरण रख सकते हैं, इसलिए कस्टम एक्शन टेबल लाइब्रेरी बन सकती है और इस प्रकार पुन: उपयोग करना आसान हो जाता है।
इस प्रकार मैं वर्तमान में अपने वाईएक्स कस्टम कार्यों को लिखता हूं, अगर कोई जानता है कि आगे कैसे सुधार किया जाए तो मैं इसकी बहुत सराहना करता हूं। :)
(आप मेरे ब्लॉग पोस्ट, Implementing Wix custom actions part 2: using custom tables में पूरा स्रोत कोड भी पा सकते हैं।)।