пятница, апреля 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? Просто запретят? Это смешно.

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