小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

vs2019 Com組件初探-實現(xiàn)vbs的CreateObject函數(shù)邏輯

 頭號碼甲 2021-06-27

vs2019 Com組件初探-簡單的COM編寫以及實現(xiàn)跨語言調(diào)用

上一篇實現(xiàn)了如何編寫基于IDispatch接口的COM以及vbs如何調(diào)用編寫的COM

本次主要是實現(xiàn)VBS的CreateObject函數(shù)的邏輯,也就是在不知道類名的情況下如何調(diào)用基于IDispathc接口的COM

前提條件

  1、掌握C++基礎(chǔ)語法

  2、平臺安裝 vs2019

  3、本地平臺為 windows 10 1909 X64

  4、基本的DLL編程知識 (不是必備)

本次目標(biāo)

  1、創(chuàng)建DLL并實現(xiàn)CreateObject函數(shù)

  2、寫一個調(diào)用DLL的demo

1、創(chuàng)建DLL并實現(xiàn)CreateObject函數(shù)

  首先通過VS創(chuàng)建一個 動態(tài)鏈接庫

  

  在編寫之前先梳理程序的執(zhí)行流程

    初始化 Com庫

    獲取函數(shù)指針

    傳入?yún)?shù) 

    調(diào)用函數(shù)指針

    卸載Com庫

  接下來就開始寫我們的DLL

    vs2019 創(chuàng)建DLL項目后系統(tǒng)會默認(rèn)多出來頭文件

      

    以及源文件

      

  我們打開pch.h頭文件定義我們的函數(shù)聲明

    

    參數(shù)為 COM組件progID,函數(shù)名,參數(shù)數(shù)量,變長參數(shù)

    extern "C" 以C的方式定義

    _declspec(dllimport) 定義此函數(shù)為要導(dǎo)出的函數(shù)

  新建一個ComInit.h 定義Com庫的初始化和卸載庫函數(shù)

 1 // ComInit.h 2  3 #pragma once 4 static bool _init = false; 5  6 // 初始化 7 bool Init(); 8  9 // 結(jié)束初始化10 void Release();

  新建一個ComInit.cpp 實現(xiàn)Init和Release函數(shù)

// ComInit.cpp#include "pch.h"#include "ComInit.h"bool Init()
{if (_init == true)
    {return _init;
    }else{if (S_OK == CoInitialize(NULL))
            _init = true;else_init = false;return _init;
    }return false;
}void Release()
{if (true == _init)
    {
        CoUninitialize();
        _init = false;
    }
}

  之后打開pch.cpp實現(xiàn)CreateObject函數(shù)

 1 #include "pch.h" 2 #include "ComStart.h" 3 #include <assert.h> 4 #include <atlbase.h> 5  6 // 報錯宏 7 #define ASSERT(s) if((s) == true) 8  9 // Com類名,函數(shù)名,傳入的參數(shù)數(shù)量,變長參數(shù)10 VARIANT CreateObject(const WCHAR* __comname,const WCHAR* __funcname,int __count, ...)11 {12     /* Com注冊到系統(tǒng)后使用 */13    14     // 是否成功初始化15     if (true == Init())16     {17         // ProgId值存放18         CLSID clsid;19 20         // 通過 ProgID 取得組件的 CLSID21         // CLSID 值存放在注冊表 HKEY_CLASSES_ROOT [以__comname加.1為鍵值(MyCom.FirstClass.1)]22         HRESULT hr = ::CLSIDFromProgID(__comname, &clsid);23 24         ASSERT(S_OK != hr)25             assert(hr != S_OK);26 27         // 智能指針獲取 IUnknow28         CComPtr<IUnknown>spUnk;29 30         /* 31         *   CoCreateInstance32         *       CLSIDFromProgId獲取的值33         *       指向接口IUnknown的指針34         *       運(yùn)行可執(zhí)行代碼的上下文[CLSCTX_ALL 為所有]35         *       IID_IUnknown為返回類型36         *       用來接收指向Com對象接口地址的指針變量37         */38         // 獲取IUnknow內(nèi)容 39         hr = ::CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_IUnknown, (LPVOID*)&spUnk);40 41         ASSERT(S_OK != hr)42             assert(hr != S_OK);43         44         // 通過IUnknown智能指針,聲明新的IDispatch智能指針45         CComDispatchDriver spDisp(spUnk);46 47         // 參數(shù)數(shù)組48         VARIANT* __args = new VARIANT[__count];49 50         // 變長參數(shù)變量51         va_list ap;52 53         // 定位到第一個函數(shù)變長參數(shù)54         va_start(ap, __count);55 56         // 循環(huán)獲取變長參數(shù),并轉(zhuǎn)換為 VARIANT 類型放入 __args變量57         for (auto i = 0; i < __count; i++)58             __args[i] = va_arg(ap, VARIANT);59 60         // 結(jié)束變長參數(shù)61         va_end(ap);62 63         // Com函數(shù)返回值存放64         VARIANT __ret;65 66         // 執(zhí)行Com函數(shù)67 68         /*69         *   [InvokeN]70         *       函數(shù)名71         *       函數(shù)參數(shù)72         *       函數(shù)數(shù)量73         *       返回值存放處74         */75         hr = spDisp.InvokeN((LPCOLESTR)__funcname, __args, __count, &__ret);76        77         ASSERT(S_OK != hr)78             assert(hr != S_OK);79 80         // 內(nèi)存回收81         delete[] __args;82 83         // 卸載 Com庫84         Release();85 86         // 返回值87         return __ret;88     }89 90     assert(_init == false);91 }

  完成后編譯(CTRL+B)獲取到新的dll和lib文件(x64)以及項目的pch.h頭文件

    

    

2、寫一個調(diào)用DLL的demo

  vs2019 新建基于 控制臺程序 的項目

  

  移動dll和lib以及pch.h文件到新建項目目錄下,并對pch.h文件添加代碼

// pch.h#pragma once#include <combaseapi.h>// 新添加的代碼#pragma comment(lib,"ComPack.lib")extern "C" _declspec(dllimport) VARIANT CreateObject(const WCHAR * __comname, const WCHAR * __funcname, int __count, ...);

   找到main函數(shù) 寫入調(diào)用代碼

#include <iostream>#include "pch.h"int main()
{// 參數(shù)類型必須為VARIANT    VARIANT __param1;// 參數(shù)類型為 LONG__param1.vt = VT_I4;// 參數(shù)值為 2__param1.lVal = 2;// 獲取ComTest.Temp并調(diào)用Number 函數(shù) 參數(shù)數(shù)量為1 對Number函數(shù)傳入?yún)?shù)__param1VARIANT __ret = CreateObject(L"ComTest.Temp", L"Number",1, __param1);

    std::cout << __ret.lVal << std::endl;
}

  執(zhí)行并運(yùn)行顯示執(zhí)行結(jié)果

  

  運(yùn)行出現(xiàn)錯誤,檢查調(diào)用的Com是否已經(jīng)注冊

  如何注冊我在上一篇里面有講過

  接下來修改代碼嘗試調(diào)用Wscript.shell里面的Run函數(shù)

#include <iostream>#include "pch.h"int main()
{
    VARIANT __param1;// 參數(shù)類型為BSTR__param1.vt = VT_BSTR;// 創(chuàng)建BSTR格式的字符串__param1.bstrVal = SysAllocString(L"notepad.exe");// 調(diào)用函數(shù)并釋放BSTRVARIANT __ret = CreateObject(L"Wscript.shell", L"run",1, __param1);
    SysFreeString(__param1.bstrVal);
}

  值得一提的是 COM組件的字符串和以往的字符串有所不同,創(chuàng)建方式和銷毀方式也不同

  SysAllocString為創(chuàng)建BSTR字符串

  SysFreeString 為釋放BSTR字符串

  運(yùn)行結(jié)果可以看到已經(jīng)成功的執(zhí)行了系統(tǒng)命令,打開了一個記事本

  

注意事項:

  com基于IDispatch 接口才可以調(diào)用

  Com必須已經(jīng)注冊到系統(tǒng) (小心誤刪或者移動路徑)

  卸載DLL函數(shù)為  regsvr32.exe -ui [DLL未知]

  DLL對應(yīng)版本盡量一致

github源碼:

  3065190005/ComTest: ComTest Code (github.com)

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多