1. 程式人生 > >PCB InCAM 獲取 JOB STEP 實現外掛指令碼除錯功能實現

PCB InCAM 獲取 JOB STEP 實現外掛指令碼除錯功能實現

PCB CAM自動化基於Incam 打造,在測試時經常遇到除錯障礙,每次自行對功能測試時,生成了exe指令碼後,再到Incam裡面執行,發現問題,再回來修改程式碼,非常不爽, 參考Genesis除錯執行模式的方式,為了工程組寫指令碼除錯時用著爽,那就讓大家爽一下,,擴充套件了一下InCAM 除錯功能(即可以在Visual Studio 中可以加斷點邊調邊執行COM指令), 先採用類似Genesis一樣查詢JOB記憶體地址,結果碰壁了, 得尋找另外一種方式,發現InCAM每個窗品標題欄都含有JOB與STEP資訊,以這個為出發點就很好解決了.

 

一.獲取JOB名的方法(同時相容,內掛,外掛,區分Genesis,InCAM)

    寫好一個指令碼,可以外掛執行,也可以內掛執行

        /// <summary>
        /// 獲取JOB名
        /// </summary>
        /// <param name="JOB_Address"> 如是外掛使用時:填寫JOB基址</param>
        /// <returns></returns>
        public static string getJOB(int JOB_Address = _JOB_Address, int pid = 0) //
97b2 0x2FE623C 99b 0x0307BF84 { if (pid > 0) //pid 大於0為外掛啟用 { if (JOB_Address == 0) { JOB_Address = _JOB_Address; } g.JOB = API.ReadMemorystring(JOB_Address, pid); } else { if (gPID > 0
) { if (g.isInCam()) { string incamTitel = getWindowAllTiltel(); //獲取incam標題 呼叫下方的函數了 不能像Genesis一樣通過基址找到JOB地址呢 if (!string.IsNullOrEmpty(incamTitel)) { incamTitel = incamTitel.Replace(" ", " "); var arrList = incamTitel.Split(' '); g.JOB = arrList[8]; g.STEP = arrList[10]; } } else { g.JOB = API.ReadMemorystring(JOB_Address, gPID); } } else { if (JOB_Address == 0) { JOB_Address = _JOB_Address; } g.JOB = System.Environment.GetEnvironmentVariable("JOB"); } } return (g.JOB); } /// <summary> /// 模糊查詢標題 incam標題獲得JOB STEP名 /// </summary> /// <param name="TitlelName">InCAM v4</param> /// <returns></returns> public static string getWindowAllTiltel(string TitlelName = "InCAM v4") { string result = ""; StringBuilder sb = new StringBuilder(256); IntPtr desktopPtr = API.GetDesktopWindow(); IntPtr winPtr = API.GetWindow(desktopPtr, GetWindowCmd.GW_CHILD); while (winPtr != IntPtr.Zero) { winPtr = API.GetWindow(winPtr, GetWindowCmd.GW_HWNDNEXT); API.GetWindowTextW(winPtr, sb, sb.Capacity); if (sb.ToString().IndexOf(TitlelName) > -1) { result = sb.ToString(); winPtr = IntPtr.Zero; } } return result; }

 

二.用於查詢InCAM標題WindowsAPI

        /// <summary>
        /// 獲取視窗Text 
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="lpString"></param>
        /// <param name="nMaxCount"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern int GetWindowTextW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount);

        /// <summary>
        /// 該函式返回桌面視窗的控制代碼。桌面視窗覆蓋整個螢幕。桌面視窗是一個要在其上繪製所有的圖示和其他視窗的區域。
        /// 【說明】獲得代表整個螢幕的一個視窗(桌面視窗)控制代碼.
        /// </summary>
        /// <returns>返回值:函式返回桌面視窗的控制代碼。</returns>
        [DllImport("user32.dll", EntryPoint = "GetDesktopWindow", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr GetDesktopWindow();
        /// <summary>
        /// 該函式返回與指定視窗有特定關係(如Z序或所有者)的視窗控制代碼。
        /// 函式原型:HWND GetWindow(HWND hWnd,UNIT nCmd);
        /// </summary>
        /// <param name="hWnd">視窗控制代碼。要獲得的視窗控制代碼是依據nCmd引數值相對於這個視窗的控制代碼。</param>
        /// <param name="uCmd">說明指定視窗與要獲得控制代碼的視窗之間的關係。該引數值參考GetWindowCmd列舉。</param>
        /// <returns>返回值:如果函式成功,返回值為視窗控制代碼;如果與指定視窗有特定關係的視窗不存在,則返回值為NULL。
        /// 若想獲得更多錯誤資訊,請呼叫GetLastError函式。
        /// 備註:在迴圈體中呼叫函式EnumChildWindow比呼叫GetWindow函式可靠。呼叫GetWindow函式實現該任務的應用程式可能會陷入死迴圈或退回一個已被銷燬的視窗控制代碼。
        /// 速查:Windows NT:3.1以上版本;Windows:95以上版本;Windows CE:1.0以上版本;標頭檔案:winuser.h;庫檔案:user32.lib。
        /// </returns>
        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr GetWindow(IntPtr hWnd, GetWindowCmd uCmd);
    /// <summary>
    /// 視窗與要獲得控制代碼的視窗之間的關係。
    /// </summary>
    public enum GetWindowCmd : uint
    {
        /// <summary>
        /// 返回的控制代碼標識了在Z序最高階的相同型別的視窗。
        /// 如果指定視窗是最高階視窗,則該控制代碼標識了在Z序最高階的最高階視窗;
        /// 如果指定視窗是頂層視窗,則該控制代碼標識了在z序最高階的頂層視窗:
        /// 如果指定視窗是子視窗,則控制代碼標識了在Z序最高階的同屬視窗。
        /// </summary>
        GW_HWNDFIRST = 0,
        /// <summary>
        /// 返回的控制代碼標識了在z序最低端的相同型別的視窗。
        /// 如果指定視窗是最高階視窗,則該柄標識了在z序最低端的最高階視窗:
        /// 如果指定視窗是頂層視窗,則該控制代碼標識了在z序最低端的頂層視窗;
        /// 如果指定視窗是子視窗,則控制代碼標識了在Z序最低端的同屬視窗。
        /// </summary>
        GW_HWNDLAST = 1,
        /// <summary>
        /// 返回的控制代碼標識了在Z序中指定視窗下的相同型別的視窗。
        /// 如果指定視窗是最高階視窗,則該控制代碼標識了在指定視窗下的最高階視窗:
        /// 如果指定視窗是頂層視窗,則該控制代碼標識了在指定視窗下的頂層視窗;
        /// 如果指定視窗是子視窗,則控制代碼標識了在指定視窗下的同屬視窗。
        /// </summary>
        GW_HWNDNEXT = 2,
        /// <summary>
        /// 返回的控制代碼標識了在Z序中指定視窗上的相同型別的視窗。
        /// 如果指定視窗是最高階視窗,則該控制代碼標識了在指定視窗上的最高階視窗;
        /// 如果指定視窗是頂層視窗,則該控制代碼標識了在指定視窗上的頂層視窗;
        /// 如果指定視窗是子視窗,則控制代碼標識了在指定視窗上的同屬視窗。
        /// </summary>
        GW_HWNDPREV = 3,
        /// <summary>
        /// 返回的控制代碼標識了指定視窗的所有者視窗(如果存在)。
        /// GW_OWNER與GW_CHILD不是相對的引數,沒有父視窗的含義,如果想得到父視窗請使用GetParent()。
        /// 例如:例如有時對話方塊的控制元件的GW_OWNER,是不存在的。
        /// </summary>
        GW_OWNER = 4,
        /// <summary>
        /// 如果指定視窗是父視窗,則獲得的是在Tab序頂端的子視窗的控制代碼,否則為NULL。
        /// 函式僅檢查指定父視窗的子視窗,不檢查繼承視窗。
        /// </summary>
        GW_CHILD = 5,
        /// <summary>
        /// (WindowsNT 5.0)返回的控制代碼標識了屬於指定視窗的處於使能狀態彈出式視窗(檢索使用第一個由GW_HWNDNEXT 查詢到的滿足前述條件的視窗);
        /// 如果無使能視窗,則獲得的控制代碼與指定視窗相同。
        /// </summary>
        GW_ENABLEDPOPUP = 6
    }

 

三.InCAM實現外掛除錯效果

      錄製花屏了