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.

ShaneKm
  • 20,823
  • 43
  • 167
  • 296
  • did you find any solution to update the content of binary sql file? AS I also facing the same issue. Able to read the content but not able to update it. – supriya khamesra May 16 '14 at 12:37
  • I had to remove the single quotes from the column and table names (and leave the string value quoted) to make this work for reading a binary table entry. Perhaps VS is using a different single quote character. – StingyJack Sep 14 '15 at 18:05
  • I was looking for a way to get the actual data contained in a Binary element... Your question didn't apply to me at all but seriously you inadvertently saved me a ton of time. – Brandon Oct 30 '15 at 19:24

1 Answers1

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;
}
codekaizen
  • 26,990
  • 7
  • 84
  • 140
Natalie Carr
  • 3,707
  • 3
  • 34
  • 68
  • I have that part working. The only issue is that it fails when writing back. – ShaneKm Jan 25 '13 at 09:37
  • 1
    An option maybe to write to a temporary file on the target machine and use it from there and then subsequently delete it? I have code for that if you need it..:) – Natalie Carr Jan 25 '13 at 09:54
  • not an option for me. I can not have sql file accessible for others to view (even in that short amount of time) during install. It needs to be a part of msi file. – ShaneKm Jan 25 '13 at 09:55
  • 1
    WcaAddTempRecord might work for you from the Wix ca - have you tried that? – Natalie Carr Jan 25 '13 at 10:07