C# Получение списка каталогов из переменной окружения PATH

Простая задачка, решаемая в две строки.

1. Получаем значение переменной окружения PATH:
string path_var=Environment.GetEnvironmentVariable("PATH");
2. Пути в PATH разделяются символом ; (точка с запятой), соответственно, можно получить массив со списком директорий с помощью функции Split():
string[] dirs = path_var.Split(';');

Единственное что нужно не забыть перед использованием — последний элемент массива может оказаться пустым, если PATH заканчивается точкой с запятой, и между элементами в переменной PATH могут быть пробелы, надо не забыть сделать Trim()перед использованием значения из массива.

C#, динамическая NotifyIcon с наложением изображения.

Спрашивают, а возможно ли совместить пример с динамически обновляемой NotifyIcon Копия с примером про наложение изображения Копия, чтобы получить что-то типа такого же эффекта, который делает иконка сетевого соединения в Windows 7 при разрыве соединения?

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

Но если очень хочется, то можно.

Для разнообразия будем считать, что основное изображение у нас уже в формате ICO:

А накладываемое должно быть PNG с прозрачностью. Накладывать будем желтый треугольник с красным восклицательным знаком:

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

— Заводим необходимые переменные:

Icon TargetIcon = Properties.Resources.target;
Bitmap TargetBitmap = null;
Bitmap ResultBitmap = null;
Bitmap OverlayBitmap = null;
IconConverter icconv = null;

И не забываем экспортировать функцию DestroyIcon из user32.dll [1]:

[System.Runtime.InteropServices.DllImport("user32.dll",
            CharSet = System.Runtime.InteropServices.CharSet.Auto)]
extern static bool DestroyIcon(IntPtr handle);

— Конвертируем иконку TargetIcon в Bitmap. Делается это при помощи класса IconConverter:

//convert icon to bitmap (target)
icconv = new IconConverter();
TargetBitmap = (Bitmap)icconv.ConvertTo(TargetIcon, typeof(Bitmap));

— Достаем из ресурсов накладываемое изображение и далее поступаем, как в [2]:

//overlay bitmap
OverlayBitmap = Properties.Resources.overlay;

//create result bitmap
ResultBitmap = new Bitmap(TargetBitmap.Width, TargetBitmap.Height,
    PixelFormat.Format32bppArgb);

//create Graphics
Graphics graph = Graphics.FromImage(ResultBitmap);
graph.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;

//Draw overlay images
graph.DrawImage(TargetBitmap, 0, 0);
graph.DrawImage(OverlayBitmap, 0, TargetBitmap.Height-OverlayBitmap.Height);            

//result =)
pbTarget.Image = TargetBitmap;
pbOverlay.Image = OverlayBitmap;
pbResult.Image = ResultBitmap;

Когда надо, преобразуем ResultBitmap, где хранится иконка с наложенным изображением, обратно в Icon, и присваиваем ее соответствующему свойству компонента NotifyIcon:

IntPtr hIcon = ResultBitmap.GetHicon();
System.Drawing.Icon niicon = System.Drawing.Icon.FromHandle(hIcon);
niTest.Icon = niicon;

DestroyIcon(niicon.Handle);

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

Источники

1. C#, динамическая NotifyIcon, иконка в области уведомления Копия
2. C#, WindowsForms, наложение изображений, изменение размеров изображения. Копия

Код примера на GitHub

Виндоофисные мелочи.

Заметка от склероза.

Завершение работы с командной строки

Команда shutdown.
Завершение работы:
C:\Windows\System32\shutdown.exe /s /t 10 /c "I am shutdown"
Перезагрузка:
C:\Windows\System32\shutdown.exe /r /t 10 /c "I am reboot"
Отмена:
C:\Windows\System32\shutdown.exe /a
Архив с готовыми ярлыками, чтоб кидать сразу на рабочий стол
Справка по команде

Батник для очистки EXIF в фотографиях

Где-нибудь в PATH должен лежать exiftool.exe
Батник из одной строки:
exiftool -all= -overwrite_original %1
Использовать: killexif.bat *.jpg
Ссылка на SFX-архив с exiftool и батником

Посадить макрос на сочетание клавиш в Word 2003

1. Идем в Сервис —> Настройка
2. Жмем кнопку Клавиатура в появившемся окне:

3. В Категории выбираем Макросы
4. В соседнем списке выбираем нужный макрос
5. Жамкаем на поле Новое сочетание клавиш
6. Нажимаем что нужно
7. Все сохраняем

Еще метеошного и ностальгического

А это рабочее место техника-метеоролога (непосредственного наблюдателя) на локальной метеостанции. Два крайних слева прибора не знаю. Нижний видел еще совсем малым, а верхний это уже какой-то новый. Поеду еще раз туда, обязательно спрошу. А два больших шкафчика — это пульты ИВО (измерителя высоты облаков). Что-то типа маломощного радара, определяющего (спасибо, Кэп) высоту облаков. Это «терминалы», правда аналоговые абсолютно. «Сервер» снаружи, несколько напоминает стиральную машинку, поставленную на «спину». Крышка, защищающая линзу, кстати, открывалась с пульта удаленно, что на меня мелкого производило впечатление, сравнимое с посещением Зоны 51!

На заднем плане шкафчик с треугольными створками. Там как раз тот самый ртутный столб живет %)

Метеошное. Ртутный столб.


По клику доступен крупный вариант

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

Так вот, ОН СУЩЕСТВУЕТ. Фотография сделана в 21 веке мною лично.

C#, WindowsForms, наложение изображений, изменение размеров изображения.

Задали вопрос, а можно ли в C# программными средствами наложить 2 изображения друг на друга. И даже сами потом предложили какое-то жуткое решение с привлечением WinAPI, и чуть ли не ассемблера со злыми духами.

На самом деле, задача вполне себе решается стандартными средствами.

Наложение изображений

Итак, предположим, что у нас есть 2 изображения, оба они PNG с прозрачностью, и лежат в ресурсах нашего приложения. Например, флаг:

и герб:

под именами, соответственно Properties.Resources.flag и Properties.Resources.trizub_small

Сначала сделаем из изображений два объекта Bitmap:

//Берем целевое изображение
Bitmap TargetBitmap = Properties.Resources.flag;

//Берем накладываемое изображение
Bitmap OverlayBitmap = Properties.Resources.trizub_small;

Теперь надо создать результирующее изображение (оно будет пока пустым) нужного размера:

//Создаем результирующее изображение (пока пустое)
Bitmap ResultBitmap = new Bitmap(TargetBitmap.Width, TargetBitmap.Height,
            PixelFormat.Format32bppArgb);

Откуда взяли высоту и ширину — понятно, третий параметр PixelFormat берется в зависимости от исходных изображений. Желательно, чтоб они совпадали по глубине цвета, иначе получится некрасиво, может потеряться прозрачность или произойти еще какая-нибудь бяка. Я сделал 2 изображения с прозрачностью (ARGB) и глубиной цвета 32 бита.

Теперь нужно создать объект Graphics, который и будет заниматься совмещением изображений. Раз мы будем рисовать в пустом Bitmap ResultBitmap, то и объект Graphics создаем из него, воспользовавшись методом Graphics.FromImage():

//Создаем объект Graphics из результирующего изображения
Graphics graph = Graphics.FromImage(ResultBitmap);

Далее объект graph надо настроить:

//настраиваем метод совмещения изображений
graph.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;

Если вместо SourceOver установить SourceCopy, то потеряется вся прозрачность у накладываемого изображения, и будет некрасиво:

Далее, производим отрисовку:

//рисуем основное изображение
graph.DrawImage(TargetBitmap, 0, 0);

//рисуем накладываемое изображение
graph.DrawImage(OverlayBitmap, (TargetBitmap.Width-OverlayBitmap.Width)/2,
(TargetBitmap.Height-OverlayBitmap.Height)/2,
OverlayBitmap.Width,OverlayBitmap.Height);

Думаю, откуда взяты все координаты и размеры, понятно.

Осталось только присвоить Bitmap'ы PictureBox'ам

Изменение размеров изображения

Тут тоже ничего сложного и сверхъестественного нет.

Чтоб два раза не вставать, возьмем полученное выше изображение и уменьшим его:

//задаем новые размеры
int NewWidth = ResultBitmap.Width / 2;
int NewHeight = ResultBitmap.Height / 2;
//Настраиваем PictureBox для вывода уменьшенного изображения
pbResize.Size = new Size(NewWidth, NewHeight);

Создадим новый Bitmap для будущего уменьшенного изображения:

//создаем новый Bitmap для измененного изображения
Bitmap ResizeBitmap = new Bitmap(NewWidth,
NewHeight);

Опять создадим объект Graphics, который будет заниматься отрисовкой:

//создаем объект Graphics, который будет изменять размер
Graphics ResizeGraph = Graphics.FromImage(ResizeBitmap);

Поставим повыше качество изображения:

//ставим высокое качество
ResizeGraph.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.High;

И делаем отрисовку:

//рисуем изображение с измененным размером
ResizeGraph.DrawImage(ResultBitmap, 0, 0, NewWidth, NewHeight);

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

Вот, что получилось:

Исходник примера на GitHub

C#, WindowsForms. Автоматическая выгрузка и загрузка содержимого контролов на форме. В объект или запись DataSet.

Решил побороть еще одно узкое место в коде, которое приводит к невероятному количеству ручного кодинга, а именно — загрузка данных из записи DataSet или произвольного объекта в форму, для изменения/ввода данных пользователем, а потом обратная выгрузка.

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

Оказывается, можно. Все инструменты для этого есть — есть System.Reflection, через инструменты данного пространства имен можно получать имена свойств или полей нужного класса, а также тип данных, и есть методы для поиска нужных контролов на форме, чтобы загрузить или сохранить данные в/из объекта.

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

Опять же, тут будет краткое рассуждение, а пример кода в конце.

Основные компоненты

Основные компоненты это:
— текстовые поля, куда можно ввести либо строку, либо число (фильтрацию ввода оставим форме)
— checkbox’ы, хранящие булево значение
— radiobutton’ы/переключатели — ограниченный выбор из определенного набора вариантов.

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

Как хранить набор вариантов

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

public enum NetConnectionType
{
    NoProxy = 0,
    SystemProxy = 1,
    ManualProxy = 2
}

Соглашение об именах

Это единственный наглый момент во всем примере — контролы придется называть не абы как, а по правилам, впрочем, правила всегда можно переопределить, и сделать удобные вам. Я делал удобно для себя.
Для TextBox‘ов и CheckBox‘ов правила такие: сначала идет префикс txt или chk, далее — название поля в записи таблицы DataSet или название свойства объекта, например chkAutorun или txtUserName. В классе, соответственно, должны быть поля bool Autorun или string UserName.

Для радиокнопок (переключателей) имя формируется по следующему принципу: префикс rb+НазваниеСвойства+ЗначениеВEnum, т.е., например, радиокнопка, указывающая на прямое соединение, будет называться rbConnectionNoProxy

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

Разные вспомогательные мелочи

Получение списка радиокнопок и поиск контрола на форме Копия

Получение значения Enum из состояния RadioButton:

private string GetEnumValFromRb(string PropName)
{
    string EnumVal = string.Empty;
    string rbName = "rb"+PropName;            
    
    foreach (RadioButton rb in RadioButtons)
    {                
        if (rb.Checked)
        {
            if (rb.Name.StartsWith(rbName))
            {
                EnumVal = rb.Name.Substring(rbName.Length);
            }
        }
    }

    return EnumVal;
}

Весь код примера

На GitHub

C#, WindowsForms — найти все переключатели (RadioButtons) на форме.

Простой поиск контрола

Если нам нужно найти контрол на форме, зная его имя, то все решается довольно просто — у массива контролов Controls есть метод Find, который найдет нам что нужно, если указать правильное имя контрола:

private Control FindControl(string ControlName, Form form)
{
    Control ctrl = null;

    Control[] buf = form.Controls.Find(ControlName, true);
    if (buf.Length == 0) return null;
    if (buf.Length > 1) return null;

    ctrl = buf[0];

    return ctrl;
}

Поиск всех RadioButton’s (или других однотипных контролов)

Вот тут уже сложнее, особенно с переключателями. Они обычно сидят на форме в контейнерах, например в GroupBox'ах, и функция Find тут не поможет. Необходим другой подход, если мы хотим получить список контролов определенного типа. А именно — надо сделать рекурсивную функцию поиска. Кто боится рекурсии и связанных с ней переполнений, скажу, что ничего страшного нет.
Мне удалось уронить студию на 5 000 однотипных компонентов, а подобное число компонентов вряд ли может быть в реальности, только если вы не радиокнопочный маньяк 🙂

Функция такая вот:

private List FindAllRadiobuttons(Control.ControlCollection collection)
{
    List  result = new List();
    foreach (Control ctrl in collection)
    {
        if (ctrl.HasChildren)
        {
            result.AddRange(this.FindAllRadiobuttons(ctrl.Controls));
        }
        if (ctrl is RadioButton)
        {
            result.Add((RadioButton)ctrl);
        }
    }

    return result;
}

Т.е. если мы просто наткнулись на переключатель, при переборе контролов из массива Controls, то добавляем переключатель в массив, если же, мы наткнулись на контрол-контейнер (ctrl.HasChildren == true), то вызываем функцию перебора массива уже для массива Controls контейнера.

C#. О конфигах и сохранении/загрузке свойств объекта, часть 2

В прошлой части Копия я рассказывал, как с помощью инструментов из пространства имен System.Reflection, можно сохранить свойства объекта, например, в таблицу DataSet, или наоборот, загрузить из DataSet данные в свойства соответствующего объекта. Таким образом, решалась проблема автоматизации работы с конфигурационными файлами.

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

Итак, переходим к сериализации.

В .NET Framework сам себя класс сериализовать не может, точнее, сериализовать-то может, а вот десериализовать — нифига. Класс и его экземпляр, получается, как Штирлиц с раненой радисткой Кэт, передать могут, а обратно нет, без дружественной помощи.

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

Итак, создадим класс-хранилище, вот такой вот, например:

[Serializable]
public class AppSettings
{
    public string DataUrl { get; set; }
    public FormatType DataFormat { get; set; }
    public string IPColumn { get; set; }
    public string FieldSeparator { get; set; }
    public string FlagColumn { get; set; }
    public string TrueValue { get; set; }
    public string FalseValue { get; set; }
    public bool LoadUpdate { get; set; }

    public AppSettings()
    {
    }
}

Если нужно, чтобы класс сериализовался, то перед описанием класса нужно обязательно установить атрибут «сериализуемый»:

[Serializable]

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

Ну, раз уж в прошлый раз, мы выбирали XML, то и сейчас я буду сериализовывать класс в XML

Особенности сериализации в XML в .NET Framework

Сериализатор XML в .NET пропускает все приватные поля и свойства класса. На мой взгляд, это больше хорошо, чем плохо, если сохранять класс, хранящий набор параметров конфигурации — приватные все равно не нужны.

Если какое-то публичное свойство не надо сериализировать, т.е. в нашем случае, сохранять в конфиг, то такому свойству надо установить атрибут [XmlIgnore], для публичных полей устанавливается атрибут [NonSerialized].

Например:

[XmlIgnore]
public string DataUrl { get; set; }

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

Класс-менеджер

Само дерево жужжать не может
Значит, кто-то тут жужжит
(Вини-Пух)

Это самая гадская особенность сериализации в .NET, а именно, если в прошлом случае могли параметры конфига, и функции для их сохранения-загрузки объединить в один класс, то в подходе с использованием сериализации не можем:

this = (Data)readerRr.Deserialize(fileRr);
this - переменная только для чтения, по крайней мере до .NET 4.0 включительно.

И такой подход считается «плохим дизайном», хотя на мой нескромный взгляд, плохой дизайн — это разносить части одного и того же по разным классам.

Но раз уж надо, значит надо. Делаем класс-менеджер:

Далее такой условный класс-менеджер с возможностью сохранения и загрузки:
Читать далее

Исходник примера на GitHub

AppSettings.cs

Источники

Киберфорум
Сериализация в XML. XmlSerializer

Навел на мысль [info]steinkrauz@ljr

L.O.S.A.I.G!

Офигенная эмо-панк группа из моего города.

Тащемта, были даже на дребедне нашего города, было холодно и неприятно (от погоды), но вообще парни пиздатые. Особенно вокалист XD

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

Прямая ссылка: кликать сюда

С днем настоящего карельского флага


В этом году совпавшим еще и с летним Солнцестоянием

Созвездие северной свободы
21 июня 2018 года исполняется столетие первого флага Карелии — синего полотнища, на котором расположены семь серебряных звезд Большой Медведицы (Otava). Впервые этот флаг был поднят над селом Ухтуа летом 1918 года, а его автором стал финский художник Йонас Хейска. Он пояснял, что на эту символику его вдохновили руны «Калевалы», где упоминается это созвездие.

Я, как всегда немного опаздываю, потому что у меня график в интернетах абсолютно не совпадает с планетой 🙂

Окончательно закрыли сайт Hexproject’а

На сайте был старый движок, бесплатные хостинги какашка, да и весь кодинг (даже с приставками «быдло-» и «около-«) можно выложить на Гитхаб, и не надо что-то отдельное изобретать.

Виртуальная сим-карта для регистрации на сервисах, требующих номер телефона.

Мои друзья делают замечательный проект, способствующий сохранению анонимности в Интернете — virtualsim.net. На этом сайте вам за небольшую сумму зарегистрируют номер телефона на год, на который можно будет регистрироваться на всяких сайтах и сервисах, требующих номер телефона (Telegram, Vkontakte, OK.RU и т.д.)

Мы вот таким образом обзавелись телеграм-каналом и страницей во Vkontakte.

У ребят огромная база данных (на несколько тысяч номеров), есть возможность выбрать страну. В настоящий момент доступны Украина, Россия, Казахстан, Латвия. При офигенно качественном и важном сервисе, избавляющем, наконец, от мобильного рабства, цены вполне демократичны: Минимальный тариф за номер — 5$ в год для некоммерческой деятельности, например, регистрации страницы в VK, для коммерческой деятельности подороже, но вполне терпимо. Если честно, дешевле я не нашел. Постоянным клиентам предоставляются скидки. Впрочем, дублировать весь прайс в данной заметке я не буду. Если вас заинтересовал сервис, пройдите по ссылке ниже

virtualsim.net

VIRTUALSIM.NET ОСТАВАЙСЯ АНОНИМНЫМ!

DetecTOR, утилита, определяющая, относится ли IP к сети TOR

Написана изначально была аж в 2013 году и довольно кривовато, но по многочисленным просьбам нашего дорогого зрителя, была переделана, с подробными объяснениями по поводу «как», «что», «где» и «куда».

Раз это приняли в качестве курсовой первокурсника, то можно и опубликовать. Тем более, на этой утилите я и сам экспериментировал, и теперь это некий пример для бывших и будущих нескольких заметок из серии «О конфигах» и всяческой там автоамтизации рутинных дел — сбора данных с форм, или сохранения конфигурационных файлов.

Выглядит главное окно вот так:

readme.txt

Чтоб два раза не вставать.
readme.txt

Смотреть исходники (на GitHub)
Скачать программу (Win32) c GitHub

Открытый отчет 2017-2018 обновление

Теперь больше не должны 10 $, нам как-то быстро за день надонатили, после публикации открытого отчета, что мы даже чихнуть не успели.

Благодарим неравнодушных людей. Зала славы и публикации имен, естественно, не будет. Как и открытых реквизитов для доната (до сентября)

Открытый отчет 2017-2018

Итак, на жизнь сайту надо 60 $ в год, по итогам года собрано 50 $, 10 остались должны, но это некритично.

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

Состав редакции:
Администратор, директор проекта: Алексей Тихонов, (aka Leha Silent) Костомукша/Tampere
Главный редактор: Анатолий Перец, (aka PunkArr[]) СПб/Кондопога
Заместитель главного редактора: Lina Lukina (Keronen) (aka Lin’Ka) Tampere
В команду пришел новый человек, консультант по IT: N.K.T, aka Nikita N. (MSK/SPb/PTZ)