0

我有一个用 C++ 编写的自定义操作 dll,在安装过程中使用按钮调用它。自定义操作的目的是捕获剪贴板内容并评估内容是否采用有效产品密钥的格式。如果是,则更新“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
}

不确定问题可能是什么,甚至更多是因为在正确设置属性时似乎执行了自定义操作。

4

1 回答 1

0

在整理添加到这个问题的代码并重建后,我发现只有当剪贴板上有一个未被评估为产品密钥格式的字符串时,我才会收到错误消息。因此自定义操作返回 1。我相信这是我的安装失败的原因。返回值 1 显然会导致安装错误。

如果我错了,请纠正我,但这已经解决了问题。

于 2012-10-05T14:00:39.157 回答