国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
C#調用非托管程序5種方式

C#調用非托管程序5種方式

 

1、COM調用
COM應該是非托管組件重用最重要的方式,特別是調用微軟的COM組件。
可以用VS添加引用的方式自動生成包裝類,也可以用Tlbimp.exe實用工具包裝COM對象生成包裝類。
COM對象需要在本機注冊,這個程序部署帶來一定的麻煩,如果調用簡單的功能,包裝COM有點大材小用。
如果只簡單的調用非托管函數(shù),可以用接下來介紹的DllImprot等方式。

  1. using System;  
  2. using OLEPRNLib;  
  3.  
  4. namespace PrinterStatus  
  5. {  
  6.     class Class1  
  7.     {  
  8.         [STAThread]  
  9.         static void Main(string[] args)  
  10.         {  
  11.             string[] ErrorMessageText = new string[8];  
  12.  
  13.             ErrorMessageText[0] = "service requested";  
  14.             ErrorMessageText[1] = "offline";  
  15.             ErrorMessageText[2] = "paper jammed";  
  16.             ErrorMessageText[3] = "door open";  
  17.             ErrorMessageText[4] = "no toner";  
  18.             ErrorMessageText[5] = "toner low";  
  19.             ErrorMessageText[6] = "out of paper";  
  20.             ErrorMessageText[7] = "low paper";  
  21.  
  22.             int DeviceID = 1;  
  23.             int Retries = 1;  
  24.             int TimeoutInMS = 2000;  
  25.             string CommunityString = "public";  
  26.             string IPAddressOfPrinter = "10.3.0.93";  
  27.  
  28.             // Create instance of COM object  
  29.             OLEPRNLib.SNMP snmp = new OLEPRNLib.SNMP();  
  30.  
  31.             // Open the SNMP connect to the printer  
  32.             snmp.Open(IPAddressOfPrinter, CommunityString, Retries, TimeoutInMS);  
  33.  
  34.             // The actual Warning/Error bits  
  35.             uint WarningErrorBits = snmp.GetAsByte(String.Format("25.3.5.1.2.{0}", DeviceID));  
  36.  
  37.             // The actual Status  
  38.             uint StatusResult = snmp.GetAsByte(String.Format("25.3.2.1.5.{0}", DeviceID));  
  39.  
  40.             // uint Result2 = snmp.GetAsByte(String.Format("25.3.5.1.1.{0}", DeviceID));  
  41.  
  42.             string Result1Str = "";  
  43.             switch (StatusResult)  
  44.             {  
  45.                 case 2: Result1Str = "OK";  
  46.                     break;  
  47.                 case 3: Result1Str = "Warning: ";  
  48.                     break;  
  49.                 case 4: Result1Str = "Being Tested: ";  
  50.                     break;  
  51.                 case 5: Result1Str = "Unavailable for any use: ";  
  52.                     break;  
  53.                 default: Result1Str = "Unknown Status Code : " + StatusResult;  
  54.                     break;  
  55.             }  
  56.  
  57.             string Str = "";  
  58.             if ((StatusResult == 3 || StatusResult == 5))  
  59.             {  
  60.                 int Mask = 1;  
  61.                 int NumMsg = 0;  
  62.                 for (int i = 0; i < 8; i++)  
  63.                 {  
  64.                     if ((WarningErrorBits & Mask) == Mask)  
  65.                     {  
  66.                         if (Str.Length > 0)  
  67.                             Str += ", ";  
  68.                         Str += ErrorMessageText[i];  
  69.                         NumMsg = NumMsg + 1;  
  70.                     }  
  71.                     Mask = Mask * 2;  
  72.                 }  
  73.             }  
  74.             Console.WriteLine(Result1Str + Str);  
  75.         }  
  76.     }  


2、DllImport
DllImport是在"System.Runtime.InteropServices"命名空間中定義的特性。

  1. [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "MessageBox")]  
  2. public static extern int InvokeMessageBox(IntPtr hWnd, String text, String caption, uint type);  
  3.  
  4. static void Main()  
  5. {  
  6.     InvokeMessageBox(new IntPtr(0), "對話框內容""對話框標題", 0);  


3、加載非托管動態(tài)鏈接庫
Win32中,有個LoadLibrary(string file)函數(shù),加載動態(tài)鏈接庫;GetProcAddress函數(shù)動態(tài)調用導出函數(shù)。
.NET類庫的 Marshal.GetDelegateForFunctionPointer 方法能將非托管函數(shù)指針轉換為委托。

  1. public delegate int MsgBox(int hwnd,string msg,string cpp,int ok);  
  2. [DllImport("Kernel32")]  
  3. public static extern int GetProcAddress(int handle, String funcname);  
  4. [DllImport("Kernel32")]  
  5. public static extern int LoadLibrary(String funcname);  
  6. [DllImport("Kernel32")]  
  7. public static extern int FreeLibrary(int handle);  
  8.  
  9. private static Delegate GetAddress(int dllModule, string functionname, Type t)  
  10. {  
  11.     int addr = GetProcAddress(dllModule, functionname);  
  12.     if (addr == 0)  
  13.         return null;  
  14.     else  
  15.         return Marshal.GetDelegateForFunctionPointer(new IntPtr(addr), t);  
  16. }  
  17.  
  18. private void button1_Click(object sender, EventArgs e)  
  19. {  
  20.     int huser32 = 0;  
  21.     huser32 = LoadLibrary("user32.dll");          
  22.     MsgBox mymsg = (MsgBox)GetAddress(huser32, "MessageBoxA"typeof(MsgBox));  
  23.     mymsg(this.Handle.ToInt32(), txtmsg.Text, txttitle.Text , 64);  
  24.     FreeLibrary(huser32);  


4、DynamicMethod
可以使用 DynamicMethod 類在運行時生成和執(zhí)行方法,而不必生成動態(tài)程序集和動態(tài)類型來包含該方法。動態(tài)方法是生成和執(zhí)行少量代碼的最有效方式。

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using Zealic.Windows;  
  5.  
  6. namespace ConsoleApplication1  
  7. {  
  8.     class Program  
  9.     {  
  10.         static void Main(string[] args)  
  11.         {  
  12.             //測試1  
  13.             DynamicLibrary hilib = new DynamicLibrary("hi.dll");  
  14.             NativeMethodBuilder hiBuilder = new NativeMethodBuilder();  
  15.             NativeMethod method = hiBuilder.MakeMethod(hilib, "func");  
  16.             Console.WriteLine("請關閉彈出的對話框 'Hille'");  
  17.             method.Invoke();  
  18.             hilib.Free();  
  19.  
  20.             //測試2  
  21.             DynamicLibrary krnlib = new DynamicLibrary("kernel32.dll");  
  22.             NativeMethodBuilder beepBuilder = new NativeMethodBuilder();  
  23.             beepBuilder.ParameterLength = 2;  
  24.             beepBuilder.SetParameterInfo(0, typeof(int));  
  25.             beepBuilder.SetParameterInfo(1, typeof(int));  
  26.             method = beepBuilder.MakeMethod(krnlib,"Beep");  
  27.             Console.WriteLine("聽,你的機器在尖叫!");  
  28.             method.Invoke(1000, 1000);  
  29.             Console.WriteLine("按任意鍵退出!");  
  30.             Console.ReadKey(true);  
  31.         }  
  32.     }  


5、直接調用執(zhí)行機器碼
機器碼是最原始的程序代碼,或稱指令,把這些指令裝載到內存,Marshal.GetDelegateForFunctionPointer方法轉換為對應的委托,調用即可。

  1. /*  
  2.       
  3.     執(zhí)行調用本機代碼、匯編代碼 shell Native Code  
  4.  
  5.     解釋  
  6.         本例中 IntPtr 其實是相當于 C 語言中的 (void *) 指向任何類型的指針,  
  7.             就是一個地址 32 位系統(tǒng)就是個 Int32,本例相當與一個函數(shù)指針  
  8.  
  9.     核心技術流程  
  10.         變量:  
  11.             【本機代碼字節(jié)數(shù)組】 byte[] codeBytes ; 一段加法本機代碼  
  12.             【函數(shù)指針】 IntPtr handle ; 指向本機函數(shù)開始地址的變量  
  13.         流程:  
  14.               
  15.         >> 給 【函數(shù)指針】劃分非托管內存 ; 使用 Marshal.AllocHGlobal(codeBytes.Length)  
  16.                 劃分大小等同于本機代碼字節(jié)總數(shù)    因為函數(shù)本身還不存在于內存中所以先開辟一塊內存;  
  17.                 以便放置函數(shù)。  
  18.                   
  19.         >> 將 【本機代碼字節(jié)數(shù)組】中的字節(jié)寫入 【函數(shù)指針】 ;  
  20.                 Marshal.Copy(codeBytes,0,handle,codeBytes.Length);  
  21.  
  22.           
  23.         >> 使用 Marshal.GetDelegateForFunctionPointer 【函數(shù)指針】 強制轉換為托管委托 DelegateAdd;  
  24.                 因為這時 handle 內的字節(jié)數(shù)組已經是內存中的一段本機方法的代碼  
  25.                 handle 的“起始地址”就相當于一個“本機函數(shù)的入口地址”  
  26.                 所以可以成功轉換為對應的委托  
  27.  
  28.         >> 調用 委托 ;  
  29.  
  30.         >> 釋放本機句柄;Marshal.FreeHGlobal(this._handle);  
  31.  
  32. 修改記錄  
  33.     2008-5-11 8:07 曲濱  
  34.         >> 基本實現(xiàn)預期功能  
  35.         [!] 明天進行優(yōu)化  
  36.  
  37.     2008-5-12 15:54 曲濱  
  38.         [E] 優(yōu)化完成  
  39.         [N] 加入 NativeCodeHelper 類便于使用  
  40. */  
  41. namespace NShellNativeCode  
  42. {  
  43.     using System;  
  44.     using System.Collections.Generic;  
  45.     using System.Text;  
  46.     using System.Runtime.InteropServices;  
  47.     using System.IO;  
  48.     using System.Diagnostics;  
  49.     using System.Reflection;  
  50.       
  51.     delegate int AddProc(int p1, int p2);  
  52.     class Program  
  53.     {  
  54.           
  55.  
  56.         static void Main(string[] args)  
  57.         {  
  58.               
  59.             //一段加法函數(shù)本機代碼;后面注釋是給會 asm 看官看的  
  60.             //筆者本身也不是太明白匯編,簡單的 10行8行的還可以  
  61.               
  62.             byte[] codeBytes = {  
  63.                   0x8B, 0x44, 0x24, 0x08    // mov eax,[esp+08h]  
  64.                 , 0x8B, 0x4C, 0x24, 0x04    // mov ecx,[esp+04h]  
  65.                 , 0x03, 0xC1                // add    eax,ecx  
  66.                 , 0xC3                        // ret  
  67.                 };  
  68.                           
  69.             /*  
  70.             上面的字節(jié)數(shù)組,就是下面函數(shù)的本機代碼;  
  71.             int add(int x,int y) {  
  72.                 return x+y;  
  73.             }  
  74.               
  75.             */  
  76.  
  77.             IntPtr handle = IntPtr.Zero;  
  78.             handle = Marshal.AllocHGlobal(codeBytes.Length);  
  79.             try  
  80.             {  
  81.  
  82.                 Marshal.Copy(codeBytes, 0, handle, codeBytes.Length);  
  83.                                   
  84.                 AddProc add  
  85.                    = Marshal.GetDelegateForFunctionPointer(handle, typeof(AddProc)) as AddProc;  
  86.                   
  87.                 int r = add(1976, 1);  
  88.  
  89.                 Console.WriteLine("本機代碼返回:{0}", r);  
  90.  
  91.  
  92.             }  
  93.             finally  
  94.             {  
  95.                 Marshal.FreeHGlobal(handle);  
  96.             }  
  97.               
  98.             //本演示內包含的已經封裝好的 本機字節(jié)代碼,轉換委托通用類  
  99.             //打開注釋就可以用了;  
  100.               
  101.             /*  
  102.             using (NativeCodeHelper helper = new NativeCodeHelper(codeBytes))  
  103.             {  
  104.                 AddProc add = helper.ToDelegate<AddProc>();  
  105.                 Type t =  add.Method.DeclaringType;  
  106.                 int r = add(1976,1);  
  107.                 Console.WriteLine("本機代碼返回:{0}",r);  
  108.             }  
  109.             */  
  110.                       
  111.               
  112.             //Console.ReadLine();  
  113.         }      
  114.               
  115.           
  116.     }  
  117.  
  118. /*  
  119.     結束語  
  120.         已知問題  
  121.             1)在操作系統(tǒng)打開 DEP 保護的情況下,這類代碼會不靈;  
  122.                 我沒有測試,有興趣的可以試驗一下,估計是不會好用的;  
  123.               
  124.             2)如果要在 本機代碼 中調用 Win API 函數(shù),因為在不同系統(tǒng)不同版本中  
  125.                 Win API 的地址是不同的;  
  126.                 要有一些編寫 shell code 能力于黑客技術關系密切這里不做詳細描述  
  127.       
  128.         本文技術的適用范圍  
  129.             >> 遺留系統(tǒng),C/C++ 的某些算法、尤其匯編形式的是如果懶的改成.net 可以直接吧二進制copy  
  130.                 出來直接調用、不過需要C/VC、反匯編、匯編有點了解要不沒法Copy;  
  131.  
  132.             >> 有些代碼不想被反編譯,給破解者增加些破解難度、郁悶有可能會改你代碼的人  
  133.                 實用性有多少看官自己感覺吧,因為技術這東西是相對的  
  134.                 如果你的程序中到處都是這類代碼是很難維護的,就是熟悉匯編的人  
  135.                 這種東西多了也很郁悶的、本機代碼遠比匯編難看的多    
  136.  
  137.             >> 忽悠小朋友  
  138.                 把我的代碼直接copy倒你的項目里,一點都不改,要算int加法的時候都這么用  
  139.                 如果有小朋友看見一定會感覺你很 Cool  
  140.           
  141.         重要聲明:  
  142.             這種本機代碼方式如果應用倒真實項目中一定要項目負責人的同意的情況下,否則出現(xiàn)  
  143.         任何人事問題,或刑事問題與本文作者無關;  
  144.             如  
  145.                 >> 在真實項目中使用本文技術,在代碼中墜入邏輯炸彈者;  
  146.                 >> 在真實項目中使用本文技術,拒不上繳本機字節(jié)代碼對應的源代碼者;  
  147.                 >> 在真實項目或共享軟件中,捆綁病毒代碼者;  
  148.           
  149. */  
  150.  
  151.     /// <summary>  
  152.     /// 用于將本機代碼 byte 數(shù)組轉換為 .net 委托  
  153.     /// </summary>  
  154.     /// <remarks>  
  155.     /// 實現(xiàn)了 IDisposable 使用了非托管資源 使用時不要忘記釋放  
  156.     /// </remarks>  
  157.     public class NativeCodeHelper:IDisposable  
  158.     {  
  159.           
  160.         private bool _disposed = false;  
  161.         private byte[] _codeBytes = {};  
  162.         private IntPtr _handle = IntPtr.Zero;  
  163.           
  164.         public NativeCodeHelper(byte[] codeBytes)  
  165.         {  
  166.              this._codeBytes =  codeBytes;  
  167.         }  
  168.           
  169.         /// <summary>  
  170.         /// 把byte數(shù)字轉換為本機類型的指針 主要處理 this._handle  
  171.         /// </summary>  
  172.         private void CreateHandle()  
  173.         {  
  174.             if (_handle == IntPtr.Zero)  
  175.             {  
  176.                 _handle = Marshal.AllocHGlobal( this._codeBytes.Length);  
  177.                 Marshal.Copy(_codeBytes, 0, _handle, _codeBytes.Length);  
  178.             }          
  179.         }  
  180.         /// <summary>  
  181.         /// 轉換為指定的委托  
  182.         /// </summary>  
  183.         /// <typeparam name="T"></typeparam>  
  184.         /// <returns></returns>  
  185.         public T ToDelegate<T>() where T:class  
  186.         {  
  187.             this.CreateHandle();  
  188.               
  189.             //把指針轉換為 委托方法  
  190.             T result = Marshal.GetDelegateForFunctionPointer(_handle, typeof(T)) as T;              
  191.               
  192.             return result;  
  193.  
  194.         }  
  195.           
  196.         #region IDisposable 成員  
  197.           
  198.         ~NativeCodeHelper()  
  199.         {  
  200.             Dispose(false);  
  201.         }  
  202.           
  203.         public void Dispose()  
  204.         {  
  205.             Dispose(true);          
  206.             GC.SuppressFinalize(this);  
  207.  
  208.         }  
  209.  
  210.           
  211.           
  212.         private void Dispose(bool disposing)  
  213.         {  
  214.             if (disposing)  
  215.             {  
  216.                 //給調用者忘記 Dispose 釋放的提示  
  217.                 MethodBase mb = System.Reflection.MethodBase.GetCurrentMethod();  
  218.                 Type t = mb.DeclaringType;  
  219.                   
  220.                 Trace.WriteLine("not Dispose"  
  221.                 , "" + t + "." + mb );  
  222.             }  
  223.               
  224.               
  225.             if (!this._disposed)  
  226.             {  
  227.                 if (disposing)  
  228.                 {  
  229.                     //釋放.net 需要 Dispose 的對象                      
  230.                 }  
  231.  
  232.                 Marshal.FreeHGlobal(this._handle);  
  233.                 _handle = IntPtr.Zero;  
  234.             }  
  235.             _disposed = true;  
  236.         }          
  237.  
  238.         #endregion  
  239.     }  
  240. }  

 

本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
運用C#編程通過OPC方式實現(xiàn)PC機與西門子PLC通訊
Marshal 類
C#面試題和答案
PHP常用函數(shù)總結
PHP 文件系統(tǒng)詳解
mt4和mt5調用對照表
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服