Wednesday, 23 April 2014

Открываем на чтение файл, открытый в другом потоке или процессе

Просто так он не открывается, придётся применить флаги:

FileStream configFile = new FileStream(engineConfigFilepath,
                    FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

С этими флагами всё должно работать, даже если файл открыт на редактирование где-то ещё.

Tuesday, 15 April 2014

WIX: проверяем установлен ли .NET Framework перед установкой приложения

Типовая задача: наше приложение разработано на основе .NET Framework 4, и инсталлятор должен проверить установлен ли фреймворк на машине перед началом установки приложения.

Следующие шаги описаны в документации WIX, информация есть и на stackoverflow

Для реализации задуманного в проекте инсталлятора надо добавить ссылку на сборку WixNetFxExtension.dll (у меня он расположен в c:\Program Files (x86)\WiX Toolset v3.8\bin\)

После чего в файл Product.wxs (если, конечно, наш главный файл проекта называется так) добавляем строку

<PropertyRef Id="NETFRAMEWORK40FULL" />

Это свойство доступно только в версии WIX  не ниже 3.5.

Затем на основе этого свойства формируем условие продолжения установки, задавая сообщение об ошибке: 

<Condition Message='This setup requires Microsoft .NET Framework 4.0 Full package or greater needs to be installed for this installation to continue.'>
  <![CDATA[Installed OR NETFRAMEWORK40FULL]]>
</Condition>

Осталось только найти машину без установленного четвёртого фреймворка и проверить наш новый инсталлятор. 

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

Проект с этими изменениями доступен в моём Git-овском хранилище учебных проектов на BitBucket.


Monday, 14 April 2014

Unhandled Exception в .NET – Разбираемся что к чему.

В книге Juval Lowy "Programming WCF Services" я встретил следующее замечание:
"In traditional .NET programming , any unhandled exception (Except ThreadAbortException) immediately terminated the AppDomain (and thus, often the process) in which it occurred."
Потом в отзывах к книге автора упрекнули в незнании .NET, поэтому я решил разобраться прав ли автор хотя бы в этом утверждении, для чего решил не экспериментировать, а обратиться за разъяснениям к авторитетам:

Джеффри Рихтер пишет во втором издании "CLR via C#", что
"Обнаружив в процессе поток с необработанным исключением, CLR немедленно уничтожает этот поток."

То есть, по этому утверждению Рихтера, при возникновении необработанного исключения в отдельном потоке завершается только поток, в котором возникло исключение. Рушится ли домен? Завершается ли процесс? О каком исключении из правил для ThreadAbortException говорит Лёви?

В главе 21 второго издания Рихтера говорится о том, что происходит с потоками при выгрузке appDomain  с помощью метода Unload():

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

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

Это уже более похоже на то, о чём говорит Лёви – исключение ThreadAbortException, генерируемое в потоках при выгрузке домена, не уничтожает процесс, даже не будучи перехваченным.

Более подробное описание этого самого "стандартного процесса" при возниконовении необработанного исключения пока найти не удалось, буду смотреть ещё в четвёртой редакции.