On Tue, Jan 3, 2012 at 4:57 PM, Kevin Hebert <ke...@legendary-immersion.com> 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 WiX-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/wix-users