目前共有6篇帖子。 內容轉換:不轉換▼
 
點擊 回復
384 5
【示例程序】快捷方式的创建与解析
一派護法 十九級
1樓 發表于:2016-8-3 10:30

【程序功能】

1.创建一个.lnk快捷方式,并读取

2.读取开始菜单中Microsoft Office文件夹下的所有快捷方式的名称及其描述。

一派護法 十九級
2樓 發表于:2016-8-3 10:30
#include <iostream>
#include <ShObjIdl.h>
#include <strsafe.h>

using namespace std;

#define TARGET TEXT("C:\\mylog.log")
#define LNKFILE L"example.lnk"

// 给cout添加输出Unicode字符串的功能
#ifdef _UNICODE
ostream &operator << (ostream &os, LPCWSTR lpwstr)
{
    if (os == cout)
        WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), lpwstr, wcslen(lpwstr), NULL, NULL);
    return os;
}
#endif

// 创建快捷方式
void CreateShortcut(void)
{
    IShellLink *psl;
    HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&psl));
    if (SUCCEEDED(hr))
    {
        psl->SetPath(TARGET);
        psl->SetDescription(TEXT("This is just an example."));
        
        IPersistFile *ppf;
        hr = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
        if (SUCCEEDED(hr))
        {
            hr = ppf->Save(LNKFILE, TRUE);
            if (SUCCEEDED(hr))
                cout << TEXT("保存文件成功") << endl;
            else
                cout << TEXT("保存文件失败") << endl;
            ppf->Release();
        }
        else
            cout << TEXT("保存文件时遇到系统错误") << endl;

        psl->Release();
    }
    else
        cout << TEXT("操作失败") << endl;
}

// 解析快捷方式
void ResolveShortcut(void)
{
    IShellLink *psl;
    HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&psl));
    if (SUCCEEDED(hr))
    {
        IPersistFile *ppf;
        hr = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
        if (SUCCEEDED(hr))
        {
            hr = ppf->Load(LNKFILE, STGM_READ);
            if (SUCCEEDED(hr))
            {
                TCHAR szPath[MAX_PATH];
                TCHAR szDesc[INFOTIPSIZE];
                hr = psl->GetPath(szPath, MAX_PATH, NULL, SLGP_RAWPATH);
                if (SUCCEEDED(hr))
                    cout << TEXT("快捷方式指向的文件: ") << szPath << endl;
                else
                    cout << TEXT("获取快捷方式指向的文件失败!") << endl;
                hr = psl->GetDescription(szDesc, INFOTIPSIZE);
                if (SUCCEEDED(hr))
                    cout << TEXT("描述: ") << szDesc << endl;
                else
                    cout << TEXT("获取快捷方式描述失败!") << endl;
            }
            else
                cout << TEXT("打开文件失败") << endl;
            ppf->Release();
        }
        else
            cout << TEXT("读取文件时遇到系统错误") << endl;
        psl->Release();
    }
    else
        cout << TEXT("操作失败") << endl;
}

void Office2010Desc(void)
{
    TCHAR szFolder[MAX_PATH] = TEXT("C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Microsoft Office\\");
    TCHAR szPath[MAX_PATH];

    int flag;
    for (flag = 0; flag <= 1; flag++)
    {
        if (flag == 1)
        {
            StringCchCat(szFolder, MAX_PATH, TEXT("Microsoft Office 2010 Tools\\"));
            cout << endl << endl << endl;
        }

        WIN32_FIND_DATA data;
        StringCchCopy(szPath, MAX_PATH, szFolder);
        StringCchCat(szPath, MAX_PATH, TEXT("*.lnk"));
        HANDLE hFind = FindFirstFile(szPath, &data);
        do
        {
            TCHAR szDesc[INFOTIPSIZE + 2] = TEXT(": ");
            IShellLink *psl;
            HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&psl));
            if (SUCCEEDED(hr))
            {
                IPersistFile *ppf;
                hr = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
                if (SUCCEEDED(hr))
                {
                    StringCchCopy(szPath, MAX_PATH, szFolder);
                    StringCchCat(szPath, MAX_PATH, data.cFileName);
    #ifdef _UNICODE
                    hr = ppf->Load(szPath, STGM_READ);
    #else
                    WCHAR szwPath[MAX_PATH];
                    MultiByteToWideChar(CP_ACP, NULL, szPath, -1, szwPath, MAX_PATH);
                    hr = ppf->Load(szwPath, STGM_READ);
    #endif

                    if (SUCCEEDED(hr))
                    {
                        hr = psl->GetDescription(szDesc + 2, INFOTIPSIZE);
                        if (FAILED(hr))
                            szDesc[0] = '\0';
                    }
                    ppf->Release();
                }
                psl->Release();
            }

            int len = lstrlen(data.cFileName);
            data.cFileName[len - 4] = '\0';
            cout << data.cFileName << szDesc << endl;
        } while (FindNextFile(hFind, &data));
        FindClose(hFind);
    }
}

int main(void)
{
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);

    Office2010Desc();

    CoUninitialize();
    return 0;
}
一派護法 十九級
3樓 發表于:2016-8-3 10:31
一派護法 十九級
4樓 發表于:2016-8-3 10:34
注意COM组件对象模型中QueryInterface的用法:相当于C++中的强制类型转换。把一个类的对象强制转换成另一个类的对象。COM中的对象强制转换不能使用C++中的括号来实现,必须用QueryInterface方法。
一派護法 十九級
5樓 發表于:2016-8-3 10:38

程序的运行结果就是输出Office2010各组件快捷方式的描述:

https://zh.arslanbar.net/post.php?t=24293

这些描述当然都是微软写的。

一派護法 十九級
6樓 發表于:2017-1-7 19:17
psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
这句话可以简写为psl->QueryInterface(IID_PPV_ARGS(&ppf));或psl->QueryInterface(&ppf);

回復帖子

內容:
用戶名: 您目前是匿名發表
驗證碼:
(快捷鍵:Ctrl+Enter)
 

本帖信息

點擊數:384 回複數:5
評論數: ?
作者:巨大八爪鱼
最後回復:巨大八爪鱼
最後回復時間:2017-1-7 19:17
 
©2010-2024 Arslanbar Ver2.0
除非另有聲明,本站採用創用CC姓名標示-相同方式分享 3.0 Unported許可協議進行許可。