Установщик Windows, ошибка 2896 от Custom Action после успешного выполнения

У меня есть пользовательское действие DLL, написанное на C ++, которое вызывается с помощью кнопки во время установки. Цель настраиваемого действия — захват содержимого буфера обмена и оценка того, находится ли содержимое в формате действительного ключа продукта. Если это так, то свойство ‘PRODUCTKEY’ обновляется, как и другое свойство, которое позволяет мне знать, что мы добились успеха.

<Control Id="PasteButton" Type="PushButton" X="25" Y="176" Width="25" Height="16" Default="yes" Text="Paste" >
<Publish Event="DoAction" Value="MsiCheckClipboardForKey" Order="1">1</Publish>
<Publish Property="PRODUCTKEY" Value="[PRODUCTKEY]" Order="2">ClipboardSuccess = 1</Publish>
</Control>

К сожалению, установка завершается неудачно после вызова этого пользовательского действия. Однако после просмотра журнала установки мои свойства были изменены, что говорит о том, что мой код настраиваемого действия успешно выполняется.

MSI (c) (20: 4C) [12: 04: 55: 281]: запуск удаленного настраиваемого действия. DLL:
C: \ Users \ xxxxx \ AppData \ Local \ Temp \ MSI5652.tmp, точка входа:
msiCheckClipboardForKey

MSI (c) (20! C4) [12: 04: 57: 746]: ИЗМЕНЕНИЕ ИМУЩЕСТВА: изменение
Свойство ClipboardSuccess. Текущее значение равно 0. Его новое значение:
‘1’.

MSI (c) (20! C4) [12: 04: 57: 746]: ИЗМЕНЕНИЕ НЕДВИЖИМОСТИ: Добавление PRODUCTKEY
имущество. Его значение равно «xxxxx-xxxxx-xxxxx-xxxxx-xxxxx».

Действие завершено 12:04:57: MsiCheckClipboardForKey. Возвращаемое значение 3.

ОТЛАДКА: Ошибка 2896: Не удалось выполнить действие MsiCheckClipboardForKey.

Это код пользовательского действия:

#include "StdAfx.h"#include "Debug.h"
#pragma comment(linker, "/EXPORT:msiCheckClipboardForKey=_msiCheckClipboardForKey@4")

BOOL GetClipboardText ( IN OUT CString& strClipBoardText)
{
strClipBoardText = _T("");
BOOL bOK = FALSE;
UINT uFormat = 0;
// We need to explicitly query the clipboard for UNICODE text
// if we have a UNICODE application
#ifdef _UNICODE
uFormat = CF_UNICODETEXT;
#else
uFormat = CF_TEXT;
#endif
if ( ::IsClipboardFormatAvailable ( uFormat ) )
{
if ( ::OpenClipboard ( NULL ) )
{
HANDLE hClipBrdData = NULL;
if ( HANDLE hClipBrdData = ::GetClipboardData ( uFormat ) )
{
if ( LPTSTR lpClipBrdText = ( LPTSTR ) ::GlobalLock ( hClipBrdData ) )
{
MessageBox("Clipboard Text",lpClipBrdText,NULL,NULL);
strClipBoardText = lpClipBrdText;
::GlobalUnlock ( hClipBrdData );
bOK = TRUE;
}
}
::CloseClipboard();
}
}
return bOK;
}

extern "C" UINT __stdcall msiCheckClipboardForKey(MSIHANDLE hMSI)
{
CString strClipboardText ( _T("") );
if ( GetClipboardText ( strClipboardText ) )
{
DebugMsg ( hMSI, _T("Found clipboard text") );

strClipboardText.Trim();
// Look at the length.  Is it 25 (wih no dashes/slashes) or 29 (with dashes/slashes)?
BOOL bValidLength = strClipboardText.Find ( '-' ) != -1 || strClipboardText.Find ( '/' ) != -1 ? strClipboardText.GetLength() == 29 : strClipboardText.GetLength() == 25;

DebugMsg ( hMSI, _T("Is it a product key? %b",bValidLength) );

if ( bValidLength )
{
//strClipboardText.Remove ( '-' );
//strClipboardText.Remove ( '/' );

MessageBox("Formatted Clipboard Text",strClipboardText,NULL,NULL);

MsiSetProperty(hMSI, "ClipboardSuccess", "1");
MsiSetProperty(hMSI, "PRODUCTKEY", strClipboardText);

return 0;
}
}
return 1;   // None-zero is error state
}

Не уверен, в чем может быть проблема, тем более, что настраиваемое действие действительно выполняется, так как свойства установлены правильно.

0

Решение

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

Пожалуйста, исправьте меня, если я ошибаюсь, но это устранило проблему.

0

Другие решения

Других решений пока нет …