ClickOnce 部屬程式的架構--Startup Argument Shortcut Execute

恩,用ClickOnce用了不少,但總沒有完整的去K架構原理,出來跑的總算要還的,今天就花了不少時間解一個 Bug?
先說說我的問題,程式第一次執行的時候會需要輸入序號,此時會立刻將序號存下來,然後我程式有一個重新啟動的功能,按下去之後會重新啟動程式,但再重新啟動的時候卻又需要輸入一次序號。
一開始研究了不少地方,想不懂為什麼我手動關閉程式然後點選開始功能表的捷徑就沒問題,可是使用程式來重新執行自己就會有問題。我是採用下列方法
Process.Start(Application.ExecutablePath, eMainCommand.Restart.ToString());
this.Close();
一直以為是ClickOnce的Bug,因為第二次輸入之後就沒有問題了,還在懷疑是不是ClickOnce是不是會需要一點時間寫入設定檔之類的,然後改用schtasks還是不行。
最後,我總算找到Key Point。原來是ClickOnce在啟動的時候會作一點手腳,而我們不能使用上面的方式重新啟動程式。
一般ClickOnce安裝程式會在
C:\Users\Jian\AppData\Local\Apps\2.0\XXXXXX\XXXXXXX\ProductName\ 下面,如果我們直接去執行下面的執行檔的話,這樣程式就不會使用 ClickOnce的 DataPath。
ClickOnce的DataPath一般是在C:\Users\Jian\AppData\Local\Apps\2.0\Data\XXXXXX\XXXXXXX\ProductName\這裡,所以我使用Settings.Default.Save();之後就會在這個目錄下面儲存一個user.config。
當我們手動去執行執行檔的時候,DataPath就會變成
C:\Users\Jian\AppData\Local\PublishName\ProductName\ 這裡。
難怪第二次重新執行的時候一直叫我再輸入一次序號,因為DataPath找不到user.config。
既然知道要走ClickOnce的啟動方式就簡單了,所以程式改為
   1:  if (ApplicationDeployment.IsNetworkDeployed)
   2:  {
   3:      string strDeploymentManifestFilename =  ApplicationDeployment.CurrentDeployment.UpdateLocation.AbsoluteUri;
   4:      XmlTextReader reader = new XmlTextReader(strDeploymentManifestFilename);
   5:      reader.MoveToContent();
   6:      reader.ReadToDescendant("description");
   7:      string ClickOncePublisherName = reader.GetAttribute("asmv2:publisher");
   8:      string ClickOnceProductName = reader.GetAttribute("asmv2:product");
   9:      string ClickOnceShortcut =  string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.Programs), "\\", ClickOncePublisherName, "\\", ClickOnceProductName, "\\", ClickOnceProductName,".appref-ms");
  10:      Process.Start(ClickOnceShortcut, eMainCommand.Restart.ToString());
  11:   }
  12:   else
  13:      Process.Start(Application.ExecutablePath, eMainCommand.Restart.ToString());
  14:   
  15:      this.Close();





ClickOnce的StartMenu Shortcut一般會在 C:\Users\Jian\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Publisher\ProductName\ProductName.appref-ms

這是一個神奇的檔案,會幫我們檢查更新,然後改變DataPath的路徑。

到這邊,我的重新啟動功能總算不會再叫我輸入一次序號了。但因為我的程式有實作Single Instance的邏輯,所以我會傳一個參數Restart給自己,避免同一時間會有兩個Instance存在而發生錯誤。但ClickOnce取參數的方法又不一樣了,所以也要修改~

   1:  public static string[] ApplicationArguments;
   2:  static void Main(string[] Command)
   3:  {
   4:        //ClickOnce 讀取 Argument 的方法
   5:        if (ApplicationDeployment.IsNetworkDeployed)
   6:            FormMain.ApplicationArguments= AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData;
   7:        else
   8:            FormMain.ApplicationArguments = Command;
   9:   
  10:        //ParseArgs(ApplicationArguments);
  11:  }       





打完收工。

PS: http://robindotnet.wordpress.com/2010/03/21/how-to-pass-arguments-to-an-offline-clickonce-application/

這裡有一些參數的討論,例如透過副檔名來開啟檔案之類的~

留言

這個網誌中的熱門文章

好貴的東元冷氣維修--馬達啟動電容

台大醫院 婁培人 耳鼻喉科 就診

機車無法充電之整流器壞掉--$650