Толик Панков
hex_laden
............ .................. ................
Page Summary

October 2025
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Back Viewing 0 - 20  
C#: Учебное задание. Конвертер температур Кельвин - Цельсий - Фаренгейт

Скриншоты





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


1. Создаем три поля ввода типа InputDigitControl Поля надо назвать соответственно idcC, idcK и idcF для значений в цельсиях, кельвинах и фаренгейтах.

2. Создаем три переменных в коде формы, они будут флагами, показывющими в каком поле происходит ввод:
bool enC = false; bool enK = false; bool enF = false;

3. Для всех полей прописываем общее событие типа Enter idc_Enter

4. В обработчике события захватываем текущий контрол в отдельную переменную:
InputDigitControl idc = (InputDigitControl)sender;

5. Вытаскиваем последний символ в имени контрола:
string fldID = idc.Name.Substring(3, 1);

6. Организуем switch, устанавливающий флаги

switch (fldID)
{
    case "C":
        {
            enC = true;
            enK = false;
            enF = false;
        }; break;
    case "K":
        {
            enC = false;
            enK = true;
            enF = false;
        }; break;
    case "F":
        {
            enC = false;
            enK = false;
            enF = true;
        }; break;
}


Копия функции целиком на PasteBin

7. Событие типа Changed тоже назначаем одно для всех контролов.

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

Ввод чисел


С помощью моего компонента InputDigitControl

Формулы для перевода температур


C2K:
K = C + 273.15

C2F:
F = C * 9.0 / 5.0 + 32.0

K2C:
C = K - 273.15

K2F:
F = (K - 273.15) * 9.0 / 5.0 + 32.0

F2C:
C = (F - 32.0) * 5.0 / 9.0

F2K:
K = (F - 32.0) * 5.0 / 9.0 + 273.15

Скомпилированный файл


На GitHub

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


На GitHub

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2023/12/10/c-uchebnoe-zadanie-konverter-temperatur-kelvin-tselsij-farengejt/

Tags: ,
Перевод температурных шкал: Цельсий/Кельвин/Фаренгейт

И заодно функции на C# для знакомого школьника, шоб себя проверил.

Градусы Цельсия в градусы Кельвина

K = C + 273.15


double C2K(double C)
{
    return C + 273.15;
}


Градусы Цельсия в градусы Фаренгейта




F = C * 9/5 + 32


double C2F(double C)
{
    return C * 9.0 / 5.0 + 32.0;
}


Градусы Кельвина в градусы Цельсия


C = K - 273.15


double K2C(double K)
{
    return K - 273.15;
}


Градусы Кельвина в градусы Фаренгейта




F = (K - 273.15) * 9/5


double K2F(double K)
{
    return (K - 273.15) * 9.0 / 5.0 + 32.0;
}


Градусы Фаренгейта в градусы Цельсия




C = (F - 32) * 5/9


double F2C(double F)
{
    return (F - 32.0) * 5.0 / 9.0;
}


Градусы Фаренгейта в градусы Кельвина




K = (F - 32) * 5/9 +273.15


double F2K(double F)
{
    return (F - 32.0) * 5.0 / 9.0 + 273.15;
}


Это репост с сайта http://tolik-punkoff.com
Оригинал: https://tolik-punkoff.com/2022/02/14/perevod-temperaturnyh-shkal-tselsij-kelvin-farengejt/

C#, вывод цветного текста на консоль и изменение цвета фона консоли.

Делается очень просто, цветом текста управляет свойство ForegroundColor объекта Console, а цветом фона - свойство BackgroundColor, которые принимают значения из перечисления ConsoleColor.

Например, если установить свойства таким образом:

Console.BackgroundColor = ConsoleColor.DarkGray;
Console.ForegroundColor = ConsoleColor.Green;


то при выводе текста, например, командой:

Console.WriteLine("Demo Text");

мы получим зеленый текст:

Demo Text
на темно-сером фоне.

Всего консоль поддерживает 16 цветов.

Сброс цветовой схемы консоли


Для возврата к цветовой схеме по умолчанию используется метод Console.ResetColor();

Пример


Демонстрационный пример на GitHub (выводит все цвета текста и фона)

Скриншоты






Это репост с сайта http://tolik-punkoff.com
Оригинал: https://tolik-punkoff.com/2021/11/21/c-vyvod-tsvetnogo-teksta-na-konsol-i-izmenenie-tsveta-fona-konsoli/

Tags: ,
C#, как сделать транслитерацию. Перевод русской строки в latinitsu.

Преамбула


Думаю, что объяснять, что такое транслит, никому не нужно - это написание русских слов latinskimi bukvami, понадобилось сделать это на C#.

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

Русская букваАБВГДЕЁЖ
Латинская буква или буквосочетаниеABVGDEYoZh
Русская букваЗИЙКЛМНО
Латинская буква или буквосочетаниеZIJKLMNO
Русская букваПРСТУФХЦ
Латинская буква или буквосочетаниеPRSTUFKhTs
Русская букваЧШЩЪЫЬЭЮ
Латинская буква или буквосочетаниеChShShch''Y'EJu
Русская букваЯ
Латинская буква или буквосочетаниеJa


Вторая проблема - этот стандарт проблематично использовать для транслитерации URL или имен файлов, надо что-то делать с пробелом (который в именах файлов и URL смотрится, как говно), так что в другом варианте таблицы, для замены Ъ, Ь и пробела, был выбран знак подчеркивания (_).

Класс, для транслитерации символов и строк


Создаем новый класс Translit:

public class Translit
{
	
}


В класс Translit добавляем словарь (Dictionary), который, в качестве ключа, будет использовать тип char (русскую букву), а в качестве значения string, содержащий ее латинский эквивалент. Думаю, ясно, почему string - некоторые русские буквы передаются латинскими буквосочетаниями:

private Dictionary<char, string> TranslitDict = new Dictionary<char,string>();

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

Для общего случая:

private void FormDictStandart()
{
    TranslitDict.Clear();

    //Заглавные буквы (общий случай)
    TranslitDict.Add('А', "A");
	
    //часть кода вырезана для экономии места
    
    TranslitDict.Add('Ъ', "''");
    TranslitDict.Add('Ы', "Y");
    TranslitDict.Add('Ь', "'");
    TranslitDict.Add('Э', "E");
    TranslitDict.Add('Ю', "Ju");
    TranslitDict.Add('Я', "Ja");

    //строчные буквы (общий случай)
    TranslitDict.Add('а', "a");
	
    //часть кода вырезана для экономии места
    
    TranslitDict.Add('ъ', "''");
    TranslitDict.Add('ы', "y");
    TranslitDict.Add('ь', "'");
    TranslitDict.Add('э', "e");
    TranslitDict.Add('ю', "ju");
    TranslitDict.Add('я', "ja");
}


И для "режима совместимости":

private void FormDictCompat()
{
    TranslitDict.Clear();

    //Заглавные буквы (режим совместимости)
    TranslitDict.Add('А', "A");
	
    //часть кода вырезана для экономии места
    
    TranslitDict.Add('Ъ', "_");
    TranslitDict.Add('Ы', "Y");
    TranslitDict.Add('Ь', "_");
    TranslitDict.Add('Э', "E");
    TranslitDict.Add('Ю', "Ju");
    TranslitDict.Add('Я', "Ja");

    //строчные буквы (режим совместимости)
    TranslitDict.Add('а', "a");
	
    //часть кода вырезана для экономии места
    
    TranslitDict.Add('ъ', "_");
    TranslitDict.Add('ы', "y");
    TranslitDict.Add('ь', "_");
    TranslitDict.Add('э', "e");
    TranslitDict.Add('ю', "ju");
    TranslitDict.Add('я', "ja");
	
    //пробел
    TranslitDict.Add(' ', "_");
}


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

private bool compatibility = false;
  
public bool Compatibility
{
    get
    {
        return compatibility;
    }
    set
    {
        if (value)
        {
            FormDictCompat();
            compatibility = true;
        }
        else
        {
            FormDictStandart();
            compatibility = false;
        }
    }
}


Добавим простой конструктор класса:

public Translit(bool Compat)
{
    Compatibility = Compat;
}


Транслитерация символа


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

public string TranslitChar(char Rus)
{
    if (TranslitDict.ContainsKey(Rus))
    {
        return TranslitDict[Rus];
    }
    else
    {
        return Rus.ToString();
    }
}


Проверка строки на наличие русских символов.


Это я уже делал в маленьком примере (копия), так что просто вставлю функции оттуда:

//русские буквы
public static bool ContainsRus(string TestString)
{
    return
        Regex.IsMatch(TestString, @"[а-я]", RegexOptions.IgnoreCase);
}

//русские буквы и пробелы
public static bool ContainsRusOrSpace(string TestString)
{
    return
        Regex.IsMatch(TestString, @"[а-я]|\s", RegexOptions.IgnoreCase);
}


Транслитерация строки


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

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

Если искомого нет - возвращаем оригинальную строку.

2. Проходимся по символам строки, транслитерируем их, возвращаем новую строку.

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

public string TranslitString(string Rus)
{
    string sBuf = "";
    StringBuilder sb = new StringBuilder();

    if (compatibility)
    {
        if (!ContainsRusOrSpace(Rus)) return Rus;
    }
    else
    {
        if (!ContainsRus(Rus)) return Rus;
    }

    for (int i = 0; i < Rus.Length; i++)
    {
        if (TranslitDict.ContainsKey(Rus[i]))
        {
            sBuf = TranslitDict[Rus[i]];
        }
        else
        {
            sBuf = Rus[i].ToString();
        }
        
        sb.Append(sBuf);
    }

    return sb.ToString();
}


Исходники


Класс Translit на GitHub
Тестовый пример на GitHub

Это репост с сайта http://tolik-punkoff.com
Оригинал: https://tolik-punkoff.com/2021/11/08/c-kak-sdelat-transliteratsiyu-perevod-russkoj-stroki-v-latinitsu/

Tags: ,
C#, как присвоить char значение null или его аналог.

Пост из серии спрашивали - отвечаем.

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

Но иногда надо объявить переменную типа char, с которой работать будем потом, например, в цикле. Как тогда быть? Можно инициализировать переменную символом с кодом 0 (0x00). Проще всего сделать это так:

char Chr = '\0';

Но можно и другими способами:

char Chr = char.MinValue;
char Chr = (char)0;


Или даже с извращениями:

char Chr = "\0".ToCharArray()[0];

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

char Chr = Convert.ToChar(0);

Это репост с сайта http://tolik-punkoff.com
Оригинал: https://tolik-punkoff.com/2021/11/04/c-kak-prisvoit-char-znachenie-null-ili-ego-analog/

Tags: ,
C#, регулярное выражение для кириллицы.

Понадобилось тут узнать, содержит ли строка кириллицу. Решение через Regexp.

Кириллица


[а-я]

Кириллица или пробел


[а-я]|\s

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


Подключаем System.Text.RegularExpressions:

using System.Text.RegularExpressions;

Код:

public static bool ContainsRus(string TestString)
{
    return
        Regex.IsMatch(TestString, @"[а-я]", RegexOptions.IgnoreCase);
}

public static bool ContainsRusOrSpace(string TestString)
{
    return
        Regex.IsMatch(TestString, @"[а-я]|\s", 	RegexOptions.IgnoreCase);
}



Код на PasteBin

Это репост с сайта http://tolik-punkoff.com
Оригинал: https://tolik-punkoff.com/2021/11/03/c-regulyarnoe-vyrazhenie-dlya-kirillitsy/

Tags: ,
C#, как записать в STDERR сообщение об ошибке из консольного приложения.

Пост из серии спрашивали - отвечаем.

Итак, как в C# записать в STDERR. STDERR - это стандартный поток вывода для сообщений об ошибках, туда правильно организованные консольные приложения отправляют, собственно, сообщения об ошибках. Отправить в STDERR сообщение можно с помощью объекта Console.Error:

Console.Error.WriteLine("Write to STDERR.");

Код тестового приложения


static void Main(string[] args)
{
    Console.WriteLine("Write to STDOUT.");
    Console.Error.WriteLine("Write to STDERR.");
}


Проверка


Для проверки можно создать BAT-файл, вызывающий тестовое приложение и переопределяющий (копия) вывод со стандартных потоков в файлы stderr_.txt и stdout_.txt. stderr и stdout являются зарезервированными системными именами, потому к именам файлов надо что-то добавить, знак _ в данном случае:

Экран при выполнении тестового приложения:

Z:\...\write2stderr\write2stderr\bin\Debug>write2stderr.exe
Write to STDOUT.
Write to STDERR.

При выполнении BAT-файла экран останется пустым, но в директории с файлом появятся два файла stderr_.txt и stdout_.txt со следующим содержимым.

stderr_.txt:
	Write to STDERR.

stdout_.txt:
	Write to STDOUT.


Пример на GitHub


Исходник
Тестовый BAT-файл
BAT-файл и скомпилированный EXE

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2021/08/26/c-kak-zapisat-v-stderr-soobshhenie-ob-oshibke-iz-konsolnogo-prilozheniya/

Tags: ,
C#, ввод только цифр (чисел) в текстовое поле (TextBox).

Или окончательное решение цифирьного вопроса.

Преамбула


Ранее мы показывали простые способы, как обеспечить, чтобы в TextBox можно было ввести только цифры, т.е. целое число (копия), а потом расширили пример до ввода в TextBox отрицательных (копия) и дробных чисел (копия)

К сожалению, во всех этих примерах есть фатальный недостаток, текст в них все-таки вставить можно, если воспользоваться стандартным контекстным меню или комбинацией клавиш CTRL+V. На уровне простого взаимодействия с формой и контролами это перехватить невозможно, придется несколько извернуться, т.к. для перехвата события "вставить", придется перехватить сообщение Windows WM_PASTE, которое отправляется окну, или элементу управления окна при выполнении операции вставки. Для Windows, тащемта, однохуйственно, кому отправлять сообщение, форме (окну) или, например, текстовому полю. Т.к. для Windows, и текстовое поле на самом деле окно, просто дочернее, т.е. размещенное в другом окне (форме, в нашем случае). Но это я залез глубоко в бок. Нам нужно добраться до сообщений. А это можно сделать только изнутри самого контрола, но не из событий стандартных контролов, так что будем писать свой!

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

Начало


Подключим необходимые пространства имен:

using System.Windows.Forms;
using System.ComponentModel;
using System.Globalization;


Начнем делать свой контрол, наследуемый от TextBox. Т.е. создадим новый класс:

public class InputDigitControl:TextBox
{
	//тут будет код :)
}


Для начала необходимо определить сообщения, которые будем перехватывать. Заводим в классе константы, определяющие коды нужных сообщений:

const int WM_PASTE = 0x0302; //Сообщение "Вставка" (через к.м. и комбинацию клавиш)
const int WM_CHAR = 0x0102; //Сообщение - нажатие алфавитно-цифровой клавиши

WM_CHAR будет отправлено форме системой только тогда, когда будет нажата алфавитно-цифровая клавиша, его будем перехватывать для отслеживания цифр (и прочего). Правда есть важный нюанс - WM_CHAR посылается и при нажатии комбинаций клавиш, например Ctrl+C и т.д., а также некоторых клавиш, которые не совсем подходят под понятие "алфавитно-цифровая", например BACKSPACE. Это надо будет учесть.

Анализ ввода с клавиатуры будем производить в функции PreProcessMessage(), которую переопределим. PreProcessMessage() вызывается для предварительной обработки входящих сообщений, и нужно будет вернуть true, если это сообщение было обработано.

Т.е. алгоритм действий таков - мы проверяем входящий символ на соответствие, и, либо пропускаем его дальше (возвращаем base.PreProcessMessage(ref msg) или false), либо что-то делаем с содержимым текстового поля, если символ нужен (это понадобится при вводе отрицательных и дробей) и возвращаем true. Или ничего не делаем, если символ нежелательный, и просто вызываем true. В последнем случае, символ просто не попадет в поле ввода, т.к. контрол будет думать, что он уже обработан.

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


Контрол



Тестовое приложение

Репозиторий

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2021/08/10/c-vvod-tolko-tsifr-chisel-v-tekstovoe-pole-textbox/

Tags: ,
C#, перехват вывода консольной программы в реальном времени из собственного приложения.

Преамбула.


Итак, необходимо перехватить в реальном времени вывод консольной программы, которая запущена собственным приложением в фоновом режиме, например, как это делает GUI Openvpn для Windows.



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

Замечу только, что для вывода перехваченных сообщений использовал немного модифицированный ListView (копия)


Главное окно основной программы


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


Теперь надо подготовить несколько приложений для теста, одно будет консольное приложение на C#, которое генерирует случайное число, выводит его на консоль, ожидает 250 мс, и так повторяет в бесконечном цикле:

Бинарник testapp.exe
Исходный код

И несколько вариантов BAT-файлов, реализующий тот же функционал, только время ожидания составляет 1 секунду.

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

Еще одна вводная


1. В более современных версиях .NET можно использовать оператор async, но я решил обойтись без него, т.к. все возможности для перехвата данных с консоли были еще в .NET Framework 2.0. были, а слова такого не было. Как в анекдоте про Вовочку.
2. Запускать вызываемую консольную программу следует в отдельном потоке, с которым мы будем общаться как обычно - с помощью событий. Иначе чуда не получится - все будет висеть и не работать.

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

Основной класс.


Создадим новый класс, например Runner:

public class Runner

Выше класса добавляем публичный делегат (он нам потом для события понадобится)

public delegate void LogMessage(string Data);

Подключаем нужные пространства имен:

using System.Threading;
using System.Diagnostics;


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

public string ProcessPath { get; set; }

Заводим событие, которое будем генерировать при перехвате сообщения с консоли.

public event LogMessage LogSend;

И приватные переменные типов ProcessStartInfo, Process, для управления вызываемым процессом и типа Thread, для управления потоком, в котором будет запущен дочерний процесс.

private ProcessStartInfo Info = null;
private Process Proc = null;
private Thread t = null;


В конструкторе инициализируем переменную Info:

public Runner(string processpath)
{
    ProcessPath = processpath; //устанавливаем значение свойства ProcessPath
    Info = new ProcessStartInfo(ProcessPath);
    Info.RedirectStandardError = true; //перехват STDERR
    Info.RedirectStandardOutput = true; //перехват STDOUT
    Info.UseShellExecute = false; //иначе перехват работать не будет, см. MSDN
    Info.CreateNoWindow = true; //не запускать процесс в новом окне
                                //это скроет консоль запускаемой программы
}


Примечание: Присвоение свойству ShellExecute значения false позволяет перенаправлять потоки ввода, вывода и ошибки.

Запуск процесса и перехват вывода консоли


В функции StartProcess() непосредственно выполняем запуск процесса и перехват.

try
{
    Proc = Process.Start(Info);
}
catch (Exception ex)
{
    LogSend("INTERNAL ERROR: "+ex.Message);
    return;
}


Запускаем процесс, если произошла ошибка, вызываем событие, ответственное за отправку сообщения и выходим.

Для перехвата создаем цикл, в котором вызываем Process.StandardOutput.ReadLine(), пока результат не будет равен null.

StandardOutput.ReadLine() будет ждать, пока программа не выведет на консоль строку, и тогда вернет ее, или же вернет null, когда программа завершится.

string ConOut = "";

do
{
    ConOut = Proc.StandardOutput.ReadLine();
    if (ConOut != null)
    {
        LogSend(ConOut);
    }                

} while (ConOut != null);


Поскольку запуск этой функции вызовет "зависание", если запустить ее в основном потоке, то вызывать ее нужно в отдельном:

public void Start()
{
    t = new Thread(StartProcess);
    t.Start();
}


Ну и функция для остановки вызванного процесса:

public void Stop()
{
    if (Proc != null)
    {
        Proc.Kill();
        Proc = null;
    }

    if (t != null)
    {
        t.Abort();
        t = null;
    }
}


Основная форма


В коде основной формы создаем объект Runner, регистрируем обработчик событий, запускаем перехват, не забывая про останов по нажатию нужной кнопки:

Runner runner = null;
//...
private void btnStart_Click(object sender, EventArgs e)
{
    runner = new Runner(txtPath.Text);
    runner.LogSend += new LogMessage(runner_LogSend);            
    runner.Start();
}

private void btnStop_Click(object sender, EventArgs e)
{
    if (runner != null)
    {
        runner.Stop();
    }
}


В обработчике события отправляем данные в нужный элемент управления, не забывая про Invoke:

void runner_LogSend(string Data)
{
    Invoke((MethodInvoker)delegate
    {
        lvConsole.Items.Add(Data);
        lvConsole.EnsureVisible(lvConsole.Items.Count - 1);
    });
}


Результат



Перехват вывода из BAT-файла

Исходники


На GitHub

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2021/08/04/c-perehvat-vyvoda-konsolnoj-programmy-v-realnom-vremeni-iz-sobstvennogo-prilozheniya/

Tags: ,
C#, тайм-аут (sleep) в консольной программе.

Проще всего это сделать с помощью остановки потока (thread):

System.Threading.Thread.Sleep(время_в_миллисекундах);

Например:

System.Threading.Thread.Sleep(250);

остановит выполнение основного потока программы (если поток один, соответственно, программу) на 250 миллисекунд:

static void Main(string[] args)
        {
            
           //какой-то код

            System.Threading.Thread.Sleep(250);
            
            //какой-то код
			
        }


Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2021/07/30/c-tajm-aut-sleep-v-konsolnoj-programme/

Tags: ,
Калькулятор пропорций

Описание


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

История версий


v 0.0.1

Простой калькулятор пропорций. Запускается без установки.

v 0.0.2

Добавлена функция вычисления суммы платежа с комиссией.

v 0.0.3

Усовершенствован ввод чисел. Используется контрол InputDigitControl

Скриншоты








Исходники


Репозиторий на GitHub

Скачать


Файл в архиве (без установки).
Установщик

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/kalkulyator-proportsij/

Tags: ,
C#, получение списка дисков, доступных в системе, и некоторых их параметров

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

Делается с помощью функции DriveInfo[] Drives = DriveInfo.GetDrives(); из пространства имен System.IO.

Ссылки


DriveInfo.GetDrives() на MSDN
Класс DriveInfo на MSDN
Пример кода на PasteBin

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2021/07/28/c-poluchenie-spiska-diskov-dostupnyh-v-sisteme-i-nekotoryh-ih-parametrov/

Tags: ,
Менеджер отложенной автозагрузки

Назначение программы


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

Описание программы


Программа помещается на системный диск и должна находиться в автозагрузке системы. Пользователь, в настройках программы указывает пути к программам и документам, которые необходимо запустить, когда соответствующие носители с указанными программами будут доступны в ОС. Это могут быть внешние носители, такие как USB-диск, зашифрованный контейнер TrueCrypt/VeraCrypt и аналогичных систем, а также сетевые диски или сетевые папки. Программа StartupDelayed периодически проверяет доступность указанных пользователем программ, и при их наличии запускает их.

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

В качестве запускаемой задачи можно указать не исполняемый файл (exe, com, bat, cmd), но и документ, тогда он откроется в ассоциированной с ним программе.

Для исполнения задач, необходимо запустить менеджер с параметром командной строки /run.

Скриншоты



Основное окно настроек


Опции «Менеджера отложенной автозагрузки»


Окно добавления/редактирования задачи


Cправка по параметрам командной строки


Параметры командной строки:
StartupDelayed /help
StartupDelayed [/run] [/d]
/help
- эта справка
/run - выполнение задач
/d - запускать в "не-портативном режиме" (конфигурационные файлы в директории %LocalApplicationsData%\StartupDelayed)

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

Скачать


Портабельная версия (ZIP)

Инсталлятор

Исходники на GitHub

Официальные странички


На tolik-punkoff.com

Копия странички программы на LJR

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/menedzher-otlozhennoj-avtozagruzki/

Tags: ,
Менеджер отложенной автозагрузки / StartupDelayed v 0.0.2

Первая версия (копия)

+ Исправлен баг с сохранением конфигурации при удалении записей (спасибо SCPicker за тестирование и сообщение).

+ Убран режим выбора каталога конфигурации из командной строки, оставлен только обычный (файлы конфигурации в LocalApplicationData\StartupDelayed\) и портативный (файлы конфигурации в директории с программой).

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

+ Исправлены прочие мелкие недочеты.

+ Инсталлятор изменен на NSIS.

Скачать


Портабельная версия (ZIP)

Инсталлятор

Исходники на GitHub

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2021/07/21/menedzher-otlozhennoj-avtozagruzki-startupdelayed-v-0-0-2/

Tags: ,
Маленький пример обработки событий клавиатуры (KeyUp, KeyDown и KeyPress)



Пример выводит на экран KeyEventArgs для KeyUp и KeyDown и KeyPressEventArgs для KeyPress.

Исходник на GitHub

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2021/05/15/malenkij-primer-obrabotki-sobytij-klaviatury-keyup-keydown-i-keypress/

Tags: ,
Калькулятор пропорций v 0.2

Задолбало меня считать сумму внесения платежей с комиссией, через терминалы (или с международными переводами, один хрен, там с комиссией), так что запряг друга $EG'у, чтоб он разобрался в вопросе и допилил эту функцию в калькулятор пропорций. Он, ВНЕЗАПНО, допилил:



Формула


var paymentWithCommission = payment / (1 - 100 / proc);

где:
payment - необходимая сумма платежа
proc - процент комиссии

Скачать


Установщик
Бинарник без установки (ZIP)

Исходник


На GitHub

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2021/05/14/kalkulyator-proportsij-v-0-2/

Tags: ,
Пакетный конвертер (перекодировщик) текстовых файлов v 0.0.3b

Обновление пакетного конвертера текстовых файлов.

Благодарим всех, кто сообщил о багах.

Изменения в версии v 0.0.3b


+ Изменения в алгоритме поиска файлов
+ Поправлен баг с сохранением конфигурации (масок файлов)

Исходники


Репозиторий на GitHub

Скачать


Портативная версия

Постоянная страничка программы (копия)

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2021/03/14/paketnyj-konverter-perekodirovshhik-tekstovyh-fajlov-v-0-0-3b/

Tags: ,
Пакетный конвертер (перекодировщик) текстовых файлов

Изначально писалось для товарищей в 2016 г., поскольку почему-то все пакетные конвертеры/перекодировщики текстовых файлов были исключительно платными, во всяком случае на тот момент и под Windows.

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


+ Пакетная перекодировка текстовых файлов
+ Создание полного дерева каталогов для перекодированных файлов
+ Доступен расширенный список кодировок (все кодировки, поддерживаемые .NET Framework)

Изменения в версии v 0.0.2b


+ Добавлена возможность сохранять изменения в целевой каталог (перезаписывать файлы)
+ Программа по умолчанию работает в портативном режиме, настройки хранятся в каталоге с программой.
+ Изменен формат файла настроек на XML

Изменения в версии v 0.0.3b


+ Изменения в алгоритме поиска файлов
+ Поправлен баг с сохранением конфигурации (масок файлов)

Системные требования


Windows XP/7/8/10
.NET Framework 2.0.
256 Мб ОП

Ключи командной строки


/help - эта помощь
/np - отключение портативного режима
(настройки программы хранятся в C:\Users\<пользователь>\AppData\Local\BatchTextConverter\)

Разработчики


D. Larin
Chang Min Ho
PunkArr[]

Скриншоты



Главный экран



Выбор кодировки


Выбор кодировок (полный список)


Маски файлов


Исходники


Репозиторий на GitHub

Скачать


Портативная версия

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/batch-text-converter/

Tags: ,
C#, поиск файла по маске, более правильное решение.

Преамбула


Когда-то уже говорил (копия) что стандартная функция C# Directory.GetFiles(); неправильно ищет файлы по маске. И даже сделал на скорую руку кривофикс, но кривофикс действительно оказался именно что криво. Во-первых, срабатывал только для некоторых масок, а во-вторых, оказался чувствительным к регистру имен файлов. Делаем более прямое исправление.

Вспомогательные функции


Заведем вспомогательную функцию, которая будет добавлять конечный слэш (\) к имени директории. Оно не особо надо, но пусть будет для порядка.

private static string AddSlash(string st)
{
    if (st.EndsWith("\\"))
    {
        return st;
    }

    return st + "\\";
}


И функцию, получающую имя файла из полного пути. Конечно, можно было бы воспользоваться классом FileInfo из System.IO, но тут операция совсем уж простая, а FileInfo может сгенерировать ненужный Exception. Проще получить имя файла с помощью строковой операции:

private static string GetNameOnly(string FullName)
{
    int LastSlash = FullName.LastIndexOf("\\");
    
    if (LastSlash == -1) return FullName;

    return FullName.Substring(LastSlash + 1);
}


Преобразование маски файла в регулярное выражение.


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

1. В имени файла могут встретиться символы, считающиеся служебными в регулярном выражении (.,^,$,{,},[,],(,),+), их необходимо экранировать, чтоб они воспринимались обработчиком регулярных выражений, как обычные, а не служебные символы.

//точка в маске файла должна быть точкой в регулярном выражении
//экранируем
Mask = Mask.Replace(".", "\\.");
//^,$,{,},[,],(,),+ в regexp служебные, в именах файла допустимые
//экранируем
Mask = Mask.Replace("^", "\\^");
Mask = Mask.Replace("$", "\\$");
Mask = Mask.Replace("{", "\\{");
Mask = Mask.Replace("}", "\\}");
Mask = Mask.Replace("[", "\\[");
Mask = Mask.Replace("[", "\\[");
Mask = Mask.Replace("(", "\\(");
Mask = Mask.Replace(")", "\\(");
Mask = Mask.Replace("+", "\\+");


2. * - в маске файла это любой символ, или их отсутствие. В регулярном выражении этому соответствует комбинация .*, заменяем:

Mask = Mask.Replace("*", ".*");

3. ? в маске файла - любой существующий символ. В регулярном выражении это символ . (точка), заменяем:

Mask = Mask.Replace("?", ".");

4. Осталось ограничить работу регулярного выражения началом и концом строки, строкой будет являться имя (маска) файла. Начало строки обозначается символом ^, конец символом $. Добавляем:

Mask = "^" + Mask + "$";

Функция целиком:

private static string Mask2Reg(string Mask)
{
    //точка в маске файла должна быть точкой в регулярном выражении
    //экранируем
    Mask = Mask.Replace(".", "\\.");
    //^,$,{,},[,],(,),+ в regexp служебные, в именах файла допустимые
    //экранируем
    Mask = Mask.Replace("^", "\\^");
    Mask = Mask.Replace("$", "\\$");
    Mask = Mask.Replace("{", "\\{");
    Mask = Mask.Replace("}", "\\}");
    Mask = Mask.Replace("[", "\\[");
    Mask = Mask.Replace("[", "\\[");
    Mask = Mask.Replace("(", "\\(");
    Mask = Mask.Replace(")", "\\(");
    Mask = Mask.Replace("+", "\\+");
    //* - любое количество любого символа, 
    //в regexp любой символ - точка, любое количество *
    Mask = Mask.Replace("*", ".*");
    //? - любой символ, в regexp любой символ - точка.
    Mask = Mask.Replace("?", ".");

    //добавляем начало и конец строки к имени файла.
    Mask = "^" + Mask + "$";

    return Mask;
}


Модификация функции поиска


В модифицированную функцию поиска передаются такие же параметры, как и в функцию Directory.GetFiles(); т.е. маска файла, путь до каталога и перечисление SearchOption, которое может принимать два значения: SearchOption.AllDirectories - поиск с подкаталогами и SearchOption.TopDirectoryOnly - поиск только в текущем каталоге.

Внутри функции:

1. Преобразуем маску файла в регулярное выражение:

string MaskRegStr = Mask2Reg(sMask);

2. Добавляем слеш к пути поиска (на всякий случай):

sPath = AddSlash(sPath);

3. Заводим List<string>, куда будем складировать отфильтрованные файлы из найденных (на то, как криво работает Directory.GetFiles() есть ссылки в начале заметки).

List<string> FoundFiles = new List<string>();

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

Regex MaskReg = new Regex(MaskRegStr, RegexOptions.IgnoreCase);

5. Вызываем функцию поиска из System.IO:

string[] files = Directory.GetFiles(sPath, sMask, SO);

6. Фильтруем вывод на предмет лишних файлов (см. подробнее по ссылке в начале заметки). Фильтрация производится путем сравнения имени файла с ранее сгенерированным регулярным выражением. Если имя файла соответствует регулярке, оно добавляется в List:

foreach (string filename in files)
{                                
    if (MaskReg.IsMatch(GetNameOnly(filename)))
    {
        FoundFiles.Add(filename);
    }
}


7. Результат возвращается в виде строкового массива:

return FoundFiles.ToArray();

Функция целиком:

public static string[] Find(string sPath, string sMask, SearchOption SO)
{
    string MaskRegStr = Mask2Reg(sMask);
    sPath = AddSlash(sPath);
    List<string> FoundFiles = new List<string>();
    Regex MaskReg = new Regex(MaskRegStr, RegexOptions.IgnoreCase);

    string[] files = Directory.GetFiles(sPath, sMask, SO);

    foreach (string filename in files)
    {                                
        if (MaskReg.IsMatch(GetNameOnly(filename)))
        {
            FoundFiles.Add(filename);
        }
    }
    return FoundFiles.ToArray();
}


Пример на GitHub


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

Пример на GitHub

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2021/03/11/c-poisk-fajla-po-maske-bolee-pravilnoe-reshenie/

Tags: ,
C#. Удаление значений (values) из ключа Реестра

Преамбула


Задача довольно простая, имеется ключ в разделе Реестра Windows, необходимо удалить оттуда все значения (values).

Термины и определения


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

HKEY_CLASSES_ROOT (HKCR) - Зарегистрированные типы файлов, объекты COM и ActiveX
HKEY_CURRENT_USER (HKCU) - Настройки текущего пользователя, в данный момент вошедшего в систему.
HKEY_LOCAL_MACHINE (HKLM) - Общие настройки для всех пользователей данного компьютера.
HKEY_USERS (HKU) - Профили всех пользователей данной машины.
HKEY_CURRENT_CONFIG (HKCC) - Профили оборудования, информация о драйверах.

Подключ/Subkey (иногда Ключ, если корневой раздел называется корневым разделом или корневым ключом) Реестра - путь в Реестре, аналогичный пути к каталогу (папке) файловой системы. Обычно каждый подключ хранит или настройки для конкретного случая. Например, настройки конкретной программы или профиль конфигурации оборудования. Выглядит примерно так: Software\TestKey (в полном виде, вместе с корневым ключом, например: HKEY_CURRENT_USER\Software\TestKey).

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



Обзорная статья про Реестр Windows на Википедии


Тестовый ключ


Для тестирования создадим тестовый ключ, который не будет влиять на какие либо программы и компоненты ОС. Это можно сделать, как вручную, с помощью программы Regedit, так и в автоматическом режиме, с помощью reg-файла, например, такого:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\TestKey]
"value0"="text0"
"value1"="text1"
"value2"="text2"
"value3"="text3"
"value4"="text4"
"value5"="text5"


Файл на GitHub

Можно создать и reg-файл для удаления тестового ключа из Реестра, если что-то пойдет не так:

Windows Registry Editor Version 5.00

[-HKEY_CURRENT_USER\Software\TestKey]


Файл на GitHub

Решение


1. Подключаем пространство имен Microsoft.Win32:

using Microsoft.Win32;

2. Создаем переменную с именем подключа Реестра и переменную типа RegistryKey. Этот объект и будет рулить нужной веткой Реестра:

string subkey = "Software\\TestKey";
RegistryKey key = null;


3. Любые операции с Реестром могут привести к ошибкам, потому их как и операции ввода-вывода желательно оборачивать в try..catch:

try
{
    //тут будет код.
}
catch (Exception ex)
{
    Console.WriteLine("ERROR: " + ex.Message);
}


4. Открываем (под)ключ Реестра:

key = Registry.CurrentUser.OpenSubKey(subkey, true);

Внимание! Если необходимо писать в ключ Реестра, обязательно устанавливаем второй параметр функции OpenSubKey в true, т.к. в противном случае, мы получим ошибку UnauthorizedAccessException: Не удалось выполнить запись в раздел реестра.



Обсуждение на Cyberforum

5. Получить список значений в (под)ключе можно функцией GetValueNames(), которая выдает строковый массив с именами значений Реестра.

6. Получаем имена всех значений и в цикле удаляем их с помощью функции DeleteValue(имя_параметра);

foreach (string valname in key.GetValueNames())
{
    Console.WriteLine("Delete value: " + valname);
    key.DeleteValue(valname);
}


7. Закрываем (под)ключ Реестра.

key.Close();

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



Код целиком


На PasteBin

Тестовый пример


Пример на GitHub

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2021/02/04/c-udalenie-znachenij-values-iz-klyucha-reestra/

Tags: ,
Back Viewing 0 - 20