Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
0 / 0 / 0
Регистрация: 03.10.2024
Сообщений: 6

Обнвление программы до актуальной (новой версии)

17.07.2025, 22:02. Показов 1480. Ответов 4

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток!
Пишу код для обновления приложения в случае опубликования новой версии. Установщик типа msi и файл version.xml лежат на яндекс диске. Но при запуске программы пишет ошибку парсинга XML из-за маркера ("Ошибка парсинга XML: "doctype" не является допустимым маркером. Ожидается маркер "DOCTYPE"., строка 1, позиция 3). Подскажите, что делаю не так? Вот код:
В программе:
C#
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
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using System.Security.Cryptography;
using School_Assistant;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Xml;
 
public class Updater
{
    private const string VersionXmlUrl = "ссылка_на_xml файл";
    private const string TempInstallerPath = "название_установщика.msi";
    private const string LocalVersionFile = "version.xml";
 
    public async Task CheckForUpdates()
    {
        var currentVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
        var latestVersion = await GetLatestVersionFromServer();
 
        if (ShouldUpdate(currentVersion, latestVersion))
        {
            if (ShowUpdateDialog(latestVersion))
            {
                await DownloadAndInstallUpdate(latestVersion);
            }
        }
    }
    public static void LogError(string message)
    {
        // Простая реализация записи в файл
        File.AppendAllText("error.log",
            $"{DateTime.Now}: {message}\n");
    }
    private async Task<UpdateInfo> GetLatestVersionFromServer()
    {
        using (var client = new HttpClient())
        {
            try
            {
                var xmlString = await client.GetStringAsync(VersionXmlUrl);
                return ParseXml(xmlString);
            }
            catch (Exception ex)
            {
                LogError("Ошибка при получении версии: " + ex.Message);
                return null;
            }
        }
    }
 
    private UpdateInfo ParseXml(string xmlString)
    {
        try
        {
            // Удаляем нечитаемые символы из начала строки
            xmlString = CleanXmlString(xmlString);
 
            var settings = new XmlReaderSettings
            {
                DtdProcessing = DtdProcessing.Ignore,
                XmlResolver = null,
                CheckCharacters = false // Отключаем проверку символов
            };
 
            using (var reader = XmlReader.Create(new StringReader(xmlString), settings))
            {
                var doc = XDocument.Load(reader);
                var updateInfo = new UpdateInfo
                {
                    Version = doc.Root.Element("version")?.Value,
                    ReleaseDate = DateTime.Parse(doc.Root.Element("releaseDate")?.Value ?? ""),
                    DownloadUrl = doc.Root.Element("downloadUrl")?.Value,
                    Size = double.Parse(doc.Root.Element("size")?.Value ?? "0"),
                    Hash = doc.Root.Element("hash")?.Value,
                    Mandatory = bool.Parse(doc.Root.Element("mandatory")?.Value ?? "false"),
                    MinRequiredVersion = doc.Root.Element("minRequiredVersion")?.Value,
                    Changes = doc.Root.Element("description")
                        ?.Elements("change")
                        .Select(e => e.Value)
                        .ToList()
                };
                return updateInfo;
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show($"Ошибка при парсинге XML: {ex.Message}");
            return null;
        }
    }
 
    private string CleanXmlString(string xml)
    {
        // Удаляем нечитаемые символы в начале файла
        int startIndex = xml.IndexOf("<?xml");
        if (startIndex > 0)
        {
            xml = xml.Substring(startIndex);
        }
        return xml;
    }
 
    private bool ShouldUpdate(string currentVersion, UpdateInfo latestVersion)
    {
        if (latestVersion == null) return false;
 
        var current = Version.Parse(currentVersion);
        var latest = Version.Parse(latestVersion.Version);
 
        return latest > current &&
               (current >= Version.Parse(latestVersion.MinRequiredVersion));
    }
 
    private bool ShowUpdateDialog(UpdateInfo latestVersion)
    {
        var changesText = string.Join(Environment.NewLine, latestVersion.Changes);
 
        var result = MessageBox.Show(
            $"Доступно обновление до версии {latestVersion.Version}" +
            $"\n\nДата релиза: {latestVersion.ReleaseDate}" +
            $"\n\nИзменения:" +
            $"\n{changesText}",
            "Обновление доступно",
            latestVersion.Mandatory ? MessageBoxButtons.OK : MessageBoxButtons.OKCancel,
            MessageBoxIcon.Information);
 
        return result == DialogResult.OK;
    }
 
    private async Task DownloadAndInstallUpdate(UpdateInfo latestVersion)
    {
        try
        {
            using (var client = new HttpClient())
            {
                var progressForm = new UpdateProgressForm();
                progressForm.Show();
 
                var progress = new Progress<double>(p =>
                    progressForm.UpdateProgress((int)(p * 100)));
 
                await client.GetStreamAsync(latestVersion.DownloadUrl)
                    .ContinueWith(task =>
                    {
                        using (var stream = task.Result)
                        using (var file = File.Create(TempInstallerPath))
                        {
                            stream.CopyTo(file);
                        }
                    },
                    CancellationToken.None,
                    TaskContinuationOptions.OnlyOnRanToCompletion,
                    TaskScheduler.Default);
                progressForm.Close();
 
                // Проверка целостности файла
                if (!VerifyHash(TempInstallerPath, latestVersion.Hash))
                {
                    throw new Exception("Неверный хеш-сумма установщика");
                }
 
                // Запуск установщика
                System.Diagnostics.Process.Start(TempInstallerPath);
 
                // Закрытие текущей версии
                Application.Exit();
            }
        }
        catch (Exception ex)
        {
            LogError("Ошибка при обновлении: " + ex.Message);
            MessageBox.Show("Ошибка при обновлении: " + ex.Message);
        }
        finally
        {
            // Очистка временных файлов
            try
            {
                File.Delete(TempInstallerPath);
            }
            catch { }
        }
    }
 
    private bool VerifyHash(string filePath, string expectedHash)
    {
        using (var file = File.OpenRead(filePath))
        {
            var computedHash = ComputeHash(file);
            return computedHash.Equals(expectedHash);
        }
    }
 
    private string ComputeHash(Stream stream)
    {
        using (var sha256 = SHA256.Create())
        {
            var hashBytes = sha256.ComputeHash(stream);
            return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
        }
    }
}
В version.xml:
XML
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
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE update [
    <!ELEMENT update (version, releaseDate, downloadUrl, size, hash, description, mandatory, minRequiredVersion)>
    <!ELEMENT version (#PCDATA)>
    <!ELEMENT releaseDate (#PCDATA)>
    <!ELEMENT downloadUrl (#PCDATA)>
    <!ELEMENT size (#PCDATA)>
    <!ELEMENT hash (#PCDATA)>
    <!ELEMENT description (change+)>
    <!ELEMENT change (#PCDATA)>
    <!ELEMENT mandatory (#PCDATA)>
    <!ELEMENT minRequiredVersion (#PCDATA)>
]>
<update>
    <version>1.0.0.1</version>
    <releaseDate>2025-07-17</releaseDate>
    <downloadUrl>Сыылка на установщик типа msi</downloadUrl>
    <size>231795712</size>
    <hash>sha256:d052258ae1a8f6619a8833146bfdfa028dcd18c4b31cf1593f17c8ad45a299c3</hash>
    <description>
        <change>...</change>
        <change>...</change>
        <change>...</change>
        <change>...</change>
        <change>...</change>
        <change>...</change>
    </description>
    <mandatory>false</mandatory>
    <minRequiredVersion>1.0.0.0</minRequiredVersion>
</update>
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
17.07.2025, 22:02
Ответы с готовыми решениями:

Программа Новый год: Чтобы она была актуальной на каждый год, а не только 2012
Чтобы программа была на каждый год, а не только 2012... Должен 1 год прибавляться с наступлением...

Скачивание папки с FTP - сервера по актуальной дате
Здравствуйте. Возможно ли реализовать скачку с фтп папки в которой находятся файлы, папок много, а...

Скачивание папки с FTP - сервера по актуальной дате (2)
Продолжение темы https://www.cyberforum.ru/csharp-net/thread2329455.html var mStr =...

4
sleep
 Аватар для I can
4931 / 4593 / 840
Регистрация: 13.04.2015
Сообщений: 9,752
17.07.2025, 23:00
Цитата Сообщение от Mihail_Smmirnov Посмотреть сообщение
DtdProcessing = DtdProcessing.Ignore,
Попробуй убрать это.
0
0 / 0 / 0
Регистрация: 03.10.2024
Сообщений: 6
19.07.2025, 19:34  [ТС]
Как закомментил эту строку. Стало писать следующее: "По соображениям безопасности использование DTD в данном XML-документе запрещено. Чтобы включить обработку DTD, установите свойство DtdProcessing в разделе XmlReaderSettings в значение Parse и передайте методу XmlReader.Create.
В итоге:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//верхняя часть кода
// Удаляем нечитаемые символы из начала строки
xmlString = CleanXmlString(xmlString);
 
var settings = new XmlReaderSettings
{
   DtdProcessing = DtdProcessing.Parse,
    XmlResolver = null,
    
    CheckCharacters = false // Отключаем проверку символов
};
 
using (var reader = XmlReader.Create(new StringReader(xmlString), settings))
{
    var doc = XDocument.Load(reader);
    var updateInfo = new UpdateInfo
//нижняя часть кода
.
При выполнении снова выдало ошибку с маркером
0
19.07.2025, 19:43

Не по теме:

Цитата Сообщение от Mihail_Smmirnov Посмотреть сообщение
лежат на яндекс диске
Купите нормальное доменное имя отдельно или хотя бы воспользуйтесь бесплатным на github.io.
Я.Диск в долгосрочном плане - плохой вариант.

0
sleep
 Аватар для I can
4931 / 4593 / 840
Регистрация: 13.04.2015
Сообщений: 9,752
19.07.2025, 19:43
Mihail_Smmirnov,
А так?
C#
1
2
3
4
5
6
var settings = new XmlReaderSettings
{
    DtdProcessing = DtdProcessing.Prohibit,
    XmlResolver = null,
    CheckCharacters = false
};
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
19.07.2025, 19:43
Помогаю со студенческими работами здесь

Когда версия языка 8.0 будет актуальной?
Сейчас у меня версия c# 7.3 (недавно обновлял VS) и в интерфейсах нельзя использовать модификатор...

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

Проверка новой версии программы
Всем привет, Есть некий код проверки новой версии программы. Помогите упростить код. И еще как...

Проверка на наличие новой версии программы
Ребят у меня есть моя программа но мне надо сделать так чтобы она могла проверять на наличие новый...

Как запустить локальную ms sql server 2016 версии на 2012 версии
Как запустить локальную ms sql server 2016 версии на 2012 версии Я в этом деле впервой, гуглил,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru