0

This is not an answer to my question because it does not explain (in all three answers) how to deal with incompatibility of @Property and @BinaryKey. Moreover it answers to the "reverse" question: How to retrieve the property not how to "put" it.

I have created a C++ program that replaces in the given file one string by another.

I try to call it from a WiX installer:

                    <Directory Id="ConfigDir" Name="configs">
                        <Directory Id="GenesisDir" Name="genesis" />
                    </Directory>
    ...
    <Binary Id="SetupDLLId" SourceFile="windows\custom.dll" />
    <CustomAction
        Id="SubstituteString"
        BinaryKey="SetupDLLId"
        DllEntry="MyCustomAction"
        Execute="deferred"
        Return="check" 
        Property="[ConfigDir]config.cfg;[GenesisDir]" />

    <InstallExecuteSequence>
        <Custom Action="SubstituteString" Before="InstallFinalize" Property="Subst" />
    </InstallExecuteSequence>

but something does not work (WiX tools compilation fails). I don't know which attribute to use in place of erroneous Property.

C:\blockchain-installer\windows\my.wxs(96) : error CNDL0022 : The CustomAction/@Property attribute cannot coexist with a previously specified attribute on this element.  The CustomAction element may only have one of the following source attributes specified at a time: BinaryKey, Directory, FileKey, Property, or Script.
C:\blockchain-installer\windows\my.wxs(105) : error CNDL0004 : The Custom element contains an unexpected attribute 'Property'.

C++ source:

#include <windows.h>
#include <cstdlib>
#include <stdio>

extern "C" _declspec(dllexport) UINT __stdcall MyCustomAction(MSIHANDLE hInstall);

extern "C" UINT __stdcall MyCustomAction(MSIHANDLE hInstall)
{   
    DWORD dwSize=0;
    UINT ret1 = MsiGetProperty(hInstaller, TEXT("CustomActionData"), TEXT(""), &dwSize);
    if(ret1 != ERROR_MORE_DATA && ret1 != ERROR_SUCCESS) {
        std::exit(1);
    }
    ++dwSize; // include the terminating null character
    TCHAR data = new TCHAR[dwSize];
    UINT ret2 = MsiGetProperty(hInstaller, TEXT("CustomActionData"), data, &dwSize);
    if(ret2 != ERROR_SUCCESS) {
        std::exit(1);
    }

    size_t pos = data.find(';');
    std::string filename = data.substr(0, pos);
    std::string directory = data.substr(pos + 1);
    std::string content;

    std::ifstream file(filename);
    std::string contents((std::istreambuf_iterator<char>(file)), (std::istreambuf_iterator<char>()));

    std::string needle = "%GenesisDir%";
    size_t pos2 = contents.find(needle);
    contents.replace(pos2, needle.length(), directory);

    std::ofstream file2(filename);
    file2 << contents << std::flush;

    delete[] data;
    return ERROR_SUCCESS;
}

Please, describe the correct code in details.

If it is impossible to do with DLL, then guide how to do it with .exe instead.

porton
  • 5,214
  • 11
  • 47
  • 95
  • [](https://wixtoolset.org/docs/v3/xsd/wix/custom/) exists purely to sequence custom actions, it doesn't accept any parameters. Similarly, you can't combine BinaryKey and Property in a [](https://wixtoolset.org/docs/v3/xsd/wix/customaction/) because those would be different types of custom actions. Those errors are the schema telling you that you're going about this the wrong way, and in fact the answer linked in the duplicate does look like it should address your problem. – sixtyten Apr 02 '23 at 14:11

0 Answers0