On Tue, Jan 3, 2012 at 4:57 PM, Kevin Hebert <[email protected]>
wrote:
> The question is though, how do I extract it? I'd thought I was going
> about it the right way, but apparently I'm not.
>
>
I did it by using these two C++ helper functions at the end of the email.
For each file I needed to be extracted I called ExtractFileToCaData(). This
function is invoked N times from an execute action and streams the binary
table data for each file into the custom action data for use by my deferred
action.
Something like this:
hr = ExtractFileToCa(k_wszBinaryKeyDUConfig, L"file1.dll",
&pwszCustomActionData);
ExitOnFailure1(hr, "Failed to extract %ls from MSI", k_wszBinaryKeyFile1);
hr = ExtractFileToCa(k_wszBinaryKeyEPWCrypto, L"file2.dll",
&pwszCustomActionData);
ExitOnFailure1(hr, "Failed to extract %ls from MSI", k_wszBinaryKeyFile2);
hr = ExtractFileToCa(k_wszBinaryKeyLibEay32, L"file3.dll",
&pwszCustomActionData);
ExitOnFailure1(hr, "Failed to extract %ls from MSI", k_wszBinaryKeyFile3);
// Schedule Deferred Action
hr = WcaDoDeferredAction(L"AxedaGenConfigExec", pwszCustomActionData,
COST_AXEDA);
ExitOnFailure(hr, "Failed to schedule Deferred Action.");
The deferred action then calls ExtractFileToDir() for each file it needs to
put in a temporary location on disk.
Something like this:
// Extract files to temp directory.
hr = PathCreateTempDirectory(NULL, L"HRCAAxeda%03x", 999, &pwszTempDir);
ExitOnFailure(hr, "Failed to load create temp directory for DLL
extraction.");
extractedFiles = true;
hr = ExtractFileToDir(&pwszCustomActionData, pwszTempDir);
ExitOnFailure(hr, "Failed to extract file from CA");
hr = ExtractFileToDir(&pwszCustomActionData, pwszTempDir);
ExitOnFailure(hr, "Failed to extract file from CA");
hr = ExtractFileToDir(&pwszCustomActionData, pwszTempDir);
ExitOnFailure(hr, "Failed to extract file from CA");
<call into DLL, whatever...>
LExit:
if (extractedFiles)
{
DirEnsureDeleteEx(pwszTempDir, DIR_DELETE_FILES | DIR_DELETE_RECURSE |
DIR_DELETE_SCHEDULE);
WcaLog(LOGMSG_VERBOSE, "Removed extracted files from '%ls': ",
pwszTempDir);
}
<other cleanup actions>
I ensure that the extracted files are deleted at the end of my deferred
action. (either due to success or failure)
NOTE: For the C++ challenged, the Wca* functions are thin WiX C++ custom
action helper wrappers for the underlying MSI functionality.
Bill
const LPCWSTR k_wszBinaryTableQuery =
L"SELECT `Binary`.`Name`, `Binary`.`Data` "
L"FROM `Binary` "
L"WHERE `Binary`.`Name` = '%s'";
HRESULT ExtractFileToCaData(LPCWSTR pwszBinaryKey, LPWSTR pwszFileName,
LPWSTR *ppwszCustomActionData)
{
HRESULT hr = S_OK;
PMSIHANDLE hView = NULL;
PMSIHANDLE hRec = NULL;
LPBYTE pbData = NULL;
DWORD cbData = 0;
LPWSTR pwszQuery = NULL;
LPWSTR pwszPath = NULL;
LPWSTR pwszIdentifier = NULL;
// Save filename to CA
hr = WcaWriteStringToCaData(pwszFileName, ppwszCustomActionData);
ExitOnFailure(hr, "Failed to set file name into CustomActionData from
ExtractFileToCa");
// Find the binary data
hr = StrAllocFormatted(&pwszQuery, k_wszBinaryTableQuery, pwszBinaryKey);
ExitOnFailure(hr, "Failed to format MSI SQL query in ExtractFileToDir");
hr = WcaOpenExecuteView(pwszQuery, &hView);
ExitOnFailure(hr, "Failed to execute ExtratFileToDir query");
hr = WcaFetchRecord(hView, &hRec);
ExitOnFailure1(hr, "Failed to fetch row for Binary PK: '%ls'",
pwszBinaryKey);
hr = WcaGetRecordString(hRec, 1, &pwszIdentifier);
ExitOnFailure1(hr, "Failed to get Identifier column for BinaryPK: '%ls'",
pwszBinaryKey);
WcaLog(LOGMSG_TRACEONLY, "Identifier column: '%ls'", pwszIdentifier);
hr = WcaGetRecordStream(hRec, 2, &pbData, &cbData);
ExitOnFailure1(hr, "Failed to get Data column for BinaryPK: '%ls'",
pwszBinaryKey);
hr = WcaWriteStreamToCaData(pbData, cbData, ppwszCustomActionData);
MessageExitOnFailure1(hr, ERROR_INSTALL_FAILURE, "Failure to extract '%ls'
from MSI Binary table.", pwszFileName);
LExit:
ReleaseStr(pwszQuery);
ReleaseStr(pwszPath);
ReleaseStr(pwszIdentifier);
WcaFreeStream(pbData);
return hr;
}
HRESULT ExtractFileToDir(LPWSTR *ppwszCustomActionData, LPWSTR pwszTempDir)
{
HRESULT hr = S_OK;
LPBYTE pbData = NULL;
DWORD cbData = 0;
LPWSTR pwszFileName = NULL;
LPWSTR pwszPath = NULL;
hr = WcaReadStringFromCaData(ppwszCustomActionData, &pwszFileName);
ExitOnFailure(hr, "Failed to get filename from CustomActionData");
hr = StrAllocFormatted(&pwszPath, L"%s%s", pwszTempDir, pwszFileName);
ExitOnFailure1(hr, "Failed to construct full path to extracted filename:
'%ls'", pwszFileName);
hr = WcaReadStreamFromCaData(ppwszCustomActionData, &pbData, &cbData);
MessageExitOnFailure1(hr, ERROR_INSTALL_FAILURE, "Failure to extract '%ls'
from CustomActionData", pwszFileName);
hr = FileWrite(pwszPath, 0, pbData, cbData, NULL);
WcaLog(LOGMSG_VERBOSE, "Extracted '%ls'", pwszPath);
LExit:
ReleaseStr(pwszFileName);
ReleaseStr(pwszPath);
WcaFreeStream(pbData);
return hr;
}
------------------------------------------------------------------------------
Write once. Port to many.
Get the SDK and tools to simplify cross-platform app development. Create
new or port existing apps to sell to consumers worldwide. Explore the
Intel AppUpSM program developer opportunity. appdeveloper.intel.com/join
http://p.sf.net/sfu/intel-appdev
_______________________________________________
WiX-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/wix-users