WSH 剪贴板访问






4.54/5 (8投票s)
在 Windows 脚本宿主中编写剪贴板内容。
引言
我最近做了一些 Windows 脚本宿主编程,我对它的强大功能、特性和灵活性感到惊喜。有一件事是我无法完成的,那就是从 WSH 访问剪贴板。在互联网上搜索,我找到了一些解决方案,例如这个,它基于 Internet Explorer 自动化。正如我在关于 Internet Explorer 自动化的文章中所述,这种方法存在一些问题:Internet Explorer 自动化有什么问题?
使用代码
在 WSH 中编写剪贴板内容的解决方案是一个使用 VC++ 和 ATL 创建的常规 COM 对象。要安装 COM 对象,请运行 register.bat。
这里有一个从 WSH 使用该组件的简单示例
var clipboardHelper = null;
try
{
    clipboardHelper = WScript.CreateObject("ClipboardHelper.ClipBoard");
}
catch (ex)
{
    WScript.Echo(ex.message + "\n\nClipboardHelper library is not properly registered!");
    WScript.Quit(1);
}
var msg = "Some text";
// Put the text into the clipboard.
clipboardHelper.SetClipboardText(msg);
// Get the text from clipboard.
var text = clipboardHelper.GetClipboardText();
WScript.Echo(text);
关注点
实现只是常规的 ATL/COM 代码。使用 Win32 API 函数来访问剪贴板文本(OpenClipboard、IsClipboardFormatAvailable、GetClipboardData、SetClipboardData、CloseClipboard、GlobalAlloc、GlobalLock、GlobalFree)。
以下是检索剪贴板文本的方法的实现(支持 CF_TEXT 和 CF_UNICODETEXT 格式)
STDMETHODIMP CClipBoard::GetClipboardText(BSTR* pBstrClipboardText)
{
    if (NULL == pBstrClipboardText)
    {
        return E_INVALIDARG;
    }
    CComBSTR bstrResult = L"";
    if (::OpenClipboard(NULL))
    {
        if (::IsClipboardFormatAvailable(CF_TEXT) || 
            ::IsClipboardFormatAvailable(CF_UNICODETEXT))
        {
            // First try to ge UNICODE text.
            BOOL   bUnicode   = TRUE;
            HANDLE hClipboard = ::GetClipboardData(CF_UNICODETEXT);
            if (NULL == hClipboard)
            {
                // If UNICODE text was not available try to get ANSI text.
                bUnicode   = FALSE;
                hClipboard = ::GetClipboardData(CF_TEXT);
            }
            if (hClipboard != NULL)
            {
                LPCSTR szClipboardData = (LPCSTR)::GlobalLock(hClipboard);
                if (szClipboardData != NULL)
                {
                    if (bUnicode)
                    {
                        LPCWSTR szClipboardWText = (LPCWSTR)szClipboardData;
                        bstrResult       = szClipboardWText;
                        szClipboardWText = NULL;
                    }
                    else
                    {
                        LPCSTR szClipboardText = (LPCSTR)szClipboardData;
                        bstrResult      = szClipboardText;
                        szClipboardText = NULL;
                    }
                    ::GlobalUnlock(hClipboard);
                    *pBstrClipboardText = bstrResult.Detach();
                    hClipboard = NULL;
                }
                else
                {
                    ATLTRACE("GlobalLock failed in CClipBoard::GetClipboardText\n");
                }
            }
            else
            {
                ATLTRACE("GetClipboardData failed in CClipBoard::GetClipboardText\n");
            }
            hClipboard = NULL;
        }
        else
        {
            ATLTRACE("CF_TEXT NOT available in CClipBoard::GetClipboardText\n");
        }
        BOOL bRes = ::CloseClipboard();
        ATLASSERT(bRes);
    }
    else
    {
        ATLTRACE("Can NOT OpenClipboard in CClipBoard::GetClipboardText\n");
    }
    return S_OK;
}


