背景: 個人電腦 安裝的 VS2015 Community 社區版。 一直用得挺好,都忘了要登錄。 直到近來,30天試用期過 —— VS彈窗:要登錄用戶名、密碼 才能繼續使用。 但是,輸入了無數次 郵箱,到下一步時,都彈出一個 白屏視窗 —— 死活沒法登錄成功。 登錄不成功,日子還得過。 尊重著作權 ...
背景:
個人電腦 安裝的 VS2015 Community 社區版。
一直用得挺好,都忘了要登錄。
直到近來,30天試用期過 —— VS彈窗:要登錄用戶名、密碼 才能繼續使用。
但是,輸入了無數次 郵箱,到下一步時,都彈出一個 白屏視窗 —— 死活沒法登錄成功。
登錄不成功,日子還得過。
尊重著作權、版權 —— 破解VS這種事,還是不做的好(雖然能力可及)。
另闢蹊徑:
試著通過 Win32 發送消息:關閉 彈出窗體。
但是 彈出窗體接收到 關閉消息後,整個VS 依然全部關掉了。
再嘗試了一下:
如果先 修改系統時間,讓修改後的系統時間 就是 試用期範圍 —— 再關閉彈窗,VS 主窗體 沒關閉。
思路明確:
> 監控系統所有窗體。
> 如果有窗體標題是 “Microsoft Visual Studio 帳戶設置” 則開始 如下操作
> 修改系統時間 到 試用期範圍。
> 發送 WM_CLOSE 消息,關閉 彈出窗體。
> 將系統時間 修改回來。
相關源碼 150行:
1 class Program 2 { 3 /// <summary> 4 /// Visual Studio 2015 可以正常啟用的 試用期 時間 5 /// </summary> 6 public static DateTime VisualStudioDate 7 { 8 get { return Convert.ToDateTime(ConfigurationManager.AppSettings["VisualStudioDate"] ?? "2018-05-01"); } 9 } 10 11 12 13 static void Main(string[] args) 14 { 15 while(true) 16 { 17 List<Win32API.WindowInfo> list = Win32API.EnumWindows(); 18 List<Win32API.WindowInfo> list2 = list.FindAll(x => x.szWindowName == "Microsoft Visual Studio 帳戶設置"); 19 20 if (list2.Count >= 1) 21 { 22 //將系統時間設置為 可試用期 23 DateTime nowTime = DateTime.Now; 24 DateTime vsTime = VisualStudioDate; 25 double timeSpanMS = (nowTime - vsTime).TotalMilliseconds; 26 Win32API.SetSystemTime(vsTime); 27 28 foreach (Win32API.WindowInfo item in list2) 29 { 30 try 31 { 32 Console.WriteLine(string.Format("即將關閉 \"{0}\" 0x{1}", item.szWindowName, item.hWnd.ToString("X8"))); 33 Win32API.SendMessage(item.hWnd, Win32API.WM_CLOSE, 0, 0); 34 } 35 catch { } 36 } 37 38 Thread.Sleep(2000); 39 40 //將系統時間還原為 實際日期 41 DateTime nowTime2 = DateTime.Now; 42 double timeSpanMS2 = (nowTime2 - vsTime).TotalMilliseconds; 43 DateTime realTime = vsTime.AddMilliseconds(timeSpanMS + timeSpanMS2); 44 Win32API.SetSystemTime(realTime); 45 } 46 47 //死迴圈, 休眠5秒 48 Thread.Sleep(5000); 49 } 50 } 51 52 53 54 55 } 56 57 public class Win32API 58 { 59 public const int WM_CLOSE = 0x0010; 60 private delegate bool WNDENUMPROC(IntPtr hWnd, int lParam); 61 62 [DllImport("User32.dll", EntryPoint = "SendMessage")] 63 public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); 64 65 66 #region 獲取所有窗體句柄 67 68 //Copyright © http://www.cnblogs.com/oraclejava/articles/1549025.html 69 70 [DllImport("user32.dll")] 71 private static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, int lParam); 72 [DllImport("user32.dll")] 73 private static extern int GetWindowTextW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount); 74 [DllImport("user32.dll")] 75 private static extern int GetClassNameW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount); 76 public struct WindowInfo 77 { 78 public IntPtr hWnd; 79 public string szWindowName; 80 public string szClassName; 81 82 public override string ToString() 83 { 84 return "0x" + hWnd.ToString("X8") + " '" + szWindowName + "' '" + szClassName + "'"; 85 } 86 } 87 88 public static List<WindowInfo> EnumWindows() 89 { 90 List<WindowInfo> wndList = new List<WindowInfo>(); 91 92 EnumWindows(delegate(IntPtr hWnd, int lParam) 93 { 94 WindowInfo wnd = new WindowInfo(); 95 StringBuilder sb = new StringBuilder(256); 96 wnd.hWnd = hWnd; 97 GetWindowTextW(hWnd, sb, sb.Capacity); 98 wnd.szWindowName = sb.ToString(); 99 GetClassNameW(hWnd, sb, sb.Capacity); 100 wnd.szClassName = sb.ToString(); 101 wndList.Add(wnd); 102 return true; 103 }, 0); 104 105 return wndList; 106 } 107 108 #endregion 109 110 111 #region 操作系統 時間修改 112 113 public static bool SetSystemTime(DateTime newDateTime) 114 { 115 SystemTime sysTime = new SystemTime(); 116 sysTime.wYear = Convert.ToUInt16(newDateTime.Year); 117 sysTime.wMonth = Convert.ToUInt16(newDateTime.Month); 118 sysTime.wDay = Convert.ToUInt16(newDateTime.Day); 119 sysTime.wHour = Convert.ToUInt16(newDateTime.Hour); 120 sysTime.wMinute = Convert.ToUInt16(newDateTime.Minute); 121 sysTime.wSecond = Convert.ToUInt16(newDateTime.Second); 122 sysTime.wMiliseconds = (ushort)newDateTime.Millisecond; 123 return SystemDateTime.SetLocalTime(ref sysTime); 124 } 125 126 private class SystemDateTime 127 { 128 [DllImport("Kernel32.dll")] 129 public static extern bool SetLocalTime(ref SystemTime sysTime); 130 131 [DllImport("Kernel32.dll")] 132 public static extern void GetLocalTime(ref SystemTime sysTime); 133 } 134 135 [StructLayout(LayoutKind.Sequential)] 136 private struct SystemTime 137 { 138 public ushort wYear; 139 public ushort wMonth; 140 public ushort wDayOfWeek; 141 public ushort wDay; 142 public ushort wHour; 143 public ushort wMinute; 144 public ushort wSecond; 145 public ushort wMiliseconds; 146 } 147 148 #endregion 149 150 }
項目編譯:
新建一個 WinForm 程式。
將上面的代碼 複製替換。
編譯之後,將 exe 創建一個 快捷方式,放到 “啟動” 菜單中,開機就啟動,讓exe在後臺運行即可。
操作爭議:
作者非常尊重 軟體著作權、版權 —— 無意傷害微軟利益。
用這種方式 延長試用,似乎有兩個爭議:修改系統時間、發送 WM_CLOSE 消息。
> 修改系統時間 是一種 普通操作,任何人都可以進行。【不具備爭議性】
> 發送 WM_CLOSE 消息,一個程式給另一個程式發送消息,改變另外的程式的行為【有點外掛的味道】。 —— 但仔細一想:電腦關機時,系統會給每一個程式 都發送 WM_CLOSE 消息。這樣一想,就突然不覺得侵權了。
尊重知識產權:
作者非常尊重 軟體著作權、版權 —— 如果本文的操作 損害了 微軟的利益,請及時聯繫作者,刪除、修改 此文。