前言 年初四月份的時候,有朋友找到我,說想開發一個模擬點擊的軟體。最終軟體做完後,發現效果不理想。唯一開發的我是認為最好是放棄了,做運營的他,堅持說這個沒問題,說是改變合作方式。最終也是不了了之了。 不過,在這中間經歷了一次重寫,三次核心方法的變更,無數次的查資料,找解決辦法至凌晨。中間穿插了無數次 ...
前言
年初四月份的時候,有朋友找到我,說想開發一個模擬點擊的軟體。最終軟體做完後,發現效果不理想。唯一開發的我是認為最好是放棄了,做運營的他,堅持說這個沒問題,說是改變合作方式。最終也是不了了之了。
不過,在這中間經歷了一次重寫,三次核心方法的變更,無數次的查資料,找解決辦法至凌晨。中間穿插了無數次的討論修改,修改討論。雖然功能很簡單,但是也花費了三個月的心血。心想,還是想好好總結一下。最後的軟體界面如下:
實現思路&使用控制項
首先,在內置瀏覽器裡面打開網頁,通過Javascript 獲取需要的點擊的坐標位置;計算網頁中的坐標,在屏幕中的坐標位置;通過模擬滑鼠的操作(滾動滑輪,移動,點擊);以及隨機的二次點擊。最後再清除緩存,更換IP,更換解析度,以及User-Agent。來達到欺騙網站,認為是不同的人來點擊的目的。
使用的具體方法,如下:
- 內置瀏覽器,CefSharp 49.0 為了相容.NET 4.0,大部分Win7可以直接使用;
- 滑鼠,鍵盤模擬輸入,InputSimulator , 最早之前是直接調用Windows API的,沒有這個好用;
- 切換IP,兩種ADSL切換 和 IP精靈軟體(ADSL 這個目前沒有使用的,DotRas.dll);
- 切換解析度,是直接拿Github上面代碼直接用。ScreenResolutionChanger;
- License 使用 EasyLicense;
- 本地資料庫SQLite;
- 代碼混淆 .NET Reactor;
小小的記錄
殺毒軟體的坑:使用模擬輸入的時候,一直提示 User Interface Privilege Isolation(用戶界面特權隔離) 的問題,許可權不夠。試了關閉Windows的UAC,用超級管理員啟動,給軟體加數字證書,放到C盤系統目錄等等。各種方法都試了就是無法模擬操作。實在沒辦法了,然後在豬八戒上面發佈任務,放上Demo。萬萬沒想到,一個大學生給我解決了,是因為360等殺毒軟體導致的。。。。
IP精靈DLL版本的坑:最開始用的他們官網提供的dll,發現他們那個dll基本用不起來,好像是許久不更新了。另外,狀態編碼也會隨意改變,也不發更新通知。造成也結果就是,明明以前好好的,怎麼今天就突然用不起來了。
ADSL測試的坑:代碼寫好後無法測試,或者測試起來很麻煩。現在這年代用ADSL撥號上網的越來越少了,同樣想測試也麻煩。好不容易找了個遠程的ADSL主機,結果一測試就斷網,尷尬。。。
獲取網路時間:為了避免用戶直接修改系統時間,來達到突破License 。獲取到 大門戶網站 http header 中的 date 來檢驗本地時間是否準確。在這中間,我發現大陸封殺了好多的時間同步的網站,只有一兩個能用,又極度不穩定,並且中科院的又用不起。坑貨!!
SQLite小巧玲瓏:之前第一個版本用 純文本來存放配置文件,記錄日誌信息。極度不方便,容易出現數組越界這樣的bug。後來採用sqlite後,才發現了開發的美好。sqlite擁有完整的sql那一套東西,並且體積又小,不用安裝,非常適合做本地少量信息的存儲。
屏幕解析度:最開始是手動實現windows api 來獲取列表,改變解析度的,bug又多又不完善。某天靈光一閃,在github上面找了一下真還有這個代碼,省了不少事情。另外,我還發現wiki上面寫的,顯示解析度列表 總共只有那麼幾十個,可見解析度的大小,不是隨意寫的。但是通過windows api 獲取到的列表 就一大堆有幾百個。我分析,是因為解析度,色深,赫茲。這三個參數排列組合導致的。
Cefsharp文檔的重要性:清除緩存,清除cookie,Storage。設置彈出方式,重寫http header,執行javascript等等。一系列的內置瀏覽器的操作,都是看github上面的wiki,以及google看英文文檔(baidu就是坑爹貨,同樣的文章,轉來轉去;一般第一頁80%廣告,前三頁都是同樣的內容,剩下的風馬牛不相及)。沒有別人幫助,只有硬著頭皮翻譯一點看一點,然後寫代碼試。如果找不到實現方法,也要去看看為什麼不能實現。記錄一些,我認為比較重要的地方:
- ILifeSpanHandler 控制Cefsharp彈出的視窗 事件。(DoClose,OnAfterCreated,OnBeforeClose,OnBeforePopup)
- IRequestHandler 控制Cefsharp發送請求的事件,太多了不一一列舉。
- Cef.Initialize 只能初始化一次,如果想徹底清除緩存,必須關閉宿主程式。 如果在主程式內,調用Cef.Shutdown 後再次初始化會報錯的。49.0版本有這個問題,後續的版本修複了這個問題。
- 執行 js 的時候,要註意鎖的問題,使用 Monitor 更加精細的控制。
- 重新翻譯了github上部分Cefsharp文檔。
WinForm開發:第一次寫winform程式,認為是小程式,各種粗製濫造。尤其是到後期,主窗體代碼到達一兩千行,邏輯調用混亂,真心看不下去了,修改起來的很費勁。乾脆重新寫吧。重新設計文檔目錄,窗體拆分,代碼分類,左搞右搞,總算勉強能看,但是今天又把代碼翻出來看了看,總感覺什麼地方不對,又說不出是哪裡不對。。。
- 線程的重要性,寫慣了web,極少情況考慮線程的問題。但是在桌面程式裡面,線程是非常重要的問題,尤其是非主線程操作UI界面的時候。
- 事件的運用,同樣,在桌面程式裡面,事件使用起來非常舒服。以前對代理,事件也僅僅知道概念。實踐之後,才知道這個是多麼優秀的設計。
- VS 所見即所得的窗體設計界面,由於 Cefsharp 運行時載入控制項的,也就是開發時設計界面打不開。這也算一點小麻煩。
- 通過句柄的操作。 主要獲得主界面句柄,獲取按鈕句柄,然後SendMessage,來觸發按鈕事件。還有就是,win7 之前和之後的SendMessage 大有不同,要註意。
輔助進程啟動:由於Cef必須完全關掉宿主進程,才可以徹底清除緩存。所以,當時就採用了,輔助進程來重啟主進程。這個比較簡單,涉及到Process的一些操作,為了方便易用,同時還設計了熱鍵功能。
License 註冊:這個比較簡單,參照demo。我獲取的是本機的CPU序列號,主板序列號,硬碟的ID(為什麼不是序列號,因為硬碟市場參差不齊,還有的廠家不存在序列號)。為了防止被猜到,我隨便加了點料(當時的真實感受)。最後MD5加密,提取哈希值。如下圖:
總結
- 經過這麼一折騰,深深得感覺到,程式員主要作用是在組裝代碼的:把不相干的代碼有機的拼裝在一起,組成一個可以使用的軟體。
- 善於利用google,github,stack overflow,基本能解決99%的技術問題。
- 英語非常非常重要,百度非常非常坑。
- 實在頭疼腦熱的時候,不舒服的時候,不如去休息。
- 需求的確認,這是非常重要的事情。