У нас есть клиентское приложение со следующей архитектурой: процесс-менеджер управляет парой рабочих процессов (считыватель и запись) и периодически запрашивает обновления версий на сервере.Если доступно обновление версии, менеджер загружает его на клиентский компьютер, закрывает рабочие потоки, запускает процесс обновления для обработки обновления и завершает работу.При запуске программа обновления получает PID менеджера и местоположение файла обновления;Затем он ожидает завершения работы менеджера, создает резервные копии всех файлов менеджера и рабочих, воссоздает их каталоги и распространяет файлы новой версии в новые каталоги.
При выполнении описанного выше процесса первый вызовна Directory.Move(string, string)
- который служит для резервного копирования каталога менеджера - выдает IOException
.Странно то, что если я позволю диспетчеру завершить работу, не запуская программу обновления, а затем сам запустю исполняемый файл программы обновления, исключение не будет выдано.
Код менеджера для управления рабочими потоками:
public void Run()
{
_config = GetConfiguration();
Process reader, writer;
//Start reader and writer with appropriate arguments
//Keep reader and writer alive
reader.Kill();
writer.Kill();
reader.WaitForExit();
writer.WaitForExit();
reader.Dispose();
writer.Dispose();
}
Код менеджера для запросов к базе данных:
EndpointAddress endpoint;
BasicHttpBinding httpBinding = new BasicHttpBinding();
httpBinding.MaxReceivedMessageSize = 2000000000;
ChannelFactory<IService> chanFactory = new ChannelFactory<IService>(httpBinding);
IService service;
try
{
endpoint = new EndpointAddress(ConfigurationManager.AppSettings["Service URL"]);
service = chanFactory.CreateChannel(endpoint);
UpdateInstructions instructions = service.GetUpdateInstructions(_config.SiteID, Assembly.GetExecutingAssembly().GetName().Version.ToString(), _config.Version);
HandleUpdateInstructions(instructions); //Downloads files and starts the updater process
}
catch (Exception ex)
{
//Report exception
}
finally
{
if (chanFactory.State != CommunicationState.Faulted)
chanFactory.Close();
}
Код менеджера для запуска процесса обновления:
private void StartUpdater(string updateFilePath, string configFilePath)
{
ProcessStartInfo updaterStartInfo = new ProcessStartInfo(_config.UpdaterExePath, string.Format("{0} \"{1}\" \"{2}\"", Process.GetCurrentProcess().Id, updateFilePath, configFilePath));
Process updater = Process.Start(updaterStartInfo);
updater.Dispose();
}
Код менеджера для ожидания закрытия менеджера:
bool isManagerUp = true;
while (isManagerUp)
{
try
{
Process managerProcess = Process.GetProcessById(bDoxForceManagerPID);
managerProcess.WaitForExit();
managerProcess.Dispose();
isManagerUp = false;
}
catch
{
isManagerUp = false;
}
}
Код обновления для обновления модуля:
//updateDirectory is the directory of the new files to be inserted, moduleDirectory is the working directory of the module that will be updated, in this case the manager
private void UpdateModule(DirectoryInfo updateDirectory, DirectoryInfo moduleDirectory)
{
string backupDirectory = MakeBackupDirectoryFullPath(moduleDirectory.Parent.FullName);
Directory.Move(moduleDirectory.FullName, backupDirectory); // IOException as described above.
Directory.CreateDirectory(moduleDirectory.FullName);
foreach (FileInfo updateFile in updateDirectory.EnumerateFiles())
{
string newFilePath = moduleDirectory.FullName + "\\" + updateFile.Name;
File.Copy(updateFile.FullName, newFilePath);
}
Directory.Delete(updateDirectory.FullName, true);
}