有需求就要改進
最近兩年沒有在春節回家過年了,主要是票太難買,雖然之前寫了一個12306“無聲購票彈窗”工具,解決了搶票問題,但是全家老小一起回去還是很累,干脆就在北京過年了。這兩天突然有一個朋友問我你之前的搶票工具還能用不,我讓他試試,他說可以,於是我覺得這樣一個小工具居然還有人繼續使用啊,既然有人用我就繼續把他做好點,讓大家過年搶票更“安心”!
之前的搶票工具是基於IEBrowser控件做的,不用說大家都知道這個控件在不同的Windows系統上表現各異,因為它主要依賴於IE內核,坑爹的是它有時候還沒有直接使用IE效果好,所以使用我這個搶票工具總有不順收的地方,比如一些顯示問題,提交訂單后無法直接支付問題等。看到朋友介紹說CefSharp控件不錯,於是決定試試,沒想到出了網上介紹的坑,還有些其它的坑沒有人寫過,這里寫出來給大家做一個參考。
1,CefSharp版本問題
最新版的CefSharp要求.NET應用程序至少支持 .NET 4.5.2以上,而我這次要整合的工具程序還是 .NET 4.0的,照做相關資料去下載了一個之前的版本,結果在JS無法調用VB.NET寫的方法,而它去可以在X64模式下調用C#寫的方法。沒法只好升級到CefSharp 57.0.0 ,才解決了這個問題。
JS調用VB.NET的代碼如下:
VB.NET代碼:
Public Class TicketNotify Dim owerForm As Form Public Sub New(ByVal owner As Form) Me.owerForm = owner End Sub Public Sub MyNotify() Dim target As frm12306Ticket = Me.owerForm target.FoundTickt = True ' target.Notify() End Sub End Class
將這個.NET類注冊到Cef瀏覽器里面去:
Dim WithEvents WebBrowser1 As CefSharp.WinForms.ChromiumWebBrowser Me.WebBrowser1 = New CefSharp.WinForms.ChromiumWebBrowser(Me.ticketUrl) Me.WebBrowser1.RegisterJsObject("jsObj", New TicketNotify(Me), Nothing)
然后,將一段調用這個.NET方法的JS函數注入到Cef瀏覽器內:
Private Sub WebBrowser1_FrameLoadEnd(sender As Object, e As FrameLoadEndEventArgs) Handles WebBrowser1.FrameLoadEnd Dim js As String = <string> var divAlert=true; function checkHaveTicket() { var div = document.getElementById('autosubmitcheckticketinfo'); if (div) { if (div.style.display == 'block' || div.style.display == '') { //txtName.value = '有票了!!!'; jsObj.myNotify(); } } } </string> '下面兩行代碼效果一樣 'Me.WebBrowser1.GetMainFrame().ExecuteJavaScriptAsync(js) Me.WebBrowser1.ExecuteScriptAsync(js) End Sub
這樣,瀏覽器執行 jsObj.myNotify(); 這個方法就可以調用我們的.NET對象的方法 MyNotify() 了。
PS:注意上面有一個代碼 <string>...</string> ,這個是VB.NET獨特的XML語句塊,XML是VB.NET的一種數據類型,就像你自定義的類型一樣,這里用來表示一個字符串,所以用它來表示多行字符串是最合適的了。
由於CefSharp版本問題,這個JS代碼必須寫到 瀏覽器控件的 FrameLoadEnd 事件中,但是之前查詢到文章里面都說可以在 IsBrowserInitializedChanged 事件里面,現在是找不到的,但不報錯,例如下面實際的代碼說明:
Private Sub WebBrowser1_IsBrowserInitializedChanged(sender As Object, e As IsBrowserInitializedChangedEventArgs) Handles WebBrowser1.IsBrowserInitializedChanged If e.IsBrowserInitialized Then '不可以在這里注冊JS代碼,新版CefSharp 找不到 '不可以在這里開啟定時器,否則定時器的事件會在當前線程,也就是UI線程之外運行,相關UI訪問代碼會發生“線程間操作無效”的異常 'Me.Timer1.Start() End If End Sub
2.Windows 8.1 閃屏問題
我在公司的Windows 10系統下CefSharp運行正常,但是回家在Windows 8.1系統上,發現Cef瀏覽器總是不能填充滿窗口,只有一半大小,但是滾動條位置卻能鼓動,滾動的時候會看到閃屏,同時頁面上控件的點擊位置也是錯位的,需要點擊下才能回復頁面大小,但很快又變小了。查了下資料,說可以通過程序集清單設置文件進行設置:

<?xml version="1.0" encoding="utf-8"?> <asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> <security> <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> <!-- UAC 清單選項 如果希望更改 Windows 用戶帳戶控制級別,請用以下節點之一替換 requestedExecutionLevel 節點。 <requestedExecutionLevel level="asInvoker" uiAccess="false" /> <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> <requestedExecutionLevel level="highestAvailable" uiAccess="false" /> 如果您希望利用文件和注冊表虛擬化提供 向后兼容性,請刪除 requestedExecutionLevel 節點。 --> <requestedExecutionLevel level="asInvoker" uiAccess="false" /> </requestedPrivileges> </security> </trustInfo> <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <application> <!-- 此應用程序設計使用的所有 Windows 版本的列表。 Windows 將會自動選擇最兼容的環境。--> <!-- 如果應用程序設計為使用 Windows Vista,請取消注釋以下 supportedOS 節點--> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS> <!-- 如果應用程序設計使用 Windows 7,請取消注釋以下 supportedOS 節點--> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> <!-- 如果應用程序設計為使用 Windows 8,請取消注釋以下 supportedOS 節點--> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS> <!-- 如果應用程序設計為使用 Windows 8.1,請取消對以下 supportedOS 節點的注釋--> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> </application> </compatibility> <!--<application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings> <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware> </windowsSettings> </application>--> </asmv1:assembly>
結果無效,后來看到可能沒有禁用GPU有關,於是做下設置:
Dim setting As CefSettings = New CefSettings() With setting .Locale = "zh-CN" .AcceptLanguageList = "zh-CN" .MultiThreadedMessageLoop = True End With Dim osVersion = Environment.OSVersion '//Disable GPU for Windows 7 ,8,8.1 If osVersion.Version.Major = 6 Then '// Disable GPU in WPF and Offscreen examples until #1634 has been resolved setting.CefCommandLineArgs.Add("disable-gpu", "1") End If CefSharp.Cef.Initialize(setting)
經過這樣的設置后,終於顯示正常了。
3,定時器失效問題
小工具是通過定時器不斷監控頁面有沒有出現特定的標記來表示有票的,就是上面注入的JS代碼中的 checkHaveTicket 函數。之前是在 CefSharp控件的 IsBrowserInitializedChanged 事件中處理的,結果發現運行時偶發錯誤,而且是Win 10不報錯但是Win 8.1報錯:
相關UI訪問代碼會發生“線程間操作無效”的異常
推測是CefSharp控件的這些事件可能不一定運行在UI線程,在非UI線程啟動定時器那么定時器的“定時事件”也不在UI線程了,所以報錯。
其它問題和運行效果
本次更新增加了“聲音通知”功能,發現有票后會不斷播放音樂提示,以方便你不在電腦跟前也能知道。
這樣不論你是否在電腦跟前並且不想被刷票問題打擾,這就是本工具最大的優勢了,第一時間彈窗通知,不用時時刻刻去看。
最后關於安全問題,既然開源了,就不會有什么偷窺您隱私問題的可能性了,可以放心使用!
其它問題就沒有了,處理方式跟之前的彈窗工具一樣,代碼我已經簽入到了SOD的Github代碼庫中,地址如下:https://github.com/znlgis/sod
下面附帶一個運行測試效果圖:
下面是打開12306自動刷票功能的效果圖:
如果有問題,或者想獲取編譯好的程序包,請加QQ群:18215717 ,加群請注明暗號:博客園看到12306刷票工具
稍后我會放到CSDN下載頻道,請大家注意本篇博客文章的更新。
PS:
“安心刷票彈窗通知工具”現在集成到了 "PDF.NET集成開發工具"里面,所以這意味着你既可以用它來做一個輕量級的多種數據庫的查詢客戶端,也可以做一個簡單的谷歌瀏覽器。
注意:
雖然“SOD框架”是基於LGPL協議發布的開源軟件,但是集成開發工具屬於GPL開源協議,你可以自由的免費的使用本軟件,但不可以使用這個工具的源碼用作商業用途。SOD框架的其它部分源碼不在此限制范圍。
詳細問題請看PDF.NET框架官網 http://www.pwmis.com/sqlmap ,如果有問題請和我們聯系。