zyl910

优化技巧、硬件体系、图像处理、图形学、游戏编程、国际化与文本信息处理。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

作者:zyl910

  这是一个小工具,枚举ActiveX控件的 CLSID 和 implemented/required CATIDs。可用来帮助分析ActiveX控件部署问题。


一、代码

  全部代码——

View Code
#include <stddef.h>
#include <stdio.h>
#include <tchar.h>
#include <locale.h> 

#include <Windows.h>
#include <crtdbg.h>
#include <comcat.h>
#include <atlconv.h>

void doenumactivex(void);

int _show_catid = FALSE;

// 获取程序位数(被编译为多少位的代码)
int GetProgramBits()
{
    return sizeof(int*) * 8;
}

int _tmain(int argc, _TCHAR* argv[])
{
    setlocale(LC_ALL, "");    // 使用系统当前代码页.

    _tprintf(_T("enumactivex v1.00 (%dbit)\n\n"), GetProgramBits());

    CoInitialize(NULL);

    _show_catid = (argc>1);    // 当带有命令行参数时,显示 implemented/required CATIDs。
    doenumactivex();
    
    CoUninitialize();

    return 0;
}



void fprint_GUID(FILE *stream, REFGUID refguid)
{
    #define GUID_STRING_LEN    50
    OLECHAR szGuid[GUID_STRING_LEN];
    int nCount = ::StringFromGUID2(refguid, szGuid, GUID_STRING_LEN);
    if (nCount<=0 || nCount>=GUID_STRING_LEN) return;
    szGuid[nCount] = 0;
    _ftprintf(stream, _T("%ls"), szGuid);    // 因OLECHAR实际上是UTF16编码的字符串.
}

// 枚举ActiveX控件.
void doenumactivex(void)
{
    // 参考了: http://hi.baidu.com/dakzjbwlqctuyzr/item/46d199e81f81f312595dd86c

    LCID lcid = GetSystemDefaultLCID();

    //
    // The Component Category Manager implemented by System
    // implements this interface
    ICatInformation* pCatInfo = NULL;

    // Create an instance of standard Component Category Manager
    HRESULT hr = CoCreateInstance(
        CLSID_StdComponentCategoriesMgr,
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_ICatInformation,
        (void **)&pCatInfo);

    // Increase ref count on interface
    pCatInfo->AddRef();

    // IEnumGUID interface provides enumerator for
    // enumerating through the collection of com objects
    IEnumGUID *pEnumGUID = NULL;

    // We are interested in finding out only controls
    // so put CATID_Control in the array
    CATID pcatidImpl[1];
    //CATID pcatidReqd[1];
    pcatidImpl[0] = CATID_Control;

    // Now enumerate the classes i.e. com objects of this type.
    pCatInfo->EnumClassesOfCategories(1, pcatidImpl, ((ULONG)-1), NULL, &pEnumGUID);    // 若cRequired为0,则仅列出没有“Required Categories”的类。只有将其设为-1,才是忽略“Required Categories”筛选。

    // Enumerate as long as you get S_OK
    CLSID clsid;     //控件的GUID
    while ((hr = pEnumGUID->Next(1, &clsid, NULL)) == S_OK)
    {
        BSTR bstrClassName; 

        // Get the information of class
        // This is what MSDN says about the parameters
        /*-----------------------------------------------
        1. USERCLASSTYPE_FULL     
        The full type name of the class. 
        2. USERCLASSTYPE_SHORT    
        A short name (maximum of 15 characters) 
        that is used for popup menus and the Links dialog box. 
        3. USERCLASSTYPE_APPNAME 
        The name of the application servicing the class and is used 
        in the Result text in dialog boxes. 
        -----------------------------------------------*/
        OleRegGetUserType (clsid, USERCLASSTYPE_FULL, &bstrClassName);
        //CString strControlName(bstrClassName);
        //// Add string in our listbox
        //m_list.AddString(strControlName);

        // == main ==
        CATID catid;
        IEnumCATID *pEnumCATID = NULL;
        fprint_GUID(stdout, clsid);
        _tprintf(_T("\t%ls"), bstrClassName);    // 因BSTR变量指向UTF16编码的字符串.
        _tprintf(_T("\n"));

        // EnumImplCategoriesOfClass
        if (_show_catid)
        {
            _tprintf(_T("\tEnumImplCategoriesOfClass:\n"));
            if (S_OK == pCatInfo->EnumImplCategoriesOfClass(clsid, &pEnumCATID))
            {
                while (S_OK == pEnumCATID->Next(1, &catid, NULL))
                {
                    _tprintf(_T("\t\t"));
                    fprint_GUID(stdout, catid);

                    PWCHAR pszDesc = NULL;
                    pCatInfo->GetCategoryDesc(catid, lcid, &pszDesc);
                    _tprintf(_T("\t%ls"), pszDesc);
                    ::CoTaskMemFree(pszDesc);


                    _tprintf(_T("\n"));
                }
                pEnumCATID->Release();
            }
        }

        // EnumReqCategoriesOfClass
        if (_show_catid)
        {
            _tprintf(_T("\tEnumReqCategoriesOfClass:\n"));
            if (S_OK == pCatInfo->EnumReqCategoriesOfClass(clsid, &pEnumCATID))
            {
                while (S_OK == pEnumCATID->Next(1, &catid, NULL))
                {
                    _tprintf(_T("\t\t"));
                    fprint_GUID(stdout, catid);

                    PWCHAR pszDesc = NULL;
                    pCatInfo->GetCategoryDesc(catid, lcid, &pszDesc);
                    _tprintf(_T("\t%ls"), pszDesc);
                    ::CoTaskMemFree(pszDesc);


                    _tprintf(_T("\n"));
                }
                pEnumCATID->Release();
            }
        }
    }

    // we are done so now release the interface ptr
    pCatInfo->Release();
}

 

  
二、测试

  在以下编译器中成功编译——
VC6:x86版。
VC2005:x86版。


2.1 仅列出ActiveX控件的CLSID与名称

  如果直接运行,即没有命令行参数时,就仅列出ActiveX控件的CLSID与名称。

  例如在命令提示符中输入“enumactivex”——

  或者运行“enumactivex_ui.exe”——


2.2 还列出 implemented/required CATIDs

  如果随便写上一个命令行参数,就还会列出 implemented/required CATIDs。
  例如在命令提示符中输入“enumactivex”——

  或者运行“enumactivex_ui.exe”,并在自定义文本框中随便输入一个参数——


参考文献——
《枚举系统的ActiveX控件并在视图中显示》. S0746. http://hi.baidu.com/dakzjbwlqctuyzr/item/46d199e81f81f312595dd86c
《[C#] cmdarg_ui:“简单参数命令行程序”的通用图形界面》.  http://www.cnblogs.com/zyl910/archive/2012/06/19/cmdarg_ui.html


源码下载——
https://files.cnblogs.com/zyl910/enumactivex.rar

posted on 2012-09-25 16:44  zyl910  阅读(1393)  评论(0编辑  收藏  举报