最新消息

[公告2014/05/30] 如有需要將部落格中,任何一篇文章的程式碼使用在商業用途,請與我聯繫。

[公告2015/04/26] Line版的 iInfo程式與投資應用 群組已上線想加入的朋友們,請先查看 "入群須知" 再與我聯繫 Line : aminwhite5168,加入請告知身分與回答 "入群須知" 的問題。

[公告2018/04/22] 台北 Python + Excel VBA 金融資訊爬蟲課程,課程如網頁內容 金融資訊爬蟲班:台北班 Python 金融資訊爬蟲、EXCEL VBA 金融資訊爬蟲

[公告2019/01/08] 請注意:我再次重申,部落格文章的程式碼,是要提供各位參考與學習,一旦網頁改版請自行修改,別要求東要求西要我主動修改,你們用我寫東西賺錢了、交差了,請問有分我一杯羹嗎?既然賺錢沒分我,請問有什麼理由要求我修改,如果沒能力改,就花錢來找我上課。

[公告2019/12/01] 若各位有 Excel VBA 案子開發需求,歡迎與我聯繫,可接案處理。

[公告2020/05/22] 頁面載入速度慢,起因為部分JS來源(alexgorbatchev.com)失效導致頁面載入變慢,目前已做調整,請多見諒。

2013年8月25日 星期日

遠端偵錯(Remote Debug) --- VC6與Winpe 3.0 x86

開發程式時最常在實際發生問題的電腦上執行除錯,才能抓到真正Bug的Root cause。程式設計師常見的偵錯方式就是在有問題的程式碼中加入偵錯紀錄,這樣的做法往往是最沒有效率,但最也能達到除錯的效果。
其實微軟有提供很多程式開發的偵錯方法,其中之一就是用Visual Studio的Remote Debug,這樣功能其實存在已久,但知道的人多用的人少,這裡就來介紹如何去使用Remote Debug幫助程式開發上的偵錯。

Remote Debug先前準備
兩台電腦、網路線、Hub或IP分享器。

使用環境
Host 機器:安裝Win7 x86 + VC6
Target 機器:Winpe 3.0 x86

Host 機器IP:192.168.0.12
Target 機器IP:192.168.0.14

Host 機器與Target 機器的操作環境設定。
[準備VC6 Remote debug檔案]
檔名
路徑
Msvcmon.exe
C:\Program Files\Microsoft Visual Studio \Common\Msdev98\Bin
Dm.DLL
C:\Program Files\Microsoft Visual Studio \Common\Msdev98\Bin
Msdis110.dll
C:\Program Files\Microsoft Visual Studio \Common\Msdev98\Bin
Tln0t.dll
C:\Program Files\Microsoft Visual Studio \Common\Msdev98\Bin
Msvcrt.dll
C:\Windows\System32
msvcp60.DLL
C:\Windows\System32
Psapi.dll
C:\Windows\System32

[程式碼]
#include <Setupapi.h>
#pragma  comment(lib,"Setupapi.lib")
#include <cfgmgr32.h>

void GetErrorMessage(DWORD dwErrorMessageCode)
{
 CString strMsg;
 LPVOID lpMsgBuf;
 
 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  NULL,
  dwErrorMessageCode,
  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 預設語言
  (LPTSTR) &lpMsgBuf,
  0,
  NULL);
 
 strMsg.Format(_T("Error Message : %sError Code : 0x%X\n"), lpMsgBuf, dwErrorMessageCode);
 printf(strMsg);
 LocalFree(lpMsgBuf); // 記得free掉空間
}

BOOL Run()
{
 HDEVINFO hdev;
 DWORD idx;
 BOOL     bFound = FALSE;
 
 hdev = SetupDiGetClassDevs( NULL,
        NULL,
        0,
        DIGCF_PRESENT | DIGCF_ALLCLASSES);
 if (hdev == INVALID_HANDLE_VALUE )
 {
  printf("ERROR : Unable to enumerate device\n");
  return FALSE;
 }
 
 
 SP_DEVINFO_DATA  devinfo;
 devinfo.cbSize = sizeof(devinfo);
 
 for (idx = 0 ; SetupDiEnumDeviceInfo(hdev,idx,&devinfo); idx++)
 {  
  BYTE    Buffer[200];
  DWORD   BufferSize = 0;
  DWORD   DataType;
  int q=0;
  DWORD Status, Problem; 
  
  CONFIGRET cr = CR_SUCCESS;  
  
  printf("NO. %d\n", idx);
  cr = CM_Get_DevNode_Status(&Status, &Problem, devinfo.DevInst ,0);
  if ( CR_SUCCESS == cr) {
   printf("OK - CM_Get_DevNode_Status()[%d]\n", cr);
   printf("OK - CM_Get_DevNode_Status() sts [%x]\n", Status);
   printf("OK - CM_Get_DevNode_Status() pro [%x]\n", Problem);
  } else {
   printf("ERROR - CM_Get_DevNode_Status()[%d]\n", cr);
   printf("ERROR - CM_Get_DevNode_Status()[%d]\n", GetLastError());
  }
  
  if (SetupDiGetDeviceRegistryProperty(hdev,
   &devinfo,
   SPDRP_HARDWAREID,
   &DataType, 
   Buffer,
   sizeof(Buffer),
   &BufferSize)){
   printf("Hardware ID : %s\n", (const char *)Buffer);
  }
  
  if (SetupDiGetDeviceRegistryProperty(hdev, 
   &devinfo, 
   SPDRP_DEVICEDESC,
   &DataType, 
   Buffer, 
   sizeof(Buffer),
   &BufferSize)){
   printf("Hardware name : %s\n", (const char *)Buffer);
  }
  
  printf("\n");  
 }
 SetupDiDestroyDeviceInfoList(hdev);
 return TRUE;
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
 int nRetCode = 0;
 nRetCode = Run();
 return nRetCode;
}

[Host 機器]
Step 1. 建立Remote Debug用的帳號與密碼,切記一定要有"密碼"且權限設為"讀取/寫入",這樣的作法是為了方便在winpe下成功建立網路磁碟機用。

Step 2. 設定VC6上要連結Target 機器的IP,點選工具列"Build"、"Debugger Remote Connention..."

Step 3. 設定 Remote Connention。
  1. 點選"Connection"、"Network(TCP/IP)"。
  2. 點選"Settings..."


Step 4. 填入Target 機器的IP:192.168.0.14。

Step 5. 設定Project執行Remote debug所需的參數,點選工具列"Project"、"Settings..."。
[Debug分頁]
Executeable for debug session:C:\REMOTEDEBUG\RemoteDebugTest\Debug\RemoteDebugTest.exe【執行檔位置,Host電腦】
Working directory:Z:\【執行檔執行目錄,Remote電腦(Remote電腦step2.路徑)】
Program arguments:-lp
Remote executable path and file name:Z:\RemoteDebugTest\Debug\RemoteDebugTest.exe【執行檔位置,Remote電腦(Remote電腦step2.路徑)】

[Link分頁]
Output file name:C:\REMOTEDEBUG\RemoteDebugTest\Debug\RemoteDebugTest.exe【執行檔輸出的位置,Host電腦】

PS:執行專案進行Remote debug,第一次執行含有MFC class的VC6專案時,會出現警告提示缺少部分DLL,像MFC42D.DLL、MSVCP60D.DLL、MSVCRTD.DLL,皆可到C:\Windows\System32資料夾中找到,並請將以上DLL拷貝至執行檔的目錄下C:\REMOTEDEBUG\RemoteDebugTest\Debug\即可,其他若不含MFC class則無需添加。

[Target 機器]
Step 1. 安裝網路環境與複製檔案。
  1. 複製Debug所需的檔案至Target 機器。
  2. 由於Winpe3.0中並沒有支援全部廠商的網卡,所以需要安裝該機器可在Win7上所用網卡Driver。
  3. 關閉防火牆。
  4. 以Command,在Winpe3.0上建立網路磁碟機連線。
  5. Command:net use [磁碟機代碼] [網路資料夾來源] /user:[使用者帳號] [使用者密碼]。
將以上的步驟寫成Batch file直接使用。
if "%1"== "" echo Please entry filepath. && goto end

::設定環境變數
set filepath=%1

::切換路徑
X:
cd \

::建立Remote Debug資料夾並切換
mkdir RemoteDebug
cd RemoteDebug

::前面列表的準備檔案,複製到X:\RemoteDebug下
xcopy %filepath%:\VC6\*.* . /e /i /k /y 

::安裝LAN Driver
drvload LAN\rt86win7.inf

::關閉Winpe的防火牆,如此網路才能對外連結
wpeutil DisableFirewall

::Windows 7以後的版本都有此timeout.exe,可至C:\Windows\System32\下找到
::延遲7秒是為了讓Lan driver在安裝後可以正常執行,低於7秒將會導致後面無法建立網路磁碟機
timeout.exe 7

::建立網路磁碟機Z:
net use z: \\AMIN-PC\RemoteDebug /user:Amin5168 12345678

Msvcmon.exe

:End

Step 2. 啟動Msvcmon.exe與Host 機器連結。

Step 3. 按下 "Settings" 設定Host 機器 IP:192.168.0.12。

Step 4. 設定Host 機器 IP按下 "Connent"與Host 機器連結。

Step 5. 操作Host 機器機器上的程式碼,當成是偵錯時連結畫面將會消失,此時將會出現程式執行的畫面於Target 機器上。

如果以上設定Host 機器與Target 機器相關步驟都確實完成了,就可以透過Host 機器對Target 機器進行Remote Debug了。



沒有留言:

張貼留言