簡體   English   中英

ClickOnce 部署留下多個版本(是的,不止兩個)

[英]ClickOnce deployment is leaving multiple versions (yes, more than two)

我有一個ClickOnce應用程序,它在我的磁盤上保留了所有舊版本。 這是一個經常更新的內部企業應用程序,因此對於快速膨脹我們的備份大小來說,這是一場災難。

根據文檔和其他 Stack Overflow 問題,應該只將當前和以前的版本保留在磁盤上。 但是,每次我部署項目和升級客戶端時,我都會得到所有 EXE、DLL 和數據文件的另一個副本。 我沒有對應用程序進行任何更改,只是在 Visual Studio 中再次推送部署。

我該如何解決這個問題?

該問題似乎在 Windows 7 和 Windows XP 以及 64 位和 32 位 Windows 上都會發生。

我已經對安裝版本的文件夾做了一個差異,以下文件是不同的:

MyApp.exe.manifest
MyApp.exe.cdf-ms
MyDll1.cdf-ms
MyDll2.cdf-ms

沒有實際的可執行文件是不同的,也沒有MyApp.manifestMyDll1.manifest等。

替代方案怎么樣。 在運行時查找包含我的應用程序的其他文件夾並刪除它們是否安全? 這會破壞任何東西嗎?

ClickOnce 只是一個明顯的神秘黑匣子嗎?

我想我終於想到了這個。 對於某些未知(並且不可接受,坦率地說)的原因,如果較新的版本正在運行,舊版本的清理將不會發生 - 它只是無聲地失敗。

清理嘗試在舊版本退出時運行,但由於我重新啟動了應用程序,新版本已經啟動,阻止清理。

另外,請注意其他答案中提到的“清道夫服務”似乎是完全捏造。 我沒有找到任何此類服務的文檔,也沒有任何證據表明它正在運行。 清理似乎是作為clickonce更新過程的一部分內聯發生的。

清道夫服務是ClickOnce引擎的一部分; 它會自動運行,而不是您可以直接訪問的內容。 它應該到來並清理舊版本。

關於min版本的問題。 如果您部署新版本並將min min required版本設置為新版本#,它是否將應用程序更新為該版本? 然后將前一個(s)留在磁盤上?

你能看到任何模式嗎? 它正在緩存的部署數量是否有限制?

還有一些關於影子文件夾的東西,它在我的記憶中徘徊; 文件不是真的存在。 我會做一些研究,看看我的筆記,看看我能找到什么。

它是什么類型的應用程序? 的WinForms / WPF / VSTO?

當你說它是緩存文件夾時,它是哪個文件夾? 例如,對於winforms應用程序,為每個版本創建了兩個文件夾(xxxxtion ...和xxxxexe ......或類似的東西)加上一堆文件夾 - 一個用於部署中包含的每個程序集 - 這些是緩存版本的程序集,以便每次都沒有更改時不必下載它們。 你看到的是xxxxtion和xxxxexe文件夾的倍數嗎?

你現在正在檢查嗎? 一天左右后它們甚至都沒有消失? ClickOnce清道夫服務應該出現並刪除舊版本。 如果您將最新版本作為必需更新推送,是否會刪除其他版本? (為此,請在“更新”對話框中將所需的最低版本設置為您正在部署的同一版本)。

這是在客戶端清除舊 ClickOnce 版本的功能。

在我的機器上,我釋放了 6Gb 的空間。 我什至不想知道舊版本組織使用的總空間......

    /// <summary>
    /// Delete directories of old ClickOnce versions leaving newest in place.
    /// NOTE: Users have privileges for installing and deleting folders in their local deployment directory.
    /// </summary>
    public static void CleanOldVersions()
    {
        
        string path = AppDomain.CurrentDomain.BaseDirectory;
        int lastSlash = path.LastIndexOf(@"\");
        path = path.Substring(0, lastSlash );
        lastSlash = path.LastIndexOf(@"\");
        path = path.Substring(0, lastSlash);

        var dirInfo = new DirectoryInfo(path);

        var directories = dirInfo.EnumerateDirectories()
                                    .OrderByDescending(d => d.CreationTime)
                                    .ToList();

        List<string> DeletedAppIDs = new List<string>();

        foreach (DirectoryInfo subDirInfo in directories)
        {

            int first_ = subDirInfo.Name.IndexOf("_");
            if (first_ < 0) continue;
            string appID = subDirInfo.Name.Substring(first_+1, 21);

            if (DeletedAppIDs.Contains(appID)) continue;

            var subdirectories = subDirInfo.Parent.EnumerateDirectories()
                                        .Where(d => d.Name.Contains(appID))
                                        .OrderByDescending(d => d.CreationTime)                                                
                                        .ToList();

            bool isNewest = true;
            foreach (DirectoryInfo subDirName in subdirectories)
            {
                if (isNewest)
                {
                    isNewest = false;
                }
                else
                {
                    try
                    {
                        SetAttributesToNormal(subDirName); //Set attributes to normal to prevent failures
                        subDirName.Delete(true);

                        if (!DeletedAppIDs.Contains(appID))
                        {
                            DeletedAppIDs.Add(appID);
                        }
                    }
                    catch (UnauthorizedAccessException)
                    {
                        //Catch unauthorized access to prevent exit if a previous version has any open dll
                    }

                }

            }
  
        }
                   
    }

    private static void SetAttributesToNormal(DirectoryInfo dir)
    {
        foreach (var subDir in dir.GetDirectories())
            SetAttributesToNormal(subDir);
        foreach (var file in dir.GetFiles())
        {
            file.Attributes = FileAttributes.Normal;
        }
    }

可以像這樣在啟動時調用它:

    private async void InitTasks()
    {
        try
        {
            await Task.Run(() => CleanOldVersions());
        }
        catch (Exception ex)
        {
            //Error handling
        }                 
    }

如何刪除

清除Click-Once(版本控制)緩存

來自文檔:

在線托管的ClickOnce應用程序受限於ClickOnce緩存大小的配額占用的空間量受到限制。 緩存大小適用於所有用戶的在線應用程序; 單個部分受信任的在線應用程序僅限於占用一半的配額空間。 已安裝的應用程序不受緩存大小的限制,也不會計入緩存限制。 對於所有ClickOnce應用程序,緩存僅保留當前版本和先前安裝的版本。 默認情況下,客戶端計算機具有250 MB的在線ClickOnce應用程序存儲空間。 數據文件不計入此限制。 系統管理員可以通過更改注冊表項HKEY_CURRENT_USER \\ Software \\ Classes \\ Software \\ Microsoft \\ Windows \\ CurrentVersion \\ Deployment \\ OnlineAppQuotaInKB來擴大或減少特定客戶端計算機上的此配額,這是一個表示緩存大小的DWORD值,以千字節為單位。 例如,為了將緩存大小減小到50 MB,您可以將此值更改為51200

暫無
暫無

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

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