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的啟動方式就簡單了,所以程式改為
ClickOnce的StartMenu Shortcut一般會在 C:\Users\Jian\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Publisher\ProductName\ProductName.appref-ms
這是一個神奇的檔案,會幫我們檢查更新,然後改變DataPath的路徑。
到這邊,我的重新啟動功能總算不會再叫我輸入一次序號了。但因為我的程式有實作Single Instance的邏輯,所以我會傳一個參數Restart給自己,避免同一時間會有兩個Instance存在而發生錯誤。但ClickOnce取參數的方法又不一樣了,所以也要修改~
打完收工。
PS: http://robindotnet.wordpress.com/2010/03/21/how-to-pass-arguments-to-an-offline-clickonce-application/
這裡有一些參數的討論,例如透過副檔名來開啟檔案之類的~
先說說我的問題,程式第一次執行的時候會需要輸入序號,此時會立刻將序號存下來,然後我程式有一個重新啟動的功能,按下去之後會重新啟動程式,但再重新啟動的時候卻又需要輸入一次序號。
一開始研究了不少地方,想不懂為什麼我手動關閉程式然後點選開始功能表的捷徑就沒問題,可是使用程式來重新執行自己就會有問題。我是採用下列方法
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/
這裡有一些參數的討論,例如透過副檔名來開啟檔案之類的~
留言