[VB6] 模擬 Process 類別

話說,上周接到個任務,要改個舊的 VB6 程式碼,裡面要呼叫執行檔進行圖檔格式轉換。

以前在 VB6 中呼叫執行檔,基本上就是用 Shell 或是呼叫 API ShellExecute,但 VBNET 裡面的 Process 實在太方便了,專案結束時間還非常充足,不由自主想要將此功能模擬出來,讓我寫 VB6 時也能依照目前習慣進行。

比較精簡的 Process 類別原始碼參考此處:cProcess

由於要支援 MainWindowHandle ,所以把呼叫關於 Window 功能的 API 也整理兩個放上去:modWindow

裡面有點心得值得記載…

1. CreateProcess

首先參考:http://support.microsoft.com/kb/129797

裡面第一個參數 lpApplicationName 使用 vbNullString ,我在 Windows 2008 / Windows 7 中,放入執行檔路徑,lpCommandLine 使用命令列參數,可正常執行,很開心地寫成我認為應該是對的版本 (註解掉的那行):
Friend Function Start(ByVal ExeFile As String, Optional ByVal CommandLine As String = vbNullString, Optional ByVal WorkDirectory As String = vbNullString, Optional ByVal ShowWindowFlags As enuShowWindow = SW_SHOWNORMAL, Optional ByVal TimeoutMilliseconds As Double = –1) As cProcess
Dim sInfo As STARTUPINFO
Dim sNull As String
Dim npv As processValue
Dim sec1 As SECURITY_ATTRIBUTES, sec2 As SECURITY_ATTRIBUTES

sec1.nLength = Len(sec1)
sec2.nLength = Len(sec2)
sInfo.cb = Len(sInfo)
sInfo.dwFlags = STARTF_USESHOWWINDOW
sInfo.wShowWindow = ShowWindowFlags
pv = npv

‘ lSuccess = CreateProcess(ExeFile, CommandLine, sec1, sec2, True, NORMAL_PRIORITY_CLASS, 0&, WorkDirectory, sInfo, pi) ‘ WinXP 不支援,Win7 支援
lSuccess = CreateProcess(vbNullString, ExeFile & " “ & CommandLine, ByVal 0&, ByVal 0&, True, NORMAL_PRIORITY_CLASS, 0&, WorkDirectory, sInfo, pi) ‘ WinXP 支援
If lSuccess = 0 Then errCode = GetLastError
CheckExitCode

If TimeoutMilliseconds > 0 Then
   Dim tf As Currency, sc As Currency, nc As Currency
tf = cPerformanceFrequency * TimeoutMilliseconds / 1000
QueryPerformanceCounter sc

    Do
DoEvents
WaitForExit 1
QueryPerformanceCounter nc
       If pv.IsExit Then
          Exit Do
       ElseIf (nc – sc) > tf Then
CloseMainWindow
          If Not pv.IsExit Then Kill
          Exit Do
      End If
   Loop

pv.WaitMilliseconds = (nc – sc) / cPerformanceFrequency
End If

Set Start = Me
End Function

好啦,拿回 WinXP Embedded 上跑,阿勒?不能跑?沒關係,上面有 VB6 IDE ,在上面除錯,還是找不到問題,最後把被呼叫的程式加入命令列內容輸出,才發現參數沒了…

回想到 KB 的範例,只好改成跟 KB 一樣,然後就能順利跑了… 我懷疑是 WinXP 的 API 在處理 lpApplicationName 的時候加入多個 Chr(0) 字元,所以組 lpCommandLine 時,會把 Chr(0) 當成字串結尾,只好改成沒註解那行才能正常執行。

另外,在使用 ShowWindow 常數時,Windows Vista / Windows 2008 / Windows 7 都沒正常跑,我想應該是 Vista 以後的安全管理機制造成,暫時沒空管,先放著。

2. MainWindowHandle

這個功能因為我除了從 EnumWindows 回頭透過 GetWindowThreadProcessId 來抓主視窗的 ProcessId 比對外,想不到用啥方法比較好。所以只好 .Net Reflector 來看,沒想到居然要升級到 6.x ,而且還要註冊… 搞個註冊拿到啟動序號繼續用,Process 類別是用 EnumThreadWindows ,這個 API 以前沒用過,看了一下 MSDN 說明,這個是抓執行緒建立的 hWnd ,很省效能,看人家的程式碼還是很能學習到東西。

那就順便一起看 Proces.Start 的程式碼,.Net framework 會呼叫 CreateProcess ,若失敗會改呼叫 ShellExecute ,這部分也懶得改了,以後需要時再改~

Categories: 工作點滴, 技術分享 | 發表留言

文章導覽

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 變更 )

Twitter picture

You are commenting using your Twitter account. Log Out / 變更 )

Facebook照片

You are commenting using your Facebook account. Log Out / 變更 )

Google+ photo

You are commenting using your Google+ account. Log Out / 變更 )

連結到 %s

在 WordPress.com 建立免費網站或網誌.

%d 位部落客按了讚: