3

I'm trying to do the following:

  1. during install open and edit sql file via custom action
  2. save edited changes and execute it during install.

In my product.wxs I have the following:

<Binary Id="SqlScriptSQLAuthentication"  SourceFile="$(sys.SOURCEFILEDIR)\MyDb.sql" />

        <Component Id='SqlComponent.SQLAuthentication' Guid='665D641C-3570-4b96-9CA5-2B4C12594A35' KeyPath='yes'>
            <Condition><![CDATA[USEINTEGRATEDSECURITY<>1]]></Condition>
            <sql:SqlDatabase Id='SqlDatabase.SQLAuthentication' Database='[DATABASE_NAME]' User='SQLUser' Server='[DATABASE_SERVER]' CreateOnInstall='yes' DropOnUninstall='yes' ContinueOnError='no' />
            <sql:SqlScript Id='SqlScriptSQLAuthentication' BinaryKey='SqlScriptSQLAuthentication' SqlDb='SqlDatabase.SQLAuthentication' ExecuteOnInstall='yes' />
        </Component>

During setup I want to edit "MyDb.sql", write changes to it and save it back, so wix can run it during install.

what's the best approach? thanks

EDIT:

MyDb.sql file:

CREATE TABLE Test12345 (Value1 CHAR(50), Value2 INTEGER)

In my custom action I have the following:

        View v = session.Database.OpenView("SELECT `Data` FROM `Binary` WHERE `Name` = '{0}'", binaryKeyName);

        v.Execute();

        var IsReadOnly = session.Database.IsReadOnly;

        Record r = v.Fetch();

        StreamReader reader = new StreamReader(r.GetStream("Data"));
        string text = reader.ReadToEnd();
        text = text.Replace(@"Test12345", "TTTest");

        byte[] byteArray = Encoding.ASCII.GetBytes(text);
        MemoryStream stream = new MemoryStream(byteArray);

        r.SetStream("Data", stream);

// Up to this point it works and I read my sql text from .sql file

    session.Database.ExecuteStringQuery("UPDATE `Binary` SET `Data` = '{0}' WHERE `Name` = '{1}')", text, binaryKeyName);

    v.Close();
    session.Database.Commit();

it's when I try to update (not sure if i'm going it right) it fails.

4

1 回答 1

1

You can use this custom action to extract the binary data. You would then have to make your changes and resave it. Not sure how you would resave it back to binary as I have not done that before - I have used it to stream temporary data into the license agreement. This should give you a good start.

HRESULT ExtractBinary(__in LPCWSTR wzBinaryId,
                      __out BYTE** pbData,
                      __out DWORD* pcbData)
{
    HRESULT hr = S_OK;
    LPWSTR pwzSql = NULL;
    PMSIHANDLE hView;
    PMSIHANDLE hRec;

    // make sure we're not horked from the get-go
    hr = WcaTableExists(L"Binary");
    if (S_OK != hr)
    {
        if (SUCCEEDED(hr))
        {
            hr = E_UNEXPECTED;
        }
        ExitOnFailure(hr, "There is no Binary table.");
    }

    ExitOnNull(wzBinaryId, hr, E_INVALIDARG, "Binary ID cannot be null");
    ExitOnNull(*wzBinaryId, hr, E_INVALIDARG, "Binary ID cannot be empty string");

    hr = StrAllocFormatted(&pwzSql, L"SELECT `Data` FROM `Binary` WHERE `Name`=\'%s\'", wzBinaryId);
    ExitOnFailure(hr, "Failed to allocate Binary table query.");

    hr = WcaOpenExecuteView(pwzSql, &hView);
    ExitOnFailure(hr, "Failed to open view on Binary table");

    hr = WcaFetchSingleRecord(hView, &hRec);
    ExitOnFailure(hr, "Failed to retrieve request from Binary table");

    hr = WcaGetRecordStream(hRec, 1, pbData, pcbData);
    ExitOnFailure(hr, "Failed to read Binary.Data.");

    LExit:
    ReleaseStr(pwzSql);

    return hr;
}
于 2013-01-25T09:35:17.237 回答