Вызов MSIGetProductInfo из службы Windows возвращает значения мусора - PullRequest
2 голосов
/ 11 октября 2011

У меня есть два приложения, над которыми я работаю, каждое из которых использует вызов MSIGetProductInfo для получения серийного номера, который пользователь ввел во время установки (стандартный проект установки и развертывания Visual Studio).

Вот код, который я использую для получения серийного номера:

Int32 len = 512;
var builder = new StringBuilder(len);
MsiGetProductInfo("{98A0A10F-5E78-4FA6-83F6-6B356D75ADD4}", "ProductId", builder, ref len);
return builder.ToString();

Первое приложение, визуальное приложение на формах c #, возвращается так, как я ожидаю (когда я ввожу 1111-1111-1111-1111, оно отображается как таковое). Однако, когда я помещаю один и тот же вызов в метод OnStart службы Windows c #, я получаю случайный мусор, такой как символы Юникода, иногда слово, и возвращаемое значение отличается в каждой среде выполнения. Иногда я получаю результат, который содержит часть пути библиотеки DLL, которая содержит вызов MsiGetProductInfo, такой как «꿈 H 꿈 Eindows \ system32 \ msi.dll».

Мне кажется (необразованное предположение), что вызов функции dll не удался, и он просто возвращает данные из неиспользуемой области памяти.

Я попытался прочитать другие свойства, такие как InstallSource и InstalledProductName, но они также являются мусором в службе (хотя в приложении форм также хорошо работают). Я также подумал, что это может быть проблема с разрешениями, поэтому я попытался запустить службу под учетными записями NetworkService, LocalService и LocalSystem, но безуспешно.

Приложение Forms и служба устанавливаются одновременно одним и тем же проектом установки, поэтому они должны использовать один и тот же код продукта, верно? Если нет, я мог понять, почему службе не удается получить информацию о продукте.

Кто-нибудь сталкивался с этим или имеет какое-либо представление о причинах этого?

Ответы [ 2 ]

1 голос
/ 10 июля 2012

Мне нужно было ответить на эту же проблему.Я добавил UserRegistrationDlg.wxs в MSI-проект wix, чтобы получить PIDKEY.Однако затем мне нужно было получить серийный номер, введенный во время установки при первом запуске программы, чтобы завершить этап активации / регистрации.

Этот код я использовал для запроса лицензионного ключа, введенного во время установки во время выполнения (VB.NET, извините):

Declare Auto Function MsiGetProductInfo Lib "msi.dll" (ByVal product As String, ByVal [property] As String, <MarshalAs(UnmanagedType.VBByRefStr)> ByRef valueBuf As String, ByRef len As Long) As Int32

Private Shared Function GetMSIKey() As String

Dim lsResult As String = Nothing
Try
    Dim loUninstallHive As RegistryKey = Registry.LocalMachine.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Uninstall")
    For Each loProgramHiveID As String In loUninstallHive.GetSubKeyNames()
        Dim loProgramHive As RegistryKey = loUninstallHive.OpenSubKey(loProgramHiveID)
        Dim lsProgramName As String = NullReaders.StringValue(loProgramHive.GetValue("DisplayName"))

        If lsProgramName.StartsWith("<your app name>", StringComparison.OrdinalIgnoreCase) Then

            Dim loInstallLocation = loProgramHive.GetValue("InstallLocation")

            Dim lsHiveName As String = loProgramHive.Name
            Dim lsGUID As String = lsHiveName.Substring(lsHiveName.LastIndexOf("\") + 1)

            Dim lsIKC As String = New String(" ", 255)
            Dim liLen As Integer = 255
            MsiGetProductInfo(lsGUID, "ProductID", lsIKC, liLen)

            lsResult = lsIKC.Substring(6, 24).Replace(" ", "-")

            Exit For
        End If
    Next
Catch ex As Exception
    TraceLog.DoErr(ex)
End Try
Return lsResult
End Function

Обратите внимание, что важно иметь ProductID с заглавной буквы D.

Подстрока / замена будет зависеть от вашего свойства PIDTemplateв вашем Setup.wxs например:

 <Property Id="PIDTemplate"><![CDATA[12345<#### #### #### #### ####>@@@@@]]></Property>

Наконец, вот строка из UserRegistrationDlg.wxs, которая помещает поля лицензионного ключа в пользовательский интерфейс установщика:

<Control Id="CDKeyEdit" Type="MaskedEdit" X="45" Y="159" Width="250" Height="16" Property="PIDKEY" Text="[PIDTemplate]" />
0 голосов
/ 13 октября 2011

Это не совсем ответ на мой вопрос, но я не хотел оставлять вопрос нерешенным в случае, если кто-то другой окажется в такой же ситуации.

Я справился с этой проблемой, сохранив введенный серийный номер пользователя в реестре во время процесса установки. Создав раздел реестра (строковое значение) со значением «[PIDKEY]», можно сохранить серийный номер пользователя, а затем извлечь его во время выполнения приложения с помощью класса .NET RegistryKey.

Если бы у меня было больше времени на эту проблему, я бы это сделал, но спасибо Гарри за то, что помог мне встать на правильный путь.

...