Процесс не может получить доступ к файлу, потому что он используется другим процессом в Directory.Move () - PullRequest
4 голосов
/ 16 января 2012

У нас есть клиентское приложение со следующей архитектурой: процесс-менеджер управляет парой рабочих процессов (считыватель и запись) и периодически запрашивает обновления версий на сервере.Если доступно обновление версии, менеджер загружает его на клиентский компьютер, закрывает рабочие потоки, запускает процесс обновления для обработки обновления и завершает работу.При запуске программа обновления получает 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);
}

Ответы [ 2 ]

3 голосов
/ 25 января 2012

Спасибо Adam Caviness ответ, мы смогли выяснить это.

Наши процессы были Консольными приложениями, они создавали файлы .vshost, которые продолжали работать после того, как процессы были заказаны дляпрекратить.Попытка переместить каталог с запущенными файлами .vshost вызвала проблему.

Превращение процессов в службы Windows не создало файлы .vshost и решило эту проблему.

2 голосов
/ 19 января 2012

Я предлагаю вам использовать MS (формально SysInternals) Process Monitor , чтобы отследить это и, таким образом, сначала исключить любые антивирусы / антивирусные программы / эвристики (если вы не собираетесь использовать av commando, как мы разработчики) делать). Ключ к этому заставляет меня указать вам в этом направлении, что вы можете запустить программу обновления самостоятельно, и исключение не выдается. Только в этом году я столкнулся с этой проблемой и должен был добавить исключение каталога AV.

...