You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C代码中内嵌运行VBS代码,而非调用外部文件?

在C代码中内嵌执行VBScript的方法

在Windows平台上,你可以通过调用Active Scripting相关的COM接口,直接在C代码里内嵌并执行VBScript,完全不需要依赖外部VBS文件。下面是两种可行的实现方案:

方案一:用IScriptControl组件(简单易上手)

IScriptControl是微软提供的高层脚本宿主控件,专门用来快速嵌入VBScript或JScript,代码量少,适合简单场景。

示例代码

#include <windows.h>
#include <ocidl.h>
#include <script.h>

int main() {
    HRESULT hr;
    IScriptControl *pScriptControl = NULL;

    // 初始化COM环境
    hr = CoInitialize(NULL);
    if (FAILED(hr)) {
        printf("COM初始化失败\n");
        return 1;
    }

    // 创建ScriptControl实例
    hr = CoCreateInstance(CLSID_ScriptControl, NULL, CLSCTX_INPROC_SERVER, IID_IScriptControl, (void**)&pScriptControl);
    if (FAILED(hr)) {
        printf("创建ScriptControl实例失败\n");
        CoUninitialize();
        return 1;
    }

    // 指定脚本语言为VBScript
    hr = pScriptControl->put_Language(_bstr_t("VBScript"));
    if (FAILED(hr)) {
        printf("设置脚本语言失败\n");
        pScriptControl->Release();
        CoUninitialize();
        return 1;
    }

    // 这里就是你要内嵌的VBS代码,直接写在宽字符串里
    const wchar_t* vbsCode = L"Function Calculate(a, b)\n"
                             L"    Calculate = a * b + a - b\n"
                             L"End Function\n"
                             L"MsgBox \"计算结果:\" & Calculate(15, 6)";

    // 执行内嵌的VBS代码
    hr = pScriptControl->ExecuteStatement(_bstr_t(vbsCode));
    if (FAILED(hr)) {
        printf("执行脚本失败\n");
        pScriptControl->Release();
        CoUninitialize();
        return 1;
    }

    // 清理资源
    pScriptControl->Release();
    CoUninitialize();

    return 0;
}

编译说明

用MSVC编译时,需要链接oleaut32.lib和scrrun.lib,命令如下:

cl your_code.c oleaut32.lib scrrun.lib

方案二:用IActiveScript接口(底层灵活)

如果需要更精细的控制(比如处理脚本错误、自定义宿主对象、双向数据交互),可以直接用底层的IActiveScript接口,这是Active Scripting的核心API。

示例代码

#include <windows.h>
#include <activscp.h>

// 实现最小化的IActiveScriptSite,用来和脚本引擎交互
class CSimpleScriptSite : public IActiveScriptSite {
private:
    ULONG m_refCount;
public:
    CSimpleScriptSite() : m_refCount(1) {}

    // IUnknown接口方法
    STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj) {
        if (riid == IID_IUnknown || riid == IID_IActiveScriptSite) {
            *ppvObj = static_cast<IActiveScriptSite*>(this);
            AddRef();
            return S_OK;
        }
        *ppvObj = NULL;
        return E_NOINTERFACE;
    }

    STDMETHODIMP_(ULONG) AddRef() {
        return InterlockedIncrement(&m_refCount);
    }

    STDMETHODIMP_(ULONG) Release() {
        ULONG count = InterlockedDecrement(&m_refCount);
        if (count == 0) delete this;
        return count;
    }

    // IActiveScriptSite接口方法
    STDMETHODIMP GetLCID(LCID *plcid) {
        *plcid = LOCALE_USER_DEFAULT;
        return S_OK;
    }

    STDMETHODIMP GetItemInfo(LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown **ppunkItem, ITypeInfo **ppti) {
        *ppunkItem = NULL;
        *ppti = NULL;
        return TYPE_E_ELEMENTNOTFOUND;
    }

    STDMETHODIMP GetDocVersionString(BSTR *pbstrVersion) {
        *pbstrVersion = SysAllocString(L"1.0");
        return S_OK;
    }

    STDMETHODIMP OnScriptTerminate(const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo) {
        return S_OK;
    }

    STDMETHODIMP OnStateChange(SCRIPTSTATE ssScriptState) {
        return S_OK;
    }

    STDMETHODIMP OnScriptError(IActiveScriptError *pError) {
        DWORD lineNum;
        BSTR errorDesc;
        pError->GetSourceLineNumber(&lineNum);
        pError->GetDescription(&errorDesc);
        printf("脚本出错:第%d行,%S\n", lineNum, errorDesc);
        SysFreeString(errorDesc);
        return S_OK;
    }

    STDMETHODIMP OnEnterScript(void) { return S_OK; }
    STDMETHODIMP OnLeaveScript(void) { return S_OK; }
};

int main() {
    HRESULT hr;
    IActiveScript *pScriptEngine = NULL;
    IActiveScriptParse *pScriptParser = NULL;
    CSimpleScriptSite *pScriptSite = new CSimpleScriptSite();

    // 初始化COM
    hr = CoInitialize(NULL);
    if (FAILED(hr)) {
        printf("COM初始化失败\n");
        return 1;
    }

    // 创建VBScript引擎实例
    hr = CoCreateInstance(CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER, IID_IActiveScript, (void**)&pScriptEngine);
    if (FAILED(hr)) {
        printf("创建VBScript引擎失败\n");
        delete pScriptSite;
        CoUninitialize();
        return 1;
    }

    // 设置脚本站点
    hr = pScriptEngine->SetScriptSite(pScriptSite);
    if (FAILED(hr)) {
        printf("设置脚本站点失败\n");
        pScriptEngine->Release();
        delete pScriptSite;
        CoUninitialize();
        return 1;
    }

    // 获取脚本解析接口
    hr = pScriptEngine->QueryInterface(IID_IActiveScriptParse, (void**)&pScriptParser);
    if (FAILED(hr)) {
        printf("获取解析接口失败\n");
        pScriptEngine->Release();
        delete pScriptSite;
        CoUninitialize();
        return 1;
    }

    // 初始化脚本引擎
    hr = pScriptParser->InitNew();
    if (FAILED(hr)) {
        printf("初始化引擎失败\n");
        pScriptParser->Release();
        pScriptEngine->Release();
        delete pScriptSite;
        CoUninitialize();
        return 1;
    }

    // 内嵌的VBS代码
    const wchar_t* vbsCode = L"Dim userName\n"
                             L"userName = InputBox(\"请输入你的名字:\")\n"
                             L"MsgBox \"你好,\" & userName & \"!\"";

    // 解析并执行脚本
    hr = pScriptParser->ParseScriptText(vbsCode, NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISVISIBLE, NULL, NULL);
    if (FAILED(hr)) {
        printf("解析脚本失败\n");
        pScriptParser->Release();
        pScriptEngine->Release();
        delete pScriptSite;
        CoUninitialize();
        return 1;
    }

    // 启动脚本执行
    hr = pScriptEngine->SetScriptState(SCRIPTSTATE_CONNECTED);
    if (FAILED(hr)) {
        printf("启动脚本失败\n");
        pScriptParser->Release();
        pScriptEngine->Release();
        delete pScriptSite;
        CoUninitialize();
        return 1;
    }

    // 清理资源
    pScriptParser->Release();
    pScriptEngine->Release();
    delete pScriptSite;
    CoUninitialize();

    return 0;
}

编译说明

用MSVC编译时,需要链接oleaut32.lib和activscp.lib,命令如下:

cl your_code.c oleaut32.lib activscp.lib

补充说明

  • 这两种方案都只适用于Windows平台,因为VBScript是Windows专属的脚本语言。
  • 内嵌的VBS代码可以直接写在C的宽字符串里,注意转义换行符和特殊字符。
  • 如果需要在C和VBS之间传递数据,可以通过IScriptControl::AddObject方法(方案一)或者自定义IActiveScriptSite::GetItemInfo方法(方案二)实现双向交互。

内容的提问来源于stack exchange,提问作者tediouscreator

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 15:09:13