Pjeroo
@Pjeroo
Веб-разработчик

Использование COM на компиляторе MinGW

Предыстория: изначально я не мог создать ярлык, по причине невозможности загрузки COM-библиотеки на MinGW(в code::blocks и qt), решил сделать костыль и скомпилировать библиотеку на VS2013, чтобы потом использовать её в своем проекте. Скомпилировал библиотеку, проверил работоспособность - работает. Подключил библиотеку к тестовому проекту в code::blocks (чтобы проверить работоспособность, ведь у них с qt одинаковый компилятор). Все отлично работает, ярлык создается. Когда я пытаюсь то же самое сделать в qt-creator, то выползает ошибка при загрузке COM. Как такое может быть вообще? Компиляторы у codeblocks и qt-creator одинаковые и это mingw, но почему один работает, а другой нет.

Код библиотеки cpp
// ShortCutLibrary.cpp: определяет экспортированные функции для приложения DLL.
//
 
#include "stdafx.h"
#include "ShortCutLibrary.h"
#include <iostream>
#include <shlobj.h>
#include <objidl.h>
#include <objbase.h>
#include <windows.h>
 
using namespace std;
 
bool ShowSum(LPWSTR pwzShortCutFileName,
    LPWSTR pszPathAndFileName,
    LPWSTR pszWorkingDirectory,
    LPWSTR pszArguments,
    WORD wHotKey,
    int iCmdShow,
    LPWSTR pszIconFileName,
    int iIconIndex)
{
    IShellLink * pSL;
    IPersistFile * pPF;
    HRESULT hRes;
    if (CoInitialize(NULL) != S_OK)
    {
        cout << "Невозможно загрузить COM\n";
        return false;
    }
    // Получение экземпляра компонента "Ярлык"
    hRes = CoCreateInstance(CLSID_ShellLink, 0, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&pSL);
 
    if (SUCCEEDED(hRes))
    {
        cout << "Создан инстанс\n";
        hRes = pSL->SetPath(pszPathAndFileName);
        if (SUCCEEDED(hRes))
        {
            cout << "Успешно установлен путь к ехе\n";
            hRes = pSL->SetArguments(pszArguments);
            if (SUCCEEDED(hRes))
            {
                cout << "Аргументы установлены\n";
                hRes = pSL->SetWorkingDirectory(pszWorkingDirectory);
                if (SUCCEEDED(hRes))
                {
                    cout << "Директория записана\n";
                    hRes = pSL->SetIconLocation(pszIconFileName, iIconIndex);
                    if (SUCCEEDED(hRes))
                    {
                        cout << "Иконка установлена\n";
                        hRes = pSL->SetHotkey(wHotKey);
                        if (SUCCEEDED(hRes))
                        {
                            cout << "Хоткей записан\n";
                            hRes = pSL->SetShowCmd(iCmdShow);
                            if (SUCCEEDED(hRes))
                            {
                                cout << "Комманды \n";
                                // Получение компонента хранилища параметров
                                hRes = pSL->QueryInterface(IID_IPersistFile, (LPVOID *)&pPF);
                                if (SUCCEEDED(hRes))
                                {
                                    cout << "связь\n";
                                    // Сохранение созданного ярлыка
                                    hRes = pPF->Save(pwzShortCutFileName, TRUE);
                                    if (SUCCEEDED(hRes))
                                        cout << "Сохранили";
                                    pPF->Release();
                                }
                            }
                        }
                    }
                }
 
            }
        }
        pSL->Release();
    }
    CoUninitialize();
    return SUCCEEDED(hRes);
}
Код библиотеки h
#ifndef __TESTDLL_H
#define __TESTDLL_H
 
#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API extern "C" __declspec(dllexport) 
#else
#define MATHFUNCSDLL_API extern "C" __declspec(dllimport) 
#endif
 
MATHFUNCSDLL_API bool ShowSum(LPWSTR pwzShortCutFileName,
    LPWSTR pszPathAndFileName,
    LPWSTR pszWorkingDirectory,
    LPWSTR pszArguments,
    WORD wHotKey,
    int iCmdShow,
    LPWSTR pszIconFileName,
    int iIconIndex);
 
#endif // __TESTDLL_H
Код вызова библиотеки в codeblocks и qt-creator
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
 
using namespace std;
 
int main()
{
    setlocale(LC_ALL, "Russian");
 
    typedef bool __cdecl (*dll_func)(LPWSTR pwzShortCutFileName,
    LPWSTR pszPathAndFileName,
    LPWSTR pszWorkingDirectory,
    LPWSTR pszArguments,
    WORD wHotKey,
    int iCmdShow,
    LPWSTR pszIconFileName,
    int iIconIndex);
 
    dll_func lol = NULL;
 
    HMODULE mod = LoadLibrary("C:\\test\\ShortCutLibrary.dll");
 
    if (!mod)
        cout << "YOU CANNOT INTO DLL\n";
    else
        cout << "YOU CAN INTO DLL\n";
 
    lol = (dll_func)GetProcAddress(mod, "ShowSum");
 
    if (!lol)
        cout << "YOU CANNOT INTO DLL";
    else
        cout << "YOU CAN INTO DLL";
 
    bool a = lol(L"C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\testing.lnk", L"C:\\test\\SmcServer.exe", L"C:\\", L"", 0, SW_SHOW, NULL, 0);
    cout << a;
    //lol(4,2);
 
    FreeLibrary(mod);
    return 0;
}


Вывод приложения: Невозможно загрузить COM. (добавил для дебага см.код)
  • Вопрос задан
  • 2810 просмотров
Пригласить эксперта
Ответы на вопрос 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
if (CoInitialize(NULL) != S_OK)

неправильная проверка. Если CoInitialize уже был вызван, вы получите S_FALSE, но это не ошибка.
Правильно будет
if (FAILED(CoInitialize(NULL)))
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы