воскресенье, марта 31, 2013

The role manager feature has not been enabled.

Используете MVC4 и столкнулись с "the role manager feature has not been enabled"? Очень просто. Добавьте в web.config следующее:

  
<system .web="">
   <compilation debug="true" targetframework="4.0">
    <assemblies>
     <add assembly="WebMatrix.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
     <add assembly="WebMatrix.WebData, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
   </assemblies>
   </compilation></system>

пятница, декабря 07, 2012

Немножко про unit tests


"А по-моему, они одинаковы"

понедельник, декабря 03, 2012

Что, мальчики, не получается?

Несчастные вы бедолажки в Эпле... Ну, кое-как портировали уродца своего на Windows, ладно. Он, правда, почти год после этого не понимал русский язык, ну, тоже спишем на вашу экстраординарную нетрадиционность. Но вы же всё-таки инженеры, нет? Я там не говорю, что все как один состоите в IETF, но хотя бы общие представления о платформе, на которую делает порт, надо иметь!

Safari это поганое: DDE не поддерживает, с COM не знакомо, требованиям Windows по проектированию оконных интерфейсов не удовлетворяет.

Что же так слабо? Не умеете? Не получается? Ай-яй-яй. Да... это вам не подсветочку вокруг кнопки рисовать. Срамота!

Простой пример DDE и C

Потребовалось получить URL из Firefox. FF вообще написан чудным образом, весьма далёким от того, как надо писать программы для Windows. Поэтому пройти по иерархии окон и получить текст окна - невозможно. Зато возможно получить нужное через DDE. О командах, которые можно использовать в DDE для получения информации из браузера, примерно можно почитать тут: http://support.microsoft.com/kb/160957 Не знаю, какие именно из них поддерживает FF, но получить URL таким образом можно. Для этого нужно использовать команду WWW_GetWindowInfo.

Несмотря на то, что DDE уже старенькая технология (в этом году ей исполнилось 22 года), она по-прежнему работает и неплохо. Её суть примерно в следующем.
  1. Клиент-серверная архитектура DDE подразумевает, что одна сторона (клиент) будет слать запросы, а другая (сервер) - их выполнять. Используется парадигма "разговора", а именно: вопрос-ответ.
  2. Клиент может задавать темы "разговора" (не знаю, для чего это нужно). Выглядит, в переводе на человеческий язык это так. Клиент говорит: "Эй, ты, сервер по имени Firefox, хочу с тобой потолковать насчёт WWW_GetWindowInfo. Ты как, в настроении?". Сервер отвечает: "Ну, давай. Дескриптор этого разговора равен 1232134. Если дальше будешь спрашивать про своё - не забывай мне напоминать, о чём толкуем, подставляя это число как идентификатор. А то много вас тут лезет поговорить, не уследишь по-другому"
  3. Если сервер согласился поддержать "разговор" (выдав HCONV не равный NULL), дальше можно задавать ему вопросы. Для каждой темы, на которую можно клиент может потолковать с сервером есть допустимый "список вопросов". В нашем случае для темы WWW_GetWindowInfo браузер предполагает, что дальше его будут спрашивать про URL и WindowText. Задать вопросы про прогресс закачки файла в разговоре, посвящённом WWW_GetWindowInfo, не выйдет.
  4. Задавание вопроса заключается в последовательном вызове 3х функций:
    1. DdeCreateStringHandle - создаёт DDE-описатель для "вопроса", такого как "URL"
    2. DdeClientTransaction - начинает транзакцию передачи данных. Можно это себе представлять как фразу "Эй, сервер, хочу тебя спросить... Ну, вот мы говорим, про WWW_GetWindowInfo. Так что там с URL?"
    3. DdeGetData - это вызывается для получения ответа на свой вопрос. В ответ на этот вызов DDE скопирует данные в переданный вами буфер и в нём будет искомый ответ.
Таким образом, для получения URL из FF надо:
  1. Инициализировать DDE, чтобы можно было дальше вызывать его функции
  2. Установить соединение с сервером DDE, каковым является FF. При установке соединения задать тему разговора WWW_GetWindowInfo
  3. Спросить FF про URL
 
Подключаемся к FF (никакой обработки ошибок и дурацкие имена для понятности)

TCHAR ddeServer[] = L"Firefox";
TCHAR conversationTopic[] = L"WWW_GetWindowInfo";
TCHAR topicSpecificCommand[] = L"URL";

DWORD idInst=0;
DdeInitialize(&idInst, (PFNCALLBACK)DdeCallback, APPCLASS_STANDARD | APPCMD_CLIENTONLY, 0 );

HSZ appStringHandle, topicStringHandle;
HCONV conversationHandle;
appStringHandle = DdeCreateStringHandle(idInst, ddeServer, 0);
topicStringHandle = DdeCreateStringHandle(idInst, conversationTopic, 0);

conversationHandle = DdeConnect(idInst, appStringHandle, topicStringHandle, NULL);
DdeFreeStringHandle(idInst, appStringHandle);
DdeFreeStringHandle(idInst, topicStringHandle);
Спрашиваем у FF, какой URL у его активной закладки активного экземпляра

HSZ commandStringHandle = DdeCreateStringHandle(idInst, topicSpecificCommand, 0);
HDDEDATA hData = DdeClientTransaction(NULL,0,conversationHandle,commandStringHandle, CF_TEXT, XTYP_REQUEST, 5000, NULL); // CF_TEXT для получения однобайтовой строки
// CF_UNICODETEXT - для юникодной

char res[255] = {0};
DdeGetData(hData, (unsigned char*)res, 255, 0);
printf("%s\n", szResult);
Всё. В res лежит URL закладки, с которой пользователь работал последней в экземпляре FF с которым пользователь работал последним.

P.S. Само собой, не забывайте проверять ошибки после вызовов. А то всякое может быть. Например, нету у вас запущенного экземляра FireFox, вы не знаете и стремитесь с ним поговорить. Не выйдет! :)

P.P.S. Удаляйте всё, что создаёте: DdeCreateStringHandle -> DdeFreeStringHandle, DdeCreateDataHandle -> DdeFreeDataHandle

P.P.P.S. То же самое работает и для Opera, только содержимое ddeServer должно быть "Opera"

суббота, октября 13, 2012

Вот и случилось

Microsoft утратила технологическое лидерство. Да, миллиард десктопов, да, сотни миллионов копий Windows, но эта эпоха начала заканчиваться.

Увы.

понедельник, сентября 10, 2012

Автоматы по продаже билетов на аэроэкспресс придумал и установил идиот. Потому что:
1. Нет надписей о принимаемых номиналах
2. Купюры, которые (по непонятным причинам) не могут быть приняты - выбрасываются на пол. Нет ни тормозящих механизмов, ни лотка-ограничителя.
3. Способ покупки нескольких билетов настолько непонятен, что им воспользоваться обычному человеку невозможно.

И я вспоминаю свои впечатления от первого полёта на Боинге. После него у меня не осталось вопросов, почему советские ТУ-154 и прочие канули в Лету. Они внутри сделаны не для пассажиров. Двигатели, планер, авионика - меня они не интересуют в той степени в какой ширина кресел, форма подголовников и удобство раскрытия столика.

Хотя, если не летать на нём, то мне очень нравится и силуэт, и компоновка ТУ-154.

вторник, августа 14, 2012

The task category text is missing in event viewer in Vista+

I bet you see the text because you can't see your category string for your event that defined inside EXE file. Calm down. I know how to resolve the issue. There are a few steps to go:

1. Run regedit, open your event source at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\Application\SRC_NAME
2. Right click it and select Permissions.
3. Give READ access to Everyone. This will allow system to determine where the strings are located exactly. Without this action you won't see messages for events if running your program in Vista+
4. Start the Windows Explorer up and locate your EXE
5. Again, right click it, then Properties->Security and allow Everyone to READ the exe. This allows event subsystem to read category definitions to be added into Event Viewer

So, you need only 2 additional permissions to see both message text and task category name for the event:
- READ permission for Event Source in the Registry
- READ permission for your executable containing task category definitions

понедельник, августа 13, 2012

Совместимость поддержана на отлично!

Дано. Windows 7. По всем правилам написанный файл сообщений .mc. Полученные .res-файлы корректно встраиваются в итоговый файл. Источник событий корректно инициализирован в реестре. А вот при попытке вызвать ReportEvent получаем в журнале Windows вот такое:

"the message resource is present but the message is not found in the string/message table"

Почему? Ответ, как оказалось, в Windows 7. Если приложение не запущено от имени администратора и не имеет прав читать реестр, то источник сообщений (пусть он хоть сто раз описан в реестре) будет проигнорирован. Вот так-то.

Настоящие молодцы. Прахрамисты!

понедельник, июня 04, 2012

Зачем убрали кнопку "Menu" в Android

Была аппаратная кнопка menu. Ей очень удобно пользоваться: нажал и получил контекстные команды. Вызвал команды и опять экран не содержит мусора. Теперь нам "рекомендуют" (в терминах: шевелитесь, а то скоро вообще исчезнет, физически) использовать actionbar. Ну смысл-то какой? У меня E730. 800x480. Ну, давайте займём сверху 100 точек под actionbar. Потом ещё 100 под subactionbar. Будет очень унифицированно. А пользоваться-то как? Мобильные устройства должны иметь минимум управляющих элементов на экране. Для этого должны применяться gestures и, как максимум, полупрозрачные кнопки. Забивать экран статическими элементами, которые кто-то то ли вызовет, то ли нет - это кретинизм. Это глумление над пользователем. И это даром не проходит.

Вот что бывает, когда концепцию развития интерфейса доверяют идиотам. Видно, что кто-то там в этом гугле в отделе UI был с мозгами, а потом ушёл. Ну, что ж: присаживайтесь поудобнее: дурачьё хочет показать нам Word 2.0 for Windows, только для Android. Но не в 1993м году, а в 2012м. Больше! Больше! Больше грузных кнопок! Давайте загадим уже этому дураку-покупателю весь экран!

четверг, мая 31, 2012

Ускорение работы WCF-сервиса

Вчера были тестовые запуски сервиса, хостящегося (теперь) на IIS. Один вызов занимал 30 секунд (или около того). От великого огорчения стал внимательно читать документацию.

Вычитал, что WCF при отсутствии частно-определённой привязки сначала лезет исследовать прокси-серверы в сети. Никаких таких устройств у нас нет, потому до таймаута сервис просто "ждал".

Но стоило определить свою привязку как дело пошло. 4 строчки в конфиге дали ускорение работы в несколько сотен тысяч раз.

А всё из-за этого: usedefaultwebproxy="false"

понедельник, мая 28, 2012

Как передать массив из Android в WCF?

Ну, то что из Android практически невозможно передать сложный тип веб-сервису на WCF, понятно. Ведь кроме Microsoft для Microsoft ничего не существует. Тут даже и вопросов никаких не возникает: "так надо". А вот почему нужны такие пляски с бубнами для передачи простого массива из приложения на Android в WCF-сервис, непонятно. Этот ваш любимый ksoap2 тоже не особо-то помогает в виде "из коробки". Приходится смотреть логи, сравнивать сообщения и подстраиваться. А что, замечательный способ разработки. Если некуда спешить.

Короче.

Полностью завершённый код C#, делающий то, что нужно
class Program
{
 static void Main(string[] args)
 {
  ServiceReference1.ServiceClient sr = new ServiceReference1.ServiceClien();
  sr.GetSomething(new []{10, 20, 30});
  sr.Close();
 }
}
Вызывает и работает.

Теперь то же самое из Android. Просто так передать массив не получится, его надо передавать изощрённо (извращённо?). Потому что в противном случае WCF не сможет десериализовать сообщение.

Делай раз
1. Сделать вид, что передаём не какой-то там паршивый int[], но настоящий Объект! настоящего Класса! Со всеми атрибутами такого. А именно
2. Полный код "взрослого класса"
public class MyIds extends Vector implements KvmSerializable {
    private static final long serialVersionUID = -1143242342342342265L;

    @Override
    public Object getProperty(int i) {
        return this.get(i);
    }
    @Override
    public int getPropertyCount() {
        return this.size();
    }
    @Override
    public void setProperty(int i, Object o) {
        this.add(Integer.parseInt(o.toString()));
    }
    @Override
    public void getPropertyInfo(int i, Hashtable hashtable, PropertyInfo propertyInfo) {
        propertyInfo.name = "int";
        propertyInfo.namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays";        propertyInfo.type = PropertyInfo.INTEGER_CLASS;
    }
}

Самый цимес в жирной строчке. Хотите неприятно провести время - уберите её.

После этого вызов метода GetSomething в Android становится очень простым
3. public static int getSomething(int[] args)
    {
        final String MethodName = "GetSomething";
        final String SoapAction = "http://mydomain.ru/MyService/IInterface/GetSomething";
        SoapObject req = new SoapObject(Namespace, MethodName);

        MyIds myIds = new MyIds();
        for(Integer i : args)
            myIds.add(i);
       
        PropertyInfo pi = new PropertyInfo();
        pi.setName("WCFParam");
        pi.setValue(myIds);
        pi.setType(myIds.getClass());
        req.addProperty(pi);
        SoapSerializationEnvelope se = getEnvelope(req);
        SoapPrimitive p = initializeTransportAndCall(SoapAction, se);

        if (null == p)
            return 0;

        return Integer.parseInt(p.toString());
    }
Всё. WCF SOAP WS принимает массив целых чисел. Ну и дальше дело техники.

среда, февраля 08, 2012

MVC, Facebook и McDonald's

Будучи погружён в пучины анонимных типов, вызовов ajax, разделение ответственности, оптимизацию модели, linq и многопоточность Windows одновременно, не могу, тем не менее, не заметить, что Facebook выходит на IPO.

Ну, выходит и выходит, казалось, бы. Но интересно замечание одного главного редактора одного русского журнала: "Вот вы знаете, сейчас FaceBook выходит на IPO и капитализация компании оценивается в 100 миллиардов долларов. Я замечу, у нас вот об этом материал Романа Карачинского в номере, который там открыл стартап в Кремниевой долине, так вот капитализация Макдональдса – 101 миллиард. Вот что такое интеллект, понимаете? И они ищут, конечно, поддержки, там, основателей FaceBook, Twitter’а и так далее. Это я понимаю, это люди, которые создают фантастический интеллектуальный продукт."

Что я хотел бы сказать. Несмотря на наличие у меня там аккаунта, я всё равно не очень-то понимаю, в чём изюм фейсбука. Что там может стоить хотя бы сто миллионов. Поясню. Из чего составлена стоимость акций Бигмачечной - мне прекрасно понятно. Основные средства и гарантия гастрономического удовлетворения клиентов. А Фейсбук? Что лежит в основе столь оптимистических оценок? Всё та же тупая модель: "у нас много хомяков, мы будем им показывать рекламу - вот вам и кэшфлоу"? Остроумно. Было в 99м году, с Гуглом. Но сейчас как бы уже не того...

Хорошо, что Альбац в курсе что там творится, но называть Фейсбук "фантастическим интеллектуальным продуктом" и считать нормальным 100 миллиардов за это - это уж чересчур. Гомеопатическое интернет-средство от неврозов должно стоить подешевле.

четверг, ноября 24, 2011

Оказывается, умер Ритчи

Для меня это исключительно печальное событие. Джобс не существовал в моём сознании как человек. А Ричи - существовал. По голубой книге издательства Мир в 90м году я начал изучать "серьёзный язык". Начал в 90м, а последнюю строчку на нём написал 20 минут назад.

Земля тебе пухом, Дэн. Ты всё изменил для меня и сотен тысяч других обормотов.

четверг, октября 27, 2011

Маленькие извращенцы из группы разработки MSBUILD

Я очень недоволен. Передо мной стоит задача, похоже неразрешимая в принципе. Один из наших продуктов должен собираться в 4х конфигурациях (да ещё и для двух серверов - тестового и production). Там много всего внутри. И asp.net, и сервисы, и серверы и чего только там нет. При этом используются одновременно очень разные технологии. В том числе - С++. Поскольку сиплюсплюсный бог велел нам пользовать условную компиляцию, то код вроде


#ifdef _DEBUG
#define LIC_SERV "127.0.0.0"
#else
#define LIC_SERV "207.46.232.182"
#endif

не только не редкость, а само собой.

Сборка из VS2010 не представляет никаких проблем. Выбрал конфигурацию, запустил, посмотрел, погонял свои тесты и можно дальше отдавать на функциональное, регрессионное, usability и т.п - пусть собирают сами и смотрят. Но тут же и собака порылась, а теперь лежит и разлагается.

Независимый сборщик собирать будет так:
msbuild proj.build /p:General=true|false /p:Debug=true|false /p:Public=true|false

внутри proj.build каждый из переданных параметров-свойств /p будет обработан и на его основе будет что-то сделано, например

<propertygroup condition="'$(Debug)'=='true'"> 
  <defineconstants>$(DefineConstants);DEBUG
</propertygroup>
И так далее и такого много. Так вот, в чём проблема. А она в том, что можно хоть жирным красным писать

msbuild proj.build /p:General=false /p:Debug=false /p:Public=true|false

это никак не повлияет на отношения msbuild и cl. Константы не передаются как аргументы ключа /D компилятору.

Нам предлагают писать отдельностоящие страницы свойств, определять CL через SET (тоже не особо-то и работает) и тому подобные элегатные решения.

У меня только один вопрос. Ладно, есть отдельные криворукие уроды, которые не в состоянии предоставить своему "революционно-удобному средству сборки" одинаковые механизмы использования любых стандартных компиляторов, ладно, есть маркетологи, которые традиционно понимают чуть больше чем 0 в том, что продают. Но должен же в микрософте быть какой-то отдел по контролю качества. Интернет плачет и рыдает - никто не может корректно определить макросы с++ компилятора для передачи их msbuild в командной строке, а этим хоть бы что.

Ну как там можно, ёшкин КодтЪ

P.S. Забыл написать. Решается эта проблема так:

msbuild client\client.vcxproj /p:configuration=debug /p:platform=win32
Тут указывается, что будет собираться DEBUG-конфигурация и одно определение уже, считай, есть. То есть, ветки #if DEBUG будут активизированы. А вот с General - пришлось писать отдельный файл, менять его перед компиляцией отдельной карликовой утилиткой (пришлось самому писать)... В общем, буэээ

суббота, декабря 25, 2010

Отладка

Закончил сложную отладку winsock-взаимодействия. Всё.

пятница, декабря 03, 2010

Яндекс

Пациент задаёт вопросы в духе "что бы такого сделать Яндексу, чтобы было лучше".

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

Ребята. В том, чем вы занимаетесь, ваш номер - вечно шестой. И лучше не будет. Не морочьте людям голову, превратитесь в интернет-магазин.

четверг, июня 24, 2010

Comodo как яркий пример отвратительно-тупого сервиса

Есть лишних пару недель? Хочется острых ощущений? Закажи в Comodo сертификат. Время пролетит незаметно, и ты много узнаешь о том, что же на самом деле такое это - получение сертификата...

Надо их в Сколково, нанопрезиденту помогать деньги красть. Больше ни на что эти придурки не годны.

вторник, апреля 13, 2010

Первый сервер и активация Windows

Пять лет назад примерно в эти же дни мы купили свой первый сервер. На самом деле это была обычная персоналка, подключенная через целый каскад ИБП к сети и интернету, но мы называли её сервером. Вчера, после пяти лет непрерывной работы, у неё сгорела мать (чему предшествовало нарушение теплового контакта между вентилятором и процессором, как показало вскрытие).

Само собой, такие купить нигде невозможно уже, пришлось сделать upgrade. После которого Windows 2003 сообщил(а/о/и), что надо активироваться. Пикантность в том, что окно с требованием провести активацию показывается до того, как установились хоть какие-то драйвера на систему. В частности, недоступна сеть. Автоматическая активация невозможна. И впервые в жизни я воспользовался средством "активировать по телефону". Более бессмысленно я ещё никогда не проводит 18.5 минут жизни.

Во-первых, надо ввести длинный цифровой код, не ошибившись ни в одной цифре. Во-вторых, механическая женщина диктует код подтверждения, произнося цифры тихо и с разной скоростью. В-третьих, нет никакой диагностики того, что я ввёл все цифры правильно (особенно касается первого пункта) пока не столкнусь с сообщением Invalid Key.

Одна итерация активации по телефону у меня занимала 6'10". В конце-концов, систему я активировал, сервер оживил и сейчас поеду его водружать на площадку. Но осадок от чьей-то глупости остался.

понедельник, апреля 05, 2010

"Тихий час. Для всех, кроме нас"

Служба MSDN Online Concierge доступна 24 часа в сутки 7 дней в неделю. Служба не работает в праздничные дни.

Ещё будут вопросы, почему Google Earth работает как часы, а Bing 3d - нет?

А вообще не до шуток. Отрезали доступ к загрузкам MSDN. Без объяснения, без разговоров, вообще. По телефону какая-то механическая гражданка на ломаном русском рассказывает, что сегодня, 5го апреля - они не работают, потому что это выходной. И предлагает позвонить в "регулярные часы". Не смог понять - "регулярные часы" это когда регулы или что-то другое. В целом, день испорчен.

Обн.: как внезапно перестало пускать, так же внезапно и был дан доступ.

суббота, апреля 03, 2010

Чёрной молнии подобный

Пока не пойму, почему, но тем не менее. Вот фрагмент кода некоего компонента.


 protected override void OnPreRender(EventArgs E)
 {
  ...
  Random rnd = new Random((int)(DateTime.Now.Ticks % Int32.MaxValue));
  Response.Write(rnd.Next(10000) + "</br>");
  ...
на странице 2 таких компонента. Логично предположить, что при вызове rnd каждая переменная будет инициализирована своим значением тиков, соответствующим моменту выполнения кода инициализации. MSDN говорит о том, что
a single tick represents one hundred nanoseconds or one ten-millionth of a second. There are 10,000 ticks in a millisecond.

А коли так, то оба компонента должны при отрисовке вывести в поток 2 разных числа. Они и выводят. Но только в Windows 7. XP и 2003 показывают одно и то же. То есть, если для W7 я увижу:
1762
7773

6851
995
то для XP и W2K3
1762
1762

6851
6851
Конечно, инициализацию RNG вынес в static, но всё равно теряюсь в догадках - что это за поведение? Как возможно всю работу по подготовке и отрисовке 2х web-компонентов свести к одному 100-нс отрезку? И почему это поведение не проявляется в Windows7?