簡體   English   中英

進程無法訪問該文件,因為它正被Directory.Move()上的另一個進程使用

[英]Process cannot access the file because it is being used by another process on Directory.Move()

我們有一個具有以下體系結構的客戶端應用程序:管理器進程管理幾個工作進程(讀取器和編寫器)並定期查詢服務器以獲取版本更新。 如果版本更新可用,則管理器將其下載到客戶端計算機,關閉工作線程,啟動更新程序進程以處理更新並退出。 updater在啟動時接收管理器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);
}

感謝Adam Caviness回答我們能夠弄明白。

我們的流程是控制台應用程序,他們創建了一個.vshost文件,這些文件在流程終止后繼續工作。 嘗試使用正在運行的.vshost文件移動目錄會導致問題。

將進程轉換為Windows服務並未創建.vshost文件並解決了此問題。

我建議你使用MS(正式的SysInternals) 進程監視器來跟蹤這個問題,從而首先排除任何反病毒/反惡意軟件/啟發式攻擊(如果你不像我們開發人員那樣去執行命令)。 這一點的線索讓我指出你在這個方向是你可以自己啟動更新程序,並且不會拋出異常。 就在今年,我已經遇到了這個問題,不得不添加AV目錄排除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM