MsiGetSummaryInformation всегда возвращает ошибку неверного параметра - PullRequest
0 голосов
/ 31 августа 2010

Я пытаюсь установить свойство Template в сводной информационной панели, но что бы я ни делал, это не получается. Я могу прочитать свойство из дескриптора, но не могу записать его обратно.

Я хочу генерировать многоязычные копии MSI, который построен (подсвечен и свет) на английском языке. Я могу заменить все соответствующие переведенные данные во всех таблицах; единственное, что я не могу изменить, это свойство Template выше.

Я перепробовал все способы, которые можно использовать для передачи нового значения String, но он всегда говорит о недопустимом параметре. Вот функция, которую я использую, чтобы сделать то же самое (C #):

public Boolean ChangeTemplateSummaryProperty(String strLangID) {
IntPtr hSIHandle;
if (MsiError.Success == MsiInterop.MsiGetSummaryInformation(IntPtr.Zero, m_strMSIPath, 1, out hSIHandle))
{
    VariantType vtType = VariantType.LPStr;
    int iVal = 0;
    FILETIME oFileTime;
    oFileTime.HighDateTime = 0;
    oFileTime.LowDateTime = 0;

    int iValSz = 0;
    MsiError err = MsiInterop.MsiSummaryInfoGetProperty(hSIHandle, (uint)(SummaryInformationStreamProperty.Template),
                            out vtType, out iVal, out oFileTime, String.Empty, ref iValSz);
    String strValue = new String('l', ++iValSz);

    if (err == MsiError.MoreData)
    {
        err = MsiInterop.MsiSummaryInfoGetProperty(hSIHandle, (uint)(SummaryInformationStreamProperty.Template),
                                out vtType, out iVal, out oFileTime, strValue, ref iValSz);

    }
    else
    {
        Logger.LogError("Failed to get SummaryInformationStreamProperty.Template... err = " + err);
    }
    //I get the correct value here. as ";1033\0"
    Logger.LogInfo("SummaryInformationStreamProperty.Template: " + strValue);

    char[] arrNV = new char[strLangID.Length+2];
    arrNV[0] = ';';
    for (int i = 1; i < strLangID.Length + 1; i++) {
        arrNV[i] = strLangID[i-1];
    }
    arrNV[strLangID.Length+1] = '\0';
    String strNewVal = new String(arrNV);

    //tried this, but fails.
    //string strNV = ";";
    //string strNV2 = strNV.Insert(1, strLangID);
    //strNV2 = strNV2.Insert(strLangID.Length + 1, "\0");

    err = MsiInterop.MsiSummaryInfoSetProperty(hSIHandle, (uint)(SummaryInformationStreamProperty.Template),
                                vtType, iVal, oFileTime, strNewVal);
    if (err != MsiError.NoError)
    {
        Logger.LogError("Failed to set SummaryInformationStreamProperty.Template... err = " + err);
        MsiInterop.MsiSummaryInfoPersist(hSIHandle);
        MsiInterop.MsiCloseHandle(hSIHandle);
        return false;
    }
    MsiInterop.MsiSummaryInfoPersist(hSIHandle);
    MsiInterop.MsiCloseHandle(hSIHandle);
}
else
{
    Logger.LogError("Failed to MsiGetSummaryInformation...");
    return false;
}
return true;
}

Ответы [ 2 ]

1 голос
/ 31 августа 2010

Избавьтесь от используемого MsiInterop и используйте взаимодействие, обнаруженное в DTF WiX.Пространство имен Microsoft.Deploymnet.WindowsInstaller имеет класс SummaryInformation, который предоставляет свойство шаблона строки для чтения / записи.Намного лучше объектная модель и взаимодействие, не беспокоясь обо всех деталях P / Invoke, с которыми ваше текущее взаимодействие заставляет вас иметь дело.

Я сейчас дома, так что вот фрагмент кода:

using Microsoft.Deployment.WindowsInstaller;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            using( var database = new Database(@"C:\orca.msi", DatabaseOpenMode.Direct  ))
            {
                database.SummaryInfo.Template = "Intel;666";
            }            
        }
    }
}

Обратите внимание на использование предложения using ().Класс Database реализует интерфейс IDisposable и автоматически обрабатывает (предназначено для каламбура) очистку всех этих надоедливых неуправляемых дескрипторов для вас.

0 голосов
/ 16 апреля 2012
Database msidb = objInstaller.OpenDatabase(MSIFileNameWithPath,MsiOpenDatabaseMode.msiOpenDatabaseModeTransact);
SummaryInfo info = msidb.get_SummaryInformation(1);
info.set_Property(2, (object)("sample title"));
info.Persist();
msidb.Commit();

Лучшая ссылка для подробного ответа -

http://blogs.msdn.com/b/mwade/archive/2007/08/07/sail-away-with-me-to-another-world.aspx

...