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;
}