[посоветуй тред]
От: jyuyjiyuijyu  
Дата: 25.07.11 20:56
Оценка:
Всем привет
хотел/в сомнениях/.. вставить это себе в "учебный проект" код очень сомнительный
покритикуйте/научите как надо по нормальному
#include <windows.h>
#include <shlwapi.h>
#include <stdio.h>
#include <loki/typemanip.h>

template<class chType>
class GetWin32ErrorEx
{
    enum{cchSize = 256};
    chType _tszBuf[cchSize];
public:
    
    operator chType * ()
    {
        return select(Loki::Type2Type<chType>());
    }

private:
    
    wchar_t * select(Loki::Type2Type<wchar_t>)
    {
        return resolve(_tszBuf);
    }

    char * select(Loki::Type2Type<char>)
    {
        wchar_t wszBuf[cchSize];
        resolve(wszBuf);
        wnsprintfA(_tszBuf, _countof(_tszBuf), "%S", wszBuf);
        return _tszBuf;
    }

    template<size_t cchSize>
    static wchar_t * resolve(wchar_t (&wszBuf)[cchSize])
    {
        DWORD dwError = GetLastError();
        
        DWORD dwLocale = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
        BOOL bOk = FormatMessageW(
            FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL, dwError, dwLocale,
            wszBuf, _countof(wszBuf), NULL);
        if (!bOk)
        {
            HMODULE hDll = LoadLibraryExW(L"netmsg.dll", NULL,
                DONT_RESOLVE_DLL_REFERENCES);
            if (hDll)
            {
                bOk = FormatMessageW(
                    FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
                    NULL, dwError, dwLocale,
                    wszBuf, _countof(wszBuf), NULL);
                FreeLibrary(hDll);
            }
        }

        if (!bOk)
        {
            wnsprintfW(wszBuf, _countof(wszBuf), L"code %#I32x", dwError);
        }
        
        return wszBuf;
    }
};

typedef GetWin32ErrorEx<char> GetWin32ErrorA;
typedef GetWin32ErrorEx<wchar_t> GetWin32ErrorW;

#ifdef _UNICODE
# define GetWin32Error GetWin32ErrorW
#else
# define GetWin32Error GetWin32ErrorA
#endif

int main()
{
    SetLastError(1);
    FatalAppExit(0, GetWin32Error());
}
Re: [посоветуй тред]
От: uzhas Ниоткуда  
Дата: 25.07.11 21:28
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>Всем привет

J>хотел/в сомнениях/.. вставить это себе в "учебный проект" код очень сомнительный
J>покритикуйте/научите как надо по нормальному
код действительно имеет кучу проблем:

Re[2]: [посоветуй тред]
От: jyuyjiyuijyu  
Дата: 25.07.11 22:05
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, jyuyjiyuijyu, Вы писали:


J>>Всем привет

J>>хотел/в сомнениях/.. вставить это себе в "учебный проект" код очень сомнительный
J>>покритикуйте/научите как надо по нормальному
U>код действительно имеет кучу проблем:

U>


излишняя зависимость от монолитного windows.h с грязными макросами

все равно windows.h через stdafx.h включен во всем проекте это винапи
проект в основном поэтому без него никак нельзя
макросы, со всеми вытекающими, особенно, при возможности их убрать
согласен макросы сакс но тут вроде всего один и имя не перепутаеш ни с кем
а как еще разрулить юникод/анси ?
шаблоны, которые имеют лишь одно инстанциирование
не понял про что Вы можно поподробнее ?
FormatMessage уже является макросом, не нужно было руками писать #ifdef _UNICODE
так я не из за FormatMessage класс то один я его настраиваю через макрос
класс называется глаголом, что может привести к неправильному использованию
согласен я бы тоже не понял чужой код с таким названием
но являющийся классом
слишком много магии
как бы вы переписали ?
сырые указатели со всеми вытекающими
тут вроде они не доставляют проблем все буферы автоматические
C-форматирование со всеми вытекающими (обрезание сообщения, отсутствие проверки типов и тд)
согласен впринципе он отстойно себя ведет с сипипи типами но с базовыми и с обычными
си строками сносно да и это просто привычка еще а так да сакс в сипипи лучше сразу привыкать к "коут"
лишняя зависимость от Loki (нашли куда его засунуть, прямо жить не можем без него)
вот это тоже мало опыта с шаблонами можно сказать что нету я потом уже когда написал
подумал что можно было просто перегрузить через char wchar_t но вот если бы
были такие типы которые занимают много памяти то это бы очень сэкономило память ?
считай мы бы обменяли на пу4стой тип сохранив уникальность и матчинг
Re[2]: [посоветуй тред]
От: jyuyjiyuijyu  
Дата: 25.07.11 23:05
Оценка:
Здравствуйте, uzhas, Вы писали:
излишняя зависимость от монолитного windows.h с грязными макросами
сложилось так что все основные заголовки включены в stdafx.h
а он включен почти во все .cpp файлы вот этот файл тут и без
windows.h мама дорогая сколько макросов представить страшно
но тьфу тьфу тьфу пока обходится но бывает что бахает в самых неожиданных
местах правда в других проектах при других обстоятельствах
#pragma once
#include <assert.h>
#include <atlcoll.h>
#include <atlcore.h>
#include <atlfile.h>
#include <commctrl.h>
#include <locale.h>
#include <loki/scopeguard.h>
#include <loki/typemanip.h>
#include <malloc.h>
#include <memory>
#include <ocidl.h>
#include <olectl.h>
#include <process.h>
#include <Richedit.h>
#include <richedit.h>
#include <setjmp.h>
#include <shlwapi.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <tlhelp32.h>
#include <windows.h>
#include <windowsx.h>
#include <winerror.h>
#include <winsock.h>
#include <winsock2.h>
Re: [посоветуй тред]
От: jyuyjiyuijyu  
Дата: 26.07.11 07:39
Оценка:
интересно посмотреть на правильное решение этой задачи
код кто нибудь может написать хороший так как должно было бы быть у меня ?
Re[3]: [посоветуй тред]
От: uzhas Ниоткуда  
Дата: 26.07.11 07:49
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>как бы вы переписали ?

для начала надо определеиться, что выдается клиентам, то есть что является интерфейсом к нашей функциональности. когда все в одном хедере, то довольно тяжело это понять
либо это GetWin32Error, либо GetWin32ErrorA + GetWin32ErrorW. обычно приложение либо полностью ANSI, либо юникодное и как раз #ifdef _UNICODE используют для понимания в каком режиме нас собирают.
далее надо продумать названия, чтобы они были ясны
//windows_merror_message.h
#pragma once

#include <cstdint>
#include <cstring>

namespace Windows
{
  std::string GetErrorMessageA();
  std::string GetErrorMessageA(int32_t errorCode);
  std::wstring GetErrorMessageW();
  std::wstring GetErrorMessageW(int32_t errorCode);
}

в одном файле я попытался определить лишь то, что реально интересно будет читать клиенту. все подробности реализации мы перемещаем в .cpp.
если вам в программе не нужно перемешивать юникодные и не юникодные функции, то я бы определил в отдельном файле строку и заюзал бы ее
  Скрытый текст
//windows_string.h
#pragma once

#include <cstring>

namespace Windows
{
#ifdef _UNICODE
  typedef std::wstring String;
#else
  typedef std::string String;
#endif
}


//windows_merror_message.h
#pragma once

#include "windows_string.h"

namespace Windows
{
  String GetErrorMessage();
  String GetErrorMessage(int32_t errorCode);
}


для форматирования сообщений можно использовать более высокоуровневые средства типа (w)stringstream
использовать C-функции лично я предпочитаю только когда душа болит за перформанс
Re[2]: [посоветуй тред]
От: jyuyjiyuijyu  
Дата: 26.07.11 08:16
Оценка:
переделал так перегрузив по char wchar_t все равно они все перед помещением
в стек расширяются до 32 бит movsx eax, byte ptr [ebp — 1] push eax
но вот что хочется убрать так это создание фейкового chType() только для того
чтоб выбрать функцию хочется чтоб все в компайл тайм разрулилось без отражения
на результирующий код знаю в релизе да с оптимизацией все будет как нельзя лучше
и функций то таких не будет не говоря уже про переменные но живем то мы в режиме
отладки а это лишний step over не говоря уже про замусоривание кода
как бы так выбрать функцию полностью в компайл тайм без chType() ?
#include <windows.h>
#include <shlwapi.h>
#include <stdio.h>
#include <tchar.h>

template<class chType>
class GetWin32ErrorEx
{
    enum{cchSize = 256};
    chType _tszBuf[cchSize];
public:
    
    operator chType * ()
    {
        return select(chType());
    }

private:
    
    wchar_t * select(wchar_t)
    {
        return resolve(_tszBuf);
    }

    char * select(char)
    {
        wchar_t wszBuf[cchSize];
        resolve(wszBuf);
        wnsprintfA(_tszBuf, _countof(_tszBuf), "%S", wszBuf);
        return _tszBuf;
    }

    template<size_t cchSize>
    static wchar_t * resolve(wchar_t (&wszBuf)[cchSize])
    {
        DWORD dwError = GetLastError();
        
        DWORD dwLocale = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
        BOOL bOk = FormatMessageW(
            FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL, dwError, dwLocale,
            wszBuf, _countof(wszBuf), NULL);
        if (!bOk)
        {
            HMODULE hDll = LoadLibraryExW(L"netmsg.dll", NULL,
                DONT_RESOLVE_DLL_REFERENCES);
            if (hDll)
            {
                bOk = FormatMessageW(
                    FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
                    NULL, dwError, dwLocale,
                    wszBuf, _countof(wszBuf), NULL);
                FreeLibrary(hDll);
            }
        }

        if (!bOk)
        {
            wnsprintfW(wszBuf, _countof(wszBuf), L"code %#I32x", dwError);
        }
        
        return wszBuf;
    }
};

typedef GetWin32ErrorEx<char> GetWin32ErrorA;
typedef GetWin32ErrorEx<wchar_t> GetWin32ErrorW;

#ifdef _UNICODE
# define GetWin32Error GetWin32ErrorW
#else
# define GetWin32Error GetWin32ErrorA
#endif

int main()
{
    //SetLastError(1);
    DeleteFile(_T("c:\\pagefile.sys"));
    FatalAppExit(0, GetWin32Error());
}
Re[4]: [посоветуй тред]
От: jyuyjiyuijyu  
Дата: 26.07.11 08:31
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, jyuyjiyuijyu, Вы писали:


J>>как бы вы переписали ?

U>для начала надо определеиться, что выдается клиентам, то есть что является интерфейсом к нашей функциональности. когда все в одном хедере, то довольно тяжело это понять
U>либо это GetWin32Error, либо GetWin32ErrorA + GetWin32ErrorW. обычно приложение либо полностью ANSI, либо юникодное и как раз #ifdef _UNICODE используют для понимания в каком режиме нас собирают.

все так но часто надо в анси проекте или наоборот заюзать
отличную от настроек проекта функцию приходится явно писать суффиксы A or W
поэтому я сделал для настрок проекта по умолчанию через макрос
#ifdef _UNICODE
# define GetWin32Error GetWin32ErrorW
#else
# define GetWin32Error GetWin32ErrorA
#endif

но если сильно надо в _UNICODE вызвать анси то можно и суффиксы применить
typedef GetWin32ErrorEx<char> GetWin32ErrorA;
typedef GetWin32ErrorEx<wchar_t> GetWin32ErrorW;

так ведет себя стандартный винапи я решил сделать так же
Re[3]: [посоветуй тред]
От: _nn_ www.nemerleweb.com
Дата: 26.07.11 08:36
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>typedef GetWin32ErrorEx<char> GetWin32ErrorA;
J>typedef GetWin32ErrorEx<wchar_t> GetWin32ErrorW;

J>#ifdef _UNICODE
J># define GetWin32Error GetWin32ErrorW
J>#else
J># define GetWin32Error GetWin32ErrorA
J>#endif

J>int main()
J>{
J>    //SetLastError(1);
J>    DeleteFile(_T("c:\\pagefile.sys"));
J>    FatalAppExit(0, GetWin32Error());
J>}
J>



Почему здесь не сделать typedef вместо #define ?

operator chType * ()
Ну хотя бы operator chType const*()

А вообще не стоит так делать.
Сделайте метод GetString или того.

Иначе багов наберетесь
if (GetWin32ErrorW() + 1) { } // happy debugging


Также не понятно зачем тут шаблон.
Почему не сделать просто класс GetWin32Error.
И конвертер UnicodeToAsciiConverter.

Нужны еще комментарии ?
Переменные которые не изменяются советую ставить const.
Как скажем DWORD dwLocale = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL).
const DWORD dwLocale = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)


А тут это вообще это константа компиляции.
Проще тогда
class GetWin32ErrorEx
{
  static const DWORD dwLocale = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);

  ...
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: [посоветуй тред]
От: Centaur Россия  
Дата: 26.07.11 08:41
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>интересно посмотреть на правильное решение этой задачи

J>код кто нибудь может написать хороший так как должно было бы быть у меня ?

Во-первых, GetLastError — это обработка ошибок. Следовательно, должен быть exception.

Во-вторых, исключение должно наследоваться, прямо или косвенно, от std::exception. Интерфейс std::exception предполагает, что текст сообщения есть строка из char’ов. То есть получать его будем через FormatMessageA. Это, кстати, снимает все вопросы о зависимости от _UNICODE.

В-третьих, нет ничего хуже, чем получить от пользователя багрепорт с сообщениями на клингонском или древнеэльфийском. Поэтому диагностические сообщения в исключениях должны быть на английском языке. Поэтому «DWORD dwLocale = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);» — это вроде бы правильно, но надо проверять.

И наконец, я в подобных случаях добавляю функцию для проверки результатов вызова функций API:

namespace win32
{

class exception : public std::exception
{
…
};

BOOL check(BOOL result)
{
    if (!result) throw exception(GetLastError());
    return result;
}

HANDLE check(HANDLE result)
{
    if (result == INVALID_HANDLE_VALUE) throw exception(GetLastError());
    return result;
}

} // namespace win32

…

win32::check(DeleteFileW(L"C:\\pagefile.sys"));
Re[2]: [посоветуй тред]
От: Abyx Россия  
Дата: 26.07.11 22:18
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>интересно посмотреть на правильное решение этой задачи

J>код кто нибудь может написать хороший так как должно было бы быть у меня ?

http://2x2is11.blogspot.com/2010/11/windows-error-reporting-in-c.html
In Zen We Trust
Re: [посоветуй тред]
От: jyuyjiyuijyu  
Дата: 26.07.11 22:50
Оценка:
спасибо всем кто отписался
Re[5]: [посоветуй тред]
От: Roman Odaisky Украина  
Дата: 27.07.11 08:30
Оценка: 1 (1)
 typedef GetWin32ErrorEx<char> GetWin32ErrorA;
 typedef GetWin32ErrorEx<wchar_t> GetWin32ErrorW;
-#ifdef _UNICODE
-# define GetWin32Error GetWin32ErrorW
-#else
-# define GetWin32Error GetWin32ErrorA
-#endif
+typedef GetWin32ErrorEx<TCHAR> GetWin32Error;
До последнего не верил в пирамиду Лебедева.
Re[6]: [посоветуй тред]
От: jyuyjiyuijyu  
Дата: 27.07.11 10:40
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

это идея
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.