Pull to refresh

Comments 77

return BitConverter.ToString(checkSumm) == summ.ToUpper() ? true : false;
воу-воу, полегче.
Угу, там же: byte[] fileData = new byte[fs.Length];. Вот прямо весь файл в память? И прямо по всему файлу считаем хэш?
Код этой функции честно в Инете нашел. Чуть-чуть поправил (как раз тернарный оператор) и пустил в работу.
Я вам настоятельно рекомендую думать над тем кодом, который вы пускаете в работу, и разбираться в работе каждого его фрагмента.
Не могу не согласиться. Здесь действительно есть над чем подумать.
Тернарный оператор не видел?
Ну тут выражение BitConverter.ToString(checkSumm) == summ.ToUpper() уже имеет тип bool, поэтому дополнительно проверять его на true/false бессмысленно. Итого:
return BitConverter.ToString(checkSumm) == summ.ToUpper();

А теперь простите, у К.О. есть другие дела ;)
Чего-то не пойму Ваш ответ…

return BitConverter.ToString(checkSumm) == summ.ToUpper() ? true : false;
Если расписать через if else, то выйдет следующий код:
if(BitConverter.ToString(checkSumm) == summ.ToUpper()) { return true; } else { return false; }

Здесь нет дополнительной проверки.
А во входящих данных переменной summ присваивается строка с контрольной суммой из xml-файла с сервера.
Вам прозрачно намекают, что результат вычисления выражения
BitConverter.ToString(checkSumm) == summ.ToUpper()
уже имеет значение true или false, поэтому его можно вернуть сразу же, без использования лишнего в данном случае тернарного оператора.
Не знал. Запомню, спасибо!
Вы же используете логический оператор "==", как это «не знал»?
У нас в универе даже когда «программирование» преподавали, такого не говорили…
… на специальности «информатика»…
Да и то про тернарный оператор узнал чисто случайно, когда изучал код CMS на PHP и увидел его…
Вот как-то так вышло)
А что, в универе должны обо всем говорить? Указанная вещи — это фундаментальные знания, и про них написано в любой книжке по C#.
У вас в универе? Смеха ради почитал ваши посты и комменты. Вы же вроде как «самоучка».
habrahabr.ru/post/217325/#comment_7442289
Кстати, вы спалили адресс сайта вашей конторы в подписи к репозиторию. Теперь все знают где вы работаете, и куда лучше не обращаться.
Все верно, самоучка, так как в ВУЗе преподавали такой уровень, на котором я еще только начинал в 2005 году на делфи писать…
Такое ощущение, что Вы тролите программистов всех языков…

Начало той строки явным образом на бытовой язык переводится «а равно ли левое значение правому?» Что еще кроме «Истина» или «Ложь» может быть ответом на тот вопрос?
А вы знаете, что будет в ex.Message, если вы ловите эксепшн, брошенный Task.WaitAll()? Я уж молчу про наличие таких приятных вещей, как ContinueWhenAll и так далее… Уже если беретесь пользоваться TPL, то хоть изучите ее. Ну и я готов спорить, что ваша DownloadFile нифига не асинхронна (а должна бы, потому что весь HttpClient асинхронен, и именно там включается IOCP wait).
                    using (var client = new WebClient())
                    {
                        try
                        {
                            if (showStatus && downloadPercent != null) { client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged); }
                            client.DownloadFileAsync(new Uri(url + filename), localFile);

                            if (!Checksumm(localFile, xmlChecksumm) && File.Exists(localFile))
                            {
                                File.Delete(localFile);
                                client.DownloadFile(new Uri(url + filename), localFile);
                            }
                        }
                        catch (Exception ex)
                        {
                            debug.Save("private void DownloadFile(string filename, string xmlVersion, string xmlChecksumm)",
                                "Filename: " + filename + Environment.NewLine +
                                "Localname: " + (localFile != null ? localFile : "null") + Environment.NewLine +
                                "URL: " + url,
                                ex.Message);
                        }
                    }


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

И я вам настоятельно рекомендую не смешивать в одном коде TAP и EAP.
Интересно то, что код 100% работает. Вот тут лежит исходник, скопированный из рабочего проекта.
Единственный, пока что, замеченный глюк — файл удаляется и заново сохраняется. И то уже устранил.
«Удаляется и заново сохраняется» — это не то поведение, которое вам изначально было нужно. Значит, вы ошиблись в коде.

Вы тесты-то писать не пробовали?
В том-то и дело, что не мог найти место глюка… Или было лень ночью.
Тесты не пробовал.
«Не смог/лень» — не выкладывай код.

(простите за прямоту)
Не, не оно :)
Захотелось мне самому сделать функцию — взял и сделал, пусть и не идеальную. Зато мозг поразмял. Так что здесь все ништяк.
Не, все хорошо, но как nuget.core, который придуман для совершенно другого сценария, тут поможет?
Извините, что сразу не ответил.

NuGet — это менеджер пакетов. NuGet.Core содержит реализацию протокола NuGet и позволяет устанавливать и обновлять пакеты из удаленных или локальных репозиториев, управлять зависимостями пакетов, осуществлять контроль версий. Разве это не то, о чем написан данный топик?

Вот хорошая книжка на эту тему rutracker.org/forum/viewtopic.php?t=3983645
В т.ч. там рассказывают «best practices» при решении различных задач (в т.ч. задачи обновления приложнеием самого себя).
Пакеты — это обычно дополнение к приложений/инфраструктуре, а не сама инфраструктура.
Чем обусловлено это ограничение?
На мой взгляд, пакеты — это любые модули (блоки) приложения. В т.ч. приложение может состоять из одного большого блока :)
Семантикой.

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

Вот, например, решарпер — у него есть нюгет-репозиторий, но сам решарпер в нем не лежит.
Да, не лежит. А что это меняет?
Повторюсь: я не видел ни одного самостоятельного приложения, которое бы полностью обновляло себя через nuget. Возможно, это просто инерция мышления, но семантика как бы намекает.

Ну и да, именно self update в nuget реализован весьма прямолинейно и неотчуждаемо, ваша книжка предлагает этот код просто копировать.
А парень все никак не угомонится. Мама дорогая, встречайте: теперь обновляемые файлы захардкожены! Хотите ад в XML — нате! Вам некуда потратить время во время релиза? — А ну-ка по забивайте контрольные суммы и версии файлов в XML. А как тестировать публикацию такого обновления, а что если ты ошибся в данных в XML?
Открываем Total Commender -> выделяем список нужных файлов -> пункт меню «Файлы» -> «Поисчитать CRC-суммы» -> «ОК». Далее открываем полученный файл и копипастом в XML. Пока что ни разу не ошибся с переносом ;)
А ничего, что CRC и MD5 — это разные вещи?

Уважающие себя люди одновременно с написанием утилиты, читающей манифест, пишут утилиту, которая этот манифест создает.
Открываем Total Commender -> выделяем список нужных файлов -> пункт меню «Файлы» -> «Поисчитать CRC-суммы» -> «ОК».
В окне видим:
image

Уважающие себя люди одновременно с написанием утилиты, читающей манифест, пишут утилиту, которая этот манифест создает.

Это лишь вопрос времени. Мне не трудно на начальном этапе вручную делать.
Это немного не то, что вы описывали изначально. А еще у людей может не быть TC (у меня вот нет).
Ну, эту сумму будет считывать не каждый пользователь, а тот, кто на сервер выкладывает апдейты. Исходя из этого, наличие «тотала» не является проблемой.
Является. Никакой сторонний софт, особенно многофункциональный, не должен быть условием для работы с предлагаемой вами системой. Есть формат манифеста? Напишите генерилку под этот формат.
Я ж говорю — это лишь вопрос времени. Написать ее не сложно)
А по поводу условий использования стороннего софта полностью с Вами согласен — нельзя к нему привязки делать ни в коем случае.
UFO just landed and posted this here
А какой план на тот случай, если зависимости (библиотеки) добавятся в следующей версии?
Действующая версия программы скачивает обновленную версию, а та, в свою очередь, скачает необходимые файлы. Уже проверял, дополнив проект библиотеками, подключенными к нему. В самом начале их ни одной не было.
Астрологи предвещают неделю говнокода. Количество апдейтеров увеличилось в трое. И говнокода тоже.
checksumm
checksum
debug debug = new debug();
Debug
Task.Factory.StartNew(() => client.DownloadFile(new Uri(url + "settings.xml"), "settings.xml")).Wait();
await client.DownloadFileTaskAsync(...)
Task.WaitAll(task1, task2, task6);
await Task.WhenAll(...)
update_launcher update = new update_launcher();
UpdateLauncher
update.Check(true, progressBar1);
IProgress<T>
Async in 4.5: Enabling Progress and Cancellation in Async APIs
The Progress Reporting Pattern in C# 5 async
Незнание — не есть сила :) Почуял себя глупцом.
«Учиться, учиться и еще раз учиться!» (с) В.И. Ленин
Не знал, что стремление учиться на ошибках вызывает у людей столько негатива…
… это наводит на определенные мысли…
await client.DownloadFileTaskAsync(...)


Ключевые слова async и await были введены в Visual Studio 2012.
У меня VS2010. С этим беда.
Поддержка VS2010 закончится чуть больше чем через год.
Поторопитесь обновиться ;)
И вот поэтому в данный момент страдаю фигней, пока удаляю VS2010 перед установкой VS2012 :)
2008 + 2010 + 2012 +… способны сосуществовать на одной машине
UFO just landed and posted this here
Код работает, а то что в нем недочеты есть — это не беда.
Поэтому рабочий код и выложил, тем более, что много информации в Инете перерыл как такое самому написать и то у одного муть написана, то еще где нашел да не то. Вот и написал свой, и выложил его. Согласен, код из числа говнокода, да вот другого-то в сети не нашел, а, на мой взгляд, идеально рабочие исходники подобных действий вряд ли кто выложит вот так на всеобщее. Так что, вот этим и руководствовался при принятии решения выложить код на хабр :)
на мой взгляд, идеально рабочие исходники подобных действий вряд ли кто выложит вот так на всеобщее.

Что, правда?
Первая простыня кода просто вопиёт о рефакторинге:
if (File.Exists(«settings.xml») && new FileInfo(«settings.xml»).Length == 0) { File.Delete(«settings.xml»); }
if (File.Exists(«Ionic.Zip.dll») && new FileInfo(«Ionic.Zip.dll»).Length == 0) { File.Delete(«Ionic.Zip.dll»); }
if (File.Exists(«restart.exe») && new FileInfo(«restart.exe»).Length == 0) { File.Delete(«restart.exe»); }

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

var task1 = Task.Factory.StartNew(() => DownloadFile(«Ionic.Zip.dll», doc.GetElementsByTagName(«Ionic.Zip»)[0].InnerText, doc.GetElementsByTagName(«Ionic.Zip»)[0].Attributes[«checksumm»].InnerText));
var task2 = Task.Factory.StartNew(() => DownloadFile(«restart.exe», doc.GetElementsByTagName(«restart»)[0].InnerText, doc.GetElementsByTagName(«restart»)[0].Attributes[«checksumm»].InnerText));
var task6 = Task.Factory.StartNew(() => DownloadFile(«LanguagePack.dll», doc.GetElementsByTagName(«languagePack»)[0].InnerText, doc.GetElementsByTagName(«languagePack»)[0].Attributes[«checksumm»].InnerText));

Здесь то же самое, плюс можно порекомендовать юзать вместо XmlDocument-a XDocument.
update.Check(true, progressBar1);

Передача классу визуального компонента — это зло!
Да, кстати, зачем вы храните в своём файле version.xml на сервере версии сборок? Ведь эту информацию можно получить всё тем же методом FileVersionInfo.GetVersionInfo?

debug.Save(«private void DownloadFile(string filename, string xmlVersion, string xmlChecksumm)», «Filename: » + filename + Environment.NewLine + «Localname: » + (localFile != null? localFile: «null») + Environment.NewLine + «URL: » + url, ex.Message);

Попробуйте использовать string.Format, будет гораздо более читабельно.

if (File.Exists(filename) && summ != null && new FileInfo(filename).Length > 0)
using (FileStream fs = File.OpenRead(filename))
{
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] fileData = new byte[fs.Length];
fs.Read(fileData, 0, (int)fs.Length);
byte[] checkSumm = md5.ComputeHash(fileData);
return BitConverter.ToString(checkSumm) == summ.ToUpper()? true: false;
}
else
return false;

Этот код, лучше написать с условием типа OR и возвратом false в начале, что позволит избежать лишней вложенности (т.е. будет меньше скобок = лучше читаемость)

Стоит также отметить отсутствие комментариев в коде, их наличие могло сократить статью в разы (например, при описании параметров функции). А также рекомендуется почитать про обработку ошибок, а для лучшего определения места в коде, кстати, хорошо использовать ex.StackTrace.
Успехов.
UFO just landed and posted this here
Да, кстати, зачем вы храните в своём файле version.xml на сервере версии сборок? Ведь эту информацию можно получить всё тем же методом FileVersionInfo.GetVersionInfo?

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

Стоит также отметить отсутствие комментариев в коде, их наличие могло сократить статью в разы (например, при описании параметров функции)

Поверьте, комментарии были в исходнике, а из-за их количества терял где код расположен, то есть комментариев по объему чуть ли не в 2 раза больше было в некоторых местах. Вот и убрал их все :)

Успехов.

И Вам удачи в делах!
У вас что за сервер? Ну т.е. где хранится файл этот version.xml? Я полагал, что у вас на IIS-е крутится какой-то сайт, где этот version.xml лежит. Если так, то сделать проверку версии файлов, лежащих на сервере (и их.контрольных сумм, кстати), лучше в коде сайта, который крутится в IIS-e. Но, если у вас, например, фтп, то лучше автоматизировать процесс выкладывания сайтов на фтп, в процессе которого этот version.xml будет генериться автоматом. С клиента вы версии файлов на сервере так не узнаете, конечно.

Да, есть еще архитектурный вопрос. Зачем вы разнесли обновление и рестарт программы в 2 разных модуля? Имхо, вполне можно было обойтись одним.
Сайт на apache крутится.

Процесс поиска и скачивания обновлений находится в теле основной программы в то время, как переименованием и заменой файлов занимается утилита updater.exe, работая с указанными параметрами («старое имя файла», «новое имя файла»).
Утилита restart.exe используется в других целях, когда требуется перезапуск основной программы.
UFO just landed and posted this here
Имелось в виду:

if (summ == null || !File.Exists(filename) || new FileInfo(filename).Length == 0)
    return false;

До первого true.
Совершенно верно.
Полно-те, парень сел на конька, который был одобрен Сообществом. Давайте не будем минусовать парня так уж сразу и в лоб, а просто намекнём, что желательно статьи и другой тематики и качества выдавать, а для подобного R&D уровня «вчера услышал про сишарп» есть гитхаб / блог / блокнот в ящике стола, или хаб «Чулан», коль так неймётся поделиться мыслями на Хабре.
Так уже третий пост. Первые 2 заплюсованы, а на третьем видимо терпение лопнуло.
«Вот так всегда — на самом интересном месте» :(
Наткнулся на картинку. Понял свои ошибки :)

image
Боже, Хабр в последнее время сильно снисходительно относится ко всем сомнительным личностям.
Человек в третий раз уже выкладывает бесполезный нерабочий код, и все еще не заминусован в бесконечность.
Его не научили две бесполезные статьи, и он тратит годы суммарного нашего с вами времени на еще одну.
Мистер, к Вашему сведению, «говнокод» не всегда является не рабочим ;)
Да, то что написал, цензурными словами выразить крайне сложно, но то что ЭТО работает, пусть и с периодическими глюками, ФАКТ!

Так что от Вашего комментария стоит задуматься…
image
А в целом Вы правы по поводу моих статетей недостатей. Код оставляет желать лучшего.
Сейчас, конечно, с нуля переписал его, НО выкладывать не буду) Может, через много времени что стоящее и размещу, а сейчас мне хватит фигней страдать, бездумно публикуя :)
Sign up to leave a comment.

Articles