0

ここでは、オフィスのすべての PC で実行される ClickOnce アプリケーションを作成しました。本日、.NET ランタイムがクラッシュし、イベント ログに次のイベントが記録されました。

Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.UnauthorizedAccessException
Stack:
    at System.IO.Directory.DeleteHelper(System.String, System.String, Boolean)
    at System.IO.Directory.Delete(System.String, System.String, Boolean)
    at System.IO.Directory.Delete(System.String, Boolean)
    at System.Deployment.Application.TempFile.DisposeUnmanagedResources()
    at System.Deployment.Application.DisposableBase.Finalize()

アプリケーションはSystem.Deployment、新しいバージョンを定期的にチェックし、バックグラウンドでダウンロードするために使用します。そうすれば、次回アプリケーションを起動したときに、新しいバージョンの準備が整います。

私の BackgroundUpdater クラスは次のようになります (関連している場合):

class BackgroundUpdaterService : IBackgroundUpdaterService
{
    private readonly BackgroundWorker backgroundWorker = new BackgroundWorker();
    private readonly DispatcherTimer checkForUpdatesTimer = new DispatcherTimer();

    public BackgroundUpdaterService()
    {
        this.backgroundWorker.WorkerSupportsCancellation = true;
        this.backgroundWorker.DoWork += (s, e) =>
            {
                // Check if the application was deployed via ClickOnce.
                if (!ApplicationDeployment.IsNetworkDeployed)
                {
                    e.Result = UpdateStatus.NotDeployedViaClickOnce;
                    return;
                }

                if (this.backgroundWorker.CancellationPending) return;

                var updateCheck = ApplicationDeployment.CurrentDeployment;

                UpdateCheckInfo info;
                try
                {
                    info = updateCheck.CheckForDetailedUpdate();
                }
                catch (DeploymentDownloadException)
                {
                    e.Result = UpdateStatus.DeploymentDownloadException;
                    return;
                }
                catch (InvalidDeploymentException)
                {
                    e.Result = UpdateStatus.InvalidDeploymentException;
                    return;
                }
                catch (InvalidOperationException)
                {
                    e.Result = UpdateStatus.InvalidOperationException;
                    return;
                }

                if (this.backgroundWorker.CancellationPending) return;

                if (info.UpdateAvailable)
                {
                    e.Result = info.IsUpdateRequired 
                        ? UpdateStatus.UpdateRequired 
                        : UpdateStatus.UpdateAvailable;
                }
                else
                {
                    e.Result = UpdateStatus.NoUpdateAvailable;
                }
            };
        this.backgroundWorker.RunWorkerCompleted += (s, e) =>
            {
                var result = (UpdateStatus) (e.Result);
                this.UpdateRequired =
                    result == UpdateStatus.UpdateAvailable
                    || result == UpdateStatus.UpdateRequired;
                if(!this.UpdateRequired) // stop looking if there is one
                {
                    this.checkForUpdatesTimer.Start();
                }
            };

        this.checkForUpdatesTimer.Interval = new TimeSpan(hours: 0, minutes: 15, seconds: 0);
        this.checkForUpdatesTimer.Tick += (s, e) =>
            {
                this.checkForUpdatesTimer.Stop();
                this.backgroundWorker.RunWorkerAsync();
            };
        this.checkForUpdatesTimer.Start();
    }

    private readonly object updateRequiredLock = new object();
    private bool updateRequired;
    public bool UpdateRequired
    {
        get
        {
            lock(this.updateRequiredLock)
            {
                return this.updateRequired;
            }
        }
        private set
        {
            lock(this.updateRequiredLock)
            {
                this.updateRequired = value;
            }
        }
    }

    public bool Update()
    {
        if(!this.UpdateRequired)
        {
            return false;
        }
        bool result;
        try
        {
            var updateCheck = ApplicationDeployment.CurrentDeployment;
            updateCheck.Update();
            result = true;
        }
        catch (DeploymentDownloadException)
        {
            result = false;
        }
        return result;
    }

    public void Dispose()
    {
        this.checkForUpdatesTimer.Stop();
        this.backgroundWorker.CancelAsync();
        Thread.Sleep(100);
        this.backgroundWorker.Dispose();
    }
}

System.Deployment名前空間からこの例外に遭遇した人はいますか? これの根本的な原因は何ですか?

4

1 に答える 1

1

はい、この問題に遭遇しました:)ここで私の答えを参照してください: https://stackoverflow.com/a/13711535/1246870 - 2 つの言葉で言えば、更新の頻繁なチェックに関連する ClickOnce のバグです。

私が思いついた唯一の回避策は、タイマー間隔をより大きな値に増やすことでした. より良いアイデアがあれば、ぜひ聞かせてください。

于 2013-10-10T14:30:47.280 に答える