вторник, 25 ноября 2008 г.

Windows Vista Bridge Sample Library

На TheVista.ru опубликовали интересную статью про Windows Vista Bridge Sample Library. Цитирую:
Windows Vista Bridge Sample Library (VBSL) является развитием одной из идей команды Microsoft SDK по созданию своеобразного моста между .NET framework и Windows API. VBSL является библиотекой классов, которая облегчает разработчикам управляемого кода доступ к наиболее важным функциям Windows Vista без необходимости заботиться об уровне взаимодействия. Vista Bridge 1.3 предлагает разработчикам набор классов, библиотек и примеров, написанных на .NET, которые позволяют разработчику использовать такие функции Vista, как UAC, Power Management, Restart & Recovery, Restart Manager, Network, Aero Glass и многие другие. Необходимо отметить, что управляемые библиотеки Vista Bridge 1.3 отлично работают и с Windows 7 API и будут работать в будущих релизах по мере того, как команда SDK будет продолжать поддержку данного проекта.
В частности, можно легко получить стандартные вистовские диалоговые окна, например такие:





четверг, 20 ноября 2008 г.

Некоторые популярные запросы в гугле :)

Вот тут еще много :) 

Для примера:

суббота, 15 ноября 2008 г.

Работа с потоками

Что делать, если хочется оптимизировать программу научив ее работать с несколькими потоками, а стандартный BackgroundWorker помочь не может (как минимум потому, что создает только 1 поток)? Например, если хочется распараллелить цикл на максимально-доступное количество потоков в соответствии с текущим процессором?

Можно это сделать разными сложными путями, например, используя класс Thread. А можно пойти простым путем. Вот про него-то я и расскажу ниже.

Существует такой замечательный класс - ThreadPool. Во-первых, он умеет запускать именно столько потоков, сколько можно на текущей машине, а остальные ставит в очередь. А во-вторых, он позволяет просто решить проблему с ожиданием окончания работы запущенных потоков.

Добавить новый поток в очередь очень просто:
ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandle);
где метод DoTask:
void DoTask(Object state)
причем параметр waitHandle передается как Object state, но об этом попозже.

Дождаться завершения работы всех потоков можно вот так (на самом деле там куча вариантов - читайте документацию):

WaitHandle[] waitHandles = new WaitHandle[] { waitHandle };
WaitHandle.WaitAll(waitHandles);
Самое замечательное, что можно дожидаться завершения любого из потоков:


WaitHandle[] waitHandles = new WaitHandle[] { waitHandle };
WaitHandle.WaitAny(waitHandles);
Ну и последнее - про переменную waitHandle. Если ее проинициализировать вот так:
WaitHandle waitHandle = new AutoResetEvent(false);
... то в теле нашего метода DoTask можно будет (даже нужно!) оповестить о том, что метод завершил свою работу. Примерно вот так:


AutoResetEvent are = (AutoResetEvent)state;
are.Set();
Ну вообщем-то и все :) Пользуйтесь. Естественно, что от всех "прелестей" многопоточного приложения это вас не спасёт.

P.S.: пытался заставить мой переводчик переводить каждое предложение в отдельном потоке (точнее по два предложения за раз) - глухо. Где-то идут конфликты в обращениях к данным и в итоге код, который раньше в одном потоке работал без ошибок начинает падать. Причем очень странно падать - сообщения вида NullRefernceException при том, что там, куда указывает отладчик - null-значений вообще нет и взяться им неоткуда. Мистика :(

Никто не встречал программы, которая могла бы проанализировав код ткнуть пальцем и сказать, что вот тут и тут работать не будет в многопоточном приложении? Ибо перелопатить текущий код просто нереально - дешевле с нуля написать :(

четверг, 13 ноября 2008 г.

RTFStringBuilder

Вот здесь есть класс, основанный на StringBuilder и предназначеный для генерации RTF при вызове метода ToString(). Очень удобно тем, кого не устраивает генерация текстов в формате rtf с использованием RichTextBox (а это произойдет очень быстро - как только вы начнете активно использовать раскраску слов/букв разными цветами или разные шрифты).

Примеры использования:

RTFBuilderbase sb = new RTFBuilder();
sb.AppendLine("AppendLine Basic Text");

sb.Append("append text1").Append("append text2").Append("append text3").Append("append text4").AppendLine();

sb.FStyle(FontStyle.Bold).AppendLine("Bold");

sb.FStyle(FontStyle.Italic).AppendLine("Italic");

sb.FStyle(FontStyle.Strikeout).AppendLine("Strikeout");

sb.FStyle(FontStyle.Underline).AppendLine("Underline");

sb.FStyle(FontStyle.Bold | FontStyle.Italic | FontStyle.Strikeout | FontStyle.Underline).AppendLine("Underline/Bold/Italic/Underline");

sb.ForeColor(KnownColor.Red).AppendLine("ForeColor Red");

sb.BackColor(KnownColor.Yellow).AppendLine("BackColor Yellow");
string rtf = sb.ToString();
this.richTextBox1.Rtf = rtf.

// Merging an RTF Document is sublimely simple
sb.AppendRTFDocument(this.richTextBox4.Rtf);

//Inserting an Image - again very simple
sb.InsertImage(image);

среда, 12 ноября 2008 г.

Windows RSS Platform

Возможно кто-то еще не знает, но с выходом Internet Explorer 7 появилась т.н. Windows RSS Platform. Это набор API позволяющий получить доступ к тем rss-записям, что загрузил IE7. Подробно про API можно почитать здесь (на английском), а пока несколько примеров.

Объектная модель вот такая:



Получить полный список каналов можно вот так:
        public void FillTree()
        {
            IFeedFolder iff = ((IFeedFolder) fm.RootFolder);

            treeView1.BeginUpdate();
            AppendFeeds(iff, null);
            treeView1.EndUpdate();
        }

        void AppendFeeds(IFeedFolder folder, TreeNode parent)
        {
            TreeNode old_parent = parent;


            foreach (IFeedFolder subfolder in (IFeedsEnum)folder.Subfolders)
            {
                if (parent == null)
                    parent = treeView1.Nodes.Add(subfolder.Name);
                else
                    parent = parent.Nodes.Add(subfolder.Name);
                AppendFeeds(subfolder, parent);
            }

            parent = old_parent;

            foreach (IFeed feed in (IFeedsEnum)folder.Feeds)
            {
                if (parent == null)
                    treeView1.Nodes.Add(feed.Name);
                else
                    parent.Nodes.Add(feed.Name);
            }
        }

В данном случае я заполняю данными TreeView, поскольку в общем виде мы имеем древовидную структуру, если вспомнить про возможность распределять каналы по папкам и подпапкам. Соответственно, самый простой способ - рекурсивная функция.

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

IFeed feed = (IFeed)fm.GetFeed(e.Node.FullPath);

Ну а дальше ничего сложного :)

пятница, 7 ноября 2008 г.

Новая утилита для анализа кода - StyleCop

Вот тут рассказывают про новую утилиту от Microsoft для проверки кода - StyleCop. Интересно в ней то, что в отличие от теперь уже стандартного FxCop'а она проверяет C#-код, а не IL-код. Например, вот так:
Вообщем, всем смотреть и пробовать :)

четверг, 6 ноября 2008 г.

среда, 5 ноября 2008 г.

Способ обнаружения deadlock'ов

Вот здесь пишут как можно быстро обнаруживать deadlock'и в своем приложении. Хотя меня сейчас больше интересует как бы проанализировать приложение на потенциальные неправильности в коде, которые помешают его сделать многопоточным....

Полезная утилита

Оказывается в Vista встроили замечательную программу Robocopy. Ранее она была частью Windows Resourse Kit. Подробнее можно почитать здесь (на английском).

Основные возможности:

  • Автоматическое восстановление сетевого соединения при обрыве
  • Копирует атрибуты файлов, права доступа, файловые потоки и т.п.
  • Зеркалирование - т.е. автоматическое копирование/удаление папок/файлов так, чтобы конечная папка содержала те же файлы, что и исходная.
  • Индикатор прогресса :)

Вообщем, must use.

понедельник, 3 ноября 2008 г.

Про новую студию и С# 4.0...

Если кому интересно - вот тут есть немного скриншотов новой Visual Studio 2010, а также немного рассказывается про новое в C# 4.0.

пятница, 31 октября 2008 г.

Вообщем, все плохо...

Мир тонет в информации:

За 2006 год в мире создано около 161 млрд. гигабайт (161 экзабайт) цифровой информации. Такие данные обнародовали эксперты аналитической компании "IDC". 
Как передает радио "Свобода", при подсчетах учитывались данные всех фотографий, видеороликов, сообщений электронной почты, Интернет-сайтов, мгновенных сообщений, телефонных звонков и всех других цифровых источников информации на нашей планете. Предполагается, что каждый цифровой файл воспроизводился в среднем три раза. Для наглядности специалисты сравнили объем созданной цифровой информации с 12 книжными стеллажами, каждый из которых имеет длину, равную расстоянию от Земли до Солнца.
Согласно прогнозам, объем информации в 2010 вырастет более чем в 6 раз и достигнет 988 экзабайт. Одной из причин очень быстрого роста информации специалисты называют распространение камер слежения, а также требования к хранению множества корпоративных данных. 
Представляете насколько поток информации увеличился к 2008 году?

Вот я все rss-ки читаю через Google Reader. Если по какой-либо причине я им не пользуюсь пару дней, то там набирается порядка 800-900 сообщений. Прочитать это физически невозможно: пока читаешь старые - приходят новые...

И вот смотрю я на записи с PDC 2008 и удивляюсь - где же хоть что-нибудь, что поможет справиться с потоками информации именно человеку, а не машинам?

Я хочу, чтобы все электронные книги, что я читаю, были сосредоточены в одном хранилище (с соответствующими требованиями к каталогизации/поиску/добавлению) так, как это сделано с музыкой в том же Windows Media Player (не без проблем, конечно - но хоть так).

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

Причем речь не идет о тупом информировании - как это делается сейчас через почтовые рассылки или rss. Нет, нет и нет! Вот представьте, что вы подписались на rss-рассылку, анпример, какого-нибудь музыкального магазина. В день в будете получать несколько десятков (если не сотен) сообщений о поступлениях новых альбомов. И когда это все читать? А если учесть, что многих интересуют только пара десятков любимых групп, а остальных они не слушают? Или наоборот - как у меня - у человека есть коллекция музыки в 2-3 тысячи исполнителей/групп, все имена/названия которых запомнить в принципе невозможно?

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

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

Я хочу, чтобы новости, которые я читаю можно было бы сгруппировать по степени важности для меня, а не в порядке их появления.

Я хочу... Я хочу... Я хочу... Да много чего еще. И где это все? Ведь никаких технических проблем реализовать это нет! Веб-сервисы, локальная БД, и немного фантазии - и всё. И никаких проблем. И я не буду тратить половину жизни на всякую фигню.

А вместо этого Microsoft мне предлагает отказоустойчивыю платформу под софт. Да нафиг не надо! Я маленький программист - у меня нет таких задач, для которых это имело бы смысл.

Вообщем, такие дела...


Ну а поскольку пока что ничего подобного нет, начем с малого.

Предлагаю разарботать читалку rss-рассылок с автоматической категоризацией новостей. Принципиальных сложностей никаких нет, готов взяться за алгоритм категоризации - тем более, что 80% его можно взять из переводчика.

вторник, 28 октября 2008 г.

Visual Studio 2010 and .NET Framework 4.0 Community Technology Preview (CTP)

PDC 2008 дает свои плоды: Visual Studio 2010 and .NET Framework 4.0 Community Technology Preview (CTP) уже доступны для скачивания. Раздают в виде образа виртуальной машины. Правда некоторые требования меня несколько смущают - в частности "Minimum 75 GB available HDD space" :)


P.S.: Кстати, трансляции с конференции можно скачать тут (день №1) и тут (день №2).

суббота, 25 октября 2008 г.

Вот такие дела...

Сегодня нашел "лишние" 100 Гб свободного места... Некоторое время назад обратил внимание что как-то маловато места стало на одном из разделов. При том, что на разделе 200 Гб, свободного места порядка 40. Ну на него пишут разные программы типа utorrent так что грешил на них.

А сегодня решил его дефрагментировать и обнаружил 100 гигабайтный файл в "System Volume Information", причем еще и залоченный и разбитый на несколько десятков тысяч фрагментов.

Ну что это за папка я знаю. По привычке полез в Мой компьютер->Свойства->Advances System Settings->SystemRestore и что бы вы думали? Ну кто бы что не подумал - а такой вкладки у меня в Windows Server 2008 почему-то нет. Мистика.

Так собственно о чем я? Если кто-нибудь столкнется с подобной ситуацией, сообщаю, что изменить размер этой папки можно из командной строки:

vssadmin resize shadowstorage /for=H: /on=H: /maxsize=2Gb


Примечание: пишут, что минимальный размер папки для Vista должен быть 500 Мб.

вторник, 21 октября 2008 г.

И снова баги...

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

А дело было так.

Правлю я там там что-то в переводчике связанное с интерфейсом взаимодействия между GUI и плагинами и в процессе тестирования вижу странное.

Берем предложение и переводим, получаем два варианта перевода. Все как ожидалось:


А теперь берем и делаем второй вариант перевода предложения основным (т.е. первым в списке переводов):


Упс! А текст-то не тот!

Надо заметить, что алгоритм сортировки вариантов перевода предложений в соответствии с предпочтениями пользователя крайне примитивен - все выбранные предложения хранятся в специальном списке. При переводе текста, по окончании процесса перевода полученные в итоге варианты сортируются. Вообщем, ну никак сортировка не может повлиять на перевод - она осуществляется в конце!

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

И совершенно случайно я все-таки нашел в чем была проблема... Вы не поверите.

Итак, где-то в классе TextTranslator (отвечающем за перевод текста) есть такой код:

            for (k = 0; k < ersent.rus.Count;k++ )
                RunProccessRVariantQueue(ersent.rus, par, sent, k);

... который в итоге вызывает такую функцию:

        static void RunProccessRVariantQueue(List<trstr> snt, int par, int sent, int variant)
        {
            for (int i = 0; i < ModulesFactory.Instance.rvar_proccess_queue.Count; i++)
            {
                ((IRStrVariantProcessor) ModulesFactory.Instance.rvar_proccess_queue[i].obj).ProcessRStringVariant(snt, variant, par, sent);
            }
        }

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

Ну и вот, чтобы не допустить ошибок при сортировке и лишних потерь в производительности, функция ProcessRStringVariant модуля сортировки начинается со строчки:


            if(variant != 0) return;

... что по идее должно было заставлять выполнять сортировку один раз. И оно даже работало. Но с одним интересным побочным эффектом.

Не вдаваясь в детали, скажу, что цепочка вызовов модулей обрабатывающих эти самые варианты перевода предложения состоит из двух элементов: модуля склоения и модуля сортировки. Что же происходило и почему в итоге возникала ошибка? Рассмотрим пошагово работу алгоритма:

Итерация №1
Вызов модуля склонения для варианта №0
Вызов сортировкщика. В сортировщике стоит указние, что надо вариант с нормером 1 поставить в начало списка (т.е. сделать его номером 0).

Итерация №2
Вызов модуля склонения для варианта №1
Сортировщик ничего не делает, т.к. вариант !=0

Так вот, на итерации №1 мы имеем что? Правильно! Тот же самый вариант, что и на итерации №0, т.к. сортировщик свое дело сделал :) В результате, второй вариант перевода не склонялся.

Решением проблемы оказалась замена приведенного выше условия на следующее:

            if(variant!=Count-1) return;

Вот так вот... Два часа на поиск одной единственной строчки...

понедельник, 20 октября 2008 г.

Запись и чтение из файлов Excel при отсутствии установленного Excel

Получил на днях очередной бюллетень-молния Technet от Microsoft (кстати, интересная штука, кто еще не подписан - рекомендую. Такой же бюллетень есть и для MSDN). И были там две интересных ссылки: How Can I Write to Excel Without Using Excel? и How Can I Read from Excel Without Using Excel?

Собственно, идея очень простая - надо открыть OleDb-соединение и вперед, с песней :)

Берем вот такой .xls-файл:


Чтение данных делаем так:

            string fileName = @"test.xls";
            string sheetName = "Sheet$";
            string connString="Provider=Microsoft.Jet.OLEDB.4.0; Data Source = " +
                                       fileName +
                                       "; Extended Properties=Excel 8.0";
            string query = "Select * from [" + sheetName + "]";

            OleDbConnection conn = new OleDbConnection(connString);
            OleDbCommand cmd=new OleDbCommand(query, conn);
            conn.Open();

            OleDbDataReader reader = cmd.ExecuteReader();

            textBox1.Text = "";

            while (reader.Read())
            {
                textBox1.Text += System.Environment.NewLine;
                textBox1.Text += reader.GetString(0) + " ("+reader.FieldCount+")";
            }

            reader.Close();
            conn.Close();

Результат будет примерно таким:

А запись данных так:

            string fileName = @"test.xls";
            string sheetName = "Sheet$";
            string connString="Provider=Microsoft.Jet.OLEDB.4.0; Data Source = " +
                                       fileName +
                                       "; Extended Properties=Excel 8.0";
            string wquery = "Insert into [Sheet$] (Name,Data) Values (?,?)";

            OleDbConnection conn = new OleDbConnection(connString);
            OleDbCommand wcmd=new OleDbCommand(wquery, conn);
            conn.Open();

            OleDbParameter namep = wcmd.Parameters.Add("Name", OleDbType.VarChar, 80);
            OleDbParameter datap = wcmd.Parameters.Add("Data", OleDbType.UnsignedInt, 16);

            namep.Value = "aaa";
            datap.Value = 15;

            wcmd.ExecuteNonQuery();;

            conn.Close();

Результат, соответственно, такой:

Вот так вот всё просто. Я надеюсь, что найти где это можно применить сможете сами :)


пятница, 17 октября 2008 г.

Горячие клавиши Visual Studio

Вот здесь предлагают скачать список горячих клавиш Visual Studio (1,5 Мб).
Слабонервным не читать :)

четверг, 16 октября 2008 г.

Семантический анализ

Нашел интересный веб-сервис осуществляющий семантический анализ - http://opencalais.com/
Вроде бы даже работает. Для экспериментов можно воспользоваться соответствующим редактором. К сожалению, на тестовых текстах, что я попробовал (тех, на которых я тестирую переводчик) работает не особо хорошо - если в тексте больше одного имени/фамилии - распознает только одно из них. К тому же почему-то не всегда различает пол для местоимений he/she - и, соответственно, ошибочно соотносит их с именем.

воскресенье, 12 октября 2008 г.

Mono 2.0

Вышла новая версия Mono . Обещают совместимость с:
  • ADO.NET 2.0 API для доступа к базам данных.
  • ASP.NET 2.0 API для создания Web-приложений.
  • Windows.Forms 2.0 API — настольные приложения.
  • System.XML 2.0: API по управлению XML-документами.
  • System.Core: поддержка языка интегрированных запросов (LINQ).
  • System.Xml.Linq: LINQ-провайдер для работы с XML.
  • System.Drawing 2.0 API: графическое API.
  • Полная поддержка LINQ-запросов и реализация компилятора C# 3.0
Вообщем, кроссплатформенность всё ближе и ближе. Там, правда, 4-ый фреймворк уже не за горами...

Parallel Extensions

Вот здесь пишут, что "Parallel Extensions to the .NET Framework" будут включены в 4-ую версию .Net Framework. Тем, кто не в курсе, что это такое можно прочитать вот тут и тут.

Сравнение XBox360 и PS3

На мой взгляд интересное сравнение приставок XBox360 и PS3. Вывод пародоксален: при большей чуть ли не в два раза производительности у PS3 за счет худшей чем у XBox360 архитектуры она сильно проигрывает. Вообщем, как обычно - выигрывает та система, геморроя при работе с которой меньше :)

пятница, 10 октября 2008 г.

:)

Нашел на rdsn.ru:


using System;

static class A
{
    static void TоString(this int x)
    {
        Console.WriteLine("haha!");
    }
    static void Main()
    {
        1.TоString();
    }
}

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


Я, кстати, быстро догадался :)

Configuration Section Designer - дизайнер настроек

А вот эта штука многим может быть интересна - это плагин к Visual Studio позволяющий создавать конфигурационный файл (файл с настройками приложения) используя интерфейс a la Class Diagram:

Свершилось!

Мой переводчик опубликован на Codeplex'e. И даже с исходными кодами :) Правда не всё - отдельные части прогрыммы я пока что попридержу... Вообщем, кому интересно - качайте и мучайте :) В исходниках много-много комментариев, думаю часть вопросов снимет... Ну и конечно - пишите, помогу чем получится...

четверг, 2 октября 2008 г.

Интересная статья

Наткнулся на интересную статью "Is Google Making Us Stupid? ". Очень рекомендую (внимание - на английском). Собственно, гугл там ни при чем :) Речь идет о том, что чем больше мы пользуемся интернетом, тем сильнее меняется наше восприятие информации. И высказанные в статье мысли во многом пересекаются с тем, что я и сам стал замечать...

среда, 1 октября 2008 г.

Мой переводчик. Обновление

Выложил текущую версию переводчика (от 01.10.2008). Куча мелких изменений :)

Все ближе к релизу...

воскресенье, 28 сентября 2008 г.

Про мой переводчик. Структура.

Продолжение. Начало смотрим тут. 

Итак, как я уже писал ранее - переводчик является модульным, причем модули должны быть независимы друг от друга. Не то чтобы это было обязательным требованием, однако, чем более связаны между собой модули - тем сложнее их менять. Соответственно, данное требование накладывает определенные ограничения на сам процесс перевода. На данный момент он является линейным. Примерная блок-схема такова:

... правда семантического анализа у меня еще нет.

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

В процессе разработки был придуман следующий подход к процессу перевода предложений:

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

Как видно - получившийся алгоритм оказался жизнеспособным.

Вот так вот мутировал изначальный линейный алгоритм в процессе развития:

... синие блоки примерно соответствуют блокам на первом рисунке.

Ну и напоследок - степень завершенности ключевых модулей анализа:

Продолжение следует...

Grammar framework

Нашел некий Grammar framework с исходниками. Если я правильно понял, то основное что он умеет это склонять русские слова. Вообщем, надо смотреть - может и полезная штука :)

пятница, 26 сентября 2008 г.

:)

Чтение из файловых потоков у файлов на NTFS разделах

Как известно, файловая система NTFS позволяет в одном файле хранить т.н. потоки. Цитирую ixbt.com:

Каждый файл на NTFS, в общем-то, имеет несколько абстрактное строение - у него нет как таковых данных, а есть потоки (streams). Один из потоков и носит привычный нам смысл - данные файла. Но большинство атрибутов файла - тоже потоки! Таким образом, получается, что базовая сущность у файла только одна - номер в MFT, а всё остальное опционально. Данная абстракция может использоваться для создания довольно удобных вещей - например, файлу можно "прилепить" еще один поток, записав в него любые данные - например, информацию об авторе и содержании файла, как это сделано в Windows 2000 (самая правая закладка в свойствах файла, просматриваемых из проводника). Интересно, что эти дополнительные потоки не видны стандартными средствами: наблюдаемый размер файла - это лишь размер основного потока, который содержит традиционные данные. Можно, к примеру, иметь файл нулевой длинны, при стирании которого освободится 1 Гбайт свободного места - просто потому, что какая-нибудь хитрая программа или технология прилепила в нему дополнительный поток (альтернативные данные) гигабайтового размера. Но на самом деле в текущий момент потоки практически не используются, так что опасаться подобных ситуаций не следует, хотя гипотетически они возможны.


Так вот, здесь рассказывают как работать с этими потоками используя C#.

Поиск

Товарищи! А не кажется ли вам что Google последнее время стал искать хуже? Ну не то чтобы совсем уж плохо - не получается ткнуть пальцем и сказать, что "вот раньше находил, а теперь нет!". Но уже не первый раз замечаю, что последнее время частенько отсутствует реакция на знаки + и - перед словами. Слова, заключенные в кавычки, зачем-то разделяются и ищутся по отдельности и т.п.

На некоторые запросы вообще выдается такой бред - круче Рамблера :( Попробуйте, например, найти информацию о том, какой у нас в стране срок за геронтофилию. Нет, ну я, конечно, понимаю, что вопрос дурацкий - но вот как-то на работе народ заинтересовался и что? А ничего! Фигни много - полезного так и не нашли...

И последнее время такое все чаще...


Странно это всё...

пятница, 19 сентября 2008 г.

Обновления Google Chrome

Если интересно узнать, что именно изменилось в обновленной сборке Google Chrome - можно почитать блог Google Chrome Releases

вторник, 16 сентября 2008 г.

Про мой переводчик. История.

Вместо предисловия



Давным-давно, аж в далеком 2002 году я совершенно случайно наткнулся на книжки замечательной писательницы Лорел К. Гамильтон. На тот момент на русский язык были переведены только первые 6 книг из серии про Аниту Блейк.

В то время я уже отказался от чтения современной американской фантастики и фэнтези ввиду их примитивности (в сравнении с отчественными). Поэтому вдвойне удивительно то, что эти книжки так меня увлекли, что я полез в сеть в поисках продолжения :) Которое и нашел на фанатском сайте.

Но радость была недолгой - пятая книга, переведенная силами фанатов обрывалась (по закону подлости) на самом интересном месте.

К счастью - в наличии был английский текст книжки и даже еще две книги-продолжения :)

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

И я совершил страшное. Я запустил ПРОМТ и перевел книжку...

Не буду говорить что из этого получилось, но результат можно было читать. Главное - не заострять внимание на том, как написано, а пытаться понять что написано :) При некотором опыте читать - можно.

При чтении я как-то обратил внимание, что, в принципе, основные ошибки перевода ПРОМТа - это ошибки склонения слов (естественно, в тех случаях, когда предложение было разобрано верно).

Вот тогда-то и появилась идея (нет-нет, не переводчика!) программы-корректора, которая бы подправляла текст, сгенерированный ПРОМТом.

Примечание: в то далекое время я еще ничего не знал про Microsoft .Net Framework. Да и был он в стадии "почти релиза" и особо нигде не упоминался. Так что писал на том, что знал - C++ Builder 6.0.



Этап №1



Была написана маленькая программа, со своим словарем слов, которая заменяла отдельные слова на альтернативные. Изначально хотелось увидев "неправильное" слово или словосочетание заменить их на "правильное".

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

Стало понятно, что необходим собственный алгоритм построения склонения/спряжения слов. Алгоритм был написан и успешно заработал. Причем он оказался настолько успешным, что без особых изменений переползал из версии в версию и существует и используется и поныне :)

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



Этап №2



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

Именно тогда родился тот подход к синтаксическому анализу, который я использую и сейчас. Как раз тогда я впервые прочитал про регулярные выражения (regexp) и подумалось: "да это же самый простой способ определить вид предложения!".

Сам алгоритм анализа основанный на регулярных выражениях был написан всего за 4 часа. А вот уже загрузчик правил писался долго и муторно. Достаточно сказать, что пока я не начал использовать формат xml для хранения этих правил анализа алгоритм чтения файла с правилами продолжал глючить и падать от малейшего чиха. И это при том, что он постоянно правился в течение нескольких месяцев! Именно после этого я так невзлюбил Си++...

Кстати, та самая реализация алгоритма анализа до сих пор вполне успешно используется :) Ну понятно, что она нексколько мутировала, но все-таки...



Этап №3



Где-то в районе 2004-го года мне попадается интересная статья про Mono. И как-то руки зачесались попробовать :) А там как раз стало понятно, что Mono и .Net Framework - братья. А там и SharpDevelop попался... Вообщем, был написан тестовый редактор правил - благо правила уже давно хранились в формате xml, поэтому, фактически, писалась оболочка.

И как-то оно всё так хорошо пошло, что буквально за неделю весь проект переполз на C#. Я сам не ожидал, честно :) Ну не без глюков, конечно... Но в целом - изменения в коде были минимальные и в основном касались работы со строками.

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



Этапы №4 и далее



Становится понятно, что то, что получилось, в принципе, даже работает. И где-то даже правильно. И вообще...

Система довольно длительное время развивается пока не упирается в принципиальный тупик: разбора только одного варианта предложения недостаточно. Вероятность ошибки неверного разбора предложения прямо зависела от того, вариант какой части речи стоял у слова в словаре первым.

Поэтому был добавлен маленький кусочек кода из-за которого пришлось переписывать половину программы :) А занимался он генерацией вариантов предложений. Основная идея - в предложении каждое слово имеет варианты перевода только одной части речи.

Примерно тогда же становится понятно, что при таком подходе легко можно получить агромаднейшее количество вариантов предложения. Главное в него подсунуть правильные слова с несколькими переводами разных частей речи (и побольше, побольше!).

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

Примечание: Например, если после артикля the стоит слово - это слово 100% не глагол. И т.д и т.п.

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



Этап №14



Худо-бедно система развивалась, пока я не уперся в потолок - каждое последующее изменение требовало все больше и больше усилий. Я думаю, многим это знакомо.

Это было страшное время :( Когда понятно, что надо сделать, но непонятно как это сделать так, чтобы ничего не сломалось...

Поэтому в начале 2006-го года было принятно решение все переписать :)

Программа была переписана полностью с нуля. Т.е. вообще всё с нуля. Естественно, часть старого кода переползла в новую версию, но все пережитки вызванные предыдущим бурным развитием безжалостно уничтожались...

Какое-то время удавалось поддерживать новую версию на плаву... Пока я не уперся в тот же самый потолок.



Этап №15



Собственно, деваться было некуда и пришлось полностью менять подход к созданию крупных программ. Благо уже "созрел".

К лету 2006-го стало понятно, что надо делать модульную систему. К такому решению подталкивало два фактора:

  • во-первых, по своей структуре она уже была модульной. Осталось только реализовать динамическую загрузку и переделать основную часть программы (ядро) под более абстрактный код.
  • во-вторых, пришло понимание, что написать переводчик полностью силами одного человека - задача из области фантастики. Использование же модулей позволяет распределить отдельные части задачи между разными разработчиками.


Практически год потребовался на полную переделку программы. Конечно, основной причиной столь длительного срока было угасание интереса - в основном из-за понимания насколько много придется переписывать заново. И желания это делать как-то не наблюдалось :)

В конце-концов, процесс подошел к своей конечной стадии. По пути программа лишилась удобного интерфейса выбора варианта перевода предложения и алгоритма поиска фраз (который был хоть и кривой и недоделанный, но все равно - жалко). Нет-нет! Они не совсем умерли. Просто пока что руки не доходят реализовать их по-новому - надо сначала доделать то, что важнее.

Зато появилось много чего нового и интересного :)

В конечном итоге - оно того стоило.



Продолжение следует...

четверг, 11 сентября 2008 г.

понедельник, 8 сентября 2008 г.

Отображение иконок для зарегистрированных типов файлов

Учитывая что тема про системные иконки является чуть ли не самой посещаемой в блоге решил поделиться еще одной полезной ссылкой на эту тему.

Вот здесь рассказывают как получить иконки для зарегистрированных в системе типов файлов.

пятница, 5 сентября 2008 г.

Жуть какая...

А бывают и вот такие извращения. Это компилятор C# в 16-ти битный код для MS-DOS. Выходной формат - .com-файл.

Вообще, конечно, интересно. Но все равно - извращение :) 25392226.a5e351c855901a7acefacc6448e97458.1221637119.f9852a452174cf0405f79164021d6cbe

среда, 3 сентября 2008 г.

Вы все еще не верите в безопасность? Тогда мы идем к вам!

Специалист по интернет-безопасности Авив Рафф (Aviv Raff) заявил, что нашел уязвимость в новом браузере Chrome компании Google.

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


А ведь прошло меньше суток... Для скачивания браузер был выложен где-то после 23:00 2-го сентября 2008.

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

среда, 27 августа 2008 г.

Type Forwarding и не только

Представьте что вы разрабатывается крупный проект состоящий из большого количества сборок. И все они, например, ссылаются на какую-то вашу или - что хуже всего - чужую сборку с нужным вам классом. И все было замечательно, пока в результате очередного рефакторинга вам не понадобилось выделить тот самый класс в отдельную сборку. Но! Ведь куча проектов ссылается на эту несчастную сборку и что, теперь во всех из них добавлять новую сборку?

Можно, конечно, и так. Но лень :) Тут-то нам и приходит на помощь Type Forwarding!

Type Forwarding позволяет в нашей главной сборке указать, что нужный нам класс находится в другой .dll, при этом все остальные сборки по-прежнему будут считать, что наш класс объявлен в главной сборке.

Показываю на пальцах:

  • Создаем два проекта MainDll и SecondDll
  • Добавляем в список зависимостей SecondDll в проекте MainDll
  • Объявляем какой-нибудь класс MyClass в SecondDll
  • В MainDll добавляем такой код в файл AssemblyInfo.cs:
    [assembly:TypeForwardedToAttribute(typeof(MyClass))] 
  • Компилируем всё что получилось
А теперь создаем какой-нибудь проект и добавляем в список его зависимостей ТОЛЬКО MainDll.dll и добавляем код вида:
MyClass mc = new MyClass();

Компилируем, запускаем, любуемся :)

Вообще, указанный метод полезен скорее для разработчиков библиотек и фреймворков.

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

Вы спросите - зачем? А затем, что если вдруг понадобится сменить библиотеку на другую, которая меньше глючит или обладает большей функциональностью - изменения в проекте коснутся только нашего прокси-класса, а не всего-всего проекта вообще.

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

Более того, похожий подход я применил и при работе с медиабиблиотеками iTunes и Windows Media Player. Даже несмотря на то, что часть функций (в частности поиск по не полному имени артиста/песни) в медиабиблиотеке Windows Media Player не работала.

суббота, 16 августа 2008 г.

Еще немного про Enum

Вот здесь можно прочитать как научить PropertyGrid отображать "человеческие" названия Enum'ов в выпадающих списках. Не так чтобы уж совсем просто, но работает :)

понедельник, 11 августа 2008 г.

Зарелизилось!

Вышли .NET Framework 3.5 SP1 ("всего" 231 Мб) and Visual Studio 2008 SP1 (831 Мб). Вообщем, скромно, учитывая размеры СП1 к Висте :)

суббота, 9 августа 2008 г.

Вывод "человеческих" имен Enum с помощью Extension Metods

В прошлом году я писал как можно реализовать вывод пользователю не внутренних имен перечислений (Enum'ов), а более человеческих, причем привязать эти самые человеческие имена к самим перечислениям.

Сегодня, вооружась новыми технологиями, я расскажу как можно сделать то же самое используя методы-расширения (Extension Metods).

Во-первых, нам понадобится следующий код:

[AttributeUsage(AttributeTargets.Field)]
public class EnumDescriptionAttribute: Attribute
{
    public readonly string description;

    public EnumDescriptionAttribute(string description)
    {
        this.description = description;
    }
}

public enum etest
{
    [EnumNameAttribute("Значение 1")]
    value1,
    [EnumNameAttribute("Значение 2")]
    value2,
    …
}
Здесь мы определяем атрибут, который отвечает за человеческие имена элементов перечисления и, собственно, само перечисление, которое мы и будем выводить пользователю. Нам понадобится вот такой класс:


public static class Specials
{
        public static string GetHumanName(this Enum p)
        {
            return ((EnumNameAttribute)p.GetType().GetField(p.ToString()).GetCustomAttributes(typeof(EnumNameAttribute), true)[0]).name;
        }
}
И теперь в нашем коде мы можем писать вот так:

Console.WriteLine(etest.value1.GetHumanName());
что на мой взгляд намного удобнее кода вида:

Console.WriteLine(Specials.GetHumanName(etest.value1));
Хотя, конечно, без "Правая кнопка мыши->Go To Definition" понять откуда у Enum'ов взялась функция GetHumanName будет сложновато :)

среда, 6 августа 2008 г.

Extension methods (методы-расширения)

Одной из очень интересных фич .Net Framework 3.0 являются extension methods (методы-расширения).

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

  • Можно наследовать от исходного класса новый класс и писать нужные методы в дочернем классе, но у этого подхода есть явный минус: мы не можем использовать эти методы для экземпляров базового класса.
  • Можно создать статический метод, принимающий этот объект, над которым необходимо сделать какие-то операции. Плюс этого подхода в том, что мы можем использовать наш метод для экземпляров базового класса, но минус в том, что код начинает напоминать процедурный подход.


Следует заметить, что первый вариант недоступен в случае sealed-класса.

В C# 3.0 появляется возможность писать статические методы, но вызывать их как методы, принадлежащие исходному классу:

static class MyDateTimeExtensions
{
        public static string ToMyDate(this DateTime date)
        {
            return date.AddDays(1).ToLongDateString();
        }
}
Вызов будет, например, таким:

MessageBox.Show(DateTime.Now.ToMyDate());

Всё это, конечно, хорошо... Кроме того, что хочется использовать такую же функциональность в старых C# 2.0 проектах. Однако компилятор матерится и не компилирует. Но хочется. А как известно - если чего-то нельзя, но очень хочется - значит можно :)

Как оказалось - использование extension methods возможно после применения небольшого "хака" :) В проект необходимо добавить следующий код:

namespace System.Runtime.CompilerServices  
{  
  [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]  
  public class ExtensionAttribute : Attribute  
  {  
  }  
}

После чего приведенный выше пример начнет успешно компилироваться и - самое главное! - даже работать в проекте C# 2.0.

среда, 30 июля 2008 г.

Базы данных для семантического анализа

Вот здесь можно скачать базы данных, которые потенциально можно использовать в алгоритмах семантического анализа. Базы созданы на основе википедии и содержат 2.18 миллионов понятий, включая информацию о 80,000 людях, 293,000 местах, 62,000 музыкальных альбомах и 36,000 фильмах. Кроме того, в DBpedia содержится порядка 218 миллионов триплетов (см. RDF).

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

Вообщем, пока поставлю в планы как "посмотреть" :) Хочется сначала доделать основноую часть переводчика. Конец уже близок...

вторник, 29 июля 2008 г.

Обзор Microsoft Live Mesh

Очень интересная статья про Microsoft Live Mesh. Вещь выглядит интересно, хотя возникает чувство, что из этого можно выжать еще больше. Но самый смак - в конце статьи, а именно то, что Live Mesh позволяет поключиться к рабочему столу удаленного компьютера (да-да! терминальный доступ! из браузера!) даже в случае если он наглухо закрыт фаерволлами и вообще не имеет внешнего ip адреса.

понедельник, 28 июля 2008 г.

Работа с потоками в c#

Пожалуй лучшая статья (часть 1, часть 2), которую я читал про работу с потоками в c#.

среда, 23 июля 2008 г.

Еще немного про сохранение настроек приложения

Старый пост на эту тему вот уже почти год как находится на вершине списка самых посещаемых страниц блога :) К сожалению, там я забыл упомянуть о том, что надо делать если вы используете для сохранения настроек класс Settings и обновили ваше приложение. Как на машине пользователя перенести настройки из старого конфигурационного файла в новый?

Ответ прост - метод Properties.Settings.Default.Upgrade() сделает все за вас!

Остается решить еще одну проблему - когда надо вызывать метод Upgrade()?

Как один из вариантов я предлагаю хранить в настройках версию сборки нашего приложения. Если текущая версия вдруг перестанет совпадать с сохраненной - это и означает, что надо вызвать метод Upgrade().

Возможно есть и другие способы - пишите, я добавлю :)

вторник, 22 июля 2008 г.

Еще одна библиотека для работы с почтой

Нсли вдруг кого не устраивает предыдущая библиотека, то вот еще одна:

C#Mail is a library to send or receive mail written by C#.

The basic class of Message is 
1---InternetTextMessage class(RFC822)
2---MimeContent class(RFC2045-RFC2049) 
3---MailAddress class( "MyName" ) 

Pop3 functionality list is ...
1---Authentication (Plain,A-Pop)
2---TCP-IP and SSL 
3---Asynchronous request and response 
4---All Pop3 command is represented as class
5---Retr command and Pop3Message class

Smtp functionality list is ...(sorry,some of them is under construction...)
1---Authentication(Plain,Login,CRAM-MD5)
2---TCP-IP and 
3---All Smtp command is represented as class


P.S.: не тестировал. Используйте на свой страх и риск :)

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

Отображение новых диалогов открытия/сохранения файлов под Vista

Наверняка вы столкнетесь с отображением не того диалога открытия или сохранения файла под Vista. Собственно отличие диалогов хорошо видно на скриншотах:



Есть несколько способов решения проблемы отображения правильного диалога. На мой взгляд, самым простым является использование вот этой библиотеки, которая позволяет вызывать стандартные для Висты диалоги открытия и сохранения файла, выбора папки, TreeView, ListView, Command Links

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

Обновление переводчика от 20.07.2008

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

воскресенье, 13 июля 2008 г.

Обновление переводчика от 13.07.2008

Итак, последнюю на данный момент версию можно взять тут.

  • Убрал использование сторонних алгоритмов анализа.
  • Убрал редактор скриптов на C# и модуль анализа - теоретически использовать можно, практически же то, что было, намного удобнее.
  • Дописан модуль добавления в словарь переводов слов напрямую из редактора-переводчика.
  • Подчищен код во всех файлах проекта. Исправлены мелкие недочеты.
  • Добавлены интерфейсы IOpenFormatConverter, ISaveFormatConverter через которые реализуется процесс чтения/сохранения данных в разных форматах.
Пожалуй скоро уже можно будет и код с документацией выкладывать... Вот доделаю еще немного...

суббота, 12 июля 2008 г.

Упрощение доступа к значениям в IDictionary

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

вторник, 8 июля 2008 г.

Переводчик

Как-то вдруг неожиданно появилось желание доделать переводчик. Не могу предсказать как долго оно у меня будет, но уже сейчас есть несколько существенных изменений. В частности, наконец-то доделал механизм загрузки/сохранения файлов в нужном формате, причем список поддерживаемых форматов определяется только наличием соответствующих модулей.

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

Вообще, хотелось бы наконец довести до ума "внешнюю" часть переводчика. Потому что смотреть на тот код, что используется в пользовательском интерфейсе (особенно в самом редакторе-переводчике) просто страшно. Кажется, что проще написать с нуля, чем понять как ЭТО вообще может работать :) Болезнь роста...

Больше всего меня удручает то, что я так и не придумал более-менее нормального варианта взаимодействия модулей с пользовательским интерфейсом. Нужно, чтобы модули могли добавлять свои пункты главного и контекстного меню, кнопки на панели и свои панели. Но вот как правильно это надо делать я так и не нашел. Если кто поможет советом - буду сильно благодарен.

Немного картинок:

понедельник, 7 июля 2008 г.

А счастье было так близко... Снова про Эльбрус

Cnews.ru опубликовал еще одну статью про отечественный микропроцессор. Ну что я могу сказать? Лет 10 назад это еще было бы ничего. Сейчас - описанные характеристики (130 нм техпроцесс и 300 мгц частота процессора) вызывают, мягко говоря, удивление.

Из интересного стоит отметить встроенный в процессор эмулятор x86-команд и значительно бОльшая производительность при вещественных вычислениях. Как заявляют разработчики:

«Мы не говорим, что «Эльбрус» быстрее Pentium’а, но при вещественных вычислениях он при своих 300 MHz показывает производительность аналогичную Pentium’ам с частотой 500 MHz — 1,5 GHz в зависимости от задачи»

P.S.: Остается надеяться на дальнейшее развитие по примеру китайцев с их процессором. Тогда лет через 15 при всемерном содействии государства есть некоторые шансы догнать ведущих разработчиков. Чудеса иногда все-таки случаются...

Полезные утилиты

Вот тут пишут про две утилиты, которые умеют генерировать код на С# и VB.NET для вызова native функций в .net приложениях. Может кому пригодится...

понедельник, 30 июня 2008 г.

"Эльбрус" жив!

А отечественный процессор "Эльбрус" оказывается еще жив, если верить вот этой новости...

P.S.: Вот как-то не верю я, учитывая как он создавался... Вот когда первые железки начнут поставляться - тогда да, поверю.

четверг, 26 июня 2008 г.

пятница, 20 июня 2008 г.

Ура!

С момента появления Windows 95 искал комбинацию клавиш для разворачивания текущего активного окна на весь экран. Потому что логично - раз есть комбинация Win+M и Win+D, то должна быть и их противоположность :) Оказалось, что искомая комбинация - Alt+Space+X.

P.S.: блог не умер - просто я в отпуске и ничего особо интересного не происходит...

воскресенье, 1 июня 2008 г.

Вычисления с помощью GPU

Совершенно случайно обнаружил вот эти интересные проекты:

Нейронная сеть на GPU
Кластеризация документов

Интересно в них то, что все вычисления выполняются на графическом процессоре. Средний прирост производительности - примерно в пять раз!

P.S.: а фреймворка для C# еще нет :( Пока что более-менее работающее решение - написать вспомогательную dll или COM-библиотеку и уже через нее осуществлять работу с видеопроцессором.

P.P.S.: а если кому надо - то вот тут еще много разные проектов.

среда, 30 апреля 2008 г.

Запуск только одной копии программы

Продолжаю делиться сакральными знаниями :) Самым простым способом определить, запущена ли уже наша программа является использование класса Mutex. Для этого создадим вот такой вспомогательный класс. Его задача - проверить наличие мутекса и если его нет - создать новый.

    public class SingleInstance
    {
        private bool firstInstance = false;

        public bool FirstInstance
        {
            get { return firstInstance; }
        }

        public SingleInstance()
        {
            Mutex mutex=null;
            try
            {
                //Пытаемся получить мутекс, если он уже существует
                mutex = Mutex.OpenExisting("ИмяНашегоПриложения");
            }
            catch (WaitHandleCannotBeOpenedException e)
            {
                //Если получили ошибку - мутекс не существует
                firstInstance = true;
            }

            //Если null - создаем новый мутекс
            if (mutex == null)
            {
                mutex = new Mutex(false, "ИмяНашегоПриложения");
                
                //Чтобы слишком умный сборщик мусора не удалил наш мутекс делаем так:
                GC.KeepAlive(mutex);
            }
        }
    }
Следующим шагом является модификация Program.cs следующим образом

        [STAThread]
        static void Main()
        {
            SingleInstance single = new SingleInstance();

            if (single.FirstInstance)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new MainForm());
            }
        }
Соответственно - если single.FirstInstance == true, то наша программа запустится как обычно. В противном случае - сразу завершит свою работу. Еще один из способов предотвращения запуска копии нашей программы описан тут. Этот способ позволяет передать параметры командной строки при попытке запуска новой копии программы в текущую копию программы. Однако в реализации он более сложен.

вторник, 15 апреля 2008 г.

Про копирайт

Рекомендую почитать вот это. Кстати, для сравнения стоит почитать и интервью Тима О'Рейли (я надеюсь вы знаете кто это? :) ). Многие мысли пересекаются...

воскресенье, 30 марта 2008 г.

How to crash MS C# Compiler :)

Посмотреть примеры можно тут. Хотя я сомневаюсь, что кому-то кроме индийцев и китайцев придет в голову такой код :)

суббота, 29 марта 2008 г.

Использование указателей в C#

"Бывают ситуации, хотя и очень редко, когда надо использовать библиотеку (*.dll) написанную скажем на Delphi. И если для использования этой библиотеки нету промежуточного COM объекта или иных достижений цивилизации, да если еще «коллеги» написали в качестве параметров указатели, то тогда эта заметка будет вам в помощь." читать дальше...

Авторское право

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

Вопросы подняты очень интересные. Если честно - у меня даже идей нет, как на них можно ответить. Ну да я и не юрист - мне простительно :)

пятница, 28 марта 2008 г.

Немного про оптимизацию программ

Всем хорош .Net Framework, но есть у него некоторые особенности, не знание которых гарантированно приводит к падению производительности алгоритмов в два и более раза. Сегодня я расскажу о двух таких особенностях.

1. Debug.Write и Debug.WriteLine

Класс Debug является, пожалуй, одним из самых полезных для более-менее крупных программ. Удобен он тем, что нет необходимости как-то заботиться о сохранении отладочных данных – этим занимается сам дотнет. Главная особенность в том, что если проинициализирован «слушатель» отладочной информации – то эта информация гарантированно будет записана в файл в независимости от того в какой части (и в какой сборке) нашей программы будет вызвана функция записи.

Примерная схема работы с этим классом выглядит так:


            Encoding enc = System.Text.Encoding.GetEncoding(1251);
            FileStream fs = new FileStream("log.txt", FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
            Debug.Listeners.Add(new TextWriterTraceListener(new StreamWriter(fs, enc)));
            Debug.AutoFlush = true;
            …
            …
            Debug.WriteLine(“Эта строка будет записана в файл log.txt”);
Однако, кроме положительных качеств, данный класс имеет и один, но очень большой, недостаток. А именно – при активной записи отладочных данных скорость выполнения программы резко падает. В частности, в моем личном опыте снижение может достигать 50-100% и более.

Как этого избежать?
Создаем вспомогательную переменную типа StringBuilder (я надеюсь, вы уже знаете, что строки складывать в time-critical алгоритмах – нельзя) и в наиболее активно использующих запись отладочной информации функциях пишем в эту переменную. По окончании работы критичной части программы – сбрасываем данные на диск «одним куском».


2. Особенности выделения памяти.

Собственно, про то, как выделяется память – пишут во всех книжках. Но! Никто не упоминает о неприятных последствиях ее выделения.

В частности, худшее, что можно придумать – это выделять память операцией new внутри цикла или нескольких вложенных циклов, а также внутри функций, вызывающихся в цикле. Такой подход гарантированно приводит к падению производительности на 200-300% и более.

Нет, ну понятно, что память выделять все-таки надо :) Но везде, где это возможно, следует вынести выделение памяти за пределы циклов.
В частности, мой переводчик активно работает со строками – это приводит к необходимости постоянно выделять память под все новые и новые строки. Основная оптимизация, которую я начал активно применять – это активное использование заранее созданных StringBuilder’ов.
Идея следующая – при первом вызове функции проверяется на null специальная вспомогательная переменная, являющаяся членом класса (т.е. внешняя по отношению к функции). Если null – вызывается new StringBuilder. В противном случае – вызывается StringBuilder.Clear(), которая очищает содержимое переменной. В этом случае повторное выделение памяти не производится.
С точки зрения всех книг по проектированию ПО – это очень плохо :) Фактически, большинство time-critical функций имеют дополнительно по 1-2 переменным-членам класса. Кроме того – эти функции нельзя использовать в многопоточном режиме. Однако, если конечная цель – обеспечить высокую производительность для однопоточного алгоритма, то такой подход имеет смысл.

Ну и как заключение.

В результате использования только этих двух методов удалось снизить время работы алгоритма перевода на тестовом тексте с 27 секунд до 6 секунд без изменения самого алгоритма. Это примерно 22% прироста. Замечу, что это суммарное время работы всех частей программы – включая и те, что невозможно оптимизировать такими способами. По отдельным функция прирост производительности составлял порядка от 100 до 300% (в основном – за счет избавления от операции new).

четверг, 27 марта 2008 г.

Немного истории

Совершенно случайно наткнулся на интервью с академиком РАН В.С. Бурцевым. Он рассказывает про отечественные суперкомпьютеры - в частности, про "Эльбрус". Оказывается, разработки были очень и очень эффективны даже не смотря на отсталую элементную базу. А уж идея использования света для передачи информации внутри суперЭВМ в 1994 (точнее в этом году проект уже защитили) - это вообще нечто!

P.S.: К сожалению, как и все у нас в стране данное направление исследований так же было загублено неумелым/глупым руководством...

вторник, 18 марта 2008 г.

Интересная книжка про Linq

LINQ Quickly by Satheesh, N Kumar:

"This book gets you started with LINQ and shows how it will make your programming life easier by making use of new features from the .NET Framework 3.0. This book is split into seven chapters, each of which is dedicated to presenting a feature of LINQ and its usage in real-life scenarios. Language Integrated Query (LINQ) is a new feature in Visual Studio 2008 that extends its query capabilities, using C# and Visual Basic. Visual Studio 2008 comes with LINQ provider assemblies that enable the use of LINQ with data sources such as in-memory collections, SQL relational databases, ADO.NET Datasets, XML documents, etc. In Visual Studio 2008, Visual C# and Visual Basic are the languages that implement the LINQ language extensions. LINQ language extensions use the new standard query operators API, which is the query language for any collection that implements IEnumerable."

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

MP3 CMS - 2

Как оказалось - вчерашний способ запуска сайта сработал только наполовину. Т.е. в режиме "или сканер или сайт". Хотелось, конечно же, и то и то :)

Но сегодня я его все-таки добил :) Оказалось, что достаточно было запустить application pool сайта в классическом режиме не меняя файл web.config - и все сразу заработало. Так что если кто будет переезжать на IIS7 и столкнется с разными проблемами - попробуйте сначала сделать именно это. Авось поможет :)

воскресенье, 16 марта 2008 г.

Mp3 CMS (Веб-разработчикам на заметку)

И все-таки мне это удалось! Я запустил сайт Mp3 CMS по-человечески :)

Собственно, проблема была в том, что некоторые секции в файле web.config "переехали" на другое место. Достаточно было отредактировать файл - и все сразу заработало!

Как подписать стороннюю сборку

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

Итак:

1. Декомпилируем неподписанную dll в MSIL код.

ildasm providedAssembly.dll /out:providedAssembly.il


2. Убираем куда-нибудь исходную dll (она нам больше не понадобится)

3. Компилируем полученный на этапе №1 код, подписывая его:

ilasm providedAssembly.il /dll /key=keypair001.snk



Самое интересное в этом методе - таким сособом можно подписать даже обфусцированные сборки.

пятница, 14 марта 2008 г.

Альтернатива Singularity OS: CosmOS

Cosmos (C# Open Source Managed Operating System) - тоже является операционной системой, написанной на дотнете. Те, кому интересно - могут почитать краткий обзор на русском, а также посетить главный сайт.

Вообщем-то, идея та же - вид сбоку. Если SingularityOS - это попытка реализовать принципиально иной способ работы с процессами в системе, то CosmOS - это (насколько я понял) перенос дотнета на уровень железа. Другими словами - тот же самый привычный .Net Framework, но без Windows.

P.S.: кстати, если попинать гугл - можно и еще несколько подобных операционных систем найти. Например - SharpOS

среда, 12 марта 2008 г.

Баги, баги... Кругом одни баги!..

Играюсь с очень интересным сервером MP3 CMS (брать/смотреть тут).

Проект представляет собой ASP.Net сайт для каталогизации/отображения фонотеки со встроенным сканером mp3-файлов. Сканер живет на тегах, поэтому у кого с тегами в музыке проблемы - будут проблемы и с сервером :)

Выглядит это все очень красиво. Работает шустро. Успешно справилось с моими 170 гигами музыки (это вторая программа после iTunes, которая способна работать без тормозов с таким количеством музыки). Есть возможность проиграть музыку прямо со страницы - что очень хорошо, можно забыть про бесконечные копирования через фтп на работу "что-нибудь послушать".

Это плюсы. А теперь про минусы.

Последняя версия - 1.5.0.1 пишет обложки к альбомам и sqllite-овскую базу в свою папку App_Data.

Проблема в том, что в новом IIS7 по-умолчанию запрещена модификация файлов. Т.е. создавать файлы можно, а вот изменять - нельзя. Соответственно, первым умер sqllite :(

Во-вторых, сервер блокирует доступ из сайта в любые папки вне папки с сайтом (я точно не уверен - но сильно на это похоже). Таким образом, вторым умер сканер. С другой стороны, проблемы со сканером могли быть вызваны невозможностью писать в базу данных. Логов нет - они тоже того... умерли.

Шаманские пляски с бубном в течение двух дней никакого эффекта не дали. В частности, пробовал дать разрешение на модификацию файлов (да и вообще на полный доступ) к папке с данными. Пробовал запускать сайт не под стандартным аккаунтом NETWORK SERVICE, а под админским - эффект нулевой. Поиски в инете дали только одно - всех очень сильно интересует вопрос изменения файлов :) Собственно, единственный внятный ответ оказался несколько неожиданным:

"As a result of this and other compatibility issues, we're considering reverting this change in Longhorn Server / Vista SP1."

Вы спросите, а как я тогда с ним экспериментировал? Берем и запускаем сайт в VS2008 ASP.Net Development Server - все начинает работать, сканер индексирует папку с музыкой в свою базу, собирает обложки альбомов и все это складывает в папку App_Data. После чего результат подсовываем уже сайту, который крутится в IIS7. Удивительно - но работает!

На днях планирую поставить/поиграться Windows Server 2008 RTM - заодно и проверю, поправили ли разработчики как обещали - или воз и ныне там.

Поиск похожих картинок

Цитирую:

В Сети появилась новая поисковая система Picollator, использующая мультимедийные запросы.

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

Уникальной особенностью системы является способность находить ресурсы с изображениями похожих людей. Пользователь может загружать фотографии с несколькими людьми, и система найдет ресурсы с изображениями людей, похожих на все лица с фотографии-запроса.


Вроде бы даже работает правильно :) Даже интересно - а что там внутри?

пятница, 7 марта 2008 г.

Quake III портировали на .Net Framework

Бывают же чудеса на свете :) Оказывается Quake III портировали на дотнет. В процессе было исправлено порядка 32000 ошибок и дофига предупреждений. Но интересно другое:

"Using Sebastian’s suggestion I ran timedemo’s without vsync and turned off the fps cap. Here are the numbers (this is from demo “four” that comes with the Ultimate Quake box you see in stores). I ran each instance three times to make sure there weren’t any flukes:

Running original Quake III commercial game:

Test run #1: 324.2 fps
Test run #2: 330.9 fps
Test run #3: 332.5 fps

.NET port:

Test run #1: 328.6 fps
Test run #2: 336.9 fps
Test run #3: 336.8 fps

At first it may seem weird that the .NET version is slightly faster, but remember, the original commercial quake3.exe uses its own custom interpreter to run QVM files responsible for all of the game logic (except rendering of course). My .NET port uses DLL’s also _interpreted_ by the .NET framework instead of QVM’s. So what you’re really doing is comparing who’s interpreter is faster."


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

О жизни

За сутки ссылка Singularity RDK на www.codeplex.com в разделе "Projects With Most Downloads" поднялась уже на второе место :) Еще вчера была на третьем.

Что, в принципе, и не удивительно, учитывая что инфрмация про "новую ОС от Майкрософт" прошла даже по телевизору...

P.S.: А запускать я ее пока не стал - времени нет. Но завтра точно попробую :) Пока что краем глаза заглянул в исходники - совершенно ничего не понятно... Хочется какой-нибудь обзор от спецов почитать... Русских.

четверг, 6 марта 2008 г.

Singularity OS доступна для закачки!

Нежданно-негаданно Microsoft опубликовала исходный код своей экспериментальной операционной системы Singularity.

Цитирую:
Корпорация Microsoft представила новую экспериментальную операционную систему под названием Singularity.

Это высоконадежная операционная система, ядро, драйверы и приложения которой написаны на управляемом коде. В Singularity применяются типобезопасные языки программирования вкупе с абстрактным набором команд, которые вместе делают возможным осуществление программно-изолированных процессов (Software Isolated Processes — SIPs).

В отличие от традиционных ОС, компоненты Singularity не запускаются в разных адресных пространствах. Вместо этого существует лишь одно адресное пространство, в котором запускаются SIPs. Каждый такой процесс изолирован, принимает и передает код и данные независимо. Взаимосвязь между процессами осуществляется через каналы более высокого уровня, которыми управляет операционная система. Процессы не могут делить память и изменять свой код, в результате чего обеспечивается высокая надежность исполняемого процессом кода. Система может работать с более чем 16-ю ядрами, а также поддерживать центральные процессоры со встроенными графическими контроллерами.

Singularity написана на Sing#, специально доработанном для данного проекта диалекте C#, и предназначена исключительно для научных целей. Некоторые идеи, реализованные в Singularity, в будущем могут найти применение в Windows, однако когда это произойдет, не известно.

«Singularity — это не следующая Windows, — рассказывает в интервью Ars Technica вице-президент Microsoft по разработкам и исследованиям Рич Рэшид (Rich Rashid). — Это прототип операционной системы, созданный с нуля для того, чтобы понять, как еще могут взаимодействовать между собой операционные системы и приложения. Новая ОС доступна сообществу, и мы надеемся, что вскоре ученые порадуют нас новыми идеями». В компании полагают, что благодаря проекту будущее программное обеспечение станет более надежным. «Мы хотели сделать Singularity достаточно маленькой, достаточно простой, с отличной архитектурой, что послужило бы мгновенному возникновению множества новых идей», — рассказал TG Daily один из ключевых разработчиков ОС Гален Хант (Galen Hunt).

Исходный код Singularity можно загрузить на сайте проекта CodePlex. При этом прототип операционной системы не может быть использован для создания коммерческих продуктов. Несмотря на открытость кода, проект не является open source, так как распространяется в рамках лицензии Microsoft Research License.

Проект Singularity был основан в 2003 г. с целью создания высоконадежной операционной системы. Первая версия исходного кода (RDK) была завершена в 2007 г. В настоящий момент на сайте CodePlex выложена версия 1.1 (~ 62 МБ), в то время как проект перемещается ко второй версии кода.

Экспериментальная ОС Singularity была представлена на ежегодной конференции TechFest во вторник, 4 марта, в Редмонде.


Скачать Singularity можно здесь.

Полезная утилита

Желающие скачать все pdb файлы для того, чтобы смотреть исходный код .Net Framework могут воспользоваться вот этой утилитой.

суббота, 23 февраля 2008 г.

Книжка про ИИ

Читаю сейчас книгу "Исскуственный интеллект - современные подходы". Скачать можно тут.

Рекомендую :)

P.S.: Больше всего меня поразил ее размер - 1400 страниц!

среда, 13 февраля 2008 г.

Книжки по C# 3.0

Нашел тут несколько книжек по C# 3.0:

OReilly.Programming.C.Sharp.3.0.5th.Edition.Jan.2008.pdf

OReilly.C.Sharp.3.0.Design.Patterns.Jan.2008.pdf

OReilly.C.Sharp.3.0.Cookbook.3rd.Edition.Jan.2008.pdf

Пожалуй стоит почитать... Особенно про паттерны.

P.S.: на сайте надо будет зарегистрироваться - иначе скачать не получится

понедельник, 4 февраля 2008 г.

Гугл знает всё!

Хотите узнать будущее? По крайней мере историю освоения космоса Гугл знает :)

P.S.: терпеливо пролистал результаты поиска - последняя известная дата - 2706. Видимо тогда и наступит конец света. Или гугл сломается :)

четверг, 31 января 2008 г.

Немного о малоиспользуемых операторах С# №2

Прочитал сейчас вот это и сильно удивился. Как-то мне показалось, что оператора ?? в языке C# нет. Просто читал я о нем в контексте "неплохо было бы добавить вот такую фичу" и почему-то решил что это относится к 3.5 фреймворку. На всякий случай решил проверить - действительно работает во втором фреймворке :)

Вообщем, оператор очень полезный и иногда позволяет существенно сократить размеры кода за счет замены конструкций проверки значения на null.

Обычно такая проверка осуществляется следующими способами (в зависимости от контекста):

#1

if(value1 != null)
{
  ... //работаем с value1
}


#2

if(value1 == null)  return;


#3

value3 = value1 != null ? value1 : value2;
... // работаем с value3


Лично я предпочитаю использовать вариант №2 там где это возможно. Это позволяет уменьшить уровень вложенности внутри функции. А это, в свою очередь, упрощает ее чтение.

Использование же оператора ?? позволяет упростить запись #3:

#3.1

value3 = value1 ?? value2;
... // работаем с value3


Удобно!

пятница, 25 января 2008 г.

Немного про почту

Последние три дня при слове "почта" громко матерюсь и скреплю зубами :)

Собственно, начну с начала.

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

Как-то пару лет назад я уже работал с почтой, но в тот раз я занимался отправкой писем. И было это все очень просто. Наивный я как обычно лезу в MSDN на предмет нахождения класса во фреймворке для работы с протоколом POP3...

Облом. Нету. И не было. Т.е. SMTP - есть, а POP3 - нету! Громко ругаюсь и лезу в гугловский поиск по исходникам. Нахожу несколько вариантов, но... все с разными глюками и на нужных мне письмах - падают. Наконец, после некоторого времени мучений и экспериментов я собираю из двух проектов более-менее рабочую конструкцию.

И все было-бы хорошо, пока я не попытался отправить письмо стандартными средствами фреймворка самому себе.

А теперь читаем внимательно: в письмах, которые я получал от разных источников все заголовки писались с заглавной буквы (Причем так письма отсылало более десятка программ). Пиьмо, сформированное средствами фреймворка содержит заголовки, написанные со строчной буквы.

Естественно, хлипкая конструкция для получения писем начала падать :( Путем целого дня отладки выяснилось, что научить ее корректно обрабатывать заголовки сообщения, написанные с маленькой буквы невозможно - фактически пришлось бы переписать 90% кода парсинга сообщений.

Сегодня опять полез в гугл - на этот раз нашел кое что более полезное проект OpenPOP.Net. Удивительно, но он не упал ни на одном письме из почтового ящика, включая и подписанные сертификатами :)

P.S.: кстати, после формирования и отсылки письма, содержащего аттачмент средствами класса System.Net.Mail.SmtpClient необходимо вызвать метод MailMessage.Dispose (т.е. у переменной, в которой производилось формирование письма). В противном случае файл-вложение окажется заблокирован на неопределенное время и его нельзя будет ни удалить ни перезаписать пока не отработает сборщик мусора или программа не завершится.