2011-09-20 70 views
6

Chúng tôi có các khách hàng yêu cầu các chức năng VBScript được gọi khi các hành động cụ thể xảy ra trong sản phẩm của chúng tôi. Tôi đã cố gắng nghiên cứu các công nghệ Windows Scripting nhưng tôi gặp khó khăn trong việc tìm kiếm chính xác những gì tôi cần. Hy vọng rằng một số bạn có thể giúp đỡ.Cách tải và gọi hàm VBScript từ bên trong C++?

Sản phẩm của chúng tôi là sản phẩm C++ Windows gốc. Khách hàng sẽ chỉ định một tập tin VBScript, mà chúng tôi sẽ tải, và bất cứ khi nào một sự kiện cụ thể xảy ra, chúng tôi sẽ gọi một chức năng cụ thể trong VBScript và để cho nó làm điều của nó. Chúng tôi có thể cung cấp các đối tượng trong không gian tên của tập lệnh để nó cũng có thể truy cập thông tin về sản phẩm của chúng tôi.

Tôi tìm thấy một số thông tin về MSDN về giao diện IActiveScript và một số thứ liên quan, nhưng không thể tìm thấy bất kỳ ví dụ nào về việc tạo đối tượng COM thực hiện giao diện này cho VBScript.

Tôi biết rằng PowerShell có lẽ sẽ là một lựa chọn tốt hơn cho những ngày này, nhưng khách hàng của chúng tôi bị kẹt trong rất nhiều hệ thống cũ và VBScript là những gì họ biết.

Bất kỳ trợ giúp nào bạn có thể cung cấp (liên kết hoặc cách khác) sẽ được đánh giá cao!

+0

Đây là một câu hỏi hay, nhưng có thể phù hợp hơn cho StackOverflow. Trang web này thực sự là chủ đề chủ quan hơn. IActiveScript là, imo, đúng hướng để bạn điều tra. – GrandmasterB

Trả lời

2

Có một cái nhìn lúc này đối với một số mẫu mã http://support.microsoft.com/kb/221992

Có một msscript.ocx mà có thể giúp bạn nhưng là rắc rối có lẽ nhiều hơn giá trị của nó nếu bạn có thể viết C++ http://msdn.microsoft.com/en-us/magazine/cc302278.aspx

+0

Cảm ơn bạn. Mã ví dụ bạn đã trỏ đến (liên kết đầu tiên) rất hữu ích. Tôi sẽ phải tìm ra cách để làm điều đó mà không MFC (kể từ khi dự án của chúng tôi không sử dụng MFC), nhưng đó là một nơi tuyệt vời để bắt đầu. – tyrel

+1

Xem http://www.codeproject.com/KB/COM/com_in_c6.aspx –

1

IActiveScript và các giao diện liên quan hoạt động rất tốt. Tôi sử dụng chúng trong sản phẩm của tôi chính xác giống như cách bạn mô tả. Một số khách hàng tự viết các tập lệnh VBScript và JScript của riêng họ để phân tích và cập nhật dữ liệu ứng dụng trước khi nó được đăng lên cơ sở dữ liệu.

Bạn sử dụng CoCreateInstance() để tạo nhanh IActiveScript, giống như bạn làm với bất kỳ đối tượng COM nào khác. Sau đó, bạn sẽ gọi phương thức QueryInterface() của mình để nhận giao diện IActiveScriptParse để tải đoạn mã của tập lệnh và sau đó bạn cập nhật trạng thái IActiveScript để thực thi mã.

Bạn có thể thêm đối tượng tùy chỉnh vào tập lệnh bằng cách triển khai IDispatch các lớp được lưu trữ và sau đó truyền chúng tới công cụ bằng cách sử dụng IActiveScript::AddNamedItem() và gọi lại IActiveScriptSite::GetItemInfo().

Có các ví dụ về sử dụng IActiveScript có sẵn trên MSDN.

+0

Cảm ơn, mặc dù điều này về cơ bản là những gì tôi đã hiểu. Lưu ý rằng tôi đã nói tôi đã tìm thấy thông tin này trên MSDN nhưng không thể tìm thấy các ví dụ. Cảm ơn bạn đã cho tôi biết có những ví dụ nhưng không chỉ đến bất kỳ ví dụ nào. (Câu trả lời của Richard đã cung cấp cho tôi) – tyrel

10

tôi đã đặt cùng một "Hello World" IActiveScript C++ console ứng dụng ATL rằng:

  • Xác định CSimpleScriptSite lớp
    • Thực hiện IActiveScriptSite giao diện (bắt buộc)
    • Thực hiện giao diện IActiveScriptSiteWindow (không bắt buộc)
    • Triển khai tối thiểu với hầu hết các chức năng được triển khai với một sơ khai giả
    • Không xử lý lỗi. Tham khảo MSDN IActiveScriptError.
  • Sử dụng CoCreateInstance một đối tượng mới IActiveSite
    • Tạo trường hợp của cả hai VBScriptJScript
    • Link IActiveSite để IActiveScriptSite sử dụng IActiveSite::SetScriptSite
    • Gọi QueryInterface để có được một giao diện IActiveScriptParse
    • Sử dụng IActiveScriptParse để thực hiện VBScript hoặc JScript đang
  • Mẫu:
    • toán một biểu thức trong JScript
    • toán một biểu thức trong VBScript
    • Chạy một lệnh trong VBScript

Code:

#include "stdafx.h" 
#include <atlbase.h> 
#include <activscp.h> 

class CSimpleScriptSite : 
    public IActiveScriptSite, 
    public IActiveScriptSiteWindow 
{ 
public: 
    CSimpleScriptSite() : m_cRefCount(1), m_hWnd(NULL) { } 

    // IUnknown 

    STDMETHOD_(ULONG, AddRef)(); 
    STDMETHOD_(ULONG, Release)(); 
    STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject); 

    // IActiveScriptSite 

    STDMETHOD(GetLCID)(LCID *plcid){ *plcid = 0; return S_OK; } 
    STDMETHOD(GetItemInfo)(LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti) { return TYPE_E_ELEMENTNOTFOUND; } 
    STDMETHOD(GetDocVersionString)(BSTR *pbstrVersion) { *pbstrVersion = SysAllocString(L"1.0"); return S_OK; } 
    STDMETHOD(OnScriptTerminate)(const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo) { return S_OK; } 
    STDMETHOD(OnStateChange)(SCRIPTSTATE ssScriptState) { return S_OK; } 
    STDMETHOD(OnScriptError)(IActiveScriptError *pIActiveScriptError) { return S_OK; } 
    STDMETHOD(OnEnterScript)(void) { return S_OK; } 
    STDMETHOD(OnLeaveScript)(void) { return S_OK; } 

    // IActiveScriptSiteWindow 

    STDMETHOD(GetWindow)(HWND *phWnd) { *phWnd = m_hWnd; return S_OK; } 
    STDMETHOD(EnableModeless)(BOOL fEnable) { return S_OK; } 

    // Miscellaneous 

    HRESULT SetWindow(HWND hWnd) { m_hWnd = hWnd; return S_OK; } 

public: 
    LONG m_cRefCount; 
    HWND m_hWnd; 
}; 

STDMETHODIMP_(ULONG) CSimpleScriptSite::AddRef() 
{ 
    return InterlockedIncrement(&m_cRefCount); 
} 

STDMETHODIMP_(ULONG) CSimpleScriptSite::Release() 
{ 
    if (!InterlockedDecrement(&m_cRefCount)) 
    { 
     delete this; 
     return 0; 
    } 
    return m_cRefCount; 
} 

STDMETHODIMP CSimpleScriptSite::QueryInterface(REFIID riid, void **ppvObject) 
{ 
    if (riid == IID_IUnknown || riid == IID_IActiveScriptSiteWindow) 
    { 
     *ppvObject = (IActiveScriptSiteWindow *) this; 
     AddRef(); 
     return NOERROR; 
    } 
    if (riid == IID_IActiveScriptSite) 
    { 
     *ppvObject = (IActiveScriptSite *) this; 
     AddRef(); 
     return NOERROR; 
    } 
    return E_NOINTERFACE; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    HRESULT hr = S_OK; 
    hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); 

    // Initialize 
    CSimpleScriptSite* pScriptSite = new CSimpleScriptSite(); 
    CComPtr<IActiveScript> spJScript; 
    CComPtr<IActiveScriptParse> spJScriptParse; 
    hr = spJScript.CoCreateInstance(OLESTR("JScript")); 
    hr = spJScript->SetScriptSite(pScriptSite); 
    hr = spJScript->QueryInterface(&spJScriptParse); 
    hr = spJScriptParse->InitNew(); 
    CComPtr<IActiveScript> spVBScript; 
    CComPtr<IActiveScriptParse> spVBScriptParse; 
    hr = spVBScript.CoCreateInstance(OLESTR("VBScript")); 
    hr = spVBScript->SetScriptSite(pScriptSite); 
    hr = spVBScript->QueryInterface(&spVBScriptParse); 
    hr = spVBScriptParse->InitNew(); 

    // Run some scripts 
    CComVariant result; 
    EXCEPINFO ei = { }; 
    hr = spJScriptParse->ParseScriptText(OLESTR("(new Date()).getTime()"), NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &result, &ei); 
    hr = spVBScriptParse->ParseScriptText(OLESTR("Now"), NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, &result, &ei); 
    hr = spVBScriptParse->ParseScriptText(OLESTR("MsgBox \"Hello World! The current time is: \" & Now"), NULL, NULL, NULL, 0, 0, 0, &result, &ei); 

    // Cleanup 
    spVBScriptParse = NULL; 
    spVBScript = NULL; 
    spJScriptParse = NULL; 
    spJScript = NULL; 
    pScriptSite->Release(); 
    pScriptSite = NULL; 

    ::CoUninitialize(); 
    return 0; 
} 
Các vấn đề liên quan