<?xml version="1.0" encoding="utf-8"?>

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
	<channel>
		<title>Форум программистов и сисадминов Киберфорум - Блоги - Rius</title>
		<link>https://www.cyberforum.ru/blogs/594854/</link>
		<description>КиберФорум - форум программистов, системных администраторов, администраторов баз данных, компьютерный форум, форум по электронике и бытовой технике, обсуждение софта. Бесплатная помощь в решении задач по программированию и наукам, решение проблем с компьютером, операционными системам</description>
		<language>ru</language>
		<lastBuildDate>Thu, 07 May 2026 07:36:48 GMT</lastBuildDate>
		<generator>vBulletin</generator>
		<ttl>60</ttl>
		<image>
			<url>https://www.cyberforum.ru//cyberstatic.net/images/misc/rss.jpg</url>
			<title>Форум программистов и сисадминов Киберфорум - Блоги - Rius</title>
			<link>https://www.cyberforum.ru/blogs/594854/</link>
		</image>
		<item>
			<title>Сага о X, Y и Z...</title>
			<link>https://www.cyberforum.ru/blogs/594854/6705.html</link>
			<pubDate>Thu, 13 Aug 2020 17:09:41 GMT</pubDate>
			<description>Однажды Новичок захотел сделать X. Но поскольку Новичок был новичком, X с ходу у него сделать не...</description>
			<content:encoded><![CDATA[<div>Однажды Новичок захотел сделать X. Но поскольку Новичок был новичком, X с ходу у него сделать не получилось...<br />
<br />
Ну, бывает, ничего в этом плохого нет: все мы были когда-то новичками. Чтобы решить проблему, Новичок решил воспользоваться форумом по программированию. Вы думаете он создал там тему вида: &quot;Я хочу получить X. Пытаюсь сделать 111, получаю 222. Как сделать X?&quot;? Нет! Новичок решил (ошибочно, т.к. Новичок пока не обладает достаточным знанием), что если он сумеет сделать Y, то с помощью Y он получит и X. Поэтому он написал: &quot;Делаю 111, получаю 222. Как получить Y?&quot; (ещё бывает, что Новичок задаёт только &quot;Как сделать Y?&quot;).<br />
<br />
Примечание: если вы зашли сюда по ссылке, оставленной в ответе на ваш вопрос на форуме, то это значит, что вы создали тему &quot;Как сделать Y?&quot; или &quot;Как сделать Y? Использовать Z не предлагать!&quot; (про Z см. ниже).<br />
<br />
Чаще всего, Y бывает невозможным, некорректным, сложным или вообще страшно извращённым и нелогичным действием. У всех Понимающих людей вопрос &quot;как сделать Y?&quot; вызывает недоумение: зачем это нужно? Это же бессмысленно. Всеми силами (иногда с привлечением утюга!) пытаются выпытать у Новичка Понимающие, что же ему на самом деле нужно. Но не сдаётся Новичок: он же хочет узнать, как сделать Y. Каких только Слонов не рождали глубокие умы, пытаясь постичь неисповедимые пути Новичка! Иногда даже бывает так, что Понимающие знают ответ на вопрос &quot;как сделать Y?&quot;, но специально его не говорят, потому что эти действия лишены смысла. Они ещё надеются наставить Новичка на путь истинный.<br />
<br />
Но вот, используя шаманский бубен, миелофон, шестое чувство, телепатор и прочие БС (Божественные Силы) кто-то из Понимающих вопрошает:<br />
- А, может быть, вы хотите сделать X?<br />
- Да, я хочу получить X. Как мне сделать Y?<br />
- Аааа! Ну тогда вам не нужно Y! Вам нужно Z! Если вы сделаете Z так и сяк, то потом с помощью Z вот так и вот этак вы получите X.<br />
- Ой, правда. Спасибо!<br />
<br />
Что ж, вот пример хорошей и доброй концовки, когда все остаются довольными.<br />
<br />
Но бывает и так, что кто-то из начинающих Понимающих (вчерашний Новичок), думая, что этим он помогает Новичку (или же сам Понимающий, но уже от безысходности, в надежде, что Новичок разумно распорядится даруемой в его руки Божественной Силой), даёт ответ на вопрос &quot;как же сделать Y&quot;. Ура! - кричит Новичок и убегает доделывать Страшного Монстра, при встрече с которым потом даже самым смелым Понимающим целый месяц снятся кошмары. Тёмные Силы празднуют победу в этот день. Душа Новичка обречена гореть в геенне огненной за грехи свои.<br />
<br />
А ещё бывает так, что Новичок думает, что ему отвечает другой новичок. И кажется ему, что ответ с Z неверен. И тогда он говорит: &quot;мне не нужен Z! Мне нужно сделать Y!&quot;. И если переубедить Новичка в том, что ему нужен Z, не удаётся, Новичок уходит на другой форум, где задаёт вопрос: &quot;Мне нужен X! Как мне сделать Y? Использовать Z не предлагать!!!!!!&quot;<br />
<br />
Вот так-то.<br />
<br />
P.S. Наглядный и простой пример: &quot;Как программно очистить все изменения на форме? Т.е. мне нужно пересоздать форму и соответственно она вернётся к начальному состоянию&quot;. В итоге: &quot;В общем-то мне нужно вернуть нулёвое значение для ComboBox2. Может это можно как-то проще сделать?&quot;. Называется: &quot;приехали!&quot;.<br />
<br />
P.P.S. Данная проблема также известна в англоязычном интернете как <b>The XY Problem</b><ul><li><a rel="nofollow noopener noreferrer" href="https://en.wikipedia.org/wiki/XY_problem" target="_blank" title="https://en.wikipedia.org/wiki/XY_problem">https://en.wikipedia.org/wiki/XY_problem</a></li>
<li><a rel="nofollow noopener noreferrer" href="https://xyproblem.info/" target="_blank" title="https://xyproblem.info/">https://xyproblem.info/</a></li>
</ul><br />
<br />
Оригинал: <a rel="nofollow noopener noreferrer" href="https://www.gunsmoker.ru/2008/10/x-y-z.html" target="_blank" title="https://www.gunsmoker.ru/2008/10/x-y-z.html">Блог GunSmoker-а - Сага о X, Y и Z...</a></div>

]]></content:encoded>
			<dc:creator>Rius</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/594854/6705.html</guid>
		</item>
		<item>
			<title>Велосипедим обновлятор</title>
			<link>https://www.cyberforum.ru/blogs/594854/6526.html</link>
			<pubDate>Sun, 26 Apr 2020 19:34:42 GMT</pubDate>
			<description>*Как организовать автообновление десктопной программы.* 
 
Безотносительно языка программирования....</description>
			<content:encoded><![CDATA[<div><b>Как организовать автообновление десктопной программы.</b><br />
<br />
Безотносительно языка программирования.<br />
<br />
Заранее, прежде чем приступать к кодингу, должно быть решено несколько вопросов:<ol style="list-style-type: decimal"><li>[ALINK=&quot;packaging&quot;]В каком виде поставлять обновления?[/ALINK]</li>
<li>[ALINK=&quot;how_check_new_version&quot;]Как проверять, что существует новая версия?[/ALINK]</li>
<li>[ALINK=&quot;when_check_new_version&quot;]Когда проверять, что существует новая версия?[/ALINK]</li>
<li>[ALINK=&quot;when_start_downloading&quot;]Когда начинать загрузку?[/ALINK]</li>
<li>[ALINK=&quot;how_download&quot;]Как загружать?[/ALINK]</li>
<li>[ALINK=&quot;when_install&quot;]Когда устанавливать?[/ALINK]</li>
<li>[ALINK=&quot;how_install&quot;]Как устанавливать?[/ALINK]</li>
<li>[ALINK=&quot;after&quot;]Что делать с данными?[/ALINK]</li>
</ol><br />
[APLACE=&quot;packaging&quot;]<b>В каком виде поставлять обновление?</b>[/APLACE]<ul><li>Если программа из нескольких файлов (dll и прочие ресурсы), то<ul><li>Либо архив, тогда также же в программе должна быть встроена функциональность распаковки/удаления/замены файлов;</li>
<li>Либо инсталлятор, который это всё автоматом берёт на себя;</li>
</ul></li>
<li>Если программа из одного EXE, можно поставлять его. Но тогда в программе должны быть предусмотрены некоторые дополнительные функции (см. ниже);</li>
<li>Если файлов достаточно много (клиент какой-либо игры на фришарде), лучше всего посмотреть через сниффер, как этот вопрос решают существующие клиенты игр (типа EVE Online, Elite Dangerous, WoT и др.).<br />
Так как в этом случае может быть оптимальнее загружать только отличающиеся файлы, а то и вовсе лишь сами отличия (патчи).<br />
Пример по ссылке в конце ↓↓↓</li>
</ul><br />
[APLACE=&quot;how_check_new_version&quot;]<b>Как проверять, что существует новая версия?</b>[/APLACE]<br />
В первую очередь, программа должна иметь при себе собственный идентификатор версии ПО.<br />
Хеш или контрольная сумма файлов программы не годятся, т.к. позволяют только определить только сам факт отличия, а не сравнить, где (здесь или там) версия новее.<br />
Это может быть либо номер версии (<i>172</i> или <i>1.0.0.8</i>), либо дата (<i>2020-04-28T23:45:00</i>), либо что-то ещё, позволяющее программе сравнить две версии и однозначно определить, какая из них новее.<br />
Если у вас такого нет вообще, стоит рассмотреть применение, например, <a rel="nofollow noopener noreferrer" href="https://semver.org/lang/ru/" target="_blank" title="https://semver.org/lang/ru/">Семантического Версионирования</a>.<br />
<br />
Далее, программа должна уметь запрашивать данные о доступных обновлениях у поставщика обновлений, а поставщик должен уметь эти данные предоставлять.<br />
В случае применения простого сетевого диска в локальной сети, можно расположить текстовый (json, xml) файлы с необходимыми данными.<br />
В случае своего сервера также можно просто выложить файл (FTP), либо реализовать Web API (на shared хостинге, VPS).<br />
<br />
Файл данных должен содержать необходимую для обновления информацию, в частности идентификатор версии ПО и url файла обновления.<br />
Реомендуется предусмотреть хеш файла, с целью проверки его корректности после загрузки.<br />
Также можно добавить дата выпуска, список отличий от предыдущей версии, хеш ревизии и дату коммита Git, и пр.<br />
С сервера, для выложенной на нём актуальной версии программы, требуется получить идентификатор версии ПО.<br />
Пример, как может выглядеть файл в простом случае:<br />
<div class="codeblock"><table class="json"><thead><tr><td colspan="2" id="413995442"  class="head">JSON</td></tr></thead><tbody><tr class="li1"><td><div id="413995442" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="de1"><pre class="de1"><span class="br0">&#123;</span>
&nbsp; <span class="st0">&quot;Items&quot;</span><span class="sy0">:</span> <span class="br0">&#91;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;Uri&quot;</span><span class="sy0">:</span> <span class="st0">&quot;https://www.cyberforum.ru/updates/program_1.0.0.exe&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;FileVersion&quot;</span><span class="sy0">:</span> <span class="st0">&quot;1.0.0.0&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;ProductVersion&quot;</span><span class="sy0">:</span> <span class="st0">&quot;1.0.0+Branch.master.Sha.bed8da0d56ea48c5e580e3e557f81360c0405431&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;SHA1&quot;</span><span class="sy0">:</span> <span class="st0">&quot;W/+KW9hRW7pmU5EpB064psKLjHs=&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;Changes&quot;</span><span class="sy0">:</span> <span class="br0">&#91;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;Первый выпуск&quot;</span>
&nbsp; &nbsp; &nbsp; <span class="br0">&#93;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;Uri&quot;</span><span class="sy0">:</span> <span class="st0">&quot;https://www.cyberforum.ru/updates/program_1.1.0.exe&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;FileVersion&quot;</span><span class="sy0">:</span> <span class="st0">&quot;1.1.0.0&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;ProductVersion&quot;</span><span class="sy0">:</span> <span class="st0">&quot;1.1.0+Branch.master.Sha.12adef0d56ea48c5e580e3e557f81360c0405431&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;SHA1&quot;</span><span class="sy0">:</span> <span class="st0">&quot;W/+459hRW7pmU5E1B064psKLjHs=&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;Changes&quot;</span><span class="sy0">:</span> <span class="br0">&#91;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;Исправлены старые баги&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;Добавлены новые баги&quot;</span>
&nbsp; &nbsp; &nbsp; <span class="br0">&#93;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; <span class="br0">&#93;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Программа просматривает такой файл и выясняет, есть ли версия новее, где её скачать, и о чём стоит сообщить пользователю.<br />
<br />
[APLACE=&quot;when_check_new_version&quot;]<b>Когда проверять, что существует новая версия?</b>[/APLACE]<br />
Встречаются такие варианты:<ul><li>Явным вызовом в меню программы Справка - Проверить наличие обновлений;</li>
<li>Автоматически при запуске программы;</li>
<li>Перидически в ходе работы программы;</li>
<li>Через планировщик заданий Windows (хотя, зачем?).</li>
</ul>Иногда при установке программы разработчик предлагает опцию &quot;Проверять обновления автоматически&quot;. В зависимости от выбора пользователя далее работает либо ручная проверка, либо автоматическая.<br />
<br />
[APLACE=&quot;when_start_downloading&quot;]<b>Когда начинать загрузку?</b>[/APLACE]<ul><li>Обычно загрузка предлагается после успешной проверки наличия новой версии;</li>
<li>Некоторые программы загружают обновление сами, в фоне;</li>
<li>Иногда стоит спрашивать о необходимости загрузки. Например, если пакет обновления большой или установка сложна;</li>
<li>При показе запроса о начале загрузки, пользователю может быть предоставлена опция отложить установку на некоторое время, в том числе и вовсе отменить (пропустить) обновление.</li>
</ul><br />
[APLACE=&quot;how_download&quot;]<b>Как загружать?</b>[/APLACE]<ul><li>Некоторые программы выдают ссылку на сайт и предлагают пользователю скачать обновление самостоятельно;</li>
<li>Другие приостанавливают работу и в модальном окне показывают ход загрузки файлов;</li>
<li>Третьи показывают прогресс где-то в статусбаре, либо вообще не показывают.</li>
</ul>Сама загрузка обычно не представляет проблемы, благодаря использованию средств фреймворка и библиотек.<br />
Разве что своего сайта нет и файлы лежат на каком-нибудь облачном хранилище, откуда скачать что-либо можно, только если зайти самостоятельно и кликнуть куда-нибудь. В этом случае следует просто выдать пользователю ссылку на сайт, либо открыть его в браузере.<br />
<br />
[APLACE=&quot;when_install&quot;]<b>Когда устанавливать?</b>[/APLACE]<br />
Обычно после загрузки сообщается о готовости к установке и предлагается установить обновления. Встречающиеся варианты:<ul><li>Закрыть программу и начать установку.</li>
<li>Дождаться закрытия программы и начать установку.</li>
</ul>Закрывать программу без разрешения пользователя не принято.<br />
<br />
[APLACE=&quot;how_install&quot;]<b>Как устанавливать?</b>[/APLACE]<br />
Если используется инсталлятор, достаточно запустить его и сразу закрыть программу.<br />
Исполняемые файлы программы под Windows обычно не могут быть удалены, если они запущены. <a rel="nofollow noopener noreferrer" href="https://www.codeproject.com/Articles/17052/Self-Deleting-Executables" target="_blank" title="https://www.codeproject.com/Articles/17052/Self-Deleting-Executables">Там всё не просто</a>, но обходные пути не нужны, т.к. уже давно придумано простое решение. →<br />
Поэтому инсталлятор должен дождаться завершения программы, и лишь потом начать установку. Сделать это можно, например, применением Mutex'а. В частности, <a rel="nofollow noopener noreferrer" href="https://jrsoftware.org/ishelp/topic_setup_appmutex.htm" target="_blank" title="https://jrsoftware.org/ishelp/topic_setup_appmutex.htm">такая опция есть у Inno Setup</a>. Инсталлятор пытается создать локальный и/или глобальный Mutex, который также создаёт и программа. А Mutex, как известно, может быть создан только один, в пределах сессии или глобально (см. <a rel="nofollow noopener noreferrer" href="https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createmutexa#parameters" target="_blank" title="https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createmutexa#parameters">CreateMutexA function (synchapi.h)</a>).<br />
Тот же инсталлятор в ходе установки определит каталог текущей версии, удалит её, и установит новую. И запустит приложение.<br />
<br />
Если используется просто архив, то, загрузив его во временный каталог, следует разместить там исполняемый файл, либо какой-нибудь консольный скрипт. Далее он получит от вашей программы путь установки, дождётся закрытия программы, удалит её, распакует в указанное место новые файлы, запустит установленную программу, удалит временные файлы. И затем удалит себя, а если не сможет, попросит об этом установленную программу.<br />
<br />
Если автор - ССЗБ и вместо инсталлятора (или иной, более полезной функциональности программы) гордо возится с <a href="https://www.cyberforum.ru/tags/%D0%B5%D0%B4%D0%B8%D0%BD%D1%8B%D0%B9%20exe.html">единым exe</a>, то единственно что в предыдущей (архив) последовательности упрощается - распаковка одного файла вместо нескольких. Всё. ]:-&gt;<br />
<br />
Также, есть вариант установить новую версию <u>рядом</u> с существующей, без её удаления. Программа при запуске проверит наличие рядом более новой версии и при обнаружении запустит её, после чего сама закроется. При обнаружении же рядом прежней версии её можно будет удалить.<br />
<br />
[APLACE=&quot;after&quot;]<b>Что делать с данными?</b>[/APLACE]<ul><li>Если программа не имеет никаких сохраняемых данных, то и проблемы нет.</li>
<li>Если есть, но их формат никак не меняется от версии к версии, то достаточно их хранить в каталоге пользовательских данных или реестре. Т.е. не в каталоге программы.</li>
<li>Если же формат меняется, требуется предусмотреть, что делать при запуске новой версии программы со старыми данными, либо старой программы с новыми данными (если надо откатиться на предыдущую версию ПО). Но хранить их также рекомендуется отдельно.</li>
<li>В случае использования базы данных всё гораздо сложнее. Если тема незнакомая, стоит почитать, например, <a rel="nofollow noopener noreferrer" href="https://habr.com/ru/post/121265/" target="_blank" title="https://habr.com/ru/post/121265/">Версионная миграция структуры базы данных: основные подходы</a>.</li>
</ul><br />
Примеры:<ul><li><a href="https://www.cyberforum.ru/qt/thread2717850.html#post14946753">Простейший обновлятор приложения на PowerShell с использованием файловой системы</a>.</li>
<li><a href="https://www.cyberforum.ru/windows-forms/thread3077011.html">Скачивание файлов с папки</a>. Только отличающихся файлов. Как у игр.</li>
</ul></div>

]]></content:encoded>
			<dc:creator>Rius</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/594854/6526.html</guid>
		</item>
		<item>
			<title>Go to MISRA C</title>
			<link>https://www.cyberforum.ru/blogs/594854/5841.html</link>
			<pubDate>Mon, 03 Jun 2019 08:03:50 GMT</pubDate>
			<description>Для справки. 
Что по этому оператору сказано в стандарте MISRA C...</description>
			<content:encoded><![CDATA[<div>Для справки.<br />
Что по этому оператору сказано в стандарте <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/MISRA_C" target="_blank" title="https://ru.wikipedia.org/wiki/MISRA_C">MISRA C</a> (версии 2012), применяемом, <s>чтобы самолёты не падали</s> в автомобильной, аэрокосмической, медицинской отраслях.<br />
<br />
<font color="Blue">Правило 15.1 Оператор goto не должен использоваться.</font><br />
<br />
<i>Обоснование</i><br />
Неограниченное использование goto может привести программы к тому, что они станут неструктурироваными и чрезвычайно сложными для понимания.<br />
<br />
В некоторых случаях полный запрет goto требует введения флагов для корректировки потока выполнения и, возможно, эти флаги могут сами по себе быть менее прозрачными, чем goto, который они заменяют.<br />
Поэтому, если не следовать этому правилу, ограниченное использование goto позволяется там, где соблюдаются правила 15.2 и 15.3.<br />
<br />
<font color="blue">Правило 15.2 Оператор goto должен переходить только к метке, объявленной позже в той же функции.</font><br />
<br />
<i>Обоснование</i><br />
Неограниченное использование goto может привести программы к тому, что они станут неструктурироваными и чрезвычайно сложными для понимания.<br />
<br />
Запрет на использование goto для переходов назад гарантирует, что итерация можно возникнуть только если применён оператор итерации, предоставленный используемым языком (программирования), помогая минимализировать визуальную сложность кода.<br />
<br />
<font color="blue">Правило 15.3 Любая метка, на которую ссылается оператор goto, должна быть определена в том же блоке, или в любом блоке, окружающем оператор goto.</font> (Т.е. наружу).<br />
<br />
<i>Обоснование</i><br />
Неограниченное использование goto может привести программы к тому, что они станут неструктурироваными и чрезвычайно сложными для понимания.<br />
<br />
Предотвращение переходов между блоками, или во вложенные блоки, помогает минимализировать визуальную сложность кода.<br />
<br />
<font color="blue">Правило 15.4 Для прерывания любого итерационного выражения должно использоваться не более одного break или goto.</font><br />
<br />
<i>Обоснование</i><br />
Ограничение числа выходов из цикла помогает минимализировать визуальную сложность кода. Использование одного break или goto позволяет создать единый вторичный путь выхода, когда требуется раннее прерывание цикла.<br />
<br />
<br />
P.S. Если Вы не знаете, что данный стандарт призван избежать ошибок в <a rel="nofollow noopener noreferrer" href="https://en.wikipedia.org/wiki/Safety-critical_system" target="_blank" title="https://en.wikipedia.org/wiki/Safety-critical_system">safety-critical системах</a>, от которых зависят жизни людей, просьба его не комментировать а-ля &quot;а давайте ещё удалим jump из ассемблера&quot;.</div>

]]></content:encoded>
			<dc:creator>Rius</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/594854/5841.html</guid>
		</item>
		<item>
			<title>Относительное зло или когда пути неисповедимы</title>
			<link>https://www.cyberforum.ru/blogs/594854/5377.html</link>
			<pubDate>Fri, 03 Aug 2018 05:24:47 GMT</pubDate>
			<description>Часто встречаются такие и подобные вопросы: 
* На отладке работает, но не работает в нужной папке -...</description>
			<content:encoded><![CDATA[<div>Часто встречаются такие и подобные вопросы:<ul><li><a href="https://www.cyberforum.ru/csharp-beginners/thread1541212.html">На отладке работает, но не работает в нужной папке - C#</a></li>
<li><a href="https://www.cyberforum.ru/windows-forms/thread1471056.html">Отказано в доступе по пути С# - C#</a></li>
<li><a href="https://www.cyberforum.ru/windows-forms/thread1751719.html">Не найден файл - C#/.NET 4.x</a></li>
<li><a href="https://www.cyberforum.ru/ado-net/thread1770904.html">Путь к базе - C#</a></li>
<li><a href="https://www.cyberforum.ru/pascalabc-net/thread2017619.html#post10626574">Программа неправильно работает при запуске через Планировщик Заданий - PascalABC.NET</a></li>
<li>И т.п.</li>
</ul>Объединяет их одно: автор проблемного кода использует <b>относительные пути</b>.<br />
<br />
<b>Что такое относительный путь?</b> Это путь к файлу/каталогу (далее просто <i>к файлу</i>) в сокращённом виде, т.е. без корневого каталога или буквы диска. Например: <code class="inlinecode">../file.txt</code> или <code class="inlinecode">./subdirectory/</code>.<br />
В противоложность, <b>есть абсолютный путь</b> (полные) вида <code class="inlinecode">/etc/network/interfaces</code> (Linux, начинается с корневого каталога) или <code class="inlinecode">c:\Windows\System32\drivers\etc\hosts</code> (Windows, начинается с буквы диска).<br />
<br />
Для обращения к файлу, операционной системе требуется знать абсолютный путь.<br />
Но если путь указан относительный, системе придётся самостоятельно приводить его к абсолютному. В этом случае вступает в игру другое понятие, известное под именами <b>current directory</b> и <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D0%B1%D0%BE%D1%87%D0%B8%D0%B9_%D0%BA%D0%B0%D1%82%D0%B0%D0%BB%D0%BE%D0%B3" target="_blank" title="https://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D0%B1%D0%BE%D1%87%D0%B8%D0%B9_%D0%BA%D0%B0%D1%82%D0%B0%D0%BB%D0%BE%D0%B3">другими</a>.<br />

<table width="95%"  class="bbcode_maincontainer"><tr><td>
	<div class="bbcode_container">
	  <div class="bbcode_quote">
	    <div class="btbtbt">
		<div class="quote_container">
	      	<div class="bbcode_quote_container"></div>
	       	<div class="bbcode_postedby">
	         	
	        </div>
	        <div class="message">Это путь к каталогу, <b>относительно</b> которого производятся операции с <b>относительными</b> именами файлов (каталогов)</div>
	      </div>
			</div> 
		</div>
	</div>
</td></tr></table>Вот на этом этапе и всплывает такое, что авторы:<ol style="list-style-type: decimal"><li>Вообще не задумываются об том, что и откуда берётся, указывая путь вида <code class="inlinecode">database.mdf</code>, <code class="inlinecode">file.txt</code>.</li>
<li>Намеренно (но без понимания), указывают путь вида <code class="inlinecode">dir/file</code>, <code class="inlinecode">..dir/file</code>, <code class="inlinecode">../file</code>, <code class="inlinecode">./file</code> и т.п., ошибочно полагая, что <font color="red">путь к файлу/каталогу будет отсчитываться от каталога, где находится программа</font>.</li>
<li>Намеренно (но c недопониманием), указывают путь вида <code class="inlinecode">current_directory + &quot;/file.txt&quot;</code>, ошибочно полагая, что <font color="red"><i>current directory</i> это каталог, где находится программа</font>.</li>
<li>...</li>
</ol>Взращивается такое ложное преставление [ALINK=&quot;default-ide-behavior&quot;]поведением среды разработки[/ALINK] по умолчанию (см. ниже).<br />
<br />
При обращении из кода (нашей программы, чужой программы или функции ОС) к файлу по относительному пути, будет задействован <b>current directory</b> текущего процесса, чтобы получить абсолютный путь к файлу. Для упрощения, можно представлять это как конкатенацию строк - строкового значения <b>current directory</b> и строкового же значения относительного пути.<br />
<blockquote><font color="Green">Увидеть значение <b>current directory</b> можно в:<ul><li>Проводнике Windows, отображается в адресной строке;</li>
<li>Консоли Windows или Linux, отображается в строке приглашения к вводу (промпт);</li>
<li>Консоли Windows, выполнив команду <div class="codeblock"><table class="winbatch"><thead><tr><td colspan="2" id="517006928"  class="head">Windows Batch file</td></tr></thead><tbody><tr class="li1"><td><div id="517006928" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw2">cd</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Консоли Linux, выполнив команду <div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="677527333"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="677527333" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw3">pwd</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul></font><br />
</blockquote>
			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Демонстрация взаимодействия относительного пути и current directory</div>
				   <div class="spoiler-body">
					   Пусть есть 2 файла <br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="232777745"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="232777745" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">R:\demo\<span class="nu0">1</span>\file1.txt
R:\demo\<span class="nu0">2</span>\file2.txt</pre></td></tr></table></div></td></tr></tbody></table></div>И есть некая программа (наша или чужая), которой требуется обратиться к этим файлам.<blockquote><font color="Green">Для демонстрации - программа <b>more</b> (консольная команда или утилита), принимающая путь к файлу и выводящая этот файл в консоль.<br />
Проблема в этом случае идентична обращению к файлам из нашего кода. Т.к. всё равно<ul><li>Есть указанный нами (относительный или абсолютный) путь к файлу;</li>
<li>Есть код, которому требуется обратиться к этому файлу;</li>
<li>Если указан относительный путь, его требуется привести к абсолютному.</li>
</ul></font><br />
</blockquote>Если мы находимся в каталоге <code class="inlinecode">R:\demo\1</code>, т.е. <b>current directory</b> = <code class="inlinecode">R:\demo\1</code>, программа может обратиться к файлу просто по имени, т.к. нужный файл находится в <b>current directory</b>:<br />
<div class="codeblock"><table class="winbatch"><thead><tr><td colspan="2" id="881495947"  class="head">Windows Batch file</td></tr></thead><tbody><tr class="li1"><td><div id="881495947" style="height: 238px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="de1"><pre class="de1">r:\demo\<span class="nu0">1</span><span class="sy0">&gt;</span><span class="kw2">dir</span>
&nbsp;Содержимое папки r:\demo\<span class="nu0">1</span>
&nbsp;
03.08.2018 &nbsp;00:07 &nbsp; &nbsp;<span class="sy0">&lt;</span>DIR<span class="sy0">&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.
03.08.2018 &nbsp;00:07 &nbsp; &nbsp;<span class="sy0">&lt;</span>DIR<span class="sy0">&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;..
03.08.2018 &nbsp;00:<span class="nu0">10</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">11</span> file1.txt
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">1</span> файлов &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">11</span> байт
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">2</span> папок &nbsp; <span class="nu0">2</span><span class="sy0">*</span>038<span class="sy0">*</span><span class="nu0">804</span><span class="sy0">*</span><span class="nu0">480</span> байт свободно
&nbsp;
r:\demo\<span class="nu0">1</span><span class="sy0">&gt;</span><span class="kw2">more</span> file1.txt
content <span class="nu0">1</span>
&nbsp;
r:\demo\<span class="nu0">1</span><span class="sy0">&gt;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Но для обращения к файлу в соседнем каталоге, надо указывать абсолютный путь, потому что просто имя файла уже не работает - такого файла в <b>current directory</b> нет:<br />
<div class="codeblock"><table class="winbatch"><thead><tr><td colspan="2" id="42769422"  class="head">Windows Batch file</td></tr></thead><tbody><tr class="li1"><td><div id="42769422" style="height: 286px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="de1"><pre class="de1">r:\demo\<span class="nu0">1</span><span class="sy0">&gt;</span><span class="kw2">dir</span>
&nbsp;Содержимое папки r:\demo\<span class="nu0">1</span>
&nbsp;
03.08.2018 &nbsp;00:07 &nbsp; &nbsp;<span class="sy0">&lt;</span>DIR<span class="sy0">&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.
03.08.2018 &nbsp;00:07 &nbsp; &nbsp;<span class="sy0">&lt;</span>DIR<span class="sy0">&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;..
03.08.2018 &nbsp;00:<span class="nu0">10</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">11</span> file1.txt
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">1</span> файлов &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">11</span> байт
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">2</span> папок &nbsp; <span class="nu0">2</span><span class="sy0">*</span>038<span class="sy0">*</span><span class="nu0">804</span><span class="sy0">*</span><span class="nu0">480</span> байт свободно
&nbsp;
r:\demo\<span class="nu0">1</span><span class="sy0">&gt;</span><span class="kw2">more</span> file2.txt
Не удается получить доступ к файлу R:\demo\<span class="nu0">1</span>\file2.txt
&nbsp;
r:\demo\<span class="nu0">1</span><span class="sy0">&gt;</span><span class="kw2">more</span> r:\demo\<span class="nu0">2</span>\file2.txt
content <span class="nu0">2</span>
&nbsp;
r:\demo\<span class="nu0">1</span><span class="sy0">&gt;</span></pre></td></tr></table></div></td></tr></tbody></table></div>К файлу в соседнем каталоге можно обратиться и проще - через относительный путь, указывая выход на каталог выше и оттуда вниз в соседний каталог:<br />
<div class="codeblock"><table class="winbatch"><thead><tr><td colspan="2" id="6766657"  class="head">Windows Batch file</td></tr></thead><tbody><tr class="li1"><td><div id="6766657" style="height: 238px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="de1"><pre class="de1">r:\demo\<span class="nu0">1</span><span class="sy0">&gt;</span><span class="kw2">dir</span>
&nbsp;Содержимое папки r:\demo\<span class="nu0">1</span>
&nbsp;
03.08.2018 &nbsp;00:07 &nbsp; &nbsp;<span class="sy0">&lt;</span>DIR<span class="sy0">&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.
03.08.2018 &nbsp;00:07 &nbsp; &nbsp;<span class="sy0">&lt;</span>DIR<span class="sy0">&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;..
03.08.2018 &nbsp;00:<span class="nu0">10</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">11</span> file1.txt
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">1</span> файлов &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">11</span> байт
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">2</span> папок &nbsp; <span class="nu0">2</span><span class="sy0">*</span>038<span class="sy0">*</span><span class="nu0">804</span><span class="sy0">*</span><span class="nu0">480</span> байт свободно
&nbsp;
r:\demo\<span class="nu0">1</span><span class="sy0">&gt;</span><span class="kw2">more</span> ..\<span class="nu0">2</span>\file2.txt
content <span class="nu0">2</span>
&nbsp;
r:\demo\<span class="nu0">1</span><span class="sy0">&gt;</span></pre></td></tr></table></div></td></tr></tbody></table></div>И это даже работает.<br />
<br />
Но если <b>current directory</b> не совпадает (<font color="red">внезапно!</font>) с предполагаемым положением, всё идёт не так:<br />
<div class="codeblock"><table class="winbatch"><thead><tr><td colspan="2" id="436100947"  class="head">Windows Batch file</td></tr></thead><tbody><tr class="li1"><td><div id="436100947" style="height: 318px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="de1"><pre class="de1">r:\demo\<span class="nu0">1</span><span class="sy0">&gt;</span><span class="kw2">dir</span>
&nbsp;Содержимое папки r:\demo\<span class="nu0">1</span>
&nbsp;
03.08.2018 &nbsp;00:07 &nbsp; &nbsp;<span class="sy0">&lt;</span>DIR<span class="sy0">&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.
03.08.2018 &nbsp;00:07 &nbsp; &nbsp;<span class="sy0">&lt;</span>DIR<span class="sy0">&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;..
03.08.2018 &nbsp;00:<span class="nu0">10</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">11</span> file1.txt
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">1</span> файлов &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">11</span> байт
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">2</span> папок &nbsp; <span class="nu0">2</span><span class="sy0">*</span>038<span class="sy0">*</span><span class="nu0">804</span><span class="sy0">*</span><span class="nu0">480</span> байт свободно
&nbsp;
r:\demo\<span class="nu0">1</span><span class="sy0">&gt;</span><span class="kw2">cd</span> r:\
&nbsp;
r:\<span class="sy0">&gt;</span><span class="kw2">more</span> ..\<span class="nu0">2</span>\file2.txt
Не удается получить доступ к файлу R:\<span class="nu0">2</span>\file2.txt
&nbsp;
r:\<span class="sy0">&gt;</span><span class="kw2">more</span> R:\demo\<span class="nu0">2</span>\file2.txt
content <span class="nu0">2</span>
&nbsp;
r:\<span class="sy0">&gt;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В этом случае (если <b>current directory</b> не совпадает с ожидаемым) относительные пути перестают работать так, как ожидалось.<br />
А вот абсолютные - продолжают работать, потому что на значение <b>current directory</b> они не опираются.<br />

				   </div>
			   </div><br />
<br />
[APLACE=&quot;default-ide-behavior&quot;]В ходе написания программы в соответствующей среде разработки никаких проблем обычно не замечается[/APLACE], потому что при запуске своей программы из среды разработки автор обычно получает <b>current directory</b> совпадающим с каталогом, куда собирается программа. Поэтому не возникает ни единой мысли о том, что в коде с относительными путями <i>что-то не так</i>.<br />
А в ходе пробной эксплуатации, или при запуске иным способом, это <i>не так</i> расцветает во всей красе.<br />
<br />
Почему? Потому что <b>current directory</b> это вовсе не каталог, где находится программа (<font color="red">внезапно!</font>). Это текущий (т.е. активный в данный момент) каталог для процесса.<br />
Они могут совпадать в какой-то момент времени, могут не совпадать, но это точно не одно и то же.<br />
<br />
Почему относительные пути работают также при<ul><li>Запуске через проводник, в котором открыт каталог с исполняемым файлом;</li>
<li>Запуске через командную строку, в которой промпт указывает каталог с программой.</li>
</ul>?<br />
<br />
В этих случаях <b>current directory</b> тоже совпадает с каталогом, где расположена программа, и относительные пути отсчитываются относительно него.<br />
Как только запуск производится в иных условиях, каковые как раз и встречены в упомянутых вверху темах, всё тут же перестаёт работать.<br />
<br />
<b>Решение: при обращении к файлам (в соответствующих методах), должны применяться только абсолютные пути, не относительные</b>.<br />
Это вовсе не значит, что надо их хардкодить, а путь к файлу, расположенному рядом с исполняемым, получить невозможно. Если понадобился путь относительно каталога программы, или любого иного каталога, нужно этот относительный путь привести программно к абсолютному.<br />
<blockquote><font color="Green"><b>Внимание</b>: здесь говорится не об архитектуре приложения, а о том, что <b>к моменту обращения к файлу, используемое значение пути должно быть абсолютным</b>, чтобы никто (система или автор) не делал предположений о том, какой же именно путь надо будет применить, потому что реальность может разойтись с предположениями.<br />
Когда именно абсолютный путь должен быть вычислен - уже иной вопрос (см. комменты ниже).<br />
Проблемы возникают у тех, кто к указанному моменту (обращение к файлу) допустил значение с относительным путём.</font></blockquote><blockquote><font color="Orange"><br />
В комментах кое-кто утверждает, что нужно пользоваться только относительными путями.<br />
Пользоваться <i>можно</i>, <s>только осторожно</s> но не <i>нужно</i>. Этот способ применим только к месту (например, в консольных утилитах) и при условии хорошего понимания, как это всё работает и отчего может измениться значение <b>current directory</b>.<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Пример того, к чему может привести</div>
				   <div class="spoiler-body">
					   <br />
При открытии диалога выбора файла, меняется значение <b>current directory</b> для процесса, и текстовый файл рядом с исполняемым уже не находится.<br />
<iframe width="640" height="360" src="https://www.youtube.com/embed/BeDqTvq2fKg" frameborder="0" allowfullscreen></iframe><br />
Данный конкретный баг взят из коммента <b>Storm23</b>. В новых версиях Windows исправлен, но можно наткнуться на что-то подобное.<br />

				   </div>
			   </div><br />
Во избежание проблем, если всё-таки <b>current directory</b> требуется, лучше сохранить это значение в переменную при старте приложения и после, на её основе, формировать абсолютные пути по мере надобности.<br />
Какие могут быть проблемы, помимо бага в ОС?<br />
Например, некий код обработки файлов в каталоге был построен на использовании относительного пути. При попытке его использования в нескольких потоках для обработки независимых каталогов, возникнет проблема с тем, что значение <b>current directory</b> одно для процесса. С абсолютными же путями никаких проблем не будет.<br />
Код надо писать так, чтобы возможностей ошибиться при его использовании было как можно меньше.<br />
</font></blockquote>Путь к каталогу программы можно получить разными способами.<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Примеры на C# .Net</div>
				   <div class="spoiler-body">
					   <ul><li><div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="98157895"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="98157895" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw4">string</span> path <span class="sy0">=</span> AppDomain<span class="sy0">.</span><span class="me1">CurrentDomain</span><span class="sy0">.</span><span class="me1">BaseDirectory</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li><div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="439366087"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="439366087" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw4">string</span> path <span class="sy0">=</span> Path<span class="sy0">.</span><span class="me1">GetDirectoryName</span><span class="br0">&#40;</span>Application<span class="sy0">.</span><span class="me1">ExecutablePath</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li><div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="219880134"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="219880134" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1"><span class="kw1">private</span> <span class="kw4">string</span> GetExeDirectory<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; <span class="kw4">string</span> codeBase <span class="sy0">=</span> Assembly<span class="sy0">.</span><span class="me1">GetExecutingAssembly</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="me1">CodeBase</span><span class="sy0">;</span>
&nbsp; UriBuilder uri <span class="sy0">=</span> <span class="kw3">new</span> UriBuilder<span class="br0">&#40;</span>codeBase<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; <span class="kw4">string</span> path <span class="sy0">=</span> Uri<span class="sy0">.</span><span class="me1">UnescapeDataString</span><span class="br0">&#40;</span>uri<span class="sy0">.</span><span class="me1">Path</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; path <span class="sy0">=</span> Path<span class="sy0">.</span><span class="me1">GetDirectoryName</span><span class="br0">&#40;</span>path<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; <span class="kw1">return</span> path<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>...</li>
</ul>
				   </div>
			   </div><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Пример на VB .Net</div>
				   <div class="spoiler-body">
					   <br />
<div class="codeblock"><table class="vbnet"><thead><tr><td colspan="2" id="602645791"  class="head">VB.NET</td></tr></thead><tbody><tr class="li1"><td><div id="602645791" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="kw1">Public</span> <span class="kw1">Function</span> GetExeDir<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw1">As</span> <span class="kw2">String</span>
&nbsp; &nbsp; GetExeDir <span class="sy0">=</span> My<span class="sy0">.</span><span class="me1">Application</span><span class="sy0">.</span><span class="me1">Info</span><span class="sy0">.</span><span class="me1">DirectoryPath</span>
<span class="kw1">End</span> <span class="kw1">Function</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Пример на C++</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="cpp"><thead><tr><td colspan="2" id="945155528"  class="head">C++</td></tr></thead><tbody><tr class="li1"><td><div id="945155528" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">TCHAR exePath<span class="br0">&#91;</span>MAX_PATH<span class="br0">&#93;</span><span class="sy4">;</span>
HMODULE hModule <span class="sy1">=</span> GetModuleHandleW<span class="br0">&#40;</span><span class="kw2">NULL</span><span class="br0">&#41;</span><span class="sy4">;</span>
GetModuleFileNameW<span class="br0">&#40;</span>hModule, exePath, MAX_PATH<span class="br0">&#41;</span><span class="sy4">;</span>
PathRemoveFileSpec<span class="br0">&#40;</span>exePath<span class="br0">&#41;</span><span class="sy4">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Пример на Delphi</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="720273"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="720273" style="height: 142px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
</pre></td><td class="de1"><pre class="de1"><span class="kw1">var</span>
&nbsp; AppDir<span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; AppDir <span class="sy1">:</span><span class="sy3">=</span> <span class="kw3">ExtractFileDir</span><span class="br0">&#40;</span>Application<span class="sy1">.</span><span class="me1">ExeName</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="co1">// Do something with AppDir, e.g.:</span>
&nbsp; ShowMessage<span class="br0">&#40;</span>AppDir<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
Есть простые, есть посложнее. Метод не один потому, что в нетривиальных условиях простые методы могут выдавать ложный результат, а в тривиальных же условиях сложный код - избыточен.<br />
<br />
Далее полученный абсолютный путь к каталогу программы надо сложить с относительным путём к файлу, чтобы получить абсолютный путь к искомому файлу. 
			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Пример на C# .Net</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="950070651"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="950070651" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1"><span class="kw4">string</span> exeDir <span class="sy0">=</span> <span class="st_h">@&quot;r:\demo\1&quot;</span><span class="sy0">;</span> <span class="co1">// Путь к исходному каталогу</span>
<span class="kw4">string</span> relPath <span class="sy0">=</span> <span class="st_h">@&quot;..\2\file2.txt&quot;</span><span class="sy0">;</span> <span class="co1">// Относительный путь к файлу</span>
<span class="kw4">string</span> resPath <span class="sy0">=</span> Path<span class="sy0">.</span><span class="me1">Combine</span><span class="br0">&#40;</span>exeDir, relPath<span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Объединяет две строки в путь.</span>
Console<span class="sy0">.</span><span class="me1">WriteLine</span><span class="br0">&#40;</span>resPath<span class="br0">&#41;</span><span class="sy0">;</span>
resPath <span class="sy0">=</span> Path<span class="sy0">.</span><span class="me1">GetFullPath</span><span class="br0">&#40;</span>resPath<span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Возвращает для указанной строки пути абсолютный путь.</span>
Console<span class="sy0">.</span><span class="me1">WriteLine</span><span class="br0">&#40;</span>resPath<span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Результат:<br />

<table width="95%"  class="bbcode_maincontainer"><tr><td>
	<div class="bbcode_container">
	  <div class="bbcode_quote">
	    <div class="btbtbt">
		<div class="quote_container">
	      	<div class="bbcode_quote_container"></div>
	       	<div class="bbcode_postedby">
	         	
	        </div>
	        <div class="message">r:\demo\1\..\2\file2.txt<br />
r:\demo\2\file2.txt</div>
	      </div>
			</div> 
		</div>
	</div>
</td></tr></table>
				   </div>
			   </div><br />
<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Пример на VB .Net</div>
				   <div class="spoiler-body">
					   <br />
<div class="codeblock"><table class="vbnet"><thead><tr><td colspan="2" id="459720078"  class="head">VB.NET</td></tr></thead><tbody><tr class="li1"><td><div id="459720078" style="height: 190px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="de1"><pre class="de1"><span class="kw1">Sub</span> Main<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw1">Dim</span> exeDir, relPath, resPath <span class="kw1">As</span> <span class="kw2">String</span>
&nbsp;
&nbsp; &nbsp; exeDir <span class="sy0">=</span> <span class="st0">&quot;r:\demo\1&quot;</span> <span class="co1">' Путь к исходному каталогу</span>
&nbsp; &nbsp; relPath <span class="sy0">=</span> <span class="st0">&quot;..\2\file2.txt&quot;</span> <span class="co1">' Относительный путь к файлу</span>
&nbsp; &nbsp; resPath <span class="sy0">=</span> System<span class="sy0">.</span><span class="me1">IO</span><span class="sy0">.</span><span class="me1">Path</span><span class="sy0">.</span><span class="me1">Combine</span><span class="br0">&#40;</span>exeDir, relPath<span class="br0">&#41;</span> <span class="co1">' Объединяет две строки в путь.</span>
&nbsp; &nbsp; Console<span class="sy0">.</span><span class="me1">WriteLine</span><span class="br0">&#40;</span>resPath<span class="br0">&#41;</span>
&nbsp; &nbsp; resPath <span class="sy0">=</span> System<span class="sy0">.</span><span class="me1">IO</span><span class="sy0">.</span><span class="me1">Path</span><span class="sy0">.</span><span class="me1">GetFullPath</span><span class="br0">&#40;</span>resPath<span class="br0">&#41;</span> <span class="co1">' Возвращает для указанной строки пути абсолютный путь.</span>
&nbsp; &nbsp; Console<span class="sy0">.</span><span class="me1">WriteLine</span><span class="br0">&#40;</span>resPath<span class="br0">&#41;</span>
<span class="kw1">End</span> <span class="kw1">Sub</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Пример на C++</div>
				   <div class="spoiler-body">
					   <br />
<div class="codeblock"><table class="cpp"><thead><tr><td colspan="2" id="623194583"  class="head">C++</td></tr></thead><tbody><tr class="li1"><td><div id="623194583" style="height: 190px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="de1"><pre class="de1">TCHAR libraryPath<span class="br0">&#91;</span>MAX_PATH<span class="br0">&#93;</span> <span class="sy1">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span> <span class="br0">&#125;</span><span class="sy4">;</span>
_tcscat_s<span class="br0">&#40;</span>libraryPath, MAX_PATH, exePath<span class="br0">&#41;</span><span class="sy4">;</span>
&nbsp;
<span class="co2">#ifdef _M_IX86</span>
&nbsp; _tcscat_s<span class="br0">&#40;</span>libraryPath, MAX_PATH, TEXT<span class="br0">&#40;</span><span class="st0">&quot;<span class="es1">\\</span>x86<span class="es1">\\</span>library.dll&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy4">;</span>
<span class="co2">#elif defined(_M_AMD64)</span>
&nbsp; _tcscat_s<span class="br0">&#40;</span>libraryPath, MAX_PATH, TEXT<span class="br0">&#40;</span><span class="st0">&quot;<span class="es1">\\</span>x64<span class="es1">\\</span>library.dll&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy4">;</span>
<span class="co2">#endif</span>
&nbsp;
LoadLibrary<span class="br0">&#40;</span>libraryPath<span class="br0">&#41;</span><span class="sy4">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div>И уже вот этот, полученный программно абсолютный путь, нужно использовать там, где происходит обращение к файлу.<br />
<br />
Почему, однако, можно запустить готовую программу типа <code class="inlinecode">notepad.exe</code> или <code class="inlinecode">more.exe</code> (что была в примере выше) без указания абсолютного пути?<br />
Потому что для поиска программ есть такая <a rel="nofollow noopener noreferrer" href="https://ru.wikipedia.org/wiki/PATH_(%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F)" target="_blank" title="https://ru.wikipedia.org/wiki/PATH_(%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F)">системная переменная PATH</a>. Поиск программ производится сначала в <b>current directory</b>, а если там не найдена - далее в каталогах, перечисленных в этой переменной.<br />
<div class="codeblock"><table class="winbatch"><thead><tr><td colspan="2" id="701935138"  class="head">Windows Batch file</td></tr></thead><tbody><tr class="li1"><td><div id="701935138" style="height: 142px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
</pre></td><td class="de1"><pre class="de1">r:\<span class="sy0">&gt;</span><span class="kw1">echo</span> <span class="co103">%PATH%</span>
C:\Program Files <span class="br0">&#40;</span>x86<span class="br0">&#41;</span>\Common Files\Oracle\Java\javapath;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Program Files\dotnet\;C:\Users\User\AppData\Local\Microsoft\WindowsApps
&nbsp;
r:\<span class="sy0">&gt;</span>where <span class="kw2">more</span>
C:\Windows\System32\<span class="kw2">more</span>.com
&nbsp;
r:\<span class="sy0">&gt;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Поэтому программу можно запускать просто по имени, если она расположена в текущем каталоге или одном из указанных в переменной PATH. В иных случаях также следует (во избежание) формировать абсолютный путь.<br />
Также, случается наличие в путях поиска нескольких исполняемых файлов с одинаковым именем. Тогда тоже помогает указание абсолютного пути, либо модификация порядка путей в %PATH% (что может потребовать админских прав или отрицательно повлиять на другие программы).<br />
<br />
P.S. Немного об упомянутых в комментах эффектах:<ul><li>Блокировка удаления каталога установкой его текущим: <a rel="nofollow noopener noreferrer" href="https://blogs.msdn.microsoft.com/oldnewthing/20101109-00/?p=12323/" target="_blank" title="https://blogs.msdn.microsoft.com/oldnewthing/20101109-00/?p=12323/">The curse of the current directory</a>;</li>
<li>Смена текущего каталога программы вызовом диалога выбора файла: <a rel="nofollow noopener noreferrer" href="https://blogs.msdn.microsoft.com/oldnewthing/20101112-00/?p=12293" target="_blank" title="https://blogs.msdn.microsoft.com/oldnewthing/20101112-00/?p=12293">Why does the common file dialog change the current directory?</a>.</li>
</ul></div>

]]></content:encoded>
			<dc:creator>Rius</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/594854/5377.html</guid>
		</item>
		<item>
			<title>Русификация вывода компилятора MSVC в QtCreator</title>
			<link>https://www.cyberforum.ru/blogs/594854/5141.html</link>
			<pubDate>Tue, 20 Feb 2018 04:38:32 GMT</pubDate>
			<description>VS 2017 Community русская, Windows 10 Home x64 русская, 
QtCreator 4.5.1, MSVC 2017 
 
Вариант на...</description>
			<content:encoded><![CDATA[<div>VS 2017 Community русская, Windows 10 Home x64 русская,<br />
QtCreator 4.5.1, MSVC 2017<br />
<br />
<font size="4">Вариант на BAT-файле</font><ol style="list-style-type: decimal"><li>Берём статическую (чтобы не искать потом библиотеки зависимостей) сборку <b>iconv</b> для Windows. Например, из проекта <a rel="nofollow noopener noreferrer" href="https://github.com/mlocati/gettext-iconv-windows/releases" target="_blank" title="https://github.com/mlocati/gettext-iconv-windows/releases">mlocati/gettext-iconv-windows</a>, <i>gettext0.19.8.1-iconv1.14-static-64.zip</i>.</li>
<li>Куда-нибудь распаковываем.</li>
<li>Переходим в каталог с <b>jom.exe</b>, например <i>c:\Qt\Qt5.10.1\Tools\QtCreator\bin\</i> .</li>
<li>Создаём файл <b>jom.bat</b>, в котором вызываем <b>jom.exe</b> и передаём его вывод в <b>iconv</b>:<br />
<div class="codeblock"><table class="winbatch"><thead><tr><td colspan="2" id="602324471"  class="head">Windows Batch file</td></tr></thead><tbody><tr class="li1"><td><div id="602324471" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="sy0">@</span><span class="kw1">echo</span> off
c:\Qt\Qt5.10.1\Tools\QtCreator\bin\jom.exe <span class="co103">%*</span> <span class="sy0">|</span> d:\Software\Installed\iconv1.14\bin\iconv.exe <span class="co101">-f</span> CP866 <span class="co101">-t</span> WINDOWS<span class="co101">-1251</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В параметрах сборки заменяем путь с <b>jom.exe</b> на <b>jom.bat</b>.<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4682&amp;d=1519101590" rel="Lightbox" id="attachment4682" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4682&amp;thumb=1&amp;d=1519101590" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 1.PNG
Просмотров: 1044
Размер:	11.2 Кб
ID:	4682" style="margin: 5px" /></a></li>
<li>Запускаем пересборку и видим русский текст:<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4683&amp;d=1519101590" rel="Lightbox" id="attachment4683" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4683&amp;thumb=1&amp;d=1519101590" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 2.PNG
Просмотров: 965
Размер:	26.6 Кб
ID:	4683" style="margin: 5px" /></a></li>
</ol><br />
С компилятором работает. А вот если ошибки выдаёт линкер, то iconv спотыкается - сообщения почему-то идут уже в нормальной кодировке и конвертировать их не надо...<br />
<br />
<font size="4">Вариант на PowerShell</font><ol style="list-style-type: decimal"><li>Переходим в каталог с <b>jom.exe</b>, например <i>c:\Qt\Qt5.10.1\Tools\QtCreator\bin\</i> .</li>
<li>Создаём файл <b>jom.bat</b> с вызовом скрипта на PowerShell:<br />
<div class="codeblock"><table class="winbatch"><thead><tr><td colspan="2" id="647077937"  class="head">Windows Batch file</td></tr></thead><tbody><tr class="li1"><td><div id="647077937" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="sy0">@</span><span class="kw1">echo</span> off
PowerShell <span class="co101">-NoProfile</span> <span class="co101">-ExecutionPolicy</span> Bypass <span class="co101">-Command</span> <span class="st0">&quot;&amp; 'c:\Qt\Qt5.10.1\Tools\QtCreator\bin\jom.ps1' %*&quot;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Создаём файл <b>jom.ps1</b>:<br />
<div class="codeblock"><table class="powershell"><thead><tr><td colspan="2" id="467908127"  class="head">PowerShell</td></tr></thead><tbody><tr class="li1"><td><div id="467908127" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
</pre></td><td class="de1"><pre class="de1"><span class="kw6">$ErrorActionPreference</span> <span class="sy0">=</span> <span class="st0">&quot;Stop&quot;</span>
<span class="co1">#$VerbosePreference = &quot;Continue&quot;</span>
&nbsp;
<span class="re0">$jomPath</span> <span class="sy0">=</span> <span class="kw1">Join-Path</span> <span class="re0">$PSScriptRoot</span> <span class="st0">&quot;jom.exe&quot;</span>
&nbsp;
<span class="kw3">function</span> RunConsole<span class="br0">&#40;</span><span class="re0">$scriptBlock</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="br0">&#91;</span>Console<span class="br0">&#93;</span>::OutputEncoding <span class="sy0">=</span> <span class="br0">&#91;</span>System.Text.Encoding<span class="br0">&#93;</span>::GetEncoding<span class="br0">&#40;</span><span class="st0">&quot;windows-1251&quot;</span><span class="br0">&#41;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw3">function</span> ConvertTo<span class="sy0">-</span>Encoding <span class="br0">&#40;</span><span class="br0">&#91;</span><span class="re3">string</span><span class="br0">&#93;</span><span class="re0">$From</span><span class="sy0">,</span> <span class="br0">&#91;</span><span class="re3">string</span><span class="br0">&#93;</span><span class="re0">$To</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; Begin
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$encFrom</span> <span class="sy0">=</span> <span class="br0">&#91;</span>System.Text.Encoding<span class="br0">&#93;</span>::GetEncoding<span class="br0">&#40;</span><span class="re0">$From</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$encTo</span> <span class="sy0">=</span> <span class="br0">&#91;</span>System.Text.Encoding<span class="br0">&#93;</span>::GetEncoding<span class="br0">&#40;</span><span class="re0">$To</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; Process
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$bytes</span> <span class="sy0">=</span> <span class="re0">$encFrom</span>.GetBytes<span class="br0">&#40;</span><span class="kw6">$_</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$bytes</span> <span class="sy0">=</span> <span class="br0">&#91;</span>System.Text.Encoding<span class="br0">&#93;</span>::Convert<span class="br0">&#40;</span><span class="re0">$encFrom</span><span class="sy0">,</span> <span class="re0">$encTo</span><span class="sy0">,</span> <span class="re0">$bytes</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$encTo</span>.GetString<span class="br0">&#40;</span><span class="re0">$bytes</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="sy0">&amp;</span><span class="re0">$scriptBlock</span> <span class="sy0">|</span> ConvertTo<span class="sy0">-</span>Encoding cp866 windows<span class="sy0">-</span><span class="nu0">1251</span> 
<span class="br0">&#125;</span>
&nbsp;
RunConsole <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="sy0">&amp;</span> <span class="re0">$jomPath</span> <span class="kw6">$args</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В параметрах сборки заменяем путь с <b>jom.exe</b> на <b>jom.bat</b>.<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4682&amp;d=1519101590" rel="Lightbox" id="attachment4682" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4682&amp;thumb=1&amp;d=1519101590" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 1.PNG
Просмотров: 1044
Размер:	11.2 Кб
ID:	4682" style="margin: 5px" /></a></li>
<li>Запускаем пересборку и видим русский текст.<ul><li>От компилятора:<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4684&amp;d=1519144499" rel="Lightbox" id="attachment4684" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4684&amp;thumb=1&amp;d=1519144499" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 2018-02-20_21-33-56.png
Просмотров: 1056
Размер:	18.8 Кб
ID:	4684" style="margin: 5px" /></a></li>
<li>И от линкера:<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4685&amp;d=1519144499" rel="Lightbox" id="attachment4685" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4685&amp;thumb=1&amp;d=1519144499" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 2018-02-20_21-34-22.png
Просмотров: 965
Размер:	8.3 Кб
ID:	4685" style="margin: 5px" /></a></li>
</ul></li>
</ol><br />
Конвертирование кодировки вывода консольной команды на PowerShell взято из статьи <a rel="nofollow noopener noreferrer" href="https://habrahabr.ru/post/321076/" target="_blank" title="https://habrahabr.ru/post/321076/">Powershell и кирилица в консольных приложениях </a></div>

]]></content:encoded>
			<dc:creator>Rius</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/594854/5141.html</guid>
		</item>
		<item>
			<title>Команда протокола формата запрос-ответ</title>
			<link>https://www.cyberforum.ru/blogs/594854/4973.html</link>
			<pubDate>Fri, 08 Dec 2017 10:45:10 GMT</pubDate>
			<description>Минимальная писанина при применении. 
Простое добавление новых команд. 
Строго типизированные...</description>
			<content:encoded><![CDATA[<div>Минимальная писанина при применении.<br />
Простое добавление новых команд.<br />
Строго типизированные результаты без необходимости дополнительного приведения типов.<br />
<br />
Использование:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="712632218"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="712632218" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="de1"><pre class="de1"><span class="kw1">using</span> <span class="co3">ConsoleAppRequestAnswer.Driver</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System</span><span class="sy0">;</span>
&nbsp;
<span class="kw1">namespace</span> ConsoleAppRequestAnswer
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">class</span> Program
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">static</span> <span class="kw4">void</span> Main<span class="br0">&#40;</span><span class="kw4">string</span><span class="br0">&#91;</span><span class="br0">&#93;</span> args<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IDriver driver <span class="sy0">=</span> <span class="kw3">new</span> Driver<span class="sy0">.</span><span class="me1">Driver</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// answerExample is CommandExample.Answer</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> answerExample <span class="sy0">=</span> driver<span class="sy0">.</span><span class="me1">Exchange</span><span class="br0">&#40;</span><span class="kw3">new</span> CommandExample<span class="br0">&#40;</span><span class="kw1">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>answerExample<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console<span class="sy0">.</span><span class="me1">WriteLine</span><span class="br0">&#40;</span>answerExample<span class="sy0">.</span><span class="kw1">Value</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Базовый класс запроса:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="101030427"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="101030427" style="height: 334px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="de1"><pre class="de1"><span class="kw1">using</span> <span class="co3">System</span><span class="sy0">;</span>
&nbsp;
<span class="kw1">namespace</span> ConsoleAppRequestAnswer<span class="sy0">.</span><span class="me1">Driver</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">class</span> RequestBase<span class="sy0">&lt;</span>AnswerType<span class="sy0">&gt;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> RequestBase<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">Query</span> <span class="sy0">=</span> <span class="kw4">String</span><span class="sy0">.</span><span class="me1">Empty</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">string</span> Query <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">protected</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">virtual</span> AnswerBase CreateAnswer<span class="br0">&#40;</span><span class="kw4">string</span> <span class="kw1">value</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">new</span> AnswerBase<span class="br0">&#40;</span><span class="kw1">value</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Базовый класс ответа:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="813630812"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="813630812" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="de1"><pre class="de1"><span class="kw1">namespace</span> ConsoleAppRequestAnswer<span class="sy0">.</span><span class="me1">Driver</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">class</span> AnswerBase
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> <span class="kw4">bool</span> mSuccess<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> AnswerBase<span class="br0">&#40;</span><span class="kw4">string</span> <span class="kw1">value</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mSuccess</span> <span class="sy0">=</span> <span class="kw1">false</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="kw4">string</span><span class="sy0">.</span><span class="me1">IsNullOrEmpty</span><span class="br0">&#40;</span><span class="kw1">value</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mSuccess</span> <span class="sy0">=</span> <span class="kw1">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">static</span> <span class="kw1">implicit</span> <span class="kw1">operator</span> <span class="kw4">bool</span><span class="br0">&#40;</span>AnswerBase o<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> o<span class="sy0">?.</span><span class="me1">mSuccess</span> <span class="sy0">??</span> <span class="kw1">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Пример команды:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="664692486"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="664692486" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
32
33
34
35
36
37
38
39
</pre></td><td class="de1"><pre class="de1"><span class="kw1">using</span> <span class="co3">System</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Globalization</span><span class="sy0">;</span>
&nbsp;
<span class="kw1">namespace</span> ConsoleAppRequestAnswer<span class="sy0">.</span><span class="me1">Driver</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">class</span> CommandExample <span class="sy0">:</span> RequestBase<span class="sy0">&lt;</span>CommandExample<span class="sy0">.</span><span class="me1">Answer</span><span class="sy0">&gt;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> CommandExample<span class="br0">&#40;</span><span class="kw4">bool</span> parameter<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">Query</span> <span class="sy0">=</span> Convert<span class="sy0">.</span><span class="me1">ToString</span><span class="br0">&#40;</span>parameter, CultureInfo<span class="sy0">.</span><span class="me1">InvariantCulture</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">override</span> AnswerBase CreateAnswer<span class="br0">&#40;</span><span class="kw4">string</span> <span class="kw1">value</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">new</span> Answer<span class="br0">&#40;</span><span class="kw1">value</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">class</span> Answer <span class="sy0">:</span> AnswerBase
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Answer<span class="br0">&#40;</span><span class="kw4">string</span> <span class="kw1">value</span><span class="br0">&#41;</span> <span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">base</span><span class="br0">&#40;</span><span class="kw1">value</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">this</span><span class="sy0">.</span><span class="me1">mSuccess</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw4">bool</span><span class="sy0">.</span><span class="me1">TryParse</span><span class="br0">&#40;</span><span class="kw1">value</span>, <span class="kw1">out</span> <span class="kw4">bool</span> b<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="kw1">Value</span> <span class="sy0">=</span> b<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mSuccess</span> <span class="sy0">=</span> <span class="kw1">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="kw1">Value</span> <span class="sy0">=</span> <span class="kw1">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">bool</span> <span class="kw1">Value</span> <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">private</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Драйвер обмена:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="730166683"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="730166683" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="de1"><pre class="de1"><span class="kw1">namespace</span> ConsoleAppRequestAnswer<span class="sy0">.</span><span class="me1">Driver</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">interface</span> IDriver
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; AnswerType Exchange<span class="sy0">&lt;</span>AnswerType<span class="sy0">&gt;</span><span class="br0">&#40;</span>RequestBase<span class="sy0">&lt;</span>AnswerType<span class="sy0">&gt;</span> request<span class="br0">&#41;</span> <span class="kw1">where</span> AnswerType <span class="sy0">:</span> AnswerBase<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">class</span> Driver <span class="sy0">:</span> IDriver
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Driver<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> AnswerType Exchange<span class="sy0">&lt;</span>AnswerType<span class="sy0">&gt;</span><span class="br0">&#40;</span>RequestBase<span class="sy0">&lt;</span>AnswerType<span class="sy0">&gt;</span> request<span class="br0">&#41;</span> <span class="kw1">where</span> AnswerType <span class="sy0">:</span> AnswerBase
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">string</span> send <span class="sy0">=</span> request<span class="sy0">.</span><span class="me1">Query</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">string</span> received <span class="sy0">=</span> send<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>AnswerType<span class="br0">&#41;</span>request<span class="sy0">.</span><span class="me1">CreateAnswer</span><span class="br0">&#40;</span>received<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4636&amp;d=1516775057">ConsoleAppRequestAnswer.zip</a> (10.3 Кб, 349 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>Rius</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/594854/4973.html</guid>
		</item>
		<item>
			<title>Контакты для вопросов по написанию программ/домашек/курсовых/дипломных</title>
			<link>https://www.cyberforum.ru/blogs/594854/4755.html</link>
			<pubDate>Fri, 19 May 2017 14:44:51 GMT</pubDate>
			<description>Итак, если вы нашли меня на форуме по вопросам программирования и решили обратиться по поводу: 
*...</description>
			<content:encoded><![CDATA[<div>Итак, если вы нашли меня на форуме по вопросам программирования и решили обратиться по поводу:<ul><li>Помощи на экзамене;</li>
<li>Срочной курсовой, которую надо сдавать вот уже завтра;</li>
<li>Программы для дипломной работы;</li>
<li>Домашней работы;</li>
<li>И т.д. и т.п. ...</li>
</ul><br />
Вам нужно знать следующее:<ul><li>В интернетах достаточно информации для самостоятельного изучения. Такой как:<ul><li>Книги;<br />
По вопросам C# почти всё можно найти в <a href="https://www.cyberforum.ru/csharp-beginners/thread1565767.html">этих источниках</a>.</li>
<li>Google/Yandex;</li>
<li>Форумы;</li>
<li>И т.д.</li>
</ul>Ответы на все ваши вопросы там есть с вероятностью 99.(9)%. Потому что, чтобы упереться в неизвестную доселе проблему, нужны знания, чтобы в эту ситуацию вляпаться. А те, у кого знания есть, смогут найти ответ самостоятельно. Если не смогут - надо задать вопрос на форуме, что повысит вероятность найти ответ среди множества знающих людей.</li>
<li>На выполнение всех работ в учебных заведениях даётся достаточный срок.<br />
Если вы прогуляли отпущенное время для самостоятельных занятий и не учились в учебное время, то просто честно получите двояк.</li>
<li>Те, кто хочет, чтобы работу просто сделали <b>за него</b>, могут обратиться в специальный <a href="https://www.cyberforum.ru/order-program/">раздел форума</a>. Там вам с радостью помогут.</li>
<li><a rel="nofollow noopener noreferrer" href="https://habrahabr.ru/post/328530/" target="_blank" title="https://habrahabr.ru/post/328530/">Почему вы не отвечаете на мой вопрос?</a></li>
<li>Я <b>не являюсь</b>:<ul><li>преподавателем;</li>
<li>тренером,</li>
<li>коучером,</li>
<li>телепатом,</li>
<li>пророком,</li>
<li>супер программистом;</li>
<li>тыжпрограммистом.</li>
</ul></li>
<li>В моё свободное время у меня есть свои, личные дела. Мне незачем его тратить на кого-то, кто не удосужился приложить усилия для самостоятельного решения и изучения своего вопроса.</li>
<li>
<table width="95%"  class="bbcode_maincontainer"><tr><td>
	<div class="bbcode_container">
	  <div class="bbcode_quote">
	    <div class="btbtbt">
		<div class="quote_container">
	      	<div class="bbcode_quote_container"></div>
	       	<div class="bbcode_postedby">
	         	
	        </div>
	        <div class="message">Идёт Будда с учениками по дороге. Видит: яма, в ней вол, крестьянин пытается его вытянуть, но сил не хватает. Будда кивнул ученикам, они быстро помогли вытянуть животное.<br />
Идут дальше, снова яма, в ней вол, на краю сидит крестьянин и горько плачет. Будда прошёл мимо и как бы не заметил. Ученики его спрашивают:<br />
<br />
- Учитель, почему ты не захотел помочь этому крестьянину?<br />
<br />
- Помочь плакать?</div>
	      </div>
			</div> 
		</div>
	</div>
</td></tr></table></li>
</ul><br />
Контакты:<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <br />
<b>Обучением, помощью лентяям, решением задач/..../дипломов за деньги и бесплатно я не занимаюсь.</b><br />
Поэтому контактов <b>нет</b>. По этим вопросам мне не пишите.<br />
Ознакомьтесь с темой <a href="https://www.cyberforum.ru/cpp-beginners/thread2080479.html">Чего и зачем мы хотим от новичков</a>.<br />
Если всё-таки решите написать в ЛС, пишите сразу вопрос. И если он меня заинтересует, что иногда случается, то может быть и отвечу.
				   </div>
			   </div></div>

]]></content:encoded>
			<dc:creator>Rius</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/594854/4755.html</guid>
		</item>
		<item>
			<title>Как встроить DLL (.Net) внутрь EXE (.Net)</title>
			<link>https://www.cyberforum.ru/blogs/594854/4705.html</link>
			<pubDate>Fri, 21 Apr 2017 15:23:35 GMT</pubDate>
			<description>Если возникает ситуация: 
* надо написать программу, решающую некую задачу; 
* есть DLL *на .Net*...</description>
			<content:encoded><![CDATA[<div>Если возникает ситуация:<ul><li>надо написать программу, решающую некую задачу;</li>
<li>есть DLL <b>на .Net</b> (с неуправляемыми DLL всё иначе), которая эту задачу решает;</li>
<li>надо взять эту DLL и применить;</li>
<li>но так, чтобы никто не догадался, что задача решается чужой DLL-кой, а не нашим кодом.</li>
</ul>Либо:<ul><li>Программа состоит из EXE и нескольких DLL;</li>
<li>Пользователю надо поставлять этот набор файлов;</li>
<li>Пользователь криворук и &quot;лишние&quot; файлы теряет;</li>
<li>В то же время программист криворук и не умеет / не хочет создавать инсталлятор.</li>
</ul>Либо такой редкий случай:<ul><li>Библиотека (плагин) для какой-то системы;</li>
<li>Система умеет сама подгружать только один файл DLL, а зависимости не умеет;</li>
<li>Зависимости надо встроить так, чтобы их загрузка средствами системы не потребовалась.</li>
</ul><br />
Первая мысль, видимо, встроить DLL внутрь EXE, чтобы пользователю поставлялся один файл EXE.<br />
<ol style="list-style-type: decimal"><li>Добавляем библиотеку в ресурсы проекта;</li>
<li>В Build Action ставим значение Embedded Resource;<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4227&amp;d=1492787977" rel="Lightbox" id="attachment4227" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4227&amp;thumb=1&amp;d=1492787977" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 2017-04-21_20-18-42.png
Просмотров: 994
Размер:	17.2 Кб
ID:	4227" style="margin: 5px" /></a></li>
<li>При запуске программы считывает все ресурсы, похожие по имени на *.dll, и собираем их в словарь;<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="712199763"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="712199763" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Загрузка библиотек из ресурсов</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;returns&gt;Словарь библиотек&lt;/returns&gt;</span>
<span class="kw1">private</span> <span class="kw1">static</span> Dictionary<span class="sy0">&lt;</span><span class="kw4">string</span>, Assembly<span class="sy0">&gt;</span> PreloadAssemblies<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; Dictionary<span class="sy0">&lt;</span><span class="kw4">string</span>, Assembly<span class="sy0">&gt;</span> result <span class="sy0">=</span> <span class="kw3">new</span> Dictionary<span class="sy0">&lt;</span><span class="kw4">string</span>, Assembly<span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; Assembly assembly <span class="sy0">=</span> Assembly<span class="sy0">.</span><span class="me1">GetExecutingAssembly</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> resources <span class="sy0">=</span> assembly<span class="sy0">.</span><span class="me1">GetManifestResourceNames</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">.</span><span class="kw1">Where</span><span class="br0">&#40;</span>x <span class="sy0">=&gt;</span> x<span class="sy0">.</span><span class="me1">StartsWith</span><span class="br0">&#40;</span><span class="st0">&quot;EmbeddedLibraryExe.Resources&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">.</span><span class="kw1">Where</span><span class="br0">&#40;</span>x <span class="sy0">=&gt;</span> x<span class="sy0">.</span><span class="me1">ToLower</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="me1">EndsWith</span><span class="br0">&#40;</span><span class="st0">&quot;dll&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">.</span><span class="me1">ToArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> item <span class="kw1">in</span> resources<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span>Stream stream <span class="sy0">=</span> assembly<span class="sy0">.</span><span class="me1">GetManifestResourceStream</span><span class="br0">&#40;</span>item<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> buffer <span class="sy0">=</span> <span class="kw3">new</span> <span class="kw4">byte</span><span class="br0">&#91;</span>stream<span class="sy0">.</span><span class="me1">Length</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stream<span class="sy0">.</span><span class="me1">Read</span><span class="br0">&#40;</span>buffer, <span class="nu0">0</span>, buffer<span class="sy0">.</span><span class="me1">Length</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Assembly loadedAssembly <span class="sy0">=</span> Assembly<span class="sy0">.</span><span class="me1">Load</span><span class="br0">&#40;</span>buffer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>loadedAssembly<span class="sy0">.</span><span class="me1">FullName</span>, loadedAssembly<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> result<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В текущем домене подписываемся на событие AssemblyResolve;</li>
<li>В обработчике события ищем запрашиваемую библиотеку в словаре по её имени и возвращаем её;<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="497112459"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="497112459" style="height: 174px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
</pre></td><td class="de1"><pre class="de1"><span class="kw1">static</span> <span class="kw5">System.<span class="me1">Reflection</span></span><span class="sy0">.</span><span class="me1">Assembly</span> CurrentDomain_AssemblyResolve<span class="br0">&#40;</span><span class="kw4">object</span> sender, ResolveEventArgs args<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>mPreloaded<span class="sy0">.</span><span class="me1">ContainsKey</span><span class="br0">&#40;</span>args<span class="sy0">.</span><span class="me1">Name</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> mPreloaded<span class="br0">&#91;</span>args<span class="sy0">.</span><span class="me1">Name</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw1">null</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Когда создаётся класс, требующий эту библиотеку, используется библиотека из словаря, а не производится поиск на диске, где её может уже не быть.<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="176794077"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="176794077" style="height: 302px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Словарь сборок, предварительно загруженных из ресурсов</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">static</span> Dictionary<span class="sy0">&lt;</span><span class="kw4">string</span>, Assembly<span class="sy0">&gt;</span> mPreloaded<span class="sy0">;</span>
&nbsp;
<span class="kw1">static</span> <span class="kw4">void</span> Main<span class="br0">&#40;</span><span class="kw4">string</span><span class="br0">&#91;</span><span class="br0">&#93;</span> args<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Загрузка из ресурсов</span>
&nbsp; &nbsp; mPreloaded <span class="sy0">=</span> PreloadAssemblies<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// События поиска библиотеки</span>
&nbsp; &nbsp; AppDomain<span class="sy0">.</span><span class="me1">CurrentDomain</span><span class="sy0">.</span><span class="me1">AssemblyResolve</span> <span class="sy0">+=</span> CurrentDomain_AssemblyResolve<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Создание класса из библиотеки</span>
&nbsp; &nbsp; Test t <span class="sy0">=</span> <span class="kw3">new</span> Test<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; Console<span class="sy0">.</span><span class="me1">WriteLine</span><span class="br0">&#40;</span>t<span class="sy0">.</span><span class="me1">Check</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ol><br />
<br />
Ещё есть ILMerge.<br />
<br />
<a href="https://www.cyberforum.ru/csharp-beginners/thread2063608.html#post11114956">Тут другой пример</a>. Есть exe, рядом с ним есть первая dll, внутри первой dll лежит вторая dll, необходимая первой для работы.</div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4226&amp;d=1492787571">EmbeddedLibrary.zip</a> (12.7 Кб, 566 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>Rius</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/594854/4705.html</guid>
		</item>
		<item>
			<title>Прикол с плавающей точкой</title>
			<link>https://www.cyberforum.ru/blogs/594854/4674.html</link>
			<pubDate>Fri, 07 Apr 2017 15:07:24 GMT</pubDate>
			<description><![CDATA[float a = 0; 
float b = 0; 
float c = a / b; 
float g = 1.0f; 
 
if (c < g) 
{ 
    printf("c < g...]]></description>
			<content:encoded><![CDATA[<div><div class="codeblock"><table class="cpp"><thead><tr><td colspan="2" id="527522500"  class="head">C++</td></tr></thead><tbody><tr class="li1"><td><div id="527522500" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="de1"><pre class="de1"><span class="kw4">float</span> a <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span>
<span class="kw4">float</span> b <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span>
<span class="kw4">float</span> c <span class="sy1">=</span> a <span class="sy2">/</span> b<span class="sy4">;</span>
<span class="kw4">float</span> g <span class="sy1">=</span> <span class="nu17">1.0f</span><span class="sy4">;</span>
&nbsp;
<span class="kw1">if</span> <span class="br0">&#40;</span>c <span class="sy1">&lt;</span> g<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;c &lt; g <span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy4">;</span>
<span class="br0">&#125;</span>
<span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>c <span class="sy1">&gt;</span> g<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;c &gt; g <span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy4">;</span>
<span class="br0">&#125;</span>
<span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>c <span class="sy1">==</span> g<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;c == g <span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy4">;</span>
<span class="br0">&#125;</span>
<span class="kw1">else</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;c ? g <span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy4">;</span> <span class="co1">// &lt;&lt; попадаем сюда</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Связано со сравнением, в котором участвует NaN.<br />

<table width="95%"  class="bbcode_maincontainer"><tr><td>
	<div class="bbcode_container">
	  <div class="bbcode_quote">
	    <div class="btbtbt">
		<div class="quote_container">
	      	<div class="bbcode_quote_container"></div>
	       	<div class="bbcode_postedby">
	         	
	        </div>
	        <div class="message">&quot;Four mutually exclusive relations are possible: less than, equal, greater than, and unordered. The last case arises when at least one operand is NaN. Every NaN shall compare unordered with everything, including itself.&quot; - Stephen Canon</div>
	      </div>
			</div> 
		</div>
	</div>
</td></tr></table></div>

]]></content:encoded>
			<dc:creator>Rius</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/594854/4674.html</guid>
		</item>
		<item>
			<title>Установка и настройка Eclipse, STM32CubeMX под Windows</title>
			<link>https://www.cyberforum.ru/blogs/594854/4589.html</link>
			<pubDate>Tue, 21 Feb 2017 18:30:00 GMT</pubDate>
			<description>Показана установка и настройка среды разработки на базе 
* Eclipse IDE for C/C++ Developers; 
*...</description>
			<content:encoded><![CDATA[<div>Показана установка и настройка среды разработки на базе<ul><li>Eclipse IDE for C/C++ Developers;</li>
<li>Java SE Runtime Environment;</li>
<li>GNU ARM Embedded Toolchain;</li>
<li>GNU ARM Eclipse Build Tools;</li>
<li>GNU ARM Eclipse plug-ins;</li>
<li>STM32CubeMX Eclipse plug in.</li>
</ul>А также создание проекта в STM32CubeMX и перенос его в Eclipse CDT. Т.е. использование GNU ARM Eclipse plug-ins вместо ST-шного SW4STM32.<br />
<br />
YouTube:<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <iframe width="640" height="360" src="https://www.youtube.com/embed/i5VUF1wYTQU" frameborder="0" allowfullscreen></iframe>
				   </div>
			   </div></div>

]]></content:encoded>
			<dc:creator>Rius</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/594854/4589.html</guid>
		</item>
		<item>
			<title>Вывод текста в шаблоны формата *.docx</title>
			<link>https://www.cyberforum.ru/blogs/594854/4379.html</link>
			<pubDate>Thu, 01 Sep 2016 17:47:08 GMT</pubDate>
			<description>Исходники тут: https://github.com/riuson/wordml-templates 
 
1. Добавляем к проекту пакет...</description>
			<content:encoded><![CDATA[<div>Исходники тут: <a rel="nofollow noopener noreferrer" href="https://github.com/riuson/wordml-templates" target="_blank" title="https://github.com/riuson/wordml-templates">https://github.com/riuson/wordml-templates</a><br />
<ol style="list-style-type: decimal"><li>Добавляем к проекту пакет DocumentFormat.OpenXML через NuGet;</li>
<li>Рисуем оставшуюся часть совы.</li>
</ol><br />
Определяем класс для пары закладки. Начало закладки и её конец - это отдельные ноды в XML документе.<br />
При создании шаблона необходимо, чтобы эти ноды находились внутри одной вышележащей ноды. Т.е. чтобы закладка покрывала только текстовую строку и не выходила за пределы своего контейнера.<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="303749294"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="303749294" style="height: 206px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">class</span> BookmarksPair
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> BookmarkStart Start <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">private</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> BookmarkEnd End <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">private</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> BookmarksPair<span class="br0">&#40;</span>BookmarkStart start, BookmarkEnd end<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">Start</span> <span class="sy0">=</span> start<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">End</span> <span class="sy0">=</span> end<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Получаем закладки из файла:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="776884374"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="776884374" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">static</span> BookmarksPair<span class="br0">&#91;</span><span class="br0">&#93;</span> GetBookmarks<span class="br0">&#40;</span><span class="kw4">string</span> filename<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> templateFile <span class="sy0">=</span> <span class="kw3">new</span> FileInfo<span class="br0">&#40;</span>filename<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>templateFile<span class="sy0">.</span><span class="me1">Exists</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> documentStream <span class="sy0">=</span> templateFile<span class="sy0">.</span><span class="me1">Open</span><span class="br0">&#40;</span>FileMode<span class="sy0">.</span><span class="me1">Open</span>, FileAccess<span class="sy0">.</span><span class="me1">ReadWrite</span>, FileShare<span class="sy0">.</span><span class="me1">Read</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> document <span class="sy0">=</span> WordprocessingDocument<span class="sy0">.</span><span class="me1">Open</span><span class="br0">&#40;</span>documentStream, <span class="kw1">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> bookmarks <span class="sy0">=</span> GetBookmarks<span class="br0">&#40;</span>document<span class="sy0">.</span><span class="me1">MainDocumentPart</span>, <span class="st0">&quot;&quot;</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="me1">ToArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> bookmarks<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">new</span> BookmarksPair<span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="br0">&#123;</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw1">static</span> IEnumerable<span class="sy0">&lt;</span>BookmarksPair<span class="sy0">&gt;</span> GetBookmarks<span class="br0">&#40;</span>MainDocumentPart documentPart, <span class="kw4">string</span> prefix<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> starts <span class="sy0">=</span> documentPart<span class="sy0">.</span><span class="me1">Document</span><span class="sy0">.</span><span class="me1">Descendants</span><span class="sy0">&lt;</span>BookmarkStart<span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> ends <span class="sy0">=</span> documentPart<span class="sy0">.</span><span class="me1">Document</span><span class="sy0">.</span><span class="me1">Descendants</span><span class="sy0">&lt;</span>BookmarkEnd<span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> result <span class="sy0">=</span> <span class="kw1">from</span> start <span class="kw1">in</span> starts
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">join</span> end <span class="kw1">in</span> ends on <span class="br0">&#40;</span><span class="kw4">string</span><span class="br0">&#41;</span>start<span class="sy0">.</span><span class="me1">Id</span> equals <span class="br0">&#40;</span><span class="kw4">string</span><span class="br0">&#41;</span>end<span class="sy0">.</span><span class="me1">Id</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">where</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">string</span><span class="br0">&#41;</span>start<span class="sy0">.</span><span class="me1">Name</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="me1">StartsWith</span><span class="br0">&#40;</span>prefix<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">where</span> start<span class="sy0">.</span><span class="me1">Parent</span> <span class="sy0">==</span> end<span class="sy0">.</span><span class="me1">Parent</span> <span class="co1">// Закладки, находящиеся внутри общего элемента</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">select</span> <span class="kw3">new</span> BookmarksPair<span class="br0">&#40;</span>start, end<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> result<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Эти закладки можно просмотреть и что-то придумать. Но, в общем-то, получать их отдельно не обязательно.<br />
<br />
Далее снова открываем документ, собираем закладки, выбираем из них одну подходящую и заменяем.<br />
<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="905082356"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="905082356" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">void</span> ReplaceAndSave<span class="br0">&#40;</span><span class="kw4">string</span> filenameSource, <span class="kw4">string</span> filenameDestination, <span class="kw4">string</span> bookmarkName, <span class="kw4">string</span> <span class="kw1">value</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> templateFile <span class="sy0">=</span> <span class="kw3">new</span> FileInfo<span class="br0">&#40;</span>filenameSource<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>templateFile<span class="sy0">.</span><span class="me1">Exists</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> tempFile <span class="sy0">=</span> templateFile<span class="sy0">.</span><span class="me1">CopyTo</span><span class="br0">&#40;</span>Path<span class="sy0">.</span><span class="me1">GetTempFileName</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, <span class="kw1">true</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> documentStream <span class="sy0">=</span> tempFile<span class="sy0">.</span><span class="me1">Open</span><span class="br0">&#40;</span>FileMode<span class="sy0">.</span><span class="me1">Open</span>, FileAccess<span class="sy0">.</span><span class="me1">ReadWrite</span>, FileShare<span class="sy0">.</span><span class="me1">Read</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> document <span class="sy0">=</span> WordprocessingDocument<span class="sy0">.</span><span class="me1">Open</span><span class="br0">&#40;</span>documentStream, <span class="kw1">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> bookmarks <span class="sy0">=</span> GetBookmarks<span class="br0">&#40;</span>document<span class="sy0">.</span><span class="me1">MainDocumentPart</span>, <span class="st0">&quot;&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BookmarksPair pair <span class="sy0">=</span> bookmarks<span class="sy0">.</span><span class="me1">FirstOrDefault</span><span class="br0">&#40;</span>x <span class="sy0">=&gt;</span> x<span class="sy0">.</span><span class="me1">Start</span><span class="sy0">.</span><span class="me1">Name</span> <span class="sy0">==</span> bookmarkName<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>pair <span class="sy0">!=</span> <span class="kw1">null</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ReplaceBookmarkContent<span class="br0">&#40;</span>pair, <span class="kw1">value</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tempFile<span class="sy0">.</span><span class="me1">MoveTo</span><span class="br0">&#40;</span>filenameDestination<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw1">static</span> <span class="kw4">void</span> ReplaceBookmarkContent<span class="br0">&#40;</span>BookmarksPair bookmarksPair, <span class="kw4">string</span> <span class="kw1">value</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CleanContentBetweenBookmarks<span class="br0">&#40;</span>bookmarksPair<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Run run <span class="sy0">=</span> <span class="kw3">new</span> Run<span class="br0">&#40;</span><span class="kw3">new</span> Text<span class="br0">&#40;</span><span class="kw1">value</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bookmarksPair<span class="sy0">.</span><span class="me1">Start</span><span class="sy0">.</span><span class="me1">InsertAfterSelf</span><span class="br0">&#40;</span>run<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw1">static</span> <span class="kw4">void</span> CleanContentBetweenBookmarks<span class="br0">&#40;</span>BookmarksPair bookmarksPair<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; List<span class="sy0">&lt;</span>OpenXmlElement<span class="sy0">&gt;</span> elements <span class="sy0">=</span> <span class="kw3">new</span> List<span class="sy0">&lt;</span>OpenXmlElement<span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OpenXmlElement element <span class="sy0">=</span> bookmarksPair<span class="sy0">.</span><span class="me1">Start</span><span class="sy0">.</span><span class="me1">NextSibling</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>element <span class="sy0">!=</span> <span class="kw1">null</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>element <span class="sy0">==</span> bookmarksPair<span class="sy0">.</span><span class="me1">End</span><span class="br0">&#41;</span> <span class="kw1">break</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elements<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>element<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; element <span class="sy0">=</span> element<span class="sy0">.</span><span class="me1">NextSibling</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> item <span class="kw1">in</span> elements<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; item<span class="sy0">.</span><span class="kw1">Remove</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Заметка и исходники, может быть :pardon:, будут дополняться. По мере наличия свободного времени.<br />
Поэтому исходники на GitHub, под VCS.</div>

]]></content:encoded>
			<dc:creator>Rius</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/594854/4379.html</guid>
		</item>
		<item>
			<title>Чтение с последовательного порта без использования Sleep</title>
			<link>https://www.cyberforum.ru/blogs/594854/4357.html</link>
			<pubDate>Sat, 13 Aug 2016 13:32:30 GMT</pubDate>
			<description>В продолжение темы https://www.cyberforum.ru/windows-forms/thread1773718.html 
 
Если возникает...</description>
			<content:encoded><![CDATA[<div>В продолжение темы <a href="https://www.cyberforum.ru/windows-forms/thread1773718.html">https://www.cyberforum.ru/wind... 73718.html</a><br />
<br />
Если возникает необходимость обмена с внешним устройством по UART, в C# для этого самый очевидный способ - применение <a rel="nofollow noopener noreferrer" href="https://msdn.microsoft.com/ru-ru/library/system.io.ports.serialport(v=vs.110).aspx" target="_blank" title="https://msdn.microsoft.com/ru-ru/library/system.io.ports.serialport(v=vs.110).aspx">System.IO.Ports.SerialPort</a>.<br />
<br />
Рассматривается случай, когда ответ от устройства приходит после посылки запроса к нему.<br />
Если с отправкой всё более-менее понятно, то приём реализуется по разному.<br />
<br />
<font size="6">Чтение SerialPort с исключениями.</font><br />
<ul><li>Опрос свойства <code class="inlinecode">BytesToRead</code> в цикле затратен по времени и ресурсам.</li>
<li>Событие <code class="inlinecode">DataReceived</code> тоже кривое. Может прийти в начале приёма данных, может позже. Работает само по себе. Поэтому для схемы запрос-ответ надо городить огород вокруг него, чтобы удостовериться в завершении приёма всех данных.</li>
<li><code class="inlinecode">Read(Byte&#91;&#93;, Int32, Int32)</code> уже получше, но таймаут у него задаётся один.</li>
</ul>Приём ответа состоит из нескольких фаз.<br />
Ответа надо дождаться, а он может и не прийти. Может прийти через длительное  время, но быть относительно коротким. Либо наоборот, прийти быстро, и быть длинным.<br />
Надо дождаться начала ответа, принять все его байты, и сделать вывод о завершении ответа.<br />
Вывод этот можно сделать по факту таймаута. Это время, в течение которого от устройства не пришло ни одного байта, время тишины. Его можно принять, например, равным времени, необходимым для передачи трёх байт на выбранной скорости.<br />
Однако, тут появляется пара проблем:<ul><li>Если таймаут небольшой, то можно не дождаться начала ответа.</li>
<li>Если таймаут большой, то время ожидания завершения ответа будет потрачено напрасно.</li>
</ul><br />
Для обхода этого можно сделать два таймаута, как показано в приведённом ниже коде.<br />
Первый таймаут - ожидание начала ответа.<br />
Второй таймаут - ожидание завершения, если ответ-таки пошёл.<br />
Это позволит и дождаться начала, и не тратить время понапрасну в конце.<br />
<br />
Сначала выставляется первый таймаут и запускается приём одного байта.<br />
Если байт не принят, вылетает TimeoutException, значит ответ не пришёл вообще.<br />
Если байт принят, выставляется второй таймаут и запускается приём оставшихся байт.<br />
Приём производится кусками, из которых заполняется буфер. Если чтение прошло без проблем, буфер дополняется новыми байтами и чтение куска перезапускается. Если вылетел TimeoutException, значит байтов больше нет и приём завершён.<br />
<br />
В функцию должен передаваться уже настроенный и открытый SerialPort.<br />
Массив байт для передаваемых байт, массив байт для принимаемых байт, переменная под количество принятых байт.<br />
А также токен отмены, на случай необходимости прерывания приёма (но из состояния ожидания таймаута этот токен не выведет).<br />
<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="239522011"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="239522011" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Отправка/приём данных через SerialPort.</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;connection&quot;&gt;SerialPort, используемый для связи.&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;sendBuffer&quot;&gt;Массив отправляемых байт.&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;waitingForStart&quot;&gt;Время ожидания от отправки до начала ответа.&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;waitForEnd&quot;&gt;Время ожидания после завершения ответа.&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;cancellationToken&quot;&gt;Токен отмены.&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;recvBuffer&quot;&gt;Массив буфера для приёма байт.&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;received&quot;&gt;Количество принятых байт.&lt;/param&gt;</span>
<span class="co1">/// &lt;returns&gt;Получен ли какой-нибудь ответ.&lt;/returns&gt;</span>
<span class="kw1">public</span> <span class="kw4">bool</span> SendRecv<span class="br0">&#40;</span>SerialPort connection, <span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> sendBuffer, <span class="kw4">int</span> waitingForStart, <span class="kw4">int</span> waitForEnd, CancellationToken cancellationToken, <span class="kw1">ref</span> <span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> recvBuffer, <span class="kw1">out</span> <span class="kw4">int</span> received<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">bool</span> result <span class="sy0">=</span> <span class="kw1">false</span><span class="sy0">;</span>
&nbsp; &nbsp; received <span class="sy0">=</span> <span class="sy0">-</span><span class="nu0">1</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Порт должен быть открыт.</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>connection<span class="sy0">.</span><span class="me1">IsOpen</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Сброс буферов.</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; connection<span class="sy0">.</span><span class="me1">DiscardInBuffer</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; connection<span class="sy0">.</span><span class="me1">DiscardOutBuffer</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>connection<span class="sy0">.</span><span class="me1">BytesToRead</span> <span class="sy0">&gt;</span> <span class="nu0">0</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; connection<span class="sy0">.</span><span class="me1">ReadExisting</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Установка таймаута начала ответа.</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; connection<span class="sy0">.</span><span class="me1">ReadTimeout</span> <span class="sy0">=</span> waitingForStart<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Отправка данных.</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; connection<span class="sy0">.</span><span class="me1">Write</span><span class="br0">&#40;</span>sendBuffer, <span class="nu0">0</span>, sendBuffer<span class="sy0">.</span><span class="me1">Length</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> readed <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Ожидание первого байта. Если ничего не придёт за waitingForStart мс, то вылетит TimeoutException.</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; recvBuffer<span class="br0">&#91;</span>readed<span class="sy0">++</span><span class="br0">&#93;</span> <span class="sy0">=</span> Convert<span class="sy0">.</span><span class="me1">ToByte</span><span class="br0">&#40;</span>connection<span class="sy0">.</span><span class="me1">ReadByte</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Установка таймаута для определения завершения ответа.</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; connection<span class="sy0">.</span><span class="me1">ReadTimeout</span> <span class="sy0">=</span> waitForEnd<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Временный буфер для приёма частями.</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> temp <span class="sy0">=</span> <span class="kw3">new</span> <span class="kw4">byte</span><span class="br0">&#91;</span><span class="nu0">16</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">do</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Чтение и заполнение буфера.</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Если ничего не принято, то вылетит TimeoutException.</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Если считано меньше или равно размеру буфера, это число возвращается функцией.</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> b <span class="sy0">=</span> connection<span class="sy0">.</span><span class="me1">Read</span><span class="br0">&#40;</span>temp, <span class="nu0">0</span>, <span class="nu0">16</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Копирование в выходной буфер.</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> b<span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; recvBuffer<span class="br0">&#91;</span>readed<span class="sy0">++</span><span class="br0">&#93;</span> <span class="sy0">=</span> temp<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Повтор до явной отмены.</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Также, выход доступен по таймауту чтения.</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">while</span> <span class="br0">&#40;</span><span class="sy0">!</span>cancellationToken<span class="sy0">.</span><span class="me1">IsCancellationRequested</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">catch</span> <span class="br0">&#40;</span>TimeoutException<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">finally</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Количество считанного.</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; received <span class="sy0">=</span> readed<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Возвращаемый результат: принято ли что-нибудь.</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result <span class="sy0">=</span> readed <span class="sy0">&gt;</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">catch</span> <span class="br0">&#40;</span>TimeoutException<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">catch</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; result <span class="sy0">=</span> <span class="kw1">false</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> result<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Среди видимых недостатков - огромное количество выбрасываемых TimeoutException, что изрядно засоряет лог отладчика.<br />
<br />
<br />
<font size="6">Чтение потока, лежащего в основе SerialPort.</font><br />
Упоминал <a href="https://www.cyberforum.ru/windows-forms/thread1773718.html#post9388689">здесь</a>, код приводил <a href="https://www.cyberforum.ru/windows-forms/thread1773718.html#post9526469">здесь</a> и пример программы <a href="https://www.cyberforum.ru/windows/thread1804932.html#post9528340">здесь</a>.<br />
На всякий случай дублирую.<br />
<br />
Идея (не реализация) способа взята в статье <a rel="nofollow noopener noreferrer" href="http://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport" target="_blank" title="http://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport">If you *must* use .NET System.IO.Ports.SerialPort</a>, где автор расстраивался по поводу криворукости разработчиков .Net Framework, написавших SerialPort так, как сделано, а не <s>по фен-шую</s> в полном соответствии с WinAPI.<br />
Смысл в том, что запускается асинхронное чтение потока SerialPort.BaseStream. По завершению получаем массив байт и обрабатываем. Всё якобы асинхронно, легковесно и просто.<br />
<div class="smallfont offtopic" onmouseover="this.style.color='#000000';" onmouseout="this.style.color='#888888';">
				<p><b>Не по теме:</b></p>
				<p>IMHO ни черта не просто, так как в .Net, версий по крайней мере &lt;= 4.0, асинхронное чтение не остановить без закрытия потока... А ещё мне необходимы вполне конкретные таймауты.</p>
				</div><br />
<br />
Но рабочую реализацию запилил-таки:<br />
<br />
<br />
Класс для таймаутов. Нужен для вызова события (callback, обратного вызова, в общем - определённого указанного кода), если обратный отсчёт времени не был остановлен/перезапущен в отведённый период времени. Аналог таймера WatchDog и прерывания UART - IDLE из области микроконтроллеров.<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="808014412"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="808014412" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
</pre></td><td class="de1"><pre class="de1"><span class="kw1">using</span> <span class="co3">System</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Threading</span><span class="sy0">;</span>
&nbsp;
<span class="kw1">namespace</span> SerialStreamTest
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// Таймер отсчёта таймаута</span>
&nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; <span class="kw4">class</span> TimerTimeout
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> Timer mTimer<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> Action mCallback<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw4">object</span> mCallbackLocker<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> TimerTimeout<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mTimer</span> <span class="sy0">=</span> <span class="kw3">new</span> Timer<span class="br0">&#40;</span><span class="kw1">this</span><span class="sy0">.</span><span class="me1">CallBack</span>, <span class="kw1">null</span>, Timeout<span class="sy0">.</span><span class="me1">Infinite</span>, Timeout<span class="sy0">.</span><span class="me1">Infinite</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mCallback</span> <span class="sy0">=</span> <span class="kw1">null</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mCallbackLocker</span> <span class="sy0">=</span> <span class="kw3">new</span> <span class="kw4">object</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw4">void</span> CallBack<span class="br0">&#40;</span><span class="kw4">object</span> state<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">lock</span> <span class="br0">&#40;</span><span class="kw1">this</span><span class="sy0">.</span><span class="me1">mCallbackLocker</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">this</span><span class="sy0">.</span><span class="me1">mCallback</span> <span class="sy0">!=</span> <span class="kw1">null</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mCallback</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Запуск/перезапуск таймера.</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;paramref name=&quot;Callback&quot;/&gt; будет вызван через &lt;paramref name=&quot;millisecondsTimeout&quot;/&gt; мс после текущего момента времени.</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Если таймер был запущен ранее, предыдущий &lt;paramref name=&quot;Callback&quot;/&gt; отменится.</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;millisecondsTimeout&quot;&gt;Время, через которое будет вызван &lt;paramref name=&quot;Callback&quot;/&gt;.&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;callback&quot;&gt;Функция обратного вызова по срабатыванию таймера.&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> ReStart<span class="br0">&#40;</span><span class="kw4">int</span> millisecondsTimeout, Action callback<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">lock</span> <span class="br0">&#40;</span><span class="kw1">this</span><span class="sy0">.</span><span class="me1">mCallbackLocker</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mCallback</span> <span class="sy0">=</span> callback<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mTimer</span><span class="sy0">.</span><span class="me1">Change</span><span class="br0">&#40;</span>millisecondsTimeout, Timeout<span class="sy0">.</span><span class="me1">Infinite</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Отмена отсчёта таймера.</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> Stop<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mTimer</span><span class="sy0">.</span><span class="me1">Change</span><span class="br0">&#40;</span>Timeout<span class="sy0">.</span><span class="me1">Infinite</span>, Timeout<span class="sy0">.</span><span class="me1">Infinite</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">lock</span> <span class="br0">&#40;</span><span class="kw1">this</span><span class="sy0">.</span><span class="me1">mCallbackLocker</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mCallback</span> <span class="sy0">=</span> <span class="kw1">null</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
<br />
Сам класс для обмена<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="569508333"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="569508333" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
</pre></td><td class="de1"><pre class="de1"><span class="kw1">using</span> <span class="co3">System</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Collections.Concurrent</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Collections.Generic</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.IO</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.IO.Ports</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Linq</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Threading</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Threading.Tasks</span><span class="sy0">;</span>
&nbsp;
<span class="kw1">namespace</span> SerialStreamTest
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// Класс чтения/записи в последовательный порт.</span>
&nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// &lt;remarks&gt;</span>
&nbsp; &nbsp; <span class="co1">/// Задача: записать данные в порт и принять ответ.</span>
&nbsp; &nbsp; <span class="co1">/// Ответа может и не быть.</span>
&nbsp; &nbsp; <span class="co1">/// Отдельные таймауты на ожидание начала приёма и на ожидание завершения приёма.</span>
&nbsp; &nbsp; <span class="co1">/// </span>
&nbsp; &nbsp; <span class="co1">/// Запись работает как обычно.</span>
&nbsp; &nbsp; <span class="co1">/// </span>
&nbsp; &nbsp; <span class="co1">/// Приём:</span>
&nbsp; &nbsp; <span class="co1">/// Запускаем таймер отсчёта начала ответа.</span>
&nbsp; &nbsp; <span class="co1">/// Входим в состояние приёма.</span>
&nbsp; &nbsp; <span class="co1">/// Выход из него возможен по таймауту начала ответа и по таймауту завершения приёма.</span>
&nbsp; &nbsp; <span class="co1">/// Если время начала ответа вышло, ожидание завершается и возвращается пустой массив.</span>
&nbsp; &nbsp; <span class="co1">/// Если за время начала ответа этот ответ начал приниматься, ждём уже завершения приёма.</span>
&nbsp; &nbsp; <span class="co1">/// &lt;/remarks&gt;</span>
&nbsp; &nbsp; <span class="kw4">class</span> SerialStream4 <span class="sy0">:</span> IDisposable
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> SerialPort mPort<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> ConcurrentQueue<span class="sy0">&lt;</span><span class="kw4">byte</span><span class="sy0">&gt;</span> mReceiveQueue<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Задача для повторяющегося чтения</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> Task mReaderTask<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Токен отмены задачи повторяющегося чтения</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> CancellationTokenSource mReaderTaskToken<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Событие приёма чего-либо</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> ManualResetEventSlim mReadEvent<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Событие таймаута начала приёма</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> ManualResetEventSlim mStartTimeoutEvent<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Событие таймаута после приёма</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> ManualResetEventSlim mEndTimeoutEvent<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Таймер для отсчёта таймаута начала пакета</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> TimerTimeout mTimerStartTimeout<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Таймер для отсчёта таймаута завершения пакета</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> TimerTimeout mTimerEndTimeout<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Время ожидания завершения приёма, мс</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> <span class="kw4">int</span> mEndTimeout<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> SerialStream4<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mPort</span> <span class="sy0">=</span> <span class="kw3">new</span> SerialPort<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mReceiveQueue</span> <span class="sy0">=</span> <span class="kw3">new</span> ConcurrentQueue<span class="sy0">&lt;</span><span class="kw4">byte</span><span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mReadEvent</span> <span class="sy0">=</span> <span class="kw3">new</span> ManualResetEventSlim<span class="br0">&#40;</span><span class="kw1">false</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mStartTimeoutEvent</span> <span class="sy0">=</span> <span class="kw3">new</span> ManualResetEventSlim<span class="br0">&#40;</span><span class="kw1">false</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mEndTimeoutEvent</span> <span class="sy0">=</span> <span class="kw3">new</span> ManualResetEventSlim<span class="br0">&#40;</span><span class="kw1">false</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mTimerStartTimeout</span> <span class="sy0">=</span> <span class="kw3">new</span> TimerTimeout<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mTimerEndTimeout</span> <span class="sy0">=</span> <span class="kw3">new</span> TimerTimeout<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mEndTimeout</span> <span class="sy0">=</span> Timeout<span class="sy0">.</span><span class="me1">Infinite</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> Dispose<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">Close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">bool</span> Open<span class="br0">&#40;</span><span class="kw4">string</span> portName, <span class="kw4">int</span> baudRate, Parity parity <span class="sy0">=</span> Parity<span class="sy0">.</span><span class="me1">None</span>, <span class="kw4">int</span> dataBits <span class="sy0">=</span> <span class="nu0">8</span>, StopBits stopBits <span class="sy0">=</span> StopBits<span class="sy0">.</span><span class="me1">One</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mPort</span><span class="sy0">.</span><span class="me1">PortName</span> <span class="sy0">=</span> portName<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mPort</span><span class="sy0">.</span><span class="me1">BaudRate</span> <span class="sy0">=</span> baudRate<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mPort</span><span class="sy0">.</span><span class="me1">Parity</span> <span class="sy0">=</span> parity<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mPort</span><span class="sy0">.</span><span class="me1">DataBits</span> <span class="sy0">=</span> dataBits<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mPort</span><span class="sy0">.</span><span class="me1">StopBits</span> <span class="sy0">=</span> stopBits<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mPort</span><span class="sy0">.</span><span class="me1">ReadTimeout</span> <span class="sy0">=</span> <span class="nu0">100</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mPort</span><span class="sy0">.</span><span class="me1">Open</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">this</span><span class="sy0">.</span><span class="me1">mPort</span><span class="sy0">.</span><span class="me1">IsOpen</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mReaderTaskToken</span> <span class="sy0">=</span> <span class="kw3">new</span> CancellationTokenSource<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mReaderTask</span> <span class="sy0">=</span> Task<span class="sy0">.</span><span class="me1">Factory</span><span class="sy0">.</span><span class="me1">StartNew</span><span class="br0">&#40;</span>o <span class="sy0">=&gt;</span> <span class="kw1">this</span><span class="sy0">.</span><span class="me1">AsyncReader</span><span class="br0">&#40;</span><span class="br0">&#40;</span>CancellationToken<span class="br0">&#41;</span>o<span class="br0">&#41;</span>, <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mReaderTaskToken</span><span class="sy0">.</span><span class="me1">Token</span>, <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mReaderTaskToken</span><span class="sy0">.</span><span class="me1">Token</span>, TaskCreationOptions<span class="sy0">.</span><span class="me1">LongRunning</span>, TaskScheduler<span class="sy0">.</span><span class="kw1">Default</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mPort</span><span class="sy0">.</span><span class="me1">IsOpen</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw4">void</span> AsyncReader<span class="br0">&#40;</span>CancellationToken token<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span><span class="kw1">true</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Task<span class="sy0">&lt;</span>ReadedData<span class="sy0">&gt;</span> task <span class="sy0">=</span> <span class="kw1">this</span><span class="sy0">.</span><span class="me1">ReadPart</span><span class="br0">&#40;</span><span class="nu0">64</span>, <span class="nu0">100</span>, <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mReaderTaskToken</span><span class="sy0">.</span><span class="me1">Token</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; task<span class="sy0">.</span><span class="me1">Wait</span><span class="br0">&#40;</span>token<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; token<span class="sy0">.</span><span class="me1">ThrowIfCancellationRequested</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> b <span class="kw1">in</span> task<span class="sy0">.</span><span class="me1">Result</span><span class="sy0">.</span><span class="me1">Array</span><span class="sy0">.</span><span class="me1">Take</span><span class="br0">&#40;</span>task<span class="sy0">.</span><span class="me1">Result</span><span class="sy0">.</span><span class="me1">Count</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mReceiveQueue</span><span class="sy0">.</span><span class="me1">Enqueue</span><span class="br0">&#40;</span>b<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mReadEvent</span><span class="sy0">.</span><span class="kw1">Set</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> Close<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">this</span><span class="sy0">.</span><span class="me1">mPort</span><span class="sy0">.</span><span class="me1">IsOpen</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mReaderTaskToken</span><span class="sy0">.</span><span class="me1">Cancel</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mReaderTask</span><span class="sy0">.</span><span class="me1">Wait</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">catch</span> <span class="br0">&#40;</span>AggregateException<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mPort</span><span class="sy0">.</span><span class="me1">Close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">bool</span> IsOpen
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mPort</span><span class="sy0">.</span><span class="me1">IsOpen</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> DiscardInBuffer<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">byte</span> b<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span><span class="kw1">this</span><span class="sy0">.</span><span class="me1">mReceiveQueue</span><span class="sy0">.</span><span class="me1">TryDequeue</span><span class="br0">&#40;</span><span class="kw1">out</span> b<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mReadEvent</span><span class="sy0">.</span><span class="me1">Reset</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> Write<span class="br0">&#40;</span><span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> buffer<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console<span class="sy0">.</span><span class="me1">WriteLine</span><span class="br0">&#40;</span><span class="st0">&quot;Send&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mPort</span><span class="sy0">.</span><span class="me1">Write</span><span class="br0">&#40;</span>buffer, <span class="nu0">0</span>, buffer<span class="sy0">.</span><span class="me1">Length</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">bool</span> Read<span class="br0">&#40;</span><span class="kw1">out</span> <span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> receivedBuffer, <span class="kw4">int</span> startTimeout, <span class="kw4">int</span> endTimeout, CancellationToken cancellationToken<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mStartTimeoutEvent</span><span class="sy0">.</span><span class="me1">Reset</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mEndTimeoutEvent</span><span class="sy0">.</span><span class="me1">Reset</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mEndTimeout</span> <span class="sy0">=</span> endTimeout<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//this.mTimerStartTimeout.ReStart(startTimeout, this.mStartTimeoutEvent.Set);</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mTimerStartTimeout</span><span class="sy0">.</span><span class="me1">ReStart</span><span class="br0">&#40;</span>startTimeout, <span class="kw1">this</span><span class="sy0">.</span><span class="me1">StartTimeoutCallback</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> completedIndex <span class="sy0">=</span> WaitHandle<span class="sy0">.</span><span class="me1">WaitAny</span><span class="br0">&#40;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">new</span> WaitHandle<span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mEndTimeoutEvent</span><span class="sy0">.</span><span class="me1">WaitHandle</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mStartTimeoutEvent</span><span class="sy0">.</span><span class="me1">WaitHandle</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cancellationToken<span class="sy0">.</span><span class="me1">WaitHandle</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">switch</span> <span class="br0">&#40;</span>completedIndex<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="nu0">0</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mEndTimeoutEvent</span><span class="sy0">.</span><span class="me1">Reset</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mStartTimeoutEvent</span><span class="sy0">.</span><span class="me1">Reset</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; List<span class="sy0">&lt;</span><span class="kw4">byte</span><span class="sy0">&gt;</span> bytes <span class="sy0">=</span> <span class="kw3">new</span> List<span class="sy0">&lt;</span><span class="kw4">byte</span><span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">byte</span> b<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span><span class="kw1">this</span><span class="sy0">.</span><span class="me1">mReceiveQueue</span><span class="sy0">.</span><span class="me1">TryDequeue</span><span class="br0">&#40;</span><span class="kw1">out</span> b<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bytes<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>b<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; receivedBuffer <span class="sy0">=</span> bytes<span class="sy0">.</span><span class="me1">ToArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw1">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="nu0">1</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="nu0">2</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">default</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mEndTimeoutEvent</span><span class="sy0">.</span><span class="me1">Reset</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mStartTimeoutEvent</span><span class="sy0">.</span><span class="me1">Reset</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; receivedBuffer <span class="sy0">=</span> <span class="kw3">new</span> <span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="br0">&#123;</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw1">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> Task<span class="sy0">&lt;</span>ReadedData<span class="sy0">&gt;</span> ReadPart<span class="br0">&#40;</span><span class="kw4">int</span> expectedCount, <span class="kw4">int</span> millisecondsTimeout, CancellationToken cancellationToken<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ReadedData data <span class="sy0">=</span> <span class="kw3">new</span> ReadedData<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; List<span class="sy0">&lt;</span><span class="kw4">byte</span><span class="sy0">&gt;</span> buffer <span class="sy0">=</span> <span class="kw3">new</span> List<span class="sy0">&lt;</span><span class="kw4">byte</span><span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> tempBuffer <span class="sy0">=</span> <span class="kw3">new</span> <span class="kw4">byte</span><span class="br0">&#91;</span>expectedCount<span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data<span class="sy0">.</span><span class="me1">Array</span> <span class="sy0">=</span> tempBuffer<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Task<span class="sy0">&lt;</span><span class="kw4">int</span><span class="sy0">&gt;</span> taskReader <span class="sy0">=</span> Task<span class="sy0">&lt;</span><span class="kw4">int</span><span class="sy0">&gt;.</span><span class="me1">Factory</span><span class="sy0">.</span><span class="me1">FromAsync</span><span class="br0">&#40;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mPort</span><span class="sy0">.</span><span class="me1">BaseStream</span><span class="sy0">.</span><span class="me1">BeginRead</span>, <span class="co1">// IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state);</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mPort</span><span class="sy0">.</span><span class="me1">BaseStream</span><span class="sy0">.</span><span class="me1">EndRead</span>, <span class="co1">// int EndRead(IAsyncResult asyncResult);</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tempBuffer,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tempBuffer<span class="sy0">.</span><span class="me1">Length</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Task<span class="sy0">&lt;</span>ReadedData<span class="sy0">&gt;</span> taskContinuation <span class="sy0">=</span> taskReader<span class="sy0">.</span><span class="me1">ContinueWith</span><span class="sy0">&lt;</span>ReadedData<span class="sy0">&gt;</span><span class="br0">&#40;</span>x <span class="sy0">=&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> actualLength <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; actualLength <span class="sy0">=</span> x<span class="sy0">.</span><span class="me1">Result</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data<span class="sy0">.</span><span class="me1">Count</span> <span class="sy0">=</span> actualLength<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mTimerStartTimeout</span><span class="sy0">.</span><span class="me1">Stop</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//this.mTimerEndTimeout.ReStart(this.mEndTimeout, this.mEndTimeoutEvent.Set);</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mTimerEndTimeout</span><span class="sy0">.</span><span class="me1">ReStart</span><span class="br0">&#40;</span><span class="kw1">this</span><span class="sy0">.</span><span class="me1">mEndTimeout</span>, <span class="kw1">this</span><span class="sy0">.</span><span class="me1">EndTimeoutCallback</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console<span class="sy0">.</span><span class="me1">WriteLine</span><span class="br0">&#40;</span><span class="st0">&quot;Received: [{0}]&quot;</span>, actualLength<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">catch</span> <span class="br0">&#40;</span>IOException exc<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console<span class="sy0">.</span><span class="me1">WriteLine</span><span class="br0">&#40;</span>exc<span class="sy0">.</span><span class="me1">Message</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data<span class="sy0">.</span><span class="me1">Exception</span> <span class="sy0">=</span> exc<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> data<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> taskContinuation<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw4">void</span> StartTimeoutCallback<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console<span class="sy0">.</span><span class="me1">WriteLine</span><span class="br0">&#40;</span><span class="st0">&quot;Answer not received&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mStartTimeoutEvent</span><span class="sy0">.</span><span class="kw1">Set</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw4">void</span> EndTimeoutCallback<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console<span class="sy0">.</span><span class="me1">WriteLine</span><span class="br0">&#40;</span><span class="st0">&quot;Answer completed&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">mEndTimeoutEvent</span><span class="sy0">.</span><span class="kw1">Set</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw4">class</span> ReadedData
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> Array <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">int</span> Count <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Exception Exception <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> ReadedData<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">Array</span> <span class="sy0">=</span> <span class="kw3">new</span> <span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="br0">&#123;</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">Count</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">this</span><span class="sy0">.</span><span class="me1">Exception</span> <span class="sy0">=</span> <span class="kw1">null</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
<br />
Пример использования<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="914852241"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="914852241" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
</pre></td><td class="de1"><pre class="de1"><span class="kw1">using</span> <span class="co3">System</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.IO.Ports</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Linq</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Threading</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Threading.Tasks</span><span class="sy0">;</span>
&nbsp;
<span class="kw1">namespace</span> SerialStreamTest
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">class</span> Program
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">static</span> <span class="kw4">void</span> Main<span class="br0">&#40;</span><span class="kw4">string</span><span class="br0">&#91;</span><span class="br0">&#93;</span> args<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CancellationTokenSource token <span class="sy0">=</span> <span class="kw3">new</span> CancellationTokenSource<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Task task <span class="sy0">=</span> Task<span class="sy0">.</span><span class="me1">Factory</span><span class="sy0">.</span><span class="me1">StartNew</span><span class="br0">&#40;</span>o <span class="sy0">=&gt;</span> Read<span class="br0">&#40;</span><span class="br0">&#40;</span>CancellationToken<span class="br0">&#41;</span>o<span class="br0">&#41;</span>, token<span class="sy0">.</span><span class="me1">Token</span>, token<span class="sy0">.</span><span class="me1">Token</span>, TaskCreationOptions<span class="sy0">.</span><span class="me1">LongRunning</span>, TaskScheduler<span class="sy0">.</span><span class="kw1">Default</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console<span class="sy0">.</span><span class="me1">ReadLine</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; token<span class="sy0">.</span><span class="me1">Cancel</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; task<span class="sy0">.</span><span class="me1">Wait</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">catch</span> <span class="br0">&#40;</span>AggregateException<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw1">static</span> <span class="kw4">void</span> Read<span class="br0">&#40;</span>CancellationToken token<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> send <span class="sy0">=</span> <span class="kw3">new</span> <span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="br0">&#123;</span> <span class="sy0">...</span> тут байты запроса <span class="sy0">...</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> port <span class="sy0">=</span> <span class="kw3">new</span> SerialStream4<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; port<span class="sy0">.</span><span class="me1">Open</span><span class="br0">&#40;</span><span class="st0">&quot;COM28&quot;</span>, <span class="nu0">19200</span>, Parity<span class="sy0">.</span><span class="me1">Odd</span>, <span class="nu0">8</span>, StopBits<span class="sy0">.</span><span class="me1">One</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span><span class="sy0">!</span>token<span class="sy0">.</span><span class="me1">IsCancellationRequested</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; port<span class="sy0">.</span><span class="me1">Write</span><span class="br0">&#40;</span>send<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> recv<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>port<span class="sy0">.</span><span class="me1">Read</span><span class="br0">&#40;</span><span class="kw1">out</span> recv, <span class="nu0">100</span>, <span class="nu0">4</span>, token<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console<span class="sy0">.</span><span class="me1">WriteLine</span><span class="br0">&#40;</span><span class="st0">&quot;[{0}] {1}&quot;</span>, recv<span class="sy0">.</span><span class="me1">Length</span>, <span class="kw4">String</span><span class="sy0">.</span><span class="kw1">Join</span><span class="br0">&#40;</span><span class="st0">&quot; &quot;</span>, recv<span class="sy0">.</span><span class="kw1">Select</span><span class="br0">&#40;</span>x <span class="sy0">=&gt;</span> x<span class="sy0">.</span><span class="me1">ToString</span><span class="br0">&#40;</span><span class="st0">&quot;X2&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; port<span class="sy0">.</span><span class="me1">Close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=3983&amp;d=1475244049">SerialStreamTest.zip</a> (30.5 Кб, 860 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>Rius</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/594854/4357.html</guid>
		</item>
		<item>
			<title>Где скачать Windows?</title>
			<link>https://www.cyberforum.ru/blogs/594854/4351.html</link>
			<pubDate>Fri, 05 Aug 2016 15:27:53 GMT</pubDate>
			<description>*Здесь только оригинальные установщики винды, которые можно скачать у Microsoft напрямую, ничего...</description>
			<content:encoded><![CDATA[<div><b>Здесь только оригинальные установщики винды, которые можно скачать у Microsoft напрямую, ничего более.</b><br />
Проверять по хешам.<br />
<br />
<br />
Образы ISO.<br />
Официально. От Microsoft. Без вирусов и SMS.<ul><li>Windows 7<br />
<a rel="nofollow noopener noreferrer" href="https://www.microsoft.com/ru-ru/software-download/windows7" target="_blank" title="https://www.microsoft.com/ru-ru/software-download/windows7">https://www.microsoft.com/ru-r... d/windows7</a><br />
Требуется ключ продукта.<br /></li>
<li>Windows 8<br />
<a rel="nofollow noopener noreferrer" href="https://www.microsoft.com/ru-ru/software-download/windows8" target="_blank" title="https://www.microsoft.com/ru-ru/software-download/windows8">https://www.microsoft.com/ru-r... d/windows8</a><br /></li>
<li>Windows 10<br />
<a rel="nofollow noopener noreferrer" href="https://www.microsoft.com/ru-ru/software-download/windows10" target="_blank" title="https://www.microsoft.com/ru-ru/software-download/windows10">https://www.microsoft.com/ru-r... /windows10</a><br />
Скачивается утилита для создания установочного носителя. В ней вместо создания флешки/диска выбирается создания ISO образа.</li>
</ul><br />
По Windows 10 здесь, на форуме: <a href="https://www.cyberforum.ru/windows10/thread1625157-page2.html">Прямые ссылки на ISO образы Windows 10 с сайта Microsoft</a>.<br />
<br />
Образы с установленной Windows для виртуальных машин, для тестирования сайтов под разными версиями браузеров:<br />
<a rel="nofollow noopener noreferrer" href="https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/" target="_blank" title="https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/">https://developer.microsoft.co... tools/vms/</a><br />

<table width="95%"  class="bbcode_maincontainer"><tr><td>
	<div class="bbcode_container">
	  <div class="bbcode_quote">
	    <div class="btbtbt">
		<div class="quote_container">
	      	<div class="bbcode_quote_container"></div>
	       	<div class="bbcode_postedby">
	         	
	        </div>
	        <div class="message">Test Microsoft Edge and versions of IE8 through IE11 using free virtual machines you download and manage locally.</div>
	      </div>
			</div> 
		</div>
	</div>
</td></tr></table>===============<br />
<br />
Ещё способ:<ul><li>Выбираете нужную версию из списка ниже.</li>
<li>Узнаёте ещё хэш.</li>
<li>Ищете торрент с таким хешем.</li>
<li>Скачиваете образ с торрента.</li>
<li>Проверяете хеш.</li>
<li>Если хеш соответствует - у вас <b>оригинальный образ винды с MSDN</b>. Никаких кряков, активаторов, встроенных троянов, ратов и бэкдоров.</li>
</ul>
			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Хеши SHA-1 образов винды с MSDN</div>
				   <div class="spoiler-body">
					   <br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="874514835"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="874514835" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
32
33
34
35
36
37
38
39
40
41
42
</pre></td><td class="de1"><pre class="de1">75d348d5708fc58eb13444700f3b2a8f61dc9472 *en-us_windows_10_business_editions_version_22h2_x64_dvd_8cf17b79.iso
08efc0c24f86cf5920b72d98e1de767719d342b2 *en-us_windows_10_business_editions_version_22h2_x86_dvd_186a68c3.iso
af8d0e9efd3ef482d0ab365766e191e420777b2b *en-us_windows_10_consumer_editions_version_22h2_x64_dvd_8da72ab3.iso
3704f52690e6f84d010f9a10faf598348ff11081 *en-us_windows_10_consumer_editions_version_22h2_x86_dvd_90883feb.iso
2fb2897373c4f71b06f4490943b3d564b0f0fd6d *en-us_windows_10_enterprise_ltsc_2021_x64_dvd_d289cf96.iso
3f7f38802043aa55ebe930655ee35be876213e4d *en-us_windows_10_enterprise_ltsc_2021_x86_dvd_9f4aa95f.iso
a68c150649089263a34b21a7f1833e3ab41d6172 *en-us_windows_11_business_editions_version_22h2_updated_march_2023_x64_dvd_4b362179.iso
4e0d7db5a79ff6c68f2076f65685739b0ae17bd0 *en-us_windows_11_business_editions_version_22h2_updated_may_2023_x64_dvd_c2d14816.iso
55bfc9add5552e315e387797cab9e0b82400b95c *en-us_windows_11_consumer_editions_version_22h2_updated_march_2023_x64_dvd_e9856a7a.iso
962ebdfe3e8c0b174c5ca5e430dac4cdefb34c66 *en_windows_10_business_editions_version_1809_updated_jun_2021_x64_dvd_68278277.iso
04565134db37ecfac8b3b52176880562ce42f584 *en_windows_10_business_editions_version_1909_updated_jun_2021_x64_dvd_df323900.iso
080ec1de94b88b0f7e8d000690a4aaaa031e2719 *en_windows_7_home_basic_with_sp1_x86_dvd_u_676470.iso
101574faa17fdb430bb027271ef0a58f0e18ad47 *en_windows_7_home_basic_x86_dvd_x15-<span class="nu0">65654</span>.iso
6c9058389c1e2e5122b7c933275f963edf1c07b9 *en_windows_7_home_premium_with_sp1_x64_dvd_u_676549.iso
6071b4553fcf0ea53d589a846b5ae76743dd68fc *en_windows_7_home_premium_with_sp1_x86_dvd_u_676701.iso
336779ea6b65f63e11a609b4d021439c47ab315b *en_windows_7_home_premium_x64_dvd_x15-<span class="nu0">65733</span>.iso
cc9d8220b2179e784d85bf1ea98d2ee2190d534f *en_windows_7_home_premium_x86_dvd_x15-<span class="nu0">65732</span>.iso
0bcfc54019ea175b1ee51f6d2b207a3d14dd2b58 *en_windows_7_professional_with_sp1_x64_dvd_u_676939.iso
d89937df3a9bc2ec1a1486195fd308cd3dade928 *en_windows_7_professional_with_sp1_x86_dvd_u_677056.iso
36ae90defbad9d9539e649b193ae573b77a71c83 *en_windows_7_ultimate_with_sp1_x64_dvd_u_677332.iso
65fce0f445d9bf7e78e43f17e441e08c63722657 *en_windows_7_ultimate_with_sp1_x86_dvd_u_677460.iso
0afc66d392503cd2508ef17be9b5444efee3d4c3 *ru-ru_windows_10_business_editions_version_22h2_x64_dvd_61849fe8.iso
04550d7496800143650b1a665f7ed45fddb134e7 *ru-ru_windows_10_business_editions_version_22h2_x86_dvd_1f394559.iso
25b6b946137c359661f2a95c524e92ce552f8772 *ru-ru_windows_10_consumer_editions_version_22h2_x64_dvd_86fd5014.iso
04c357121776ff09aa5e92557c229167392c2aa6 *ru-ru_windows_10_consumer_editions_version_22h2_x86_dvd_2e77f200.iso
b8addd641b1ac9121ebccdc1a3c86153f6020cf4 *ru-ru_windows_10_enterprise_ltsc_2021_x64_dvd_5044a1e7.iso
2dd68f358f41056c04b509a58a68d4182b28694b *ru-ru_windows_10_enterprise_ltsc_2021_x86_dvd_cdf355eb.iso
0b8c33e55dd39f0b0e1e494728f44cf1493a77d4 *ru-ru_windows_11_business_editions_version_22h2_updated_march_2023_x64_dvd_9c7515af.iso
75f1def1c3d0941c0d17b4409244cd7594200e69 *ru-ru_windows_11_business_editions_version_22h2_updated_may_2023_x64_dvd_90166b2e.iso
a3c89108eb1a0ba714e22bfa8a4de556ba7a6f97 *ru-ru_windows_11_consumer_editions_version_22h2_updated_march_2023_x64_dvd_d3b36a20.iso
f4664fcbc4da42d638c32e6b9899438e984d65a8 *ru_windows_10_business_editions_version_1809_updated_jun_2021_x64_dvd_41c42150.iso
bd027567284044f06664661a3bd2e341fbbe431f *ru_windows_10_business_editions_version_1909_updated_jun_2021_x64_dvd_acc57c13.iso
7c7446200c478814cc983a04fa8431bfdba95f19 *ru_windows_7_home_basic_with_sp1_x86_dvd_u_676482.iso
7f68c908f04dd6f3ece4c595416acf53d72c2bb6 *ru_windows_7_home_basic_x86_dvd_x15-<span class="nu0">65691</span>.iso
3f467e896feb5ea817b14b5f9483800b36b989b8 *ru_windows_7_home_premium_with_sp1_x64_dvd_u_676728.iso
4187e9bd9d591215ac27898c0a070ad31f94a7e1 *ru_windows_7_home_premium_with_sp1_x86_dvd_u_676719.iso
b29a597223233aa5f408adfc0238f82960cb665f *ru_windows_7_home_premium_x64_dvd_x15-<span class="nu0">65763</span>.iso
efbe7ec9e8d8924785012a4bc22d2810995dbec3 *ru_windows_7_home_premium_x86_dvd_x15-<span class="nu0">65762</span>.iso
6aafbbffc12bb63894932210d5bcb69773b46c98 *ru_windows_7_professional_with_sp1_x64_dvd_u_677024.iso
e1c39ccc6c83985c2208fc19ca7058044b682f08 *ru_windows_7_professional_with_sp1_x86_dvd_u_677084.iso
106caf0695318ad0d82e441a54be8460bf099b09 *ru_windows_7_ultimate_with_sp1_x64_dvd_u_677391.iso
d224888cfa62847faa3505630a206bdcd10a9930 *ru_windows_7_ultimate_with_sp1_x86_dvd_u_677463.iso</pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div></div>

]]></content:encoded>
			<dc:creator>Rius</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/594854/4351.html</guid>
		</item>
		<item>
			<title>C# .Net + WindowsForms + плагины</title>
			<link>https://www.cyberforum.ru/blogs/594854/3740.html</link>
			<pubDate>Sat, 05 Sep 2015 14:11:15 GMT</pubDate>
			<description>*1. Обычный способ сбора плагинов.* 
* Рекурсивно в каталоге с приложением ищутся все dll файлы...</description>
			<content:encoded><![CDATA[<div><b>1. Обычный способ сбора плагинов.</b><ul><li>Рекурсивно в каталоге с приложением ищутся все dll файлы сборок.</li>
<li>Найденные по очереди перебираются и загружаются в память с помощью Assembly.LoadFile().</li>
<li>Из сборки достаются <b>все</b> существующие в ней типы. Опять же, по одному <b>перебираются</b> и проверяются на наличие интерфейса плагина.</li>
<li>Если таковой у типа имеется, тип считается плагином и сохраняется для последующего использования.</li>
</ul><br />
<a rel="nofollow noopener noreferrer" href="https://github.com/riuson/Bugs.Net/blob/a12876a13bc8bd551f5d70f9c746255e0c548444/BugTracker.Core/Classes/Plugins.cs" target="_blank" title="https://github.com/riuson/Bugs.Net/blob/a12876a13bc8bd551f5d70f9c746255e0c548444/BugTracker.Core/Classes/Plugins.cs">Пример кода на GitHub</a><br />
<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="698897614"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="698897614" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
32
33
34
35
36
37
</pre></td><td class="de1"><pre class="de1"><span class="kw1">private</span> List<span class="sy0">&lt;</span>IPlugin<span class="sy0">&gt;</span> ScanPlugins<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; List<span class="sy0">&lt;</span>IPlugin<span class="sy0">&gt;</span> result <span class="sy0">=</span> <span class="kw3">new</span> List<span class="sy0">&lt;</span>IPlugin<span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">string</span><span class="br0">&#91;</span><span class="br0">&#93;</span> files <span class="sy0">=</span> <span class="kw1">this</span><span class="sy0">.</span><span class="me1">GetLibraries</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">var</span> watch <span class="sy0">=</span> <span class="kw5">System.<span class="me1">Diagnostics</span></span><span class="sy0">.</span><span class="me1">Stopwatch</span><span class="sy0">.</span><span class="me1">StartNew</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> filename <span class="kw1">in</span> files<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Assembly assembly <span class="sy0">=</span> Assembly<span class="sy0">.</span><span class="me1">LoadFile</span><span class="br0">&#40;</span>filename<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Type<span class="br0">&#91;</span><span class="br0">&#93;</span> types <span class="sy0">=</span> assembly<span class="sy0">.</span><span class="me1">GetTypes</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> type <span class="kw1">in</span> types<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Type t <span class="sy0">=</span> type<span class="sy0">.</span><span class="me1">GetInterface</span><span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>IPlugin<span class="br0">&#41;</span><span class="sy0">.</span><span class="me1">FullName</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>t <span class="sy0">!=</span> <span class="kw1">null</span> <span class="sy0">&amp;&amp;</span> <span class="sy0">!</span>type<span class="sy0">.</span><span class="me1">IsAbstract</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IPlugin pluginInfo <span class="sy0">=</span> <span class="br0">&#40;</span>IPlugin<span class="br0">&#41;</span>Activator<span class="sy0">.</span><span class="me1">CreateInstance</span><span class="br0">&#40;</span>type<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>pluginInfo<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">catch</span> <span class="br0">&#40;</span>Exception exc<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw5">System.<span class="me1">Diagnostics</span></span><span class="sy0">.</span><span class="me1">Debug</span><span class="sy0">.</span><span class="me1">WriteLine</span><span class="br0">&#40;</span>exc<span class="sy0">.</span><span class="me1">Message</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; watch<span class="sy0">.</span><span class="me1">Stop</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> elapsedMs <span class="sy0">=</span> watch<span class="sy0">.</span><span class="me1">ElapsedMilliseconds</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> result<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Просто. Удобно. Распространено. Долго.<br />
<br />
<b>2. Сборка плагинов через атрибуты.</b><br />
<u>В общей</u> для всех плагинов сборке, например содержащей интерфейс плагина IPlugin, создаётся класс атрибута. В этом классе хранится конкретный тип, реализующий интерфейс IPlugin.<br />
<br />
<a rel="nofollow noopener noreferrer" href="https://github.com/riuson/Bugs.Net/blob/c9ca522500b6424270f5a54f53e650baf730e92a/BugTracker.Core/Classes/Plugins.cs" target="_blank" title="https://github.com/riuson/Bugs.Net/blob/c9ca522500b6424270f5a54f53e650baf730e92a/BugTracker.Core/Classes/Plugins.cs">Пример кода на GitHub</a><br />
<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="835058549"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="835058549" style="height: 270px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="de1"><pre class="de1"><span class="kw1">using</span> <span class="co3">System</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Collections.Generic</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Linq</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Text</span><span class="sy0">;</span>
&nbsp;
<span class="kw1">namespace</span> MyApp<span class="sy0">.</span><span class="me1">Core</span><span class="sy0">.</span><span class="me1">Classes</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="br0">&#91;</span>AttributeUsage<span class="br0">&#40;</span>AttributeTargets<span class="sy0">.</span><span class="me1">Assembly</span><span class="br0">&#41;</span><span class="br0">&#93;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">class</span> AssemblyPluginTypeAttribute <span class="sy0">:</span> Attribute
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Type PluginType <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">private</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> AssemblyPluginTypeAttribute<span class="br0">&#40;</span>Type <span class="kw1">value</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">this</span><span class="sy0">.</span><span class="me1">PluginType</span> <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В файлах AssemblyInfo.cs сборок плагинов прописываются эти атрибуты, с указанием типа плагина.<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="882870400"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="882870400" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="br0">&#91;</span>assembly<span class="sy0">:</span> MyApp<span class="sy0">.</span><span class="me1">Core</span><span class="sy0">.</span><span class="me1">Classes</span><span class="sy0">.</span><span class="me1">AssemblyPluginType</span><span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>MyApp<span class="sy0">.</span><span class="me1">About</span><span class="sy0">.</span><span class="me1">Classes</span><span class="sy0">.</span><span class="me1">Plugin</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#93;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Теперь поиск типов плагинов немного иной:<ul><li>Рекурсивно в каталоге с приложением ищутся все dll файлы сборок.</li>
<li>Найденные по очереди перебираются и загружаются в память с помощью Assembly.LoadFile().</li>
<li>Из сборки достаются её указанные атрибуты. Из атрибутов получаются типы, реализующие интерфейс плагина.</li>
<li>Тип плагина сохраняется для последующего использования.</li>
</ul><b>Участок кода проверки всех типов в сборке теперь отсутствует.</b> Атрибуты запрашиваются только у самой сборки.<br />
<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="773886819"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="773886819" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
32
33
34
35
36
37
38
</pre></td><td class="de1"><pre class="de1"><span class="kw1">private</span> List<span class="sy0">&lt;</span>IPlugin<span class="sy0">&gt;</span> ScanPlugins<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; List<span class="sy0">&lt;</span>IPlugin<span class="sy0">&gt;</span> result <span class="sy0">=</span> <span class="kw3">new</span> List<span class="sy0">&lt;</span>IPlugin<span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">string</span><span class="br0">&#91;</span><span class="br0">&#93;</span> files <span class="sy0">=</span> <span class="kw1">this</span><span class="sy0">.</span><span class="me1">GetLibraries</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">var</span> watch <span class="sy0">=</span> <span class="kw5">System.<span class="me1">Diagnostics</span></span><span class="sy0">.</span><span class="me1">Stopwatch</span><span class="sy0">.</span><span class="me1">StartNew</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> filename <span class="kw1">in</span> files<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Assembly assembly <span class="sy0">=</span> Assembly<span class="sy0">.</span><span class="me1">LoadFile</span><span class="br0">&#40;</span>filename<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">object</span><span class="br0">&#91;</span><span class="br0">&#93;</span> attributesPlugin <span class="sy0">=</span> assembly<span class="sy0">.</span><span class="me1">GetCustomAttributes</span><span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>AssemblyPluginTypeAttribute<span class="br0">&#41;</span>, <span class="kw1">false</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> attributePlugin <span class="kw1">in</span> attributesPlugin<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Type pluginType <span class="sy0">=</span> <span class="br0">&#40;</span>attributePlugin <span class="kw1">as</span> AssemblyPluginTypeAttribute<span class="br0">&#41;</span><span class="sy0">.</span><span class="me1">PluginType</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Type t <span class="sy0">=</span> pluginType<span class="sy0">.</span><span class="me1">GetInterface</span><span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>IPlugin<span class="br0">&#41;</span><span class="sy0">.</span><span class="me1">FullName</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>t <span class="sy0">!=</span> <span class="kw1">null</span> <span class="sy0">&amp;&amp;</span> <span class="sy0">!</span>pluginType<span class="sy0">.</span><span class="me1">IsAbstract</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IPlugin pluginInfo <span class="sy0">=</span> <span class="br0">&#40;</span>IPlugin<span class="br0">&#41;</span>Activator<span class="sy0">.</span><span class="me1">CreateInstance</span><span class="br0">&#40;</span>pluginType<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>pluginInfo<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">catch</span> <span class="br0">&#40;</span>Exception exc<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw5">System.<span class="me1">Diagnostics</span></span><span class="sy0">.</span><span class="me1">Debug</span><span class="sy0">.</span><span class="me1">WriteLine</span><span class="br0">&#40;</span>exc<span class="sy0">.</span><span class="me1">Message</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; watch<span class="sy0">.</span><span class="me1">Stop</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> elapsedMs <span class="sy0">=</span> watch<span class="sy0">.</span><span class="me1">ElapsedMilliseconds</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> result<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div><br />
Время выполнения проверки (в одной моей небольшой программке) по первому способу составляет в среднем 390 мс. По второму - 90 мс.<br />
Не так важны сами числа, как их соотношение. Без перебора всех типов в сборке время проверки сокращается. Чем больше типов содержится в сборке, тем более это должно быть заметно.<br />
<br />
Можно было бы в первом способе попробовать применить assembly.GetType(string typeName), но это чревато жёсткими требования к именам классов плагина в сборках и ошибками при рефакторинге (правильность строк не отслеживается компилятором).<br />
<br />
<br />
<b>3. Немного параллельности.</b><br />
Будет ли выгода, зависит от длительности инициализации плагинов. Если оно и так мало, то снижение времени инициализации всего списка плагинов с 6 до 2 мс будет совершенно незаметно на фоне 100-200 мс, потраченных на загрузку файлов сборок в память.<br />
При некоторых условиях загрузка сборок в память может и замедлиться.<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="280098750"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="280098750" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">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
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> List<span class="sy0">&lt;</span>IPlugin<span class="sy0">&gt;</span> ScanPlugins<span class="br0">&#40;</span>IApplication app<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; List<span class="sy0">&lt;</span>IPlugin<span class="sy0">&gt;</span> result <span class="sy0">=</span> <span class="kw3">new</span> List<span class="sy0">&lt;</span>IPlugin<span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> files <span class="sy0">=</span> <span class="kw1">this</span><span class="sy0">.</span><span class="me1">GetLibraries</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> plugins <span class="sy0">=</span> <span class="kw1">from</span> filename <span class="kw1">in</span> files<span class="sy0">.</span><span class="me1">AsParallel</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let assembly <span class="sy0">=</span> Assembly<span class="sy0">.</span><span class="me1">LoadFile</span><span class="br0">&#40;</span>filename<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">from</span> attributePlugin <span class="kw1">in</span> assembly<span class="sy0">.</span><span class="me1">GetCustomAttributes</span><span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>AssemblyPluginTypeAttribute<span class="br0">&#41;</span>, <span class="kw1">false</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="me1">AsParallel</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let pluginType <span class="sy0">=</span> <span class="br0">&#40;</span>attributePlugin <span class="kw1">as</span> AssemblyPluginTypeAttribute<span class="br0">&#41;</span><span class="sy0">.</span><span class="me1">PluginType</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let interfaceType <span class="sy0">=</span> pluginType<span class="sy0">.</span><span class="me1">GetInterface</span><span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>IPlugin<span class="br0">&#41;</span><span class="sy0">.</span><span class="me1">FullName</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">where</span> interfaceType <span class="sy0">!=</span> <span class="kw1">null</span> <span class="sy0">&amp;&amp;</span> <span class="sy0">!</span>pluginType<span class="sy0">.</span><span class="me1">IsAbstract</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let pluginInfo <span class="sy0">=</span> <span class="br0">&#40;</span>IPlugin<span class="br0">&#41;</span>Activator<span class="sy0">.</span><span class="me1">CreateInstance</span><span class="br0">&#40;</span>pluginType<span class="br0">&#41;</span> <span class="co1">// Создание экземпляра</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">select</span> pluginInfo<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result <span class="sy0">=</span> plugins<span class="sy0">.</span><span class="me1">ToList</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Parallel<span class="sy0">.</span><span class="kw1">ForEach</span><span class="br0">&#40;</span>result, <span class="br0">&#40;</span>plugin<span class="br0">&#41;</span> <span class="sy0">=&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plugin<span class="sy0">.</span><span class="me1">Initialize</span><span class="br0">&#40;</span>app<span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Дополнительная инициализация каждого экземпляра</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">catch</span> <span class="br0">&#40;</span>Exception exc<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw5">System.<span class="me1">Diagnostics</span></span><span class="sy0">.</span><span class="me1">Debug</span><span class="sy0">.</span><span class="me1">WriteLine</span><span class="br0">&#40;</span>exc<span class="sy0">.</span><span class="me1">Message</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> result<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></div>

]]></content:encoded>
			<dc:creator>Rius</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/594854/3740.html</guid>
		</item>
	</channel>
</rss>
