2010-03-01 208 views
129

我需要在控制檯ClickOnce .application(可執行文件)所在的同一文件夾中編寫一個文件。它從中啓動的文件夾。如何獲取ClickOnce應用程序的文件夾路徑

我嘗試使用Application.StartupPath & Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) 但路徑c:\Documents & Settings下指向一個子文件夾。我如何獲得.application所在的路徑?

回答

3

ClickOnce應用程序DO駐留在C:\ Documents &設置的子目錄中。它們沒有「乾淨的」安裝目錄,因爲本地文件實質上是「臨時」下載,以允許應用程序在本地PC上運行,並且應用程序的執行由部署它們的ClickOnce服務器控制,具體取決於發佈設置(檢查更新,版本要求等)。

+0

我無法訪問服務器上的C:\ Documents&Settings文件夾,這意味着我無權訪問應用程序創建的文件。我從某個文件夾運行應用程序。這是該應用發佈的文件夾。我如何獲得該文件夾的路徑? – 2010-03-01 21:20:32

+0

哦,你想要部署網址。對不起,我一點都沒有。您是否試圖從ClickOnce應用程序或外部應用程序中獲取它? – RobinDotNet 2010-03-10 09:52:12

107

路徑在C指向一個子文件夾:\文件&設置

這是正確的。 ClickOnce applications安裝在安裝它們的用戶的配置文件下。你是否已經從正在執行的程序集中獲取信息的路徑提供給你,然後去檢查它?

在Windows Vista和Windows 7中,你會發現的ClickOnce緩存這裏:

c:\users\username\AppData\Local\Apps\2.0\obfuscatedfoldername\obfuscatedfoldername 

在Windows XP中,你會發現它在這裏:

C:\Documents and Settings\username\LocalSettings\Apps\2.0\obfuscatedfoldername\obfuscatedfoldername 
+1

我明白這一切。我想從我點擊應用程序的位置獲取文件夾。我沒有權限訪問C:\ Documents and Settings,因此如果我要使用該函數返回的文件夾路徑,並且我不想使用硬編碼的路徑值,那麼我將無法訪問日誌文件。 – 2010-03-09 20:10:00

23

ApplicationDeployment.CurrentDeployment.ActivationUri可能工作

「如果部署清單中的TrustUrlParameters屬性爲false,或者用戶提供了UNC以打開部署或已打開部署,則爲零長度字符串LLY。否則,返回值是用來啓動應用程序的完整URL,包括任何參數。」


但我覺得你真正想要的是ApplicationDeployment.CurrentDeployment.DataDirectory,讓你可以將數據寫入到一個文件夾,當你更新應用程序無論如何都會丟失原始.exe文件夾中的內容,但是您可以將數據目錄遷移到新版本的應用程序中。您的應用程序可以使用它的任何日誌文件向此文件夾寫入數據 - 而且很確定它的保證是可寫的。

+2

+1用於指出DataDirectory。感謝那 – 2012-11-07 21:01:20

+0

我什麼都沒做,但是在部署之後,舊DataDirectory中的文件會自動複製到新的DataDirectory中。還沒有.pre目錄。 (.NET Framework 3.5和4.5) – 2014-03-25 07:02:58

197

要找到文件夾位置,您可以運行應用程序,打開任務管理器(CTRL-SHIFT-ESC),選擇應用程序並右鍵單擊|打開文件位置。

+2

嘿,親提示!但它不適用於老舊的XP機器。 :) – Jalal 2012-12-16 07:27:36

+4

@Jalal for「老蹩腳的機器」去www.SysInternals.com並下載Process Explorer。我懷疑Win7的TaskManager中的變化,然後Win8只是從它複製。 – 2013-03-21 19:16:07

+1

如何在客戶計算機上運行的應用程序中實現這一目標? – user3285954 2015-09-10 16:46:00

12

我正在使用Assembly.GetExecutingAssembly().Location獲取在.Net 4.5.1中部署的應用程序的路徑ClickOnce。但是,不管部署方法如何(xcopy,ClickOnce,InstallShield,任何內容),您都不應寫入應用程序部署到的任何文件夾,因爲這些文件通常只能讀取應用程序,尤其是在較新的Windows版本中服務器環境。

應用程序必須始終寫入爲此目的保留的文件夾。您可以從Environment.SpecialFolder Enumeration開始獲取所需的文件夾。MSDN頁面解釋了每個文件夾的用途: http://msdn.microsoft.com/en-us/library/system.environment.specialfolder.aspx

即,數據,日誌和其他文件可以使用ApplicationData(漫遊),LocalApplicationData(本地)或CommonApplicationData。 臨時文件使用Path.GetTempPathPath.GetTempFileName

以上在服務器和桌面上的工作也是如此。

編輯: Assembly.GetExecutingAssembly()在主可執行文件中調用。

+0

偉大的答案。謝謝 – stigzler 2015-11-09 13:42:17

+0

這一直在爲我工作的ClickOnce應用程序,以及也在VS開發環境中工作,同時調試同一個應用程序。 – Developer63 2016-06-02 19:08:47

0

這裏是我發現,工作了,能夠讓我的ClickOnce應用程序的部署文件夾位置並沒有被提及任何地方我在搜索看到,我的同類,具體情況:

  • clickonce應用程序部署到公司LAN網絡文件夾。
  • clickonce應用程序設置爲可在線或離線使用。
  • 我的項目屬性中的clickonce安裝URL和更新URL沒有任何指定。也就是說,沒有單獨的安裝或更新位置。
  • 在我的發佈選項中,我爲clickonce應用程序創建了桌面快捷方式。
  • 我想要在啓動時獲取路徑的文件夾是我希望通過應用程序的DEV,INT和PROD版本訪問的文件夾,而無需對路徑進行硬編碼。

這裏是一個可視化我的使用情況:

enter image description here

  • 藍色盒裝文件夾是每個 環境的應用我的目錄位置。
  • 紅色方塊文件夾是我想要獲取 (需要先獲取應用程序的已部署文件夾位置 「MyClickOnceGreatApp_1_0_0_37」,與OP相同)的路徑的目錄。

我沒有在這個問題中找到任何建議或他們的意見,以返回clickonce應用程序部署到的文件夾(然後我將相對於此文件夾移動以找到感興趣的文件夾) 。沒有其他互聯網搜索或相關的SO問題也找到了答案。

由於對象(例如ActivationUri)爲空或者指向本地PC的緩存安裝的應用程序文件夾,所有建議的屬性都失敗。是的,我可以通過檢查IsNetworkDeployed來優雅地處理空對象 - 這不是問題 - 但令人驚訝的是,即使我實際上爲clickonce應用程序擁有網絡部署的文件夾位置,IsNetworkDeployed也會返回false。這是因爲應用程序是從本地高速緩存位運行的。

解決的辦法是看:

  • AppDomain.CurrentDomain.BaseDirectory當應用程序被Visual Studio中運行,因爲我開發和
  • System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation當它正常執行。

System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation正確地返回我的clickonce應用程序部署到的網絡目錄,在所有情況下。也就是說,當它通過推出:

  • SETUP.EXE
  • MyClickOnceGreatApp.application
  • 創建在第一次安裝並啓動應用程序的桌面快捷方式。

下面是我在應用程序啓動時使用的代碼,以獲取WorkAccounts文件夾的路徑。獲取部署的應用程序文件夾是隻是沒有踏着高達父目錄簡單:

string directoryOfInterest = ""; 
if (System.Diagnostics.Debugger.IsAttached) 
{ 
    directoryOfInterest = Directory.GetParent(Directory.GetParent(Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory).FullName).FullName).FullName; 
} 
else 
{ 
    try 
    { 
     string path = System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation.ToString(); 
     path = path.Replace("file:", ""); 
     path = path.Replace("/", "\\"); 
     directoryOfInterest = Directory.GetParent(Directory.GetParent(path).FullName).FullName; 
    } 
    catch (Exception ex) 
    { 
     directoryOfInterest = "Error getting update directory needed for relative base for finding WorkAccounts directory.\n" + ex.Message + "\n\nUpdate location directory is: " + System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation.ToString(); 
    } 
} 
1

經過一番詳盡的搜索,我終於找到了一種方法找到通過註冊表混淆的文件夾名稱。以下是一個簡單的方法:

private static Tuple<string, string> GetClickonceDirectories() 
{ 
    var appToken = (string) Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\Classes\Software\Microsoft\Windows\CurrentVersion\Deployment\SideBySide\2.0", "ComponentStore_RandomString", null); 
    var dataToken = (string) Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\Classes\Software\Microsoft\Windows\CurrentVersion\Deployment\SideBySide\2.0\StateManager", "StateStore_RandomString", null); 

    if (string.IsNullOrWhiteSpace(appToken) || string.IsNullOrWhiteSpace(dataToken)) 
    { 
     throw new Exception("Unable to find clickonce directories."); 
    } 

    var appDir = 
      [email protected]"{appToken.Substring(0, 8)}.{appToken.Substring(8, 3)}\{appToken.Substring(11, 8)}.{appToken.Substring(19, 3)}"; 

    var dataDir = 
      [email protected]"Data\{dataToken.Substring(0, 8)}.{dataToken.Substring(8, 3)}\{dataToken.Substring(11, 8)}.{dataToken.Substring(19, 3)}"; 

    var rootPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); 
    rootPath = Path.Combine(rootPath, "Apps", "2.0"); 

    return new Tuple<string, string>(Path.Combine(rootPath, appDir), Path.Combine(rootPath, dataDir)); 
} 
相關問題