<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      AhDung

      /*追求代碼質量的野生碼農*/

        博客園  :: 首頁  :: 新隨筆  :: 聯系 :: 訂閱 訂閱  :: 管理

      注冊/反注冊dll或ocx文件時,無論是用regsvr32還是DllRegisterServer/DllUnregisterServer,可能會遇到【內存位置訪問無效】的問題:

      此時把操作系統的數據執行保護(Data Execution Prevention,下稱DEP)徹底關掉,重啟,應該就能解決問題。操作:

      • NT6.x系統:運行  bcdedit /set nx alwaysoff 
      • NT5.x系統:修改 %systemdrive%\boot.ini 文件,將當前操作系統條目的/noexecute參數的值改為AlwaysOff,若沒有則添加。若是多系統,要注意修改到正確的條目

      本文主要是討論,作為開發者,當需要在自己的程序中注冊dll時(反注冊的情況一樣,下文只拿注冊說事,其實適用于所有受DEP影響的問題),如何避免改動系統DEP,避免重啟地把問題解決掉。其實這個問題的關鍵是,執行注冊的進程是否啟用了DEP,啟用就不能注冊,關閉就能,跟系統DEP沒有直接關系,但進程DEP受系統DEP的影響。

      來自系統DEP的原因

      系統DEP策略有4種,每種策略下對進程DEP的影響如下(注意,64位程序總是啟用DEP,且不可禁用,不論系統DEP如何設置。所以下表和接下來說的都是32位程序的情況):

      系統DEP策略 進程默認DEP 能否更改進程DEP
      OptIn (僅為基本的Windows程序和服務啟用DEP;默認策略) 關閉 允許更改
      OptOut (除指定的程序外,全部啟用DEP) 開啟 允許更改
      AlwaysOn (全部啟用DEP) 開啟 不允許更改
      AlwaysOff (全部禁用DEP) 關閉 不允許更改

      我們的目的是關閉進程DEP??梢钥吹?,系統DEP為OptIn和AlwaysOff時,進程DEP已經是默認關閉的。其余兩種情況中,OptOut雖然是默認開啟DEP,但它允許被關閉,所以這是一種可以搶救的情況,唯獨AlwaysOn不可搶救,必須修改系統DEP策略并重啟。

      插播一下,系統默認的策略是OptIn,這種策略下普通程序的DEP是關閉的,但是系統程序例外,所以在程序中調用regsvr32進行注冊會失敗,因為實際執行注冊的進程是regsvr32而非自己的程序,而regsvr32是系統程序,它在OptIn下是會被開啟DEP的。可以在任務管理器進程頁面中添加【數據執行保護】列,以呈現進程DEP的開閉情況。

      小結:

      • 系統DEP有4種,除了AlwaysOn,其余3種都可以讓(或已經是)自己的程序處于DEP關閉狀態;
      • 系統DEP可以用GetSystemDEPPolicy API獲取,沒有發現用于設置的API;
      • 進程DEP可以用GetProcessDEPPolicy獲取,同時該函數還返回可否修改DEP的信息,如果是可修改,則可以用SetProcessDEPPolicy更改自身DEP狀態;
      • 一個簡易的DepHelper分享給大家:
         1 using System;
         2 using System.ComponentModel;
         3 using System.Runtime.InteropServices;
         4 
         5 namespace AhDung.Win32
         6 {
         7     /// <summary>
         8     /// 數據執行保護(DEP)輔助類
         9     /// </summary>
        10     public static class DepHelper
        11     {
        12         /// <summary>
        13         /// 獲取進程DEP狀態
        14         /// </summary>
        15         /// <param name="hProcess">進程句柄</param>
        16         /// <param name="permanently">是否永久。該參數同時指示了是否可以更改進程DEP,為true表示不可修改</param>
        17         public static ProcessDepFlag GetProcessDepPolicy(IntPtr hProcess, out bool permanently)
        18         {
        19             if (!GetProcessDEPPolicy(hProcess, out var lpFlags, out permanently))
        20             {
        21                 throw new Win32Exception();
        22             }
        23 
        24             return (ProcessDepFlag)lpFlags;
        25         }
        26 
        27         /// <summary>
        28         /// 設置進程DEP狀態
        29         /// </summary>
        30         public static void SetProcessDepPolicy(ProcessDepFlag flag)
        31         {
        32             if (!Enum.IsDefined(typeof(ProcessDepFlag), flag))
        33             {
        34                 throw new InvalidEnumArgumentException();
        35             }
        36 
        37             if (!SetProcessDEPPolicy((int)flag))
        38             {
        39                 throw new Win32Exception();
        40             }
        41         }
        42 
        43         /// <summary>
        44         /// 獲取系統DEP狀態
        45         /// </summary>
        46         [DllImport("Kernel32.dll", EntryPoint = "GetSystemDEPPolicy")]
        47         public static extern SystemDepPolicyType GetSystemDepPolicy();
        48 
        49         [DllImport("kernel32.dll", SetLastError = true)]
        50         static extern bool SetProcessDEPPolicy(int dwFlags);
        51 
        52         [DllImport("kernel32.dll", SetLastError = true)]
        53         static extern bool GetProcessDEPPolicy(IntPtr hProcess, out int lpFlags, out bool lpPermanent);
        54     }
        55 
        56     public enum SystemDepPolicyType
        57     {
        58         AlwaysOff,
        59         AlwaysOn,
        60         OptIn,
        61         OptOut
        62     }
        63 
        64     public enum ProcessDepFlag
        65     {
        66         Disabled,
        67         PROCESS_DEP_ENABLE,
        68         PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION
        69     }
        70 }
        DepHelper.cs

      基本上,由于系統默認策略是OptIn,我們的32程序按說不太會遇到DEP的問題,但事情并沒有這么簡單,尤其作為.Neter,我們往往會遇到來自另一方面的原因。

      來自PE標記的原因

      如果系統DEP已經是OptIn或OptOut,程序也是32位,根據上面的表格,按說程序DEP應該是處于關閉或可以關閉的狀態,但它偏偏處于開啟狀態,并且不可更改。這是因為,程序DEP除了會受系統DEP影響外,還會受程序文件PE頭中的一個標記影響。

      這個標記叫IMAGE_DLLCHARACTERISTICS_NX_COMPAT,有些地方叫NX Compatible。

      標記的意思大概是標識該PE文件是否是DEP兼容,這里不必深究該標記的明確意義及其所在位置,只要知道擁有該標記的exe程序,會在除AlwaysOff外的情況下開啟DEP且不可關閉,而據稱在.net framework 2.0 SP1后,.net的編譯器就會為生成的PE文件打上該標記,導致今天的.net程序,相信大多都是攜帶該標記的。

      VC構建工具中有個叫editbin.exe的命令行工具,可以簡單移除該標記:

      editbin.exe /NXCOMPAT:NO xxx.exe

      如果安裝VS時沒裝c++相關的東西,那你的電腦可能沒有這個工具,可以選擇把c++組件裝上,或搜單獨的vc build tools裝上。

      說回DLL注冊

      上面說過如果是調用regsvr32來注冊的,那就算搞掂程序的DEP也無濟于事,需要考慮用regsvr32以外的辦法進行注冊,比如直接調用dll的DllRegisterServer函數,事實上regsvr32也應該是這么搞。下面是c#版的實現:

       1 using System;
       2 using System.ComponentModel;
       3 using System.Runtime.InteropServices;
       4 
       5 namespace AhDung.Win32
       6 {
       7     /// <summary>
       8     /// COM組件注冊輔助類
       9     /// </summary>
      10     public static class ComRegHelper
      11     {
      12         /// <summary>
      13         /// 反注冊
      14         /// </summary>
      15         public static void UnRegister(string file)
      16         {
      17             Register(file, false);
      18         }
      19 
      20         /// <summary>
      21         /// 注冊或反注冊
      22         /// </summary>
      23         /// <param name="file">文件路徑</param>
      24         /// <param name="isRegister">true為注冊,false為反注冊</param>
      25         /// <remarks>抄于https://limbioliong.wordpress.com/2011/08/11/programmatically-register-com-dlls-in-c/</remarks>
      26         public static void Register(string file, bool isRegister = true)
      27         {
      28             file = Environment.ExpandEnvironmentVariables(file);
      29 
      30             var hModuleDLL = LoadLibrary(file);
      31 
      32             if (hModuleDLL == IntPtr.Zero)
      33             {
      34                 throw new Win32Exception();
      35             }
      36 
      37             try
      38             {
      39                 // Obtain the required exported API.
      40                 var pExportedFunction = GetProcAddress(hModuleDLL, isRegister
      41                     ? "DllRegisterServer"
      42                     : "DllUnregisterServer");
      43 
      44                 if (pExportedFunction == IntPtr.Zero)
      45                 {
      46                     throw new Win32Exception();
      47                 }
      48 
      49                 // Obtain the delegate from the exported function, whether it be
      50                 // DllRegisterServer() or DllUnregisterServer().
      51                 var pDelegateRegUnReg =
      52                     (DllRegUnRegAPI)Marshal.GetDelegateForFunctionPointer(pExportedFunction, typeof(DllRegUnRegAPI));
      53 
      54                 // Invoke the delegate.
      55                 var hResult = pDelegateRegUnReg();
      56 
      57                 if (hResult != 0)
      58                 {
      59                     throw new Win32Exception();
      60                 }
      61             }
      62             finally
      63             {
      64                 FreeLibrary(hModuleDLL);
      65             }
      66         }
      67 
      68         // All COM DLLs must export the DllRegisterServer()
      69         // and the DllUnregisterServer() APIs for self-registration/unregistration.
      70         // They both have the same signature and so only one
      71         // delegate is required.
      72         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
      73         delegate uint DllRegUnRegAPI();
      74 
      75         [DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
      76         static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string strLibraryName);
      77 
      78         [DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
      79         static extern int FreeLibrary(IntPtr hModule);
      80 
      81         [DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
      82         static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName);
      83     }
      84 }
      ComRegHelper.cs

      如果不關DEP,LoadLibrary就會遇到問題。

      -文畢-

      posted on 2020-04-20 17:49  ahdung  閱讀(842)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 蜜臀精品视频一区二区三区| 精品精品国产国产自在线| 国产成人不卡一区二区| √8天堂资源地址中文在线| 国产办公室秘书无码精品99| 人人妻人人澡人人爽| 国产精品大全中文字幕| 无套内射极品少妇chinese| 强奷白丝美女在线观看| 国产精品无码av不卡| 洛隆县| 麻豆一区二区三区精品视频| 久热综合在线亚洲精品| 福利一区二区不卡国产| 久久成人国产精品免费软件 | 国产毛1卡2卡3卡4卡免费观看| 久久久婷婷成人综合激情| 亚洲乱妇老熟女爽到高潮的片| 东京热高清无码精品| 欧美日韩一线| 欧美拍拍视频免费大全| 国产超碰无码最新上传| 欧洲精品码一区二区三区| 另类 专区 欧美 制服| 日韩av综合免费在线| 国产啪视频免费观看视频| 波多野结系列18部无码观看AV| 久久久久久毛片免费播放| 影视先锋av资源噜噜| 视频区 国产 图片区 小说区| 国产亚洲精品第一综合麻豆| 亚洲AV永久无码嘿嘿嘿嘿| 久久99精品国产麻豆婷婷| 武鸣县| 欧美成人www免费全部网站 | 国产毛片基地| 日韩中文字幕高清有码| 强行交换配乱婬bd| 国产在线观看91精品亚瑟| 国产大片黄在线观看| 国产亚洲精品中文字幕|