這個難題可是整整搞了我2天時候。
直至目前,才算有一個解決方案。
經過 Xenocode 的 WinForm 程式,如果你想實現一鍵式自動更新(就是不需要客戶點一下點一下),那是相當困難的。
原因是 Xenocode 不但混淆了代碼,還進行“加殼”保護了!至於什麼是加殼,我個人理解是:在一個程式裡運行另外一個程式(沒有看過相關的知識,見笑了)。
我來說說我的自動升級構思:
代碼
ProcessStartInfo info = new ProcessStartInfo();
info.WorkingDirectory = Application.StartupPath;
info.FileName = "AutoUpdater.exe";
info.Arguments = string.Format("\"{0}\" \"{1}\" \"{2}\"",
Process.GetCurrentProcess().Id,
StaticModel.GetServerUrl() + versionAndFilename[1],
versionAndFilename[2]);
// ProgramEx.Mutex.TryDispose();
info.UseShellExecute = false;
Process.Start(info);
Application.ExitThread();
而 AutoUpdater.exe 很簡單,到指定網址下載一個 rar,刪除當前檔案夾裡的所有檔案並解壓。
這裡涉及到一個問題:如果不使用混淆加殼,這一段代碼,是完全行得通的。
可是一旦保護了,問題就來了,使用 Process.Start 後仍處於Xenocode 加殼進程中。
通俗的說:在加殼混淆後的程式(程式A)裡,調用了任何外部程式(程式B)以後,都無法刪除來源程式(程式A)。
這可忙得我焦頭爛額。到網上搜羅無數辦法,包括是CreateProcess API,什麼拷貝到臨時檔案,然後再返回來,等等等等……神啊,救救我吧!
其實緩解方案還是有的,就是雷同 ClickOnce ,建立一個“版本檔案夾”。但是這個方法比較麻煩,因為我在安裝包的時候,就已經建立案頭快速鍵,如此一改,將會涉及到更多的問題。
琢磨了2天,直到今晚,無意中想起,Xenocode加殼了,我自己就不能“加殼”?
說幹就幹,程式很簡單,建立一個新的WinForm應用程式:
代碼
/// <summary>
/// 應用程式的主進入點。
/// </summary>
[STAThread]
static void Main()
{
Process p = new Process();
p.StartInfo.FileName = "AthleticPos2011.Views.exe";
p.StartInfo.Arguments = "1";
p.Start();
p.WaitForExit();
if (File.Exists("update.ath"))
{
Thread.Sleep(1000);
var args = File.ReadAllText("update.ath");
File.Delete("update.ath");
ProcessStartInfo info = new ProcessStartInfo();
info.WorkingDirectory = Application.StartupPath;
info.FileName = "AutoUpdater.exe";
info.Arguments = args;
info.UseShellExecute = false;
Process.Start(info);
Application.ExitThread();
}
}
而來源程式的發現需要更新後的操作變成如下:
代碼
File.WriteAllText("update.ath", string.Format("\"{0}\" \"{1}\" \"{2}\"",
Process.GetCurrentProcess().Id,
StaticModel.GetServerUrl() + versionAndFilename[1],
versionAndFilename[2]));
this.Close();
// ProgramEx.Mutex.TryDispose();
//ProcessStartInfo info = new ProcessStartInfo();
//info.WorkingDirectory = Application.StartupPath;
//info.FileName = "AutoUpdater.exe";
//info.Arguments = string.Format("\"{0}\" \"{1}\" \"{2}\"",
// Process.GetCurrentProcess().Id,
// StaticModel.GetServerUrl() + versionAndFilename[1],
// versionAndFilename[2]);
//// ProgramEx.Mutex.TryDispose();
//info.UseShellExecute = false;
//Process.Start(info);
//Application.ExitThread();
好了!!搞定!明天最佳化一下!大家早點休息吧!