вторник, апреля 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?

пятница, апреля 02, 2010

Концы строк, разбор XML и пустые страницы в IIS

Стоило не завершить строку \n, как чтение содержания элемента начало приводить к проглатыванию следующего тэга. Интересно.

Ещё интересней влияние размера буфера обработки запросов в IIS. Мы пишем в скрытое поле большую криптостроку и её наличие приводит к показу в ответ пустой строки. Оказывается, к этому имеет отношение слишком малое значение свойства uploadreadaheadsize. Увеличили до 100 КБ и дело пошло. Кстати, uploadreadaheadsize измеряется в байтах, а не в килобайтах, как ошибочно указано в документации.

среда, марта 17, 2010

Что такое эти "социальные сети"?

Я откровенно не понимаю. Не понимаю, в чём тут технологический вызов и ещё больше не понимаю, в чём тут интерес для конечного пользователя. Мошенничество и тупость.

четверг, февраля 04, 2010

Чётко по графику!

Как и запланировано, именно сегодня выпущена версия с поддержкой ЭЦП. Горжусь!

среда, февраля 03, 2010

The caller was not authenticated by the service

Может вызываться недействительным сертификатом пользователя, либо таким сертификатом, который подписан ключом, сертификат которого отсутствует в Trusted Root.

Разумеется, в том случае, если клиент WCF аутентифицируется при помощи сертификатов

вторник, февраля 02, 2010

Подписание данных в браузере

Гора Сен-МишельПотратил несколько дней на обзор ситуации с подписанием документов в браузере. Что удалось выяснить...

Простое подписание документа при помощи DSIG в Windows (IE) невозможно. Для этого необходимо либо использовать нерекомендованную версию MSXML (5.0), либо самостоятельно заниматься такими малоприятными вещами, как покусочное формирование XML Digital Signature. Бесплатного COM-компонента или библиотеки для выполнения этой работы не существует. Это с одной стороны. С другой, есть .NET и XSign, но требования к текущей задачи не позволяют рассчитывать на наличие у пользователя хотя бы .NET 1.1, не говоря уже об XSign.

Хоть и очень хотелось, но от XMLDSIG пришлось отказаться. Вместо этого принято решение использовать цифровые подписи PKCS #7. На клиенте (в Internet Explorer) документ подписывается и в составе скрытого поля отправляется на сервер, там подпись проверяется и если всё в порядке, то и ... всё.

Если кратко. На клиенте (CAPICOM + C++)


  1. Дать выбрать сертификат из персонального хранилища текущего пользователя.


  2. IStorePtr store(__uuidof(Store));
    HRESULT hr = store->Open(CAPICOM_CURRENT_USER_STORE, _T("My"), CAPICOM_STORE_OPEN_READ_ONLY);
    if (FAILED(hr))
    return hr;

    ICertificates2Ptr ptr(store->Certificates);
    ICertificates2Ptr selected = ptr->Select(_T(""), _T(""), VARIANT_FALSE);

  3. Проверить факт выбора сертификата и наличие закрытого ключа (а то мало ли...)

  4. Подписать сообщение

  5.  ICertificate2Ptr p(selected->Item[1]);

    ISignerPtr signer(__uuidof(CAPICOM::Signer));
    signer->PutCertificate(CComQIPtr(p));

    ISignedDataPtr data(__uuidof(SignedData));
    data->put_Content(*m_Xml);

    bstr_t signature = data->Sign(signer, FALSE, CAPICOM_ENCODE_BASE64);
    m_Signature = new CComBSTR(signature.GetBSTR());


На сервере (.NET)

  1. Декодировать (привести в бинарный вид) полученное сообщение

  2.  byte[] data = Convert.FromBase64String(signature);
    SignedCms cms = new SignedCms();
    cms.Decode(signed);


Поскольку подпись объединена с исходным сообшением, то это всё. Только не забывайте, что CAPICOM выдаёт Unicode-строки, а .NET - если его не трогать специально - ожидает UTF-8 строк.

среда, января 20, 2010

Список обязательных документов проекта

1. План выпуска версий
2. Отчёт о состоянии работ
3. Функциональная спецификация
4. Техническая спецификация
5. Перечень инцидентов на ближайший релиз

суббота, января 16, 2010

Вот такие технологии

"Просим Вас отнестись с пониманием к тому, что низкий уровень цен не позволяет нам принимать к оплате пластиковые карты."

Думаете, семечками торгуют? Нет. Компьютерами.

пятница, апреля 24, 2009

Доделываем за халтурщиками

Меня всегда удивляло, почему после установки MS SQL Server нужно ещё дополнительно руками конфигурировать SSRS. При этом "конфигурирование" - это просто тупое протыкивание кнопок, не требующее никакого воображения. Это с одной стороны. С другой - SSRS в составе MSSQL Server 2005 EE with AS должен быть установлен в процессе развёртывания решения. Мы не можем предположить, что все наши 2000 пользователей (на первом этапе. далее - 140000) смогут что-то установить себе. Там где есть нажатия на кнопки - просто должна быть техподдержка. Но это стоит денег и похоже, что написать 100 строк (так казалось) - будет попроще, чем тратить миллионы на телефонные разговоры с несчастными "доустанавливательщиками".

Для работы были использованы:
1. MSDN из состава VS2008
2. Онлайновый MSDN
3. Собственно - VS2008 (C#)

Алгоритм доустановки:
1. Создать виртуальные каталоги для службы и менеджера отчётов
2. Развернуть БД сервера отчётов
3. Назначить на неё права
4. Установить WS-identity

В общем, всё, что надо сделать руками в конфигураторе, должно быть сделано
автоматически

Как это всё делается
Есть некоторые проблемы на этом пути. Прежде всего, MSDN что в составе поставки VS2008 безбожно врёт. Не те сигнатуры методов даже. Затем, сам процесс очень плохо документирован. До такой степени, что непонятно даже с чего начинать. И наконец - уже когда всё вроде бы работает, всплывают мелкие детали, которые надо знать, иначе вся работа -- зря. Итак.

1. Берём в левую руку Reporting Services WMI Provider. Запускаем VS2008 и создаём Console application (это по желанию, но как человек, которому скоро умирать - я ближе к консолям, чем к окнам, хотя казалось бы...).
2. Импортируем System.Management и System.DirectoryServices.

Подготовительная работа завершена

Дальше - создаём виртуальные каталоги сервиса и менеджера:

private static void Main(string[] args)
{
string scopeName = String.Format(@"\\{0}\root\Microsoft\SqlServer\ReportServer\v9\Admin", Environment.MachineName);

// Свойства сервиса
string rsCls = String.Format(@"\\{0}\root\Microsoft\SqlServer\ReportServer\v9\Admin:MSReportServer_ConfigurationSetting", Environment.MachineName);
// Свойства менеджера
string rsmCls = String.Format(@"\\{0}\root\Microsoft\SqlServer\ReportServer\v9:MSReportManager_ConfigurationSetting", Environment.MachineName);

ManagementScope scope = new ManagementScope(scopeName);
scope.Connect();

ManagementObject instance = GetInstance(scope, rsmCls);
CreateVirtualDirectory(instance, "Reports");
ResetUrls(instance);

instance = GetInstance(scope, rsCls);
GenerateDbScript(instance);
CreateVirtualDirectory(instance, "ReportServer");


При этом
CreateVirtualDirectory
выглядит так:

///
/// Создать виртуальный каталог в IIS и записать в .config RS (сервиса или менеджера) изменения
///

/// Объект администрирования
/// Имя создаваемого каталога
private static void CreateVirtualDirectory(ManagementObject instance, string VirtualDirectory)
{
ManagementBaseObject inParams = instance.GetMethodParameters("CreateVirtualDirectory");
inParams["Name"] = VirtualDirectory;
inParams["IISPath"] = String.Format("IIS://{0}/w3svc/1/root", Environment.MachineName);

ManagementBaseObject outParams = instance.InvokeMethod("CreateVirtualDirectory", inParams, null);
CheckErrorCode(outParams);
}


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


private static ManagementObject GetInstance(ManagementScope Scope, string ManagementClass)
{
ManagementClass serverClass = new ManagementClass(ManagementClass) {Scope = Scope};
ManagementObjectCollection mcol = serverClass.GetInstances();
ManagementObject instance = null;

foreach(ManagementObject o in mcol)
{
instance = o;
break;
}

return instance;
}

Наш случай - прост. Я точно знаю, что сервер отчётов разворачивался в единственном экземпляре и поэтому умничать - "с каким именно экземпляром мы работаем" я не стал. С одним единственным.

Итак, каталоги установлены и две красных лампочки в конфигураторе погасли. Устанавливаем теперь Web service identity
private static void SetWebServiceIdentity(ManagementObject instance)
{
ManagementBaseObject inParams = instance.GetMethodParameters("SetWebServiceIdentity");
inParams["ApplicationPool"] = String.Empty;

ManagementBaseObject outParams = instance.InvokeMethod("SetWebServiceIdentity", inParams, null);
CheckErrorCode(outParams);
}


создаём БД

/// 
/// Сгенерировать скрипт для создания БД RS
///

/// Объект администрирования (MSReportServer_ConfigurationSetting)
private static void GenerateDbScript(ManagementObject instance)
{
ManagementBaseObject inParams = instance.GetMethodParameters("GenerateDatabaseCreationScript");
inParams["DatabaseName"] = "ReportServer";
inParams["Lcid"] = "1033";
ManagementBaseObject outParams = instance.InvokeMethod("GenerateDatabaseCreationScript", inParams, null);
object s = outParams["Script"];

using(FileStream fs = new FileStream("database.sql", FileMode.Create))
{
using(TextWriter tw = new StreamWriter(fs))
tw.Write(s);
}

ExecSQL("database.sql");
}

устанавливаем права на эту БД
private static void SetupDatabase(ManagementObject instance)
{
ManagementBaseObject inParams = instance.GetMethodParameters("SetDatabaseConnection");
inParams["Server"] = @"(local)\SQLEXPRESS";
inParams["DatabaseName"] = "ReportServer";
inParams["CredentialsType"] = 2;
inParams["UserName"] = String.Empty;
inParams["Password"] = String.Empty;

ManagementBaseObject outParams = instance.InvokeMethod("SetDatabaseConnection", inParams, null);
CheckErrorCode(outParams);

SetupRights(instance, @"NT AUTHORITY\Network Service");
SetupRights(instance, String.Format(@"{0}\ASPNET", Environment.MachineName));
}

private static void SetupRights(ManagementObject instance, string Account)
{
ManagementBaseObject inParams = instance.GetMethodParameters("GenerateDatabaseRightsScript");
inParams["UserName"] = Account;
inParams["DatabaseName"] = "ReportServer";
inParams["IsRemote"] = false;
inParams["IsWindowsUser"] = true;

ManagementBaseObject outParams = instance.InvokeMethod("GenerateDatabaseRightsScript", inParams, null);
object s = outParams["Script"];
CheckErrorCode(outParams);

using(FileStream fs = new FileStream("permissions.sql", FileMode.Create))
{
using(TextWriter tw = new StreamWriter(fs))
tw.Write(s);
}

ExecSQL("permissions.sql");
}

устанавливаем NTLM-аутентификацию на IIS
private static void SetupIIS()
{
DirectoryEntry de = new DirectoryEntry(String.Format("IIS://{0}/w3svc/1/root", Environment.MachineName));
de.Properties["AuthFlags"].Value = 4;

de.CommitChanges();
}


и наконец правим конфигурационный файл менеджера таким образом, чтобы менеджер мог запускаться без ошибок:
private static void ResetUrls(ManagementObject instance)
{
ManagementBaseObject inParams = instance.GetMethodParameters("SetReportServerURLs");
inParams["ReportServerURL"] = String.Empty;
inParams["ReportServerVirtualDirectory"] = "ReportServer";
inParams["ReportServerExternalURL"] = String.Empty;

ManagementBaseObject outParams = instance.InvokeMethod("SetReportServerURLs", inParams, null);
CheckErrorCode(outParams);
}


Да. Чуть не забыл.
CheckErrorCode
выглядит так:
private static void CheckErrorCode(ManagementBaseObject outParams)
{
int errorCode = Convert.ToInt32(outParams["HRESULT"]);
if (0 == errorCode)
Console.Write('+');
else
Console.Write('-');
}


Моменты, связанные с превращением виртуальных каталогов в приложения - пропускаю. На выходе - полностью настроенный SSRS2005. Мы прилично сэкономим на техподдержке

суббота, февраля 21, 2009

VS2008 + SQL Server 2005

По-моему, это настоящий кретинизм - не добавить в 2008ю студию средства для работы с SSRS 2005.

понедельник, февраля 16, 2009

Тест на память и сообразительность

COM-класс запускает поток, в который через
IGlobalInterfaceTable передаёт указатель на какой-то интерфейс для дальнейшей асинхронной обработки. Один из методов интерфейса в этом случае всегда возвращает 0x800401fd "Object is not connected to server", а некоторые другие иногда произвольно вместо валидного указателя из CoCreateInstance возвращают NULL.

Почему?

Правильный ответ: а кто будет корректно инициализировать поток для COM?

вторник, февраля 10, 2009

А вот у нас был случай

На днях решил заказать себе домой бесперебойник. Остановился на Ippon. Во-первых, потому что у меня был уже этой серии агрегат, а во-вторых, потому что они по известному соотношению рвут всех. Даже бесплатному пиву угрожают. Ну так вот. на price.ru увидел, что некий озон предлагает такой прибор по неплохой цене. Разместил заказ. Они подтвердили. Прошла неделя - получаю письмо: "Мы сожалеем, что нам приходится сообщать Вам об аннулировании Вашего заказа № 11111111-2222 Аннулирование произошло по причине: товар отсутствует у поставщика. "В качестве компенсации за причиненное неудобство вазон предлагает Вам воспользоваться 5% скидкой на один заказ*, которая действует в течение 2 недель."

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

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

В общем, товарищи интернет-покупатели, плюйте на газоны. И выгуливайте на них собакЪ. А дебилы из газонов - учитесь работать у amazon.com, а то так в собственном... и захлебнётесь.

вторник, января 20, 2009

О техническом кретинизме русских банков

Имея р./с. в Банке Москвы, мы подключены к счёту через интернет-банк. Это удобно и, безо всяких сомнений, выгодно. Однако теперь, по требованию какого-то высокопоставленного идиота из этого же деревенского банка, мы должны предоставить перечень всех ip-адресов, с которых планируем "осуществлять доступ к счёту". Разговоры со службой поддержки сводятся всё к тому же: "мы сделаем вас счастливыми". Вариант того, что мне не нужно никакое ограничение, что оно даже хуже, чем не нужно - его не должно быть - не рассматриваются: "Тефтель с рисом, котлета с картошкой". Чёрт его знает, что это за банк такой.

Такие же или примерно такие всё так и норовят написать наци-а-нальную операционную систему, потому что "слышали" что "в Windows есть закладки". Как я устал этих технодикарей! "Так бы и убила паразита чем-нибудь!"

пятница, января 16, 2009

И вновь не сидится кое-кому на заднице

http://cnews.ru/news/top/index.shtml?2009/01/15/334523

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

1. Для чего это нужно?
2. Кто это будет делать?

1. Предлагаю принять за данность то, что это нужно для получения денег из госказны. Как показывает практика реализации проектов в области информационных технологий в нашей стране, it -- это идеальная тема для получения денег без необходимости их отрабатывать. Ну что там говорить, если в подземных паркингах людей выпускают, поднимая шлагбаум вручную, приняв талончик с пробитым на нём временем. Уж не говоря про Горбушку в г.-г. Москве - два дюжих молодца как из колодца качают - поднимают шлагбаумы на выпуске.

2. Кто это будет делать? Чем вообще славится Российская Федерация в плане информационных технологий? На что мы можем гордо показать и сказать миру - вот это сделали мы? А что если перечислить? Не так давно умер Донской. Один из авторов чёрт знает когда написанной шахматной программы. Никто кроме него и не помнил, что это сделал он, но примем с оговорками, что это было достижение хотя бы и своего времени. Дальше. Пажитнов написал "Тетрис". Хорошая игра. Но вообще-то Sierra, Atari и прочие писали в то время игры сотнями и тысячами. "Тетрис" это прорыв, но ему, как бы не соврать, опять же на днях будет 20 лет. Что ещё? "Лексикон"? На нём в мире никто не работал. Больше как будто и ничего. Про аппаратную часть скажу только "EC". Как говорится, "а сам плачу...".

С чего на этом фоне могла появиться мысль, что кто-то в нашей стране может осилить задачу написания коммерческой ОС? В техническом плане это не так сложно, как в идеологическом: ну как меня будут уговаривать отказаться от Windows? Просто запретят? Это смешно.

Ну и напоследок, кто продвигает эту идиотическую мысль? Илюша Пономарёв? Костик Бакулев, "зам. директора Московского городского центра инноваций и высоких технологий" (кто слышал в Москве за высокие технологии кроме как технологий кражи бюджетных денег на фиктивных тендерах и технологий пускания пыли в глаза? - не считать же московский аутсорсинговых рабов творцами высоких технологий, ей богу...)? Наш старый знакомый из "Престарелого Линуха" болтун и халявщик Лёшик Смирнов? Денег от государства хочет, а взамен дать ничего не может... "В том числе и поэтому, по словам Смирнова, в конце прошлого года властное одобрение инициативы «национальной ОС» ощущалось как «весьма вероятное» вплоть до выделения проекту финансирования". Ворята учатся у своих старших коллег. Блевотина какая-то. Вторяк гоношится как я не знаю, кто... ОС они писать захотели... И смех, и грех.

суббота, декабря 13, 2008

Моё стремление к гигантомании удовлетворено

Моя компания стала генеральным подрядчиком создания ИС федерального уровня, как и 4 года назад. Но в этот раз всё по-честному. Договора, ответственность и т.п.

Наконец-то появилась работёнка по нам.

четверг, августа 07, 2008

О проведении тендеров

Заявляю совершенно ответственно, что т.н. "госзакупки" в виде "тендеров", "аукционов" и т.п. - обман и коррупция в чистом виде. Как проводится типичный тендер (точнее, как проводится подсчёт баллов после вскрытия конвертов)? Нам это в красках рассказывает cnews. Я могу рассказать нечто похожее и даже не одно. Посмотрите на т.н. "интеграторов". Люди очумели от шальных денег, которые направо и налево в позе сеятеля швыряют чиновнички: что ни тендер "на разработку", то 20 и более миллионов. На ЦБД УИГ в 2004-2007 было потрачено не менее 300 (трёхсот!) миллионов рублей. Что получено взамен? Ничего. На разработку ЕГАИС - тоже дай бох всякому. Что взамен? Ничего.

Для чего проводятся конкурсы службами, министерствами и т.п.? Ответ в одно слово: воровать. С государством в этих "тендерах" можно связываться только в одном случае - если можешь повлиять на результат тендера: знаком, вместе отдыхали, служили, учились и т.п. Впрочем, можно занести куда надо и тоже решить вопрос, но таким я лично заниматься брезгую.

А вы сходите, посмотрите на то, куда утекают денежки: http://zakupki.gov.ru

понедельник, июля 21, 2008

Главное правило писателей Office Add-ins

Никогда не вызывать модальные формы из основного потока addin. А то с катаклизмами бороться некому. Билгейц уже не при делах.

воскресенье, июля 20, 2008

Как не надо

Всю неделю наслаждался всеми видами негодных интерфейсов. Пора раздать места.

3 МЕСТО
Душевому крану в гостинице Hotel An Der Oper. Открывается от себя, горячая и холодная вода поменяны местами.

2 МЕСТО
Одной дерьмовой программке навигации, которая вместо английского Navigate To... предлагает "Идти на точку". Моя жена, например, не поняла-  о какой точке идёт речь? Почему - на точку? Почему не "идти туда", что хоть и отвратительно коряво, но хоть как-то объясняет смысл операции.

1 МЕСТО
Уходит "Стриму". Это трудно объяснить, не показав. Но показать уже не смогу, поэтому на словах. Представьте себе, что у вас закончились деньги на телефоне и надо срочно пополнить счёт. Видели ли вы хоть один автомат оплаты, который требует назвать номер лицевого счёта (я своего не знаю, кстати), пароль на ИССА, АССА, ответ на контрольный вопрос и только после этого принимает деньги? Я - нет. Это дико и противоестественно. У меня есть постоянный идентификатор - номер телефона. +7910 и т.п. Точно так же и в Стриме - у меня есть номер домашнего телефона. Зачем мне знать что-то ещё? Но без этого не получится пополнить свой счёт - пришлось ехать в офис в субботу утром.

Человеческая лень и глупость так разнообразны, что я не перестаю удивляться.