NX二次開發-C#使用DllImport呼叫libufun.dll裡的UF函式(反編譯.net.dll)呼叫loop等UF函式

Caesar盧尚宇發表於2020-09-29

在寫這篇文章的時候,我正在頭暈,因為下班坐車回家,有些暈車了。頭疼的要死。也吃不下去飯。

早就想些這篇文章了,但是最近臨近中秋十一,晚上太忙了。

版本:NX11+VS2013

最近這一年已經由C++過度到C#,改用C#做應用程式開發和NX二次開發。

C#在做複雜介面開發的時候,WinFrom要比MFC簡單的多(這個時候純BlockUI已經滿足不了整合功能的複雜介面需求了),資料庫連線也簡單。

言歸正傳

在我經過一段時間的看QQ群別人討論技術,給了我點啟發,以及帶著興趣百度到了一些相關資料。學會了這種方法。

1.有需求

在用C#做NX二次開發的時候,我們一般需要引用NX官方封裝好的的這幾個dll。

 用C#的,一般都是用NXOpen的比較多,用UF的比較少,因為UF官方封裝的不全,有很多沒有封裝。也因為C#用NXOpen語言上特別簡單,好用。

不需要delete,不需要迭代器,快速轉換成字串等等。

那麼在專案開發中,如果遇到loop這種官方沒有封裝的函式怎麼辦?

UF_MODL_ask_face_loops
UF_MODL_ask_loop_list_count
UF_MODL_ask_loop_list_item
UF_MODL_delete_loop_list

沒關係,官方沒有封裝的UF函式,我們可以直接去這5個dll裡呼叫。用DllImport去呼叫(是什麼,怎麼用請自行百度)。

libufun.dll
libnxopencpp.dll
libugopenint.dll
libnxopenuicpp.dll
libopenpp.dll

比如,我們現在想要呼叫UF_OBJ_set_color這個函式(這個函式官方已經封裝了,這裡只講呼叫是怎麼用的),給一個塊設定顏色。

2.反編譯C.dll

首先,找到這個函式,在上面5箇中的哪個dll裡。

這時就需要使用VC程式的反編譯工具Depends.exe這個工具了,按個開啟dll,去裡面找到看有沒有這個函式。

功能介紹:

檢視 PE 模組的匯入模組
檢視 PE 模組的匯入和匯出函式
動態剖析 PE 模組的模組依賴性
解析 C++ 函式名稱

等等

這裡我先開啟libufun.dll這個函式

 錯誤不用管,點確定關掉

 然後在這裡找看有沒有UF_OBJ_set_color

 已經找到了,我們知道了可以去這個dll裡調UF函式。

下一步我們要開始去C#裡呼叫,但是怎麼呼叫?不知道?對吧?

3.反編譯.net.dll

這個時候又需要另外一個反編譯dll工具了,dnSpy。

功能介紹:

dnSpy中文版是一款net程式反編譯工具,可以對net程式進行反編譯,還有替代庫文件的功能,如果遇到了程式碼丟失或者損壞的情況,可以直接恢復。還可以設斷點加程式除錯程式碼。

我們開啟後是這個樣子

 下面我們開啟官方封裝的C# NXOpen.UF這個dll,去反編譯下,看看裡面都寫了什麼。(dnSpy是可以反編譯別人寫的普通的C#exe和dll的,桌面應用程式和NX二次開發的C#程式都可以反編譯出來原始碼,只要不加殼,加殼能反編譯出部分程式碼)

開啟後如下

我們先去找到封裝的UF_OBJ_set_color這個函式

 這個時候我們就找到了,官方是怎麼呼叫,怎麼封裝的NXOpen.UF.dll的了,是有出處的。

4.我們如何呼叫

 我們把這句抄下來,去我們的NX C#專案中使用。

        [DllImport("libufun.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "UF_OBJ_set_color")]
        internal static extern int _SetColor(Tag object_id, int color);

先加名稱空間

using System;
using NXOpen;
using NXOpen.UF;
using System.Collections.Generic;//C# List<>的名稱空間
using System.Runtime.InteropServices;//DllImport的名稱空間

在新增一個類,寫程式碼

 然後在專案的Main入口函式裡寫程式碼。建立塊-特徵找體-設定顏色(用我們呼叫的函式)

//建立塊
FeatureSigns sign = FeatureSigns.Nullsign;//定義布林
double[] cornet_pt = { 100.0, 0.0, 0.0 };//定義原點
string[] edge_len = { "100.0", "100.0", "100.0" };//定義長寬高
Tag blk_obj_id = Tag.Null;
theUfSession.Modl.CreateBlock1(sign, cornet_pt, edge_len, out blk_obj_id);

//特徵找體
Tag BodyTag = Tag.Null;
theUfSession.Modl.AskFeatBody(blk_obj_id, out BodyTag);

NXOpen.Utilities.JAM.StartUFCall();

//設定顏色(呼叫UF函式)
OpenAPI._SetColor(BodyTag, 186);

NXOpen.Utilities.JAM.EndUFCall();

Caesar盧尚宇
2020年9月29日

在我們反編譯的程式碼中可以看到,在呼叫UF函式的時候,一定要用

NXOpen.Utilities.JAM.StartUFCall();和NXOpen.Utilities.JAM.EndUFCall();

這兩個方法來開始和結束,中間呼叫。執行才有效,要不然執行不起作用。有點類似UF的

UF_initialize和UF_terminate

下面來執行下,我們上面的程式碼。看看效果。答案是可以呼叫的。也是這種方法呼叫的。

5.如何呼叫loop等函式

好,現在我們已經知道怎麼呼叫函式了,現在我們去呼叫loop那些函式。可以借鑑下已經封裝的UF_MODL_ask_list_item是怎麼定義輸入輸出的。

NX11+VS2013


using System;
using NXOpen;
using NXOpen.UF;
using System.Collections.Generic;//C# List<>的名稱空間
using System.Runtime.InteropServices;//DllImport的名稱空間

public class OpenAPI
{
    [DllImport("libufun.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "UF_OBJ_set_color")]
    internal static extern int _SetColor(Tag object_id, int color);

    [DllImport("libugopenint.dll")]
    public static extern void uc1601(string msg, int mode);

    [DllImport("libufun.dll", EntryPoint = "UF_MODL_ask_face_loops")]
    public static extern void AskFaceLoops(Tag faceld, out IntPtr loopList);

    [DllImport("libufun.dll", EntryPoint = "UF_MODL_ask_loop_list_count")]
    public static extern void AskLoopListCount(IntPtr loop, out int count);

    [DllImport("libufun.dll", EntryPoint = "UF_MODL_ask_loop_list_item")]
    public static extern void AskLoopListItem(IntPtr loopList, int index, out int type, out IntPtr list);

    [DllImport("libufun.dll", EntryPoint = "UF_MODL_delete_loop_list")]
    public static extern void DeleteLoopList(out IntPtr loopList);

    [DllImport("libufun.dll", EntryPoint = "UF_MODL_ask_list_count")]
    public static extern void AskListCount(IntPtr list, out int count);

    [DllImport("libufun.dll", EntryPoint = "UF_MODL_ask_list_item")]
    public static extern void AskListItem(IntPtr list, int index, out Tag obj);

    [DllImport("libufun.dll", EntryPoint = "UF_MODL_delete_list")]
    public static extern void DeleteList(out IntPtr list);

    [DllImport("libufun.dll", EntryPoint = "UF_MODL_create_exp")]
    public static extern void CreateExp(string expr_str);
}


public class Program
{
    // class members
    private static Session theSession;
    private static UI theUI;
    private static UFSession theUfSession;
    public static Program theProgram;
    public static bool isDisposeCalled;

    //------------------------------------------------------------------------------
    // Constructor
    //------------------------------------------------------------------------------
    public Program()
    {
        try
        {
            theSession = Session.GetSession();
            theUI = UI.GetUI();
            theUfSession = UFSession.GetUFSession();
            isDisposeCalled = false;
        }
        catch (NXOpen.NXException ex)
        {
            // ---- Enter your exception handling code here -----
            // UI.GetUI().NXMessageBox.Show("Message", NXMessageBox.DialogType.Error, ex.Message);
        }
    }


    /// <summary>
    /// 獲取面的loop
    /// </summary>
    /// <param name="face">輸入面的tag</param>
    /// <param name="loops">輸出lopps連結串列</param>
    public static void MyAskFaceLoops(Tag face, out List<List<Tag>> loops)
    {
        NXOpen.Utilities.JAM.StartUFCall();
        loops = new List<List<Tag>>();
        IntPtr loopList = IntPtr.Zero;
        OpenAPI.AskFaceLoops(face, out loopList);

        int loopCount = 0;
        OpenAPI.AskLoopListCount(loopList, out loopCount);
        var listPtrList = new List<IntPtr>();
        for (int i = 0; i < loopCount; i++)
        {
            var tagList = new List<Tag>();
            int type = 0;
            IntPtr list = IntPtr.Zero;
            OpenAPI.AskLoopListItem(loopList, i, out type, out list);
            listPtrList.Add(list);
            int listCount = 0;
            OpenAPI.AskListCount(list, out listCount);
            for (int j = 0; j < listCount; j++)
            {
                Tag obj = Tag.Null;
                OpenAPI.AskListItem(list, j, out obj);
                tagList.Add(obj);
            }
            loops.Add(tagList);
            OpenAPI.DeleteList(out list);
        }
        OpenAPI.DeleteLoopList(out loopList);
        NXOpen.Utilities.JAM.EndUFCall();
    }


    //------------------------------------------------------------------------------
    //  Explicit Activation
    //      This entry point is used to activate the application explicitly
    //------------------------------------------------------------------------------
    public static int Main(string[] args)
    {
        int retValue = 0;
        try
        {
            theProgram = new Program();

            //TODO: Add your application code here 


            Tag aa = (Tag)47147;//通過移刀工具得到面的tag
            theUfSession.Obj.SetColor(aa, 1);

            //獲得面的所有loop
            List<List<Tag>> loops = new List<List<Tag>>();
            MyAskFaceLoops(aa, out loops);

            //高亮面的所有loop
            for (int i = 0; i < loops.Count; i++)
            {
                for (int j = 0; j < loops[i].Count; j++)
                {
                    theUfSession.Ui.DisplayMessage("1", 1);
                    theUfSession.Disp.SetHighlight(loops[i][j], 1);
                }
            }


            theProgram.Dispose();
        }
        catch (NXOpen.NXException ex)
        {
            // ---- Enter your exception handling code here -----

        }
        return retValue;
    }

    //------------------------------------------------------------------------------
    // Following method disposes all the class members
    //------------------------------------------------------------------------------
    public void Dispose()
    {
        try
        {
            if (isDisposeCalled == false)
            {
                //TODO: Add your application code here 
            }
            isDisposeCalled = true;
        }
        catch (NXOpen.NXException ex)
        {
            // ---- Enter your exception handling code here -----

        }
    }

    public static int GetUnloadOption(string arg)
    {
        //Unloads the image explicitly, via an unload dialog
        //return System.Convert.ToInt32(Session.LibraryUnloadOption.Explicitly);

        //Unloads the image immediately after execution within NX
        return System.Convert.ToInt32(Session.LibraryUnloadOption.Immediately);

        //Unloads the image when the NX session terminates
        // return System.Convert.ToInt32(Session.LibraryUnloadOption.AtTermination);
    }

}


Caesar盧尚宇
2020年9月29日

6.反編譯別人的NX二次開發.net.dll原始碼

這裡博主我不提倡隨便就去反編譯別人的原始碼,要尊重作者的開發成果。

至於什麼時候,反編譯,自行斟酌吧,哈哈~~。

在不加殼,加密的時候,.net很容易被反編譯,加殼也能去破解的,畢竟是託管語言,只要在中間就能反編譯,不像C++那種直接到記憶體中。

例子:就用我上面寫的loop例子,用DnSpy反編譯原始碼

 

 

 

Caesar盧尚宇

2020年9月29日

 

相關文章