пятница, 25 декабря 2009 г.

Ubuntu Karmic. Настройка Grub

На компьютере установлены Ubuntu Karmic и Windows 7, по умолчанию загружается Ubuntu. Необходимо изменить ОС по умолчанию на семерку, убрав из меню загрузчика лишние пункты.

В файле /etc/default/grub
  • GRUB_TIMEOUT=5 - время показа меню, 5 секунд.
  • раскомментировать GRUB_DISABLE_LINUX_RECOVERY="true" для отключения recovery пунктов меню.
Из файла /etc/grub.d/20_memtest86+ убрать код memtest'а с выводом на консоль.

menuentry "Memory test (memtest86+, serial console 115200)" {
linux16    $MEMTESTPATH console=ttyS0,115200n8
}

Для того, чтобы убрать все пункты memtest, необходимо сбросить с этого файла исполняемый бит.

После этого меню будет иметь вид
  • Ubuntu
  • Memtest
  • Windows 7
Переместим семерку на первое место в списке. Для этого добавим файл /etc/grub.d/08_windows_7. Код в этом файле будет искать на диске Windows 7 и, найдя, добавлять ее в меню загрузчика. Код скопируем из /etc/grub.d/30_os-prober

prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib

. ${libdir}/grub/grub-mkconfig_lib

if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then
exit 0
fi

if [ -z "`which os-prober 2> /dev/null`" ] ; then
# missing os-prober
exit 0
fi

OSPROBED="`os-prober | tr ' ' '^' | paste -s -d ' '`"
if [ -z "${OSPROBED}" ] ; then
# empty os-prober output, nothing to do
exit 0
fi

for OS in ${OSPROBED} ; do
DEVICE="`echo ${OS} | cut -d ':' -f 1`"
LONGNAME="`echo ${OS} | cut -d ':' -f 2 | tr '^' ' '`"
LABEL="`echo ${OS} | cut -d ':' -f 3 | tr '^' ' '`"
BOOT="`echo ${OS} | cut -d ':' -f 4`"

if [ -z "${LONGNAME}" ] ; then
LONGNAME="${LABEL}"
fi

echo "Found ${LONGNAME} on ${DEVICE}" >&2

if [ "x${LONGNAME}" = "xWindows 7 (loader)" ]; then
cat << EOF
menuentry "Windows 7" {
EOF
save_default_entry | sed -e "s/^/\t/"
prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/"

cat <<EOF
chainloader +1
}
EOF
fi

done

Все подробности можно найти здесь https://help.ubuntu.com/community/Grub2

воскресенье, 12 июля 2009 г.

Заполнение placeholder'ов в string.Format()

Рассмотрим код:

using System;

namespace StringFormat
{
  class Program
  {
    static void Main()
    {
      const string innerString = "first = {0}, second = {1}";
      const string outerString = "inner string = '{0}', second outer placeholder = '{1}'";

      string fullString = string.Format(outerString, innerString, "filled");
      string completeFullString = string.Format(fullString, 1, 2);

      Console.WriteLine(completeFullString);
      Console.ReadKey();
    }
  }
}

В строку, содержащую placeholder'ы {0} и {1}, подставляется строка, также содержащая такие placeholder'ы, которые затем заполняются. Что будет в результате?


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

Исходный код здесь.

Подписка UI на события синглетона

Предположим, что у нас есть некоторое приложения с графическим интерфейсом (GUI). Пусть в приложении существует класс, являющийся синглетоном. Такая архитектура может быть продиктована логикой работы приложения: синглетон представляет собой объект, существующий в единственно экземпляре, он может соответствовать, например, очереди печати или отправки сообщений куда-либо, хранить настройки приложения. Пусть наш синглетон является источником событий (events), через которые он оповещает приложение о ходе выполнения неких операций. На эти события подписывается UI приложения и обеспечивает информирование пользователя.

Для моделирования этого взаимодействия создадим небольшое тестовое приложение (ссылка на исходный код в конце поста). Источником события синглетона является кнопка Trigger event главное формы, подписчиком - дочерние формы, создаваемые кнопкой Create a new child form. Данными, передаваемыми от сиглетона UI, является номер последней созданной дочерней формы.

Главное окно приложения выглядит весь незамысловато:



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

Первое. Создадим две дочерних формы и активируем событие синглетона.



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

Второй момент гораздо более интересен. Пользователь может закрыть дочернее окно, UI при этом будут уничтожен (будут вызваны методы Dispose()), но сами объекты останутся и будут продолжать получать события синглетона. Эти события будут для них корнями (root) и объекты не будут уничтожены сборщиком мусора. Попытка обновить уничтоженый UI может вызвать исключение. В данном демонстрационном приложении используется следующая конструкция:


using System;
using System.Windows.Forms;

namespace SingletonEvents
{
  public partial class ChildForm : Form
  {
    #region Fields

    private readonly int number;
    private readonly bool unsubscribeFromEvents;
    private bool disposed;

    #endregion Fields

    #region Constructors

    public ChildForm(int number, bool unsubscribeFromEvents)
    {
      InitializeComponent();

      this.number = number;
      this.unsubscribeFromEvents = unsubscribeFromEvents;

      Closing += ThisClosingEventHandler;
      Disposed += ThisDisposedEventHandler;
      Singleton.Instance.EventTriggered  += SingletonEventTriggeredEventsHandler;
    }

    #endregion Constructors

    #region Event handlers

    private void SingletonEventTriggeredEventsHandler(object sender, EventTriggeredEventsArgs e)
    {
      if (disposed)
      {
        string errorText = string.Format("Form #{0} has been already disposed", number);
        throw new InvalidOperationException(errorText);
      }

      MessageLabel.Text = string.Format("Form #{0} is active", e.ActiveChildFormNumber);
    }

    private void ThisClosingEventHandler(object sender, EventArgs e)
    {
      if (unsubscribeFromEvents)
      {
        Singleton.Instance.EventTriggered -= SingletonEventTriggeredEventsHandler;
      }
    }

    private void ThisDisposedEventHandler(object sender, EventArgs e)
    {
      disposed = true;
    }

    #endregion Event handlers
  }
}

Факт уничтожения UI определяется по флагу disposed, исключение при обработке события генерируется искусственно, приложение падает.


При закрытии формы необходимо отписываться от событий, для этого как раз и предназначен флажок Unsubscribe from events. В этом случае старые объекты не будут получать события и не имея корней будут уничтожены сборщиком мусора.

Исходный код здесь.

понедельник, 6 июля 2009 г.

Miranda IM. Сделай сам

Сама Miranda.

Плагины:

  • Modern Contact List — нормальный, не минималистичный, контакт лист.
  • TabSRMM Unicode — окна сообщений с вкладками.
  • Fingerprint Plus — определение версии клиента, используемого контактом.
  • SmileyAdd Unicode — нормальные смайлики.

Некоторые настройки:

  • Options | Contact list | Tray | System tray icon mode | Show multiple icons | Only when statuses differ — всегда ли показывать по иконке для каждого протокола.
  • Options | Contact list | Row items | Second line | Use 'XStatus: XMessage — для любителей разрывать свой расширенный статус на две части.
  • Options | Customize | Fonts | Contac list | Row items | Second line — шрифт для x-статуса в ростере.
  • Options | Message sessions | Message log | Timestamp settings | Show seconds in timestamp — показывать секунды в метках времени чатов.
  • Options | Message sessions | Message log | Other options | Log status changes — показывать в логе события изменения статуса.

воскресенье, 5 июля 2009 г.

ReSharper NHibernate plugin. Общие сведения

Плагин для ReSharper'а, добавляющий поддержку файлов маппинга NHibernate. Домашняя страница - http://nhplugin.lieser-online.de/, скачать можно с Google Code - http://code.google.com/p/nhplugin/. Последний коммит в репозиторий - 21 ноября 2008. Плагин поддерживает 2005 и 2008 студии, но только 4.1-ый решарпер. Под доступным сейчас 4.5-м решарпером плагин не работает. Распространяется по GPLv2.

Основные фичи

(Вольный перевод части домашней страницы проекта)

Навигация и рефакторинг

  • В файлах маппинга определяется ссылка на свойство или поле класса. На замаппленном свойстве можно использовать Ctrl+Click (Go To Declaration) для того, чтобы перейти к его объявлению.
  • Для замаппленных свойств и полей полностью поддерживается рефакторинг переименования.
  • Можно перейти от объявления к маппинг-файлу с помощью Go To Usage (или Find Usages).
  • Атрибуты NHibernate рассматриваются так, как если бы были найдены соответствующие маппинг-файлы. Private или internal поля не поддерживаются из-за ограничений механизма поиска ссылок ReSharper'а. Если маппинг-файл и реализация замаппленного класса находятся в разных сборках, сборка с маппингом должна ссылаться на сборку с классом для разрешения зависимостей.

Анализ .hbm.xml файлов

  • Неопределенные замаппленные свойства помечаются.
  • Неопределенные типы и пространства имен помечаются.
  • Помечаются маппинг файлы, не включенные в сборку как внедренный ресурс - embedded resouce (ошибка №1).
  • Помечаются неопределенные значения атрибутов доступа (поддерживаются только предопределенные значения)
  • Уровень строгости, присваиваемый ошибкам, может быть настроен в ReSharper | Options | Code Inspection | Inspection Severity | NHibernate mappings.