次のアーキテクチャのクライアントアプリケーションがあります。マネージャプロセスが2つのワーカープロセス(リーダーおよびライター)バージョンアップ用のサーバー。バージョンの更新が利用可能な場合、マネージャはそれをクライアントコンピュータにダウンロードし、ワーカースレッドをシャットダウンし、アップデータを処理するアップデータプロセスを開始して終了します。アップデータは起動時にマネージャPIDと更新ファイルの場所を受け取ります。マネージャーとワーカーのすべてのファイルをバックアップし、ディレクトリを再作成し、新しいバージョンのファイルを新しいディレクトリに展開します。ファイルがDirectory.Move()の別のプロセスで使用されているため、ファイルにアクセスできません。
説明したようにこのプロセスを実行すると、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();
}
Managerコード:
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();
}
updaterプロセスを開始するための管理コード:
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);
}
MakeBackupDirectoryFullPathメソッドコードもplzを表示 –
@MrMush:空の 'catch'ブロックで例外を飲み込むと、デバッグが難しくなります。たとえば、Updaterコードでは、 'isManagerUp'変数は何が起こっても偽に設定されるため、完全に冗長です。 – Groo
1 - いつStartUpdaterを呼びますか? whileループの後?とにかく、メッセージを信頼してください:あなたのディレクトリへのロックアクセスがまだあります。つまり、以前のプロセスでmanagerディレクトリがまだ使用中であることを意味します。私の推測では、StartUpdaterを呼び出すときにmanagerProcessがまだ実行されていないか、ディレクトリが別のプロセスによって何らかの形でまだ使用されているかのいずれかです。ロックを使用して注意深くデバッグする必要があります。 –