2019年5月14日 星期二

在64位元環境下動態載入DLL



繼2011年發佈一篇文章
將非 COM 元件的外部 DLL ,包入 .NET 開發的執行檔中
直到現在又遇到問題了,趕緊寫下來記錄
本來專案都 Complier 成 x86,所以在64位元系統下仍然以 32位元在RUN,
但最近公司要求換成 AnyCPU,這下子就出問題了,

''原來的寫法,在64位元系統會取到 IntPtr 值為 0 的問題
    Friend Declare Function GetProcAddress Lib "kernel32" (ByVal ModuleHandle As Integer, ByVal ProcName As String) As Integer
    ''改成 IntPtr ,執行到 GetProcAddress 會有數學運算溢位的錯誤
    Friend Declare Function GetProcAddress Lib "kernel32" (ByVal ModuleHandle As Integer, ByVal ProcName As String) As IntPtr 
    

後來在
https://www.daniweb.com/programming/software-development/threads/207639/getprocaddress-and-function-pointers
的文章發現一個寫法,
    Friend Declare Function GetProcAddress Lib "kernel32" (ByVal ModuleHandle As IntPtr, <[In](), MarshalAs(UnmanagedType.LPStr)> ByVal lpProcName As String) As IntPtr


我一直以為在 64位元 GetProcAddress 回傳的值要改成 IntPtr,漏了傳入參數也要跟著換,
   '最後換成以下寫法就可以
   Friend Declare Function GetProcAddress Lib "kernel32" (ByVal ModuleHandle As IntPtr, ByVal ProcName As String) As IntPtr

換完後,好奇的我再試一下 x86 是否可以通用,
結果是可以的,再查了一下 IntPtr ,才發現這個元件根據 OS 的位元數,所回傳的值也會不同,
也就是從頭到尾只要統一用 IntPtr 就可以了,嗯~又學到一課了!

2019年1月24日 星期四

挑戰 9x9乘法表 練習小程式 (小學數學 加法,減法,乘法 練習)

為了小朋友的9x9乘法表練習,寫了一個挑戰9x9乘法表的小程式,
主要目的是訓練小朋友熟悉9x9乘法表,
可以選擇時間長度,最少1分鐘
再來是要做的題目數多少?


當點撃[開始挑戰] 按鈕時,會進入另一個答題畫面,

只要在答案欄中輸入答案,直接按下 Enter 就可以繼續下一題,
結束後會有統計資料,若是答題錯誤,在右邊的記錄欄可以清楚看到紅色標記

當時間有限,有時又要思考比較久,小朋友可以直接按下 Enter 讓答案空白,
在事後統計時,可以針對答錯的部份再多加練習。
程式中也加了一些音效,增加趣味性,希望小朋友願意多練習!

執行檔下載 (7z 檔案, 173 kB)
程式碼下載 (VB.Net 2015)



2019/10/28 更新
1. 新增加法,減法的練習
2. 新增測驗範圍設定畫面

在程式主畫面中,點選題目範圍的綠色框內容,會跳出設定畫面
預設 加減法最大到99,乘法最大數到10


設定題目最大的數目,若勾選加入測驗,
則出題會包含所選的算式,

如果回答錯誤,右邊記錄欄會順便把正確解答放在後面


V1.0.1.1 執行檔下載 (7z 檔案, 181 kB)
V1.0.1.1 程式碼下載 (VB.Net 2015) (7z 檔案, 162 kB)

檔案壓縮為 7Z 若無法解壓縮請到官網自行下載軟體安裝(免費). https://www.developershome.com/7-zip/

2018年12月7日 星期五

System.IO.Directory.GetFiles 在 C:\ 槽和其它磁碟槽取得的檔案名稱數量不同

一支用很久的程式,今天客戶突然報案說開啟有錯誤發生,
問題是相同的設定檔和檔案,為何在我電腦不會有錯,在客戶端會發生錯誤,
剛好同事也提到,同樣的檔案放到他家裡電腦也發生同樣的錯誤,但在公司電腦不會,
這下子激起我的好奇心想一探究竟。

請同事把發生問題的檔案給我,讓我試試,
因為 Skype 傳來的檔案,我預設放 C:\
結果開啟真的出錯,我再把檔案放到開發專案磁碟槽準備 Debug 結果正常沒錯誤!見鬼了....

將專案 Copy 一份到 C:\ 同時開啟後進入 Debug Mode 看怎麼回事,
看來真的採到 Microsoft 的雷了!

首先在 C:\ 和另一個磁碟槽建立測試用檔案
我把檔案放在 C:\ 和 E:\


然後將程式中斷,在 [即時運算視窗] 中,把資料印出來,
可以發現檔案數量不同,(F3.xml.123 是屬於副檔名 123 不是 XML 所以不會被列出來)
? System.IO.Directory.GetFiles("C:\DEMO_TEST", "*.XML", SearchOption.TopDirectoryOnly)
{Length=5}
    (0): "C:\DEMO_TEST\F1.xml"
    (1): "C:\DEMO_TEST\F2.xml"
    (2): "C:\DEMO_TEST\F3.xml"
    (3): "C:\DEMO_TEST\F3.xml_123"
    (4): "C:\DEMO_TEST\F3.xml123"
? System.IO.Directory.GetFiles("E:\DEMO_TEST", "*.XML", SearchOption.TopDirectoryOnly)
{Length=3}
    (0): "E:\DEMO_TEST\F1.xml"
    (1): "E:\DEMO_TEST\F2.xml"
    (2): "E:\DEMO_TEST\F3.xml"


我同時用 System.IO.Directory.GetFiles 還有 System.IO.Directory.EnumerateFiles 兩個寫法測試,結果一樣,
        '使用 GetFiles 方式
        For Each strFileName As String In System.IO.Directory.GetFiles("E:\DEMO_TEST", "*.XML", SearchOption.TopDirectoryOnly)
            Debug.Print(strFileName)
        Next
        '使用 EnumerateFiles 方式
        Dim fn As Object = System.IO.Directory.EnumerateFiles("E:\DEMO_TEST", "*.XML", SearchOption.TopDirectoryOnly)
        For Each strFileName As String In fn
            Debug.Print(strFileName)
        Next

查了一下官網的 System.IO.Directory.GetFilesSystem.IO.Directory.EnumerateFiles 說明,
原來兩個 SearchPattern 作用相同,難怪結果一樣,

當 SearchPattern 設定的 Extension(副檔名) 剛好為三個字元,
會同時將副檔名符合的三個字元以外的其它檔案也一並找出來,
造成 .XMLxxx 的副檔名都一起被列出來了,
所以官網上的說明符合 C:\ 搜尋的結果,但和我電腦上其它磁碟槽的結果不符!

這個問題還真是擾人呀,
趕快把這個問題記錄下來,不然下次忘記又要踩雷了!!


2018年9月14日 星期五

多執行緒中的多執行緒錯誤


早先遇到一個問題,最近又被問到同樣問題,先做個記錄.

主程式 Load 一個 DLL 檔進來,而 DLL 內有個 Form ,
Form 裡面又用到另一個 COM 元件或另一執行緒,這時會出現以下錯誤 :
[ 目前的執行緒必須先設為單一執行緒 Apartment (STA) 模式,才能進行 OLE 呼叫。請確認您的 Main 函式上已經標記有 STAThreadAttribute ]

解決方式為

1. 在 Class 中先宣告一個全域變數

    ''宣告一個全域變數
    Dim _threadForm As Threading.Thread


2. 加入 Delegate 委派呼叫
    ''--- 寫法一 直接帶參數的委派呼叫
    Private Delegate Sub OpenFormCallback(frm As Windows.Forms.Form)
    Private Sub OpenForm(frm As Windows.Forms.Form)
        If frm.InvokeRequired Then
            frm.Invoke(New OpenFormCallback(AddressOf Me.OpenForm), New Object() {frm})
        Else
            frm.ShowDialog()
        End If
    End Sub
    ''--- 寫法二 不帶參數的委派呼叫
    'Private Delegate Sub OpenFormCallback()
    'Private Sub OpenForm()
    '    If FormObject.InvokeRequired Then
    '        FormObject.Invoke(New OpenFormCallback(AddressOf Me.OpenForm), New Object() {})
    '    Else
    '        FormObject.ShowDialog()
    '    End If
    'End Sub



3. 在要呼叫的 Function 中寫
''--- 寫法一 直接帶參數的委派呼叫
 _threadForm = New Threading.Thread(Sub() Me.OpenForm(Me.FormObject))
''--- 寫法二 不帶參數的委派呼叫
'_threadForm = New Threading.Thread(AddressOf OpenForm)

 _threadForm.SetApartmentState(Threading.ApartmentState.STA) '將執行緒指定為單一執行緒
 _threadForm.Start()


以上,打完,收工,做記錄!

2017年8月9日 星期三

GPS 導航 APP 比較及試用心得

最近因為舊手機 HTC D500 換電池,要測試電池是否能用,順便裝GPS導航軟體比較一下,
所以拿目前的 ASUS PadFone S 一起測試,

我主要是以評分較優的為主要測試目標,另外再以其它主流導航軟體比較
首先裝了
Karta GPS - 離線導航  另一支手機安裝   導航Polnav mobile

Karta GPS 若是晚上使用,會自動轉成夜間模式,
另外超速時,會有嗶聲提示,轉彎處也會播路名,

白天模式   夜間模式


同一路段兩個導航畫面比較

Karta GPS  導航Polnav



Karta GPS  導航Polnav

導航Polnav 還多了休息站及交流道提示
不過,,導航Polnav若要播報路名和測速相機,就要另外購買套件,
但價格都比任何一家導航便宜,
路名播報 $60 , 測速相機 $90,即時路況 $65 ,進階 $90
這些我都沒買,所以沒法測試。

兩者比較:
Karta GPS 的路徑規劃較容易導到巷弄中,在重新規劃路徑時很容易迷路,操作介面不太友善,有很大的進步空間 (直接淘汰)
導航Polnav的路徑規劃是我測試以來算是較優秀的,畫面資訊也詳細,所以決定最後 PK 賽,就以這版來比較其它導航軟體



接下來再測試

Waze (位智)社群導航、地圖與交通另一支手機安裝樂客導航王N5
(我是裝 N3 舊版的,拿N5的圖和連結來用)

先來看兩者在同一路段的比較

Waze (位智)   PAPAGO!

Waze (位智)   導航王


Waze (位智)還有一個特色,就是我把車停好後,走路到某定點,它會記錄車子停放的位置,對於找車很方便

不過,Waze (位智)在程式起來和結束都會一直連網路,送一堆東西,不知道背後送了什麼出去,心理總是毛毛的。


兩者比較:
Waze (位智)的地圖在很多較小的巷子或較少車子開的雙線道並沒有記錄,所以導航會稍微多繞一點路,但都以大馬路為主,所以差異不大,
語音是中國口音及語法,會播報 [前方兩百米處,向右拐,再向右拐,然後直行] 或是 [前方有攝像頭], 但不會播報路名和限速,路線規劃能力比其它導航軟體差(直接淘汰)

導航王在主要路口和交流道,都會有圖示提醒如何轉彎或顯示路線,路線規劃還是會導到巷弄中,但還可以接受,他的測速提示就做得不錯,



再來輪到 PAPAGO 了, 我拿第一輪的導航Polnav來比較
導航PAPAGO!Taiwan體驗版-GOLiFE    VS   導航Polnav mobile

(楠梓百幕達)
導航PAPAGO!   導航Polnav

導航PAPAGO!   導航Polnav

導航PAPAGO!   導航Polnav

兩者比較:

PAPAGO! 主要路口和交流道有更貼心的圖示警告,和導航王一樣,也有速限和測速警告

導航Polnav路線規劃能力差不多,若故意開錯路,重新規劃的速度到是比 PAPAGO 要快得多



整體比較

路徑規劃 : 導航Polnav(優) >  PAPAGO! > 導航王 > Waze(位智) > Karta GPS
畫面美觀 : 導航王(優) > PAPAGO! > 導航Polnav > Waze(位智) > Karta GPS
操作方便 : 導航Polnav(優)  > 導航王 > PAPAGO! > Karta GPS > Waze(位智)
開機速度 : Karta GPS > PAPAGO! = 導航王 > Waze(位智) > 導航Polnav (最慢)
規劃速度 : 導航Polnav(優) > PAPAGO! > 導航王 > Karta GPS > Waze(位智)
路線優異 : 導航Polnav(優) > PAPAGO! > 導航王 > Karta GPS > Waze(位智)

目前的測試結果,
我會考慮花錢買的導航軟體應該是
1.  導航Polnav (最便宜,效果也還可以接受)
2. 再來會是 PAPAGO!
3. 最後是 導航王 ,
不過我用了導航王的語音,感覺很方便,只是辨識率不高,常會找不到,下次要來試 PAPAGO 的語音,看哪一個比較好用。

後續若有測試再補上結果!