Разрешая ссылку


Как я могу убрать?

std::wstring LinkResolve::ResolveLink( const std::wstring& source ) const
{
    HRESULT errorCheck;
 wchar_t linkTarget[MAX_PATH];
 wchar_t expandedTarget[MAX_PATH];
 wchar_t arguments[INFOTIPSIZE];
    ATL::CComPtr<IPersistFile> ipf;
    errorCheck = ipf.CoCreateInstance(CLSID_ShellLink, 0, CLSCTX_INPROC_SERVER);
    if (!SUCCEEDED(errorCheck))
    {
        throw _com_error(errorCheck);
    }
    errorCheck = ipf->Load(source.c_str(), 0);
    ATL::CComPtr<IShellLink> shellLink;
    errorCheck = ipf->QueryInterface(&shellLink);
    if (!SUCCEEDED(errorCheck))
    {
        throw _com_error(errorCheck);
    }
    errorCheck = shellLink->Resolve(0, SLR_NO_UI);
    if (!SUCCEEDED(errorCheck))
    {
        throw _com_error(errorCheck);
    }
    errorCheck = shellLink->GetPath(linkTarget, MAX_PATH, 0, SLGP_RAWPATH);
    if (!SUCCEEDED(errorCheck))
    {
        throw _com_error(errorCheck);
    }
    ExpandEnvironmentStringsW(linkTarget, expandedTarget, MAX_PATH);
    errorCheck = shellLink->GetArguments(arguments, INFOTIPSIZE);
    if (SUCCEEDED(errorCheck))
    {
        return std::wstring(expandedTarget) + L" " + arguments;
    }
    else
    {
        return expandedTarget;
    }
}


3284
36
задан 27 января 2011 в 07:01 Источник Поделиться
Комментарии
5 ответов

Лично я мог бы написать простую функцию:

void ThrowOnFail( HRESULT hrcode )
{
if (FAILED(hrcode))
throw _com_error(hrcode);
}

Затем функция звонки становятся:

ThrowOnFail( ipf.CoCreateInstance(CLSID_ShellLink, 0, CLSCTX_INPROC_SERVER) );
ThrowOnFail( ipf->Load(source.c_str(), 0) );
ATL::CComPtr<IShellLink> shellLink;
ThrowOnFail( ipf->QueryInterface(&shellLink) );
ThrowOnFail( shellLink->Resolve(0, SLR_NO_UI) );
ThrowOnFail( shellLink->GetPath(linkTarget, MAX_PATH, 0, SLGP_RAWPATH) );

Кстати, вы пропустили чек на errorCheck после нагрузки. Это становится легче обнаружить с функцией проверки.

56
ответ дан 27 января 2011 в 07:01 Источник Поделиться

Если я нахожу мой сам написать то же самое снова и снова, я обычно ставлю его в functiion где-то. Даже если эта функция в вашем случае так же просто, как это:

void check(HRESULT result) {
if (FAILED(result)) {
throw _com_error(result);
}
}

Я думаю, что код выглядит довольно прямо вперед, если вы используйте ошибка проверки кода. Я не знаком с API, который вы используете, поэтому я не могу прокомментировать, если есть другой способ, чтобы использовать его, что может привести в более чистый код.

18
ответ дан 27 января 2011 в 07:01 Источник Поделиться

По крайней мере, при использовании DirectX, я использую макрос.

#define D3DCALL(a) { auto __ = a; if (FAILED(__)) DXTrace(__FILE__, __LINE__, __, WIDEN(#a), TRUE); }

Вы могли бы получить новые идеи и использовать тип с помощью оператора=(значение), чтобы проверить.

6
ответ дан 27 января 2011 в 07:01 Источник Поделиться

Проверка ошибок не все равно.
иногда вы действуете по специальному возвращаемые значения HRESULT. иногда есть еще.
иногда вы хотите записать ошибку,то вы не ...

Также - хотя очень вряд ли будут уместны в COM/АТЛ мира - вызов функции имеет эксплуатационные расходы.

поэтому я предпочитаю использовать, если после вызова, вместо вызова функции.
Сколько вы экономите ? набрав 10 символов ?

1
ответ дан 27 января 2011 в 08:01 Источник Поделиться

Я думаю, что вы можете сделать тоже самое, используя поддержкой com в компиляторе вот пример.

#import "CLSID:lnkfile" //use the clsid of the ShellLink class.

IPersistFilePtr ptr = IPersistFilePtr.CreateInstance(...);

_com_ptr_t::метод createinstance() будет бросать исключение (типа _com_error если вызов заканчивается неуспешно)

Все остальные "если" в вашем коде может быть заменен с помощью смарт-указатели, сгенерированный импорт#. Я знаю, что я немного скупы на детали, но это было долгое время, так как я коснулся ком.

1
ответ дан 27 января 2011 в 01:01 Источник Поделиться