Click here to Skip to main content
15,867,453 members
Articles / Desktop Programming / ATL

WSH Clipboard Access

Rate me:
Please Sign up or sign in to vote.
4.54/5 (8 votes)
26 Feb 2009CPOL 46.5K   409   16   7
Scripting the clipboard content in Windows Script Host.

Introduction

I did some Windows Script Host programming recently, and I was pleasantly surprised by its power, features, and flexibility. One thing that I couldn't accomplish was accessing the clipboard from WSH. Digging the Internet, I found some solutions like this one based on Internet Explorer Automation. There are several problems with this approach as you can read in my article about Internet Explorer Automation: What's wrong with Internet Explorer Automation?

Using the code

The solution for scripting the clipboard content in WSH is a regular COM object created with VC++ and ATL. To install the COM object, run register.bat.

Here is a simple example of using the component from WSH:

JavaScript
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);

Points of interest

The implementation is just regular ATL/COM code. Win32 API functions are used to get access to clipboard text (OpenClipboard, IsClipboardFormatAvailable, GetClipboardData, SetClipboardData, CloseClipboard, GlobalAlloc, GlobalLock, GlobalFree).

Here is the implementation of the method that retrieves the text from clipboard (CF_TEXT and CF_UNICODETEXT formats supported):

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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Codecentrix Software
Romania Romania
Software consultant in Bucharest Romania writing Windows programs and browsers plug-ins since 1998 with Visual C++.

Comments and Discussions

 
QuestionCOM Event Listener possible? Pin
Member 40613579-Feb-11 11:36
Member 40613579-Feb-11 11:36 
AnswerRe: COM Event Listener possible? Pin
Adrian Dorache9-Feb-11 20:20
Adrian Dorache9-Feb-11 20:20 
GeneralCould Not Create Object named "ClipboardHelper.Clipboard" Pin
masonfoley22-Feb-10 10:51
masonfoley22-Feb-10 10:51 
GeneralRe: Could Not Create Object named "ClipboardHelper.Clipboard" Pin
Adrian Dorache22-Feb-10 20:43
Adrian Dorache22-Feb-10 20:43 
I assume you try to run the .vbs file by double clicking it. This usually starts wscript.exe which will interpret the .vbs file. However since you are on Win 64 the 64 bit version of wscript.exe is launched and it tries to instantiate the 64bit version of clipboard COM object which does not exist.

You have 2 options:
- compile a 64bit version of clipboard COM project and register it in the system.
- start the .vbs using from command line using the 32bit version of wscript.exe you may find in %windir%\SysWOW64

Cheers,
Adrian.
GeneralProblem Pin
Uros Calakovic27-Feb-09 8:53
Uros Calakovic27-Feb-09 8:53 
GeneralRe: Problem Pin
Adrian Dorache28-Feb-09 1:14
Adrian Dorache28-Feb-09 1:14 
GeneralRe: Problem Pin
Uros Calakovic28-Feb-09 3:34
Uros Calakovic28-Feb-09 3:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.