Hungry Mind , Blog about everything in IT - C#, Java, C++, .NET, Windows, WinAPI, ...

Unable to step into .NET v4.0.30319 source

У меня длительное время пункт меню Go To Source Code недоступен, отлаживать исходный код .NET Framework невозможно. В окне Modules почти все сборки имеют Symbol Status = Symbols loaded. Проблема лишь в том, что pdb файлы маленького размера, а это значит, что информации об исходном коде в них нет.

Ответ нашелся в разделе Reference Source Server Discussion.

Решение состоит в использовании следующих версий сборок:

Name Version
mscorlib.dll 4.0.30319.1 (RTMRel.030319-0100)
PresentationFramework.dll 4.0.30319.1
WindowsBase.dll 4.0.30319.1 built by: RTMRel

Поэтому нужен .NET Framework 4 RTM, без патчей, которые накатывает операционная система. Следующие версии сборок не имеют соответствий в базе pdb файлов хранилища Reference Source:

Name Version
mscorlib.dll 4.0.30319.488 (RTMLDR.030319-4800)
PresentationFramework.dll 4.0.30319.450
WindowsBase.dll 4.0.30319.450 built by: RTMLDR

iPhone 4S around the world

Китайцы наконец собрали мой iPhone 4S 32Gb White и отдали в службу доставки. Теперь он отправится в Торонто, затем в Нью-Йорк, а уж после приедет в Киев :-).

Location Date Local Time Activity
Concord, ON, Canada 11/14/2011 18:45 Delivered
11/14/2011 16:11 The customer was not available on the 1st attempt. A 2nd delivery attempt will be made
11/14/2011 7:55 Out for Delivery
11/14/2011 5:49 Arrival Scan
Mount Hope, ON, Canada 11/14/2011 4:50 Departure Scan
Buffalo, NY, United States 11/13/2011 23:33 Departure Scan
11/13/2011 23:32 Arrival Scan
Mount Hope, ON, Canada 11/13/2011 10:07 Arrival Scan
Louisville, KY, United States 11/12/2011 11:25 Departure Scan
Anchorage, AK, United States 11/11/2011 4:56 Arrival Scan
Chek Lap Kok, Hong Kong 11/11/2011 12:59 Departure Scan
Chek Lap Kok, Hong Kong 11/09/2011 16:30 Arrival Scan
Shenzhen, China 11/09/2011 15:15 Departure Scan
11/09/2011 13:30 Origin Scan
China 11/09/2011 0:15 Order Processed: Ready for UPS

Oakley Polarized Juliet

Заказал себе Oakley Polarized Juliet. 400$ в США, без примерки, естественно. Я идиот?

Вот так нужно с тупыми бабами за рулем!


ICU quick starter

Часто бывает необходимо выполнить преобразование текста из одной кодировки в другую. Скажем, отослать на HTTP сервер строку в Windows-1251, а после декодировать ответ.

WinAPI как всегда выручает - функции MultiByteToWideChar и WideCharToMultiByte делают преобразование из UTF-16 в необходимую кодировку и обратно. Список поддерживаемых кодовых страниц велик, но нет механизма для получения идентификатора кодировки по имени. Поэтому я задался целью найти альтернативу этим функциям. И я ее нашел - библиотека ICU. Есть еще iconv, но меня она оттолкнула всей этой гнушной чепухой, не захотелось даже возиться. А вот ICU вполне прилежно поставляется с проектными файлами для свежайшей версии Visual Studio.

Собрать ICU проще простого:

  1. Скачиваем архив с исходными кодами со странички проекта, под колонкой ICU4C;
  2. Разворачиваем содержимое и открываем source\allinone\allinone.sln;
  3. Собираем обе конфигурации - Debug и Release;
  4. Запускаем bin\icuinfo.exe, проверяем, что ICU Initialization returned: U_ZERO_ERROR;
  5. Файл bin\icudtXY.dll должен быть внушительного размера - около 20 мегабайт.

    В случае получения ошибок U_FILE_ACCESS_ERROR или U_MISSING_RESOURCE_ERROR - проверяем размер файла. Если слишком маленький - пересобираем проект makedata, у меня один раз случилось подобное, долго не мог понять в чем дело. Нашел на сайте следующее:

    Why am I seeing a small ( only a few K ) instead of a large ( several megabytes ) data shared library (icudt)? Opening ICU services fails with U_MISSING_RESOURCE_ERROR and u_init() returns failure.

    ICU libraries always must link with the ICU data library. However, so that ICU can bootstrap itself, it first builds a 'stub' data library, in icu\source\stubdata, so that the tools can function. You should only use this in production if you are NOT using DLL-mode data access, in which case you are accessing ICU data as individual files, as an archive (.dat) file, or some other means. Normally, you should be using the larger library built from icu\source\data. If you see this issue after ICU has completed building, re-run 'make' in icu\source\data, or the 'makedata' project in Visual Studio.

Размер bin\icudtXY.dll можно уменьшить с помощью ICU Data Library Customizer. Файл icudt48l.dat из скачанного архива необходимо раскрыть в папку source\data\in (а может и source\data\out, точно не помню) и пересобрать проект makedata.

Рассмотрим пример использования этой замечательной библиотеки. Попытаемся получить строку Приветик, ICU! в кодировке Windows 1251, затем обратно в UTF-16 и сравнить с оригиналом:

#include "stdafx.h"
 
#include <cassert>
 
#include <unicode/ucnv.h>
#include <unicode/ucsdet.h>
 
int _tmain(int argc, _TCHAR* argv[])
{
   const wchar_t * const sourceUTF16 = L"Приветик, ICU!";
   const size_t len = wcslen(sourceUTF16);
 
   UErrorCode uError(U_ZERO_ERROR);
 
   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   UConverter * const pConverter = ucnv_open("windows-1251", &uError);
   if (U_FAILURE(uError)) {
      return -1;
   }
 
   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   const char * const pszCharsetInternalName = ucnv_getName(pConverter, &uError);
   assert(U_SUCCESS(uError));
   assert(pszCharsetInternalName);
   const char * const pszCharsetIANAName = ucnv_getStandardName(pszCharsetInternalName, "IANA", &uError);
   assert(U_SUCCESS(uError));
   assert(pszCharsetIANAName);
 
   const size_t minCharSize = ucnv_getMinCharSize(pConverter);
   const size_t maxCharSize = ucnv_getMaxCharSize(pConverter);
 
   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   const wchar_t *pSourceW = &sourceUTF16[0];
   const wchar_t * const pSourceLimitW = &sourceUTF16[len];
   
   char *targetEncoding = reinterpret_cast<char *>(_alloca(maxCharSize * (len + 1)));
   char *pTarget = &targetEncoding[0];
   const char * const pTargetLimit = &targetEncoding[len];
   ucnv_fromUnicode(pConverter, &pTarget, pTargetLimit, &pSourceW, pSourceLimitW, NULL, true, &uError);
   assert(U_SUCCESS(uError));
   *pTarget = '\0';
 
   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   const char *pSource = &targetEncoding[0];
   const char * const pSourceLimit = &targetEncoding[len];
 
   wchar_t * const targetUTF16 = reinterpret_cast<wchar_t *>(_alloca(sizeof(wchar_t) * (len + 1)));
   wchar_t *pTargetW = &targetUTF16[0];
   const wchar_t * const pTargetLimitW = &targetUTF16[len];
   ucnv_toUnicode(pConverter, &pTargetW, pTargetLimitW, &pSource, pSourceLimit, NULL, true, &uError);
   assert(U_SUCCESS(uError));
   *pTargetW = L'\0';
 
   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   ucnv_close(pConverter);
 
   return 0;
}

Разберем по порядку:

  1. Включение заголовочных файлов unicode/ucnv.h и unicode/ucsdet.h из папки include;
  2. Открытие конвертера функцией ucnv_open.

    В качестве параметра передаем имя кодовой страницы или ее аналог, один из многих альтернативных имен, поддерживаемых ICU.

  3. В отладочных целях получаем внутреннее и стандартное имена открытого конвертера функциями ucnv_getName и ucnv_getStandardName;
  4. Основная часть - аллокация памяти под результат и использование конвертера по назначению (функции ucnv_fromUnicode и ucnv_toUnicode);
  5. Освобождение ресурсов, закрытие конвертера функцией ucnv_close.

Линкеру понадобятся icuuc.lib и icuin.lib для успешного создания исполняемого файла. А ему, в свою очередь, - библиотеки icuuc48.dll, icudt48.dll и icuin48.dll для успешного запуска.

В результате выполнения получаем следующий результат:

ICU proof of concept
Copyright 2007-2011 Chabster