金蝶K3 WISE版本過服務期后打補丁方法-完善版本
讀了這位博主的內容有所啟發
https://blog.csdn.net/hzfw2008/article/details/106991629
金蝶補丁一般安裝過后,都會進行解包,分兩部分,第一部分為完整解包,第二部分為使用備份包

先講第二部分,使用的備份包,也就這里有用,不是全系列產品完整的包補丁內容。

比如,k3 wise 15.0 PT124991包,只需要更新 一個exe和VER內容,其他不需要的東東,不在此處體現,在完整包里面體現。
Kingdee_SP_Install_Log_PT124991.log,為安裝日志,從而可以用來參考復制到哪里。
********* Start installation: 6-17-2020 09:31:54 ********* call K3DCOMManageStop.exe File : C:\Program Files (x86)\Kingdee\K3ERP\K3ClassDEFINENewUSER.exe FileName : K3ClassDEFINENewUSER.exe Path : C:\Program Files (x86)\Kingdee\K3ERP\ Backup File : C:\Program Files (x86)\Kingdee\K3ERP\K3ClassDEFINENewUSER.exe Replace File: C:\Program Files (x86)\Kingdee\K3ERP\K3ClassDEFINENewUSER.exe File : C:\Program Files (x86)\Kingdee\K3ERP\KDSYSTEM\K3MFYGLMakeVoucher.VBR FileName : K3MFYGLMakeVoucher.VBR Path : C:\Program Files (x86)\Kingdee\K3ERP\KDSYSTEM\ Backup File : C:\Program Files (x86)\Kingdee\K3ERP\KDSYSTEM\K3MFYGLMakeVoucher.VBR Replace File: C:\Program Files (x86)\Kingdee\K3ERP\KDSYSTEM\K3MFYGLMakeVoucher.VBR ------- Finish Copying File(s): 6-17-2020 09:32:34 ------- call BatAndExe.bat call K3DCOMManageStart.exe ********** End installation: 6-17-2020 09:32:37 **********
現在講第一部分
還以PT124991補丁包舉例子,這里面是次補丁涉及到的所有,不僅局限與客戶端、服務端,還有其他等等,也不用仔細研究這個,總之是完整解包的內容。

KDPatchs這個文件夾其實木有卵用。
因為新的金蝶補丁全部加殼,在服務期內的通過驗證后,可以打補丁。超過服務期的,正常是打不了的,可以通過如下方法變通處理下:
1、找一臺已經裝好補丁的客戶端(如果找不到,那就用金蝶服務器也行)。將客戶端下面如下2個目錄的文件夾打包壓縮備用。如果提示被占用,請先使用任務管理器結束K3或者KD打頭的進程;


2、在新的系統上按照標準方法安裝金蝶K3客戶端。跑一遍中間層組件注冊;
3、將上面打包壓縮的2個文件夾覆蓋掉新系統的同名文件夾;
4、打開新系統的該目錄,使用管理員權限運行如下2個批處理文件,重新進行組件注冊;
這兩個bat,一個是注冊中間件的,一個是注冊產品的。總之重新注冊一下就好。
有人該問了,控制面板卸載軟件里面有木有補丁包信息,已經注冊表里面有木有,這個肯定木有了,相當于綠色了。這就涉及到第5條的內容,第5條繼續說。



5、運行桌面K3圖標即可正常使用金蝶客戶端。
這里就遇見坑了。什么坑呢,只要打開金蝶就自己下載補丁包進行安裝,這不扯淡了嘛。本來拷貝過來的文件里面就有補丁。其實呢是因為一個自動打補丁的東東,只要你打開金蝶就開始檢測注冊表里面是不是已經安裝過這個補丁了,沒有就下載進行安裝。
這么蛋疼的事情,就不備份已經安裝過補丁電腦的相關注冊表了,直接干掉這個自動補丁安裝程序就好了。
Kingdee.K3.BaseNet.UpdatePatchApp.exe
這個程序在金蝶安裝根目錄里面,將其刪掉,或者改名就好。

Program
using System; using System.Windows; using Kingdee.K3.BaseNet.AutoUpdatePatchCommon; namespace Kingdee.K3.BaseNet.UpdatePatchApp { // Token: 0x02000003 RID: 3 public class Program { // Token: 0x06000005 RID: 5 RVA: 0x000021D0 File Offset: 0x000003D0 [STAThread] private static void Main(string[] args) { Log.WriteLog("進入客戶端補丁升級工具Kingdee.K3.BaseNet.UpdatePatchApp.exe"); if (args == null || args.Length != 1) { Log.WriteLog("args == null || args.Length != 1,退出客戶端補丁升級工具!"); return; } Log.WriteLog("外部傳入客戶端補丁升級工具參數:" + args[0]); new Application().Run(new ProgressWindow(args[0])); } } }
Common
using System; using System.Diagnostics; using System.Reflection; using Kingdee.K3.BaseNet.AutoUpdatePatchCommon; namespace Kingdee.K3.BaseNet.UpdatePatchApp { // Token: 0x02000002 RID: 2 public class Common { // Token: 0x06000001 RID: 1 RVA: 0x00002050 File Offset: 0x00000250 public static string LoadKDString(string strText) { string result; try { Type typeFromProgID = Type.GetTypeFromProgID("K3BaseDataAccess.CMultiLanguage"); object target = Activator.CreateInstance(typeFromProgID); object[] args = new object[] { strText, "K3Base" }; result = (string)typeFromProgID.InvokeMember("LoadKDString", BindingFlags.Public | BindingFlags.InvokeMethod, null, target, args); } catch { Log.WriteLog("Kingdee.K3.BaseNet.UpdatePathApp.LoadKDString(),Error strText=" + strText); result = strText; } return result; } // Token: 0x06000002 RID: 2 RVA: 0x000020CC File Offset: 0x000002CC public static bool IsOpenAntivirus() { bool result = false; try { Process[] processesByName = Process.GetProcessesByName("360sd"); if (processesByName.Length == 0) { processesByName = Process.GetProcessesByName("360Tray"); if (processesByName.Length > 0) { Log.WriteLog("檢測到客戶端安裝了360安全衛士"); result = true; } } else { Log.WriteLog("檢測到客戶端安裝了360殺毒軟件"); result = true; } } catch (Exception ex) { Log.WriteLog("判斷是否開啟殺毒軟件報錯IsOpenAntivirus:" + ex.ToString()); } return result; } // Token: 0x06000003 RID: 3 RVA: 0x00002144 File Offset: 0x00000344 public static void ClosedK3Proc(string strProcName) { try { Log.WriteLog(string.Format("檢測K3進程{0}", strProcName)); Process[] processesByName = Process.GetProcessesByName(strProcName); int num = processesByName.Length; Log.WriteLog(string.Format("檢測K3進程{0}有{1}個,下一步這些關閉進程", strProcName, num)); if (num > 0) { for (int i = 0; i < num; i++) { processesByName[i].Kill(); } } } catch (Exception ex) { Log.WriteLog(string.Format("強制關閉{0}主控臺報錯:{1}", strProcName, ex.ToString())); } } } }
ProgressWindow
using System; using System.CodeDom.Compiler; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Markup; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Threading; using Kingdee.K3.BaseNet.AutoUpdatePatchClient; using Kingdee.K3.BaseNet.AutoUpdatePatchCommon; namespace Kingdee.K3.BaseNet.UpdatePatchApp { // Token: 0x02000004 RID: 4 public class ProgressWindow : Window, IComponentConnector { // Token: 0x17000001 RID: 1 // (get) Token: 0x06000007 RID: 7 RVA: 0x00002228 File Offset: 0x00000428 // (set) Token: 0x06000008 RID: 8 RVA: 0x0000223A File Offset: 0x0000043A public string Message { get { return (string)base.GetValue(ProgressWindow.MessageProperty); } set { base.SetValue(ProgressWindow.MessageProperty, value); } } // Token: 0x17000002 RID: 2 // (get) Token: 0x06000009 RID: 9 RVA: 0x00002248 File Offset: 0x00000448 // (set) Token: 0x0600000A RID: 10 RVA: 0x0000225A File Offset: 0x0000045A public int ProgressValue { get { return (int)base.GetValue(ProgressWindow.ProgressValueProperty); } set { base.SetValue(ProgressWindow.ProgressValueProperty, value); } } // Token: 0x17000003 RID: 3 // (get) Token: 0x0600000B RID: 11 RVA: 0x0000226D File Offset: 0x0000046D // (set) Token: 0x0600000C RID: 12 RVA: 0x0000227F File Offset: 0x0000047F public int ProgressMaximum { get { return (int)base.GetValue(ProgressWindow.ProgressMaximumProperty); } set { base.SetValue(ProgressWindow.ProgressMaximumProperty, value); } } // Token: 0x0600000D RID: 13 RVA: 0x00002294 File Offset: 0x00000494 public ProgressWindow(string k3StartupProgromName) { try { this.m_lstNeedInstallPatch = this.GetNeesInstallPatchs(); if (this.m_lstNeedInstallPatch.Count == 0) { Log.WriteLog(string.Format("本客戶端沒有補丁需要安裝,直接退出補丁更新工具", new object[0])); Application.Current.Shutdown(); } else { string text = ""; try { text = PatchVerify.GetRegistryKeyValue("", "IsAuto"); } catch (Exception) { } Log.WriteLog("讀取注冊表 IsAuto=" + text + "," + ((text == "1") ? "當前機器正在安裝補丁,請稍后再嘗試!。" : "空值可進行補丁安裝")); if (text == "1") { Process[] processesByName = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName); if (processesByName.Length > 1) { MessageBox.Show(Common.LoadKDString("客戶端正在更新補丁,請稍后再嘗試!"), Common.LoadKDString("金蝶提示"), MessageBoxButton.OK, MessageBoxImage.Asterisk); Application.Current.Shutdown(); return; } } this.InitializeComponent(); base.DataContext = this; this._k3StartupProgromName = k3StartupProgromName; } } catch (Exception ex) { Log.WriteLog(string.Format("補丁更新工具報錯,直接退出:{0}", ex.ToString())); } } // Token: 0x0600000E RID: 14 RVA: 0x000024AC File Offset: 0x000006AC private void UpdatePatchs() { bool flag = false; try { PatchVerify.SetIsAutoRegedit("1"); } catch (Exception ex) { Log.WriteLog("讀取注冊表" + ex.ToString()); } Action<string> method = delegate(string message) { this.Message = message; }; Action<int> method2 = delegate(int progressValue) { this.ProgressValue = progressValue; }; Action<int> method3 = delegate(int progressMaximum) { this.ProgressMaximum = progressMaximum; }; Action method4 = delegate() { Storyboard storyboard = base.Resources["ClosedStoryboard"] as Storyboard; storyboard.Completed += delegate(object A_1, EventArgs A_2) { base.Close(); }; storyboard.Begin(); }; try { Thread.Sleep(3000); ProcessStartInfo processStartInfo = null; Process process = null; int num = 0; bool flag2 = true; Func<bool> func = delegate() { process = new Process { StartInfo = processStartInfo }; process.Start(); bool result = process.WaitForExit(1800000); process.Close(); return result; }; List<string> lstNeedInstallPatch = this.m_lstNeedInstallPatch; base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method3, lstNeedInstallPatch.Count * 4); int num2 = 0; int count = lstNeedInstallPatch.Count; foreach (string text in lstNeedInstallPatch) { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method2, num2 * 4); string[] array = text.Split(new char[] { '|' }); bool flag3 = array[0] == "0"; string patchNo = array[1]; string arg = string.Concat(new object[] { Common.LoadKDString("正在安裝第"), num2 + 1, Common.LoadKDString("個補丁"), patchNo, Common.LoadKDString(",共"), count, Common.LoadKDString("個,請稍候...") }); PatchTransfer patchTransfer = new PatchTransfer(); string text2 = Path.Combine(SocketTransferData.PatchDiretory, string.Format("{0}.rar", patchNo)); base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method2, num2 * 4 + 1); base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, arg); patchTransfer.DownloadPatchToServer(string.Format("{0}.rar", patchNo), ref num); if (flag2) { string text3 = Path.Combine(Path.Combine(SocketTransferData.PatchDiretory, patchNo), string.Format("{0}.exe", patchNo)); if (flag3 && PatchVerify.IsPatchInstallLocal(patchNo)) { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, patchNo + Common.LoadKDString("已安裝,不進行重復安裝")); Log.WriteLog(string.Format("{0}已安裝,不進行重復安裝", patchNo)); continue; } string text4 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WinRAR.exe"); Path.GetDirectoryName(text4); FileInfo fileInfo = new FileInfo(text2); string arguments = string.Format("x \"{0}\" \"{1}\" -y -ibck -inul", text2, fileInfo.DirectoryName); if (File.Exists(text2)) { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method2, num2 * 4 + 2); processStartInfo = new ProcessStartInfo { FileName = text4, Arguments = arguments, WindowStyle = ProcessWindowStyle.Hidden, UseShellExecute = false, CreateNoWindow = true, RedirectStandardError = true, RedirectStandardInput = true, RedirectStandardOutput = true, Verb = "runas" }; base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, Common.LoadKDString("正在解壓") + patchNo); if (func()) { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, patchNo + Common.LoadKDString("已解壓")); Log.WriteLog(string.Format("{0}已解壓", patchNo)); PatchVerify.DeleteRegedit(patchNo); if (File.Exists(text3)) { processStartInfo = new ProcessStartInfo { FileName = text3, WindowStyle = ProcessWindowStyle.Hidden, UseShellExecute = false, CreateNoWindow = true, Arguments = " -slient", Verb = "runas" }; base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, arg); base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method2, num2 * 4 + 3); if (func()) { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, Common.LoadKDString("已安裝") + patchNo); Log.WriteLog(string.Format("{0}已安裝", patchNo)); if (!flag3) { if ((from dr1 in PatchInstall.dt_InstalledPatch where dr1.PatchNo == patchNo select 1).Count<int>() == 0) { DataSet1.DT_InstalledPatchRow dt_InstalledPatchRow = PatchInstall.dt_InstalledPatch.NewDT_InstalledPatchRow(); dt_InstalledPatchRow.PatchNo = patchNo; PatchInstall.dt_InstalledPatch.AddDT_InstalledPatchRow(dt_InstalledPatchRow); PatchInstall.dt_InstalledPatch.WriteXml(PatchInstall.installedPatchFilePath); } Log.WriteLog(string.Format("{0}已更新補丁狀態", patchNo)); } } else { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, patchNo + Common.LoadKDString("安裝失敗")); Log.WriteLog(string.Format("{0}安裝失敗", patchNo)); File.Delete(text3); if (flag3) { flag2 = false; continue; } continue; } } else { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, Common.LoadKDString("無法找到補丁文件") + text3); Log.WriteLog(string.Format("無法找到補丁文件 {0}", text3)); } } else { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, patchNo + Common.LoadKDString("解壓失敗")); Log.WriteLog(string.Format("{0}解壓失敗", patchNo)); if (flag3) { flag2 = false; continue; } continue; } } else { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, Common.LoadKDString("無法找到補丁壓縮包文件") + text2); Log.WriteLog(string.Format("無法找到補丁壓縮包文件 {0}", text2)); } } else { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, Common.LoadKDString("由于前置補丁安裝異常,未安裝") + patchNo); Log.WriteLog(string.Format("由于前置補丁安裝異常,{0}未安裝", patchNo)); if (!flag3) { flag2 = true; } } base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method2, num2 * 4 + 4); num2++; } base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, Common.LoadKDString("更新完成,啟動K3WISE控制臺")); flag = true; } catch (Exception ex2) { flag = false; Log.WriteLog(ex2.ToString()); } finally { try { PatchVerify.SetIsAutoRegedit(""); } catch (Exception ex3) { Log.WriteLog("讀取注冊表" + ex3.ToString()); } Thread.Sleep(1000); base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method4); if (!flag) { MessageBoxResult messageBoxResult = MessageBox.Show(Common.LoadKDString("補丁安裝過程中出現異常,可能導致K3使用過程中出現異常,請聯系管理員。\r\n是否要繼續打開K3?"), Common.LoadKDString("金蝶提示"), MessageBoxButton.YesNo, MessageBoxImage.Exclamation); if (messageBoxResult == MessageBoxResult.Yes) { flag = true; } } if (flag) { string text5 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, this._k3StartupProgromName + ".exe"); Log.WriteLog("補丁更新完成,啟動主控臺,啟動路徑:" + text5); if (!File.Exists(text5)) { MessageBox.Show(text5 + Common.LoadKDString("路徑不正確!")); } ProcessStartInfo startInfo = new ProcessStartInfo { FileName = text5, WindowStyle = ProcessWindowStyle.Hidden, UseShellExecute = false, Arguments = "updated", Verb = "runas" }; Process process2 = new Process { StartInfo = startInfo }; process2.Start(); } } } // Token: 0x0600000F RID: 15 RVA: 0x00002D30 File Offset: 0x00000F30 private List<string> GetNeesInstallPatchs() { List<string> list = new List<string>(); try { bool flag = PatchInstall.IsNeedUpdatePatch(); if (flag) { list = PatchInstall.m_NeedInstallPatchList; if (list == null) { Log.WriteLog(string.Format("方法GetNeesInstallPatchs判斷客戶端是否有補丁需要安裝得出值為null", new object[0])); return list; } int count = list.Count; Log.WriteLog(string.Format("方法GetNeesInstallPatchs判斷客戶端是否有補丁需要安裝檢測到有{0}個補丁需要安裝", count)); for (int i = count - 1; i >= 0; i--) { string text = list[i]; string[] array = text.Split(new char[] { '|' }); string text2 = array[1]; bool flag2 = PatchVerify.IsPatchInstallLocal(text2); if (flag2) { list.RemoveAt(i); } } } } catch (Exception ex) { Log.WriteLog(string.Format("方法GetNeesInstallPatchs判斷客戶端是否有補丁需要安裝報錯:{0}", ex.ToString())); } return list; } // Token: 0x06000010 RID: 16 RVA: 0x00002E28 File Offset: 0x00001028 private void Window_Loaded(object sender, RoutedEventArgs e) { try { int count = this.m_lstNeedInstallPatch.Count; if (count > 0) { Common.ClosedK3Proc(this._k3StartupProgromName); (base.Resources["OpenStoryboard"] as Storyboard).Begin(); this.Main.OpacityMask = (base.Resources["ClosedBrush"] as LinearGradientBrush); Log.WriteLog(string.Format("客戶端補丁更新工具最終結果檢測到有{0}個補丁需要在本客戶端安裝,馬上進入安裝階段", count)); if (Common.IsOpenAntivirus()) { MessageBox.Show(Common.LoadKDString("安裝補丁前請關閉殺毒軟件!"), Common.LoadKDString("金蝶提示"), MessageBoxButton.OK, MessageBoxImage.Exclamation); } new Thread(new ThreadStart(this.UpdatePatchs)).Start(); } else { Log.WriteLog(string.Format("本客戶端沒有補丁需要安裝", new object[0])); } } catch (Exception ex) { Log.WriteLog(string.Format("客戶端補丁更新工具Kingdee.K3.BaseNet.UpdatePatchApp.exe報錯:{0}", ex.ToString())); } } // Token: 0x06000011 RID: 17 RVA: 0x00002F24 File Offset: 0x00001124 [DebuggerNonUserCode] [GeneratedCode("PresentationBuildTasks", "4.0.0.0")] public void InitializeComponent() { if (this._contentLoaded) { return; } this._contentLoaded = true; Uri resourceLocator = new Uri("/Kingdee.K3.BaseNet.UpdatePatchApp;component/progresswindow.xaml", UriKind.Relative); Application.LoadComponent(this, resourceLocator); } // Token: 0x06000012 RID: 18 RVA: 0x00002F54 File Offset: 0x00001154 [GeneratedCode("PresentationBuildTasks", "4.0.0.0")] [EditorBrowsable(EditorBrowsableState.Never)] [DebuggerNonUserCode] void IComponentConnector.Connect(int connectionId, object target) { switch (connectionId) { case 1: ((ProgressWindow)target).Loaded += this.Window_Loaded; return; case 2: this.Screen = (Grid)target; return; case 3: this.Main = (Border)target; return; default: this._contentLoaded = true; return; } } // Token: 0x04000001 RID: 1 private string _k3StartupProgromName; // Token: 0x04000002 RID: 2 public static readonly DependencyProperty MessageProperty = DependencyProperty.Register("Message", typeof(string), typeof(ProgressWindow), new PropertyMetadata(Common.LoadKDString("開始更新"))); // Token: 0x04000003 RID: 3 public static readonly DependencyProperty ProgressValueProperty = DependencyProperty.Register("ProgressValue", typeof(int), typeof(ProgressWindow), new PropertyMetadata(0)); // Token: 0x04000004 RID: 4 public static readonly DependencyProperty ProgressMaximumProperty = DependencyProperty.Register("ProgressMaximum", typeof(int), typeof(ProgressWindow), new PropertyMetadata(100)); // Token: 0x04000005 RID: 5 private List<string> m_lstNeedInstallPatch = new List<string>(); // Token: 0x04000006 RID: 6 internal Grid Screen; // Token: 0x04000007 RID: 7 internal Border Main; // Token: 0x04000008 RID: 8 private bool _contentLoaded; } }
至于有木有真正的打上補丁,自己去實驗吧。總之我是驗證過了,包括補丁包里面的內容md5值都已經比對過,和安裝過補丁的電腦文件md5值一樣。
有點拗口,這里可以忽略。

使用的系統也忽略哈,Linux是我的主戰場,一條md5sum進行計算,多么方便。

浙公網安備 33010602011771號