Skip to content

Commit bab9645

Browse files
committed
Весь функционал локально работает. В играх не проверял. Уведомление об обновлении приходят. Немного доработать UI и в релиз.
1 parent 6ddccb1 commit bab9645

13 files changed

Lines changed: 422 additions & 481 deletions

ChatCaster.Core/ChatCaster.Core.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
<Nullable>enable</Nullable>
77
<AssemblyTitle>ChatCaster Core Library</AssemblyTitle>
88
<AssemblyDescription>Core functionality for ChatCaster voice input application</AssemblyDescription>
9-
<AssemblyVersion>1.0.0</AssemblyVersion>
10-
<FileVersion>1.0.0</FileVersion>
9+
<AssemblyVersion>0.0.1</AssemblyVersion>
10+
<FileVersion>0.0.1</FileVersion>
1111
<Company>ChatCaster</Company>
1212
<Product>ChatCaster</Product>
1313
<Copyright>Copyright © 2025</Copyright>

ChatCaster.Core/Updates/IUpdateService.cs

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,6 @@ namespace ChatCaster.Core.Updates;
77
/// </summary>
88
public interface IUpdateService
99
{
10-
/// <summary>
11-
/// Событие изменения прогресса операции обновления
12-
/// </summary>
13-
event EventHandler<UpdateResult>? ProgressChanged;
14-
15-
/// <summary>
16-
/// Событие завершения операции обновления
17-
/// </summary>
18-
event EventHandler<UpdateResult>? OperationCompleted;
19-
2010
/// <summary>
2111
/// Проверяет наличие доступных обновлений
2212
/// </summary>
@@ -29,30 +19,6 @@ Task<UpdateResult> CheckForUpdatesAsync(
2919
bool includePreReleases = false,
3020
CancellationToken cancellationToken = default);
3121

32-
/// <summary>
33-
/// Скачивает указанное обновление
34-
/// </summary>
35-
/// <param name="updateInfo">Информация об обновлении для скачивания</param>
36-
/// <param name="downloadPath">Путь для сохранения файла (если null, используется временная папка)</param>
37-
/// <param name="cancellationToken">Токен отмены операции</param>
38-
/// <returns>Результат скачивания с путем к файлу</returns>
39-
Task<UpdateResult> DownloadUpdateAsync(
40-
UpdateInfo updateInfo,
41-
string? downloadPath = null,
42-
CancellationToken cancellationToken = default);
43-
44-
/// <summary>
45-
/// Применяет скачанное обновление (запускает процесс обновления)
46-
/// </summary>
47-
/// <param name="updateFilePath">Путь к скачанному файлу обновления</param>
48-
/// <param name="restartApplication">Перезапустить ли приложение после обновления</param>
49-
/// <param name="cancellationToken">Токен отмены операции</param>
50-
/// <returns>Результат применения обновления</returns>
51-
Task<UpdateResult> ApplyUpdateAsync(
52-
string updateFilePath,
53-
bool restartApplication = true,
54-
CancellationToken cancellationToken = default);
55-
5622
/// <summary>
5723
/// Получает информацию о последней доступной версии без полной проверки
5824
/// </summary>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>net9.0-windows</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
8+
<!-- Информация о приложении -->
9+
<AssemblyTitle>ChatCaster Updater</AssemblyTitle>
10+
<AssemblyDescription>Update utility for ChatCaster application</AssemblyDescription>
11+
<AssemblyVersion>0.0.1</AssemblyVersion>
12+
<FileVersion>0.0.1</FileVersion>
13+
<Company>ChatCaster</Company>
14+
<Product>ChatCaster Updater</Product>
15+
<Copyright>Copyright © 2025</Copyright>
16+
17+
<!-- Настройки для уменьшения размера и независимости -->
18+
<PublishSingleFile>true</PublishSingleFile>
19+
<SelfContained>false</SelfContained>
20+
<PublishTrimmed>false</PublishTrimmed>
21+
22+
<!-- Для работы с ZIP архивами -->
23+
<UseSystemIO>true</UseSystemIO>
24+
</PropertyGroup>
25+
</Project>

ChatCaster.Updater/Program.cs

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.IO;
4+
using System.IO.Compression;
5+
using System.Threading;
6+
7+
namespace ChatCaster.Updater;
8+
9+
class Program
10+
{
11+
private static string _logPath = "";
12+
13+
static int Main(string[] args)
14+
{
15+
try
16+
{
17+
// Настраиваем логирование
18+
_logPath = Path.Combine(Path.GetTempPath(), "ChatCaster-updater.log");
19+
20+
Log("=== ChatCaster Updater запущен ===");
21+
Log($"Аргументы: {string.Join(" ", args)}");
22+
23+
// Проверяем аргументы
24+
if (args.Length < 3)
25+
{
26+
Log("ОШИБКА: Недостаточно аргументов");
27+
Log("Использование: ChatCaster.Updater.exe <путь_к_текущему_exe> <путь_к_ZIP_архиву> <перезапустить_true/false>");
28+
return 1;
29+
}
30+
31+
string currentExePath = args[0];
32+
string zipFilePath = args[1];
33+
bool restartApp = bool.Parse(args[2]);
34+
35+
Log($"Текущий exe: {currentExePath}");
36+
Log($"ZIP архив: {zipFilePath}");
37+
Log($"Перезапуск: {restartApp}");
38+
39+
// Ждем закрытия основного приложения
40+
Log("Ожидание закрытия основного приложения...");
41+
Thread.Sleep(3000);
42+
43+
// Принудительно завершаем процессы ChatCaster
44+
Log("Завершение процессов ChatCaster...");
45+
TerminateChatCasterProcesses();
46+
Thread.Sleep(2000);
47+
48+
// Проверяем существование файлов
49+
if (!File.Exists(zipFilePath))
50+
{
51+
Log($"ОШИБКА: ZIP файл не найден: {zipFilePath}");
52+
return 1;
53+
}
54+
55+
if (!File.Exists(currentExePath))
56+
{
57+
Log($"ОШИБКА: Текущий exe файл не найден: {currentExePath}");
58+
return 1;
59+
}
60+
61+
// Получаем директорию приложения
62+
string appDirectory = Path.GetDirectoryName(currentExePath);
63+
if (string.IsNullOrEmpty(appDirectory))
64+
{
65+
Log("ОШИБКА: Не удалось определить директорию приложения");
66+
return 1;
67+
}
68+
69+
Log($"Директория приложения: {appDirectory}");
70+
71+
// Создаем временную папку для распаковки
72+
string tempExtractPath = Path.Combine(Path.GetTempPath(), "ChatCaster-Update-Extract");
73+
Log($"Временная папка: {tempExtractPath}");
74+
75+
// Удаляем старую временную папку если есть
76+
if (Directory.Exists(tempExtractPath))
77+
{
78+
Log("Удаление старой временной папки...");
79+
Directory.Delete(tempExtractPath, true);
80+
}
81+
82+
// Создаем временную папку
83+
Directory.CreateDirectory(tempExtractPath);
84+
Log("Временная папка создана");
85+
86+
// Распаковываем ZIP архив
87+
Log("Распаковка ZIP архива...");
88+
ZipFile.ExtractToDirectory(zipFilePath, tempExtractPath);
89+
Log("ZIP архив распакован успешно");
90+
91+
// Проверяем что распаковка прошла успешно
92+
var extractedFiles = Directory.GetFiles(tempExtractPath, "*", SearchOption.AllDirectories);
93+
Log($"Распаковано файлов: {extractedFiles.Length}");
94+
95+
if (extractedFiles.Length == 0)
96+
{
97+
Log("ОШИБКА: ZIP архив пустой или не распаковался");
98+
return 1;
99+
}
100+
101+
// Создаем резервную копию основного exe файла
102+
string backupPath = currentExePath + ".backup";
103+
Log("Создание резервной копии...");
104+
File.Copy(currentExePath, backupPath, true);
105+
Log($"Резервная копия создана: {backupPath}");
106+
107+
// Копируем новые файлы
108+
Log("Копирование новых файлов...");
109+
CopyDirectory(tempExtractPath, appDirectory);
110+
Log("Файлы скопированы успешно");
111+
112+
// Проверяем что основной файл обновился
113+
if (File.Exists(currentExePath))
114+
{
115+
var newFileInfo = new FileInfo(currentExePath);
116+
Log($"Основной файл обновлен успешно. Размер: {newFileInfo.Length} байт, Дата: {newFileInfo.LastWriteTime}");
117+
118+
// Удаляем резервную копию
119+
File.Delete(backupPath);
120+
Log("Резервная копия удалена");
121+
}
122+
else
123+
{
124+
Log("КРИТИЧЕСКАЯ ОШИБКА: Основной файл не найден после копирования!");
125+
126+
// Восстанавливаем из резерва
127+
if (File.Exists(backupPath))
128+
{
129+
File.Copy(backupPath, currentExePath, true);
130+
File.Delete(backupPath);
131+
Log("Основной файл восстановлен из резервной копии");
132+
}
133+
return 1;
134+
}
135+
136+
// Запускаем приложение если нужно
137+
if (restartApp)
138+
{
139+
Log("Запуск обновленного приложения...");
140+
var startInfo = new ProcessStartInfo
141+
{
142+
FileName = currentExePath,
143+
UseShellExecute = true,
144+
WorkingDirectory = appDirectory
145+
};
146+
147+
Process.Start(startInfo);
148+
Log("Приложение запущено успешно");
149+
}
150+
151+
// Очищаем временные файлы
152+
Log("Очистка временных файлов...");
153+
try
154+
{
155+
if (Directory.Exists(tempExtractPath))
156+
{
157+
Directory.Delete(tempExtractPath, true);
158+
}
159+
160+
if (File.Exists(zipFilePath))
161+
{
162+
File.Delete(zipFilePath);
163+
}
164+
165+
Log("Временные файлы удалены");
166+
}
167+
catch (Exception ex)
168+
{
169+
Log($"Предупреждение: Не удалось удалить временные файлы: {ex.Message}");
170+
}
171+
172+
Log("=== Обновление завершено успешно ===");
173+
return 0;
174+
}
175+
catch (Exception ex)
176+
{
177+
Log($"КРИТИЧЕСКАЯ ОШИБКА: {ex.Message}");
178+
Log($"Stack trace: {ex.StackTrace}");
179+
return 1;
180+
}
181+
}
182+
183+
private static void TerminateChatCasterProcesses()
184+
{
185+
try
186+
{
187+
var processes = Process.GetProcessesByName("ChatCaster.Windows");
188+
foreach (var process in processes)
189+
{
190+
try
191+
{
192+
Log($"Завершение процесса: PID {process.Id}");
193+
process.Kill();
194+
process.WaitForExit(5000);
195+
}
196+
catch (Exception ex)
197+
{
198+
Log($"Не удалось завершить процесс {process.Id}: {ex.Message}");
199+
}
200+
}
201+
}
202+
catch (Exception ex)
203+
{
204+
Log($"Ошибка при завершении процессов: {ex.Message}");
205+
}
206+
}
207+
208+
private static void CopyDirectory(string sourceDir, string destinationDir)
209+
{
210+
var dir = new DirectoryInfo(sourceDir);
211+
212+
if (!dir.Exists)
213+
throw new DirectoryNotFoundException($"Исходная директория не найдена: {sourceDir}");
214+
215+
DirectoryInfo[] dirs = dir.GetDirectories();
216+
217+
// Создаем целевую директорию если не существует
218+
Directory.CreateDirectory(destinationDir);
219+
220+
// Копируем файлы в текущей директории
221+
foreach (FileInfo file in dir.GetFiles())
222+
{
223+
string targetFilePath = Path.Combine(destinationDir, file.Name);
224+
Log($"Копирование файла: {file.Name}");
225+
file.CopyTo(targetFilePath, true);
226+
}
227+
228+
// Рекурсивно копируем поддиректории
229+
foreach (DirectoryInfo subDir in dirs)
230+
{
231+
string newDestinationDir = Path.Combine(destinationDir, subDir.Name);
232+
Log($"Копирование директории: {subDir.Name}");
233+
CopyDirectory(subDir.FullName, newDestinationDir);
234+
}
235+
}
236+
237+
private static void Log(string message)
238+
{
239+
string logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {message}";
240+
Console.WriteLine(logMessage);
241+
242+
try
243+
{
244+
File.AppendAllText(_logPath, logMessage + Environment.NewLine);
245+
}
246+
catch
247+
{
248+
// Игнорируем ошибки записи в лог
249+
}
250+
}
251+
}

ChatCaster.Windows/ChatCaster.Windows.csproj

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
<ImplicitUsings>enable</ImplicitUsings>
77
<UseWPF>true</UseWPF>
88
<EnableDefaultApplicationDefinition>false</EnableDefaultApplicationDefinition>
9-
10-
<!-- Информация о приложении -->
119
<AssemblyTitle>ChatCaster for Windows</AssemblyTitle>
1210
<AssemblyDescription>Voice input application for Steam Input with gamepad control</AssemblyDescription>
1311
<AssemblyVersion>0.0.1</AssemblyVersion>
@@ -16,8 +14,6 @@
1614
<Company>ChatCaster</Company>
1715
<Product>ChatCaster</Product>
1816
<Copyright>Copyright © 2025</Copyright>
19-
20-
<!-- Иконка приложения -->
2117
<ApplicationIcon>Resources\Logo.ico</ApplicationIcon>
2218
</PropertyGroup>
2319

@@ -42,14 +38,20 @@
4238
<ProjectReference Include="..\ChatCaster.SpeechRecognition.Whisper\ChatCaster.SpeechRecognition.Whisper.csproj" />
4339
</ItemGroup>
4440

45-
<!-- Ресурсы -->
4641
<ItemGroup>
4742
<Resource Include="Resources\Logo.ico" />
4843
<Resource Include="Resources\free-icon-mic-7663253.png" />
4944
<Resource Include="Styles\DarkTheme.xaml" />
50-
<None Remove="Resources\usa-flag.png" />
5145
<Resource Include="Resources\usa-flag.png" />
52-
<None Remove="Resources\russia-flag.png" />
5346
<Resource Include="Resources\russia-flag.png" />
5447
</ItemGroup>
48+
49+
<!-- Копирование ChatCaster.Updater.exe в выходную папку -->
50+
<Target Name="CopyUpdater" AfterTargets="Build">
51+
<Copy
52+
SourceFiles="$(SolutionDir)ChatCaster.Updater\bin\$(ConfigurationName)\net9.0-windows\ChatCaster.Updater.exe"
53+
DestinationFolder="$(TargetDir)"
54+
SkipUnchangedFiles="true"
55+
Condition="Exists('$(SolutionDir)ChatCaster.Updater\bin\$(ConfigurationName)\net9.0-windows\ChatCaster.Updater.exe')" />
56+
</Target>
5557
</Project>

0 commit comments

Comments
 (0)