2016-09-20 8 views
2

情報:C#、ハンドルのリストを取得しますAcessViolationException

  • Win7の64ビット

  • Win10 64ビット(仮想:でテスト

    • の.Net 4.5

    ボックス)

私は外部プロセスのハンドルのリストを取得し、後で特定のプロセスを閉じることができるように文字列として名前を返そうとしています。 `

 const int CNST_SYSTEM_HANDLE_INFORMATION = 16; 
     const uint STATUS_INFO_LENGTH_MISMATCH = 0xc0000004; 

     public static string getObjectTypeName(Win32API.SYSTEM_HANDLE_INFORMATION shHandle, Process process) 
     { 
      IntPtr m_ipProcessHwnd = Win32API.OpenProcess(Win32API.ProcessAccessFlags.All, false, process.Id); 
      IntPtr ipHandle = IntPtr.Zero; 
      var objBasic = new Win32API.OBJECT_BASIC_INFORMATION(); 
      IntPtr ipBasic = IntPtr.Zero; 
      var objObjectType = new Win32API.OBJECT_TYPE_INFORMATION(); 
      IntPtr ipObjectType = IntPtr.Zero; 
      IntPtr ipObjectName = IntPtr.Zero; 
      string strObjectTypeName = ""; 
      int nLength = 0; 
      int nReturn = 0; 
      IntPtr ipTemp = IntPtr.Zero; 


      if (!Win32API.DuplicateHandle(m_ipProcessHwnd, shHandle.Handle, 
              Win32API.GetCurrentProcess(), out ipHandle, 
              0, false, Win32API.DUPLICATE_SAME_ACCESS)) 
       return null; 



      ipBasic = Marshal.AllocHGlobal(Marshal.SizeOf(objBasic)); 
      Win32API.NtQueryObject(ipHandle, (int)Win32API.ObjectInformationClass.ObjectBasicInformation, 
            ipBasic, Marshal.SizeOf(objBasic), ref nLength); 
      objBasic = (Win32API.OBJECT_BASIC_INFORMATION)Marshal.PtrToStructure(ipBasic, objBasic.GetType()); 
      Marshal.FreeHGlobal(ipBasic); 

      ipObjectType = Marshal.AllocHGlobal(objBasic.TypeInformationLength); 
      nLength = objBasic.TypeInformationLength; 
      while ((uint)(nReturn = Win32API.NtQueryObject(
       ipHandle, (int)Win32API.ObjectInformationClass.ObjectTypeInformation, ipObjectType, 
        nLength, ref nLength)) == 
       Win32API.STATUS_INFO_LENGTH_MISMATCH) 
      { 
       Marshal.FreeHGlobal(ipObjectType); 
       ipObjectType = Marshal.AllocHGlobal(nLength); 
      } 

      objObjectType = (Win32API.OBJECT_TYPE_INFORMATION)Marshal.PtrToStructure(ipObjectType, objObjectType.GetType()); 
      if (Is64Bits()) 
      { 
       ipTemp = new IntPtr(Convert.ToInt64(objObjectType.Name.Buffer.ToString(), 10) >> 32); 
      } 
      else 
      { 
       ipTemp = objObjectType.Name.Buffer; 
      } 

     strObjectTypeName = Marshal.PtrToStringUni(ipTemp, objObjectType.Name.Length >> 1); 


     Marshal.FreeHGlobal(ipObjectType); 
      Win32API.CloseHandle(ipHandle); 
      return strObjectTypeName; 
     }` 

が問題しかし、このコードではありませんWin10で、Win7の64ビットで動作していることである。したがって、私は、ハンドルは私が閉じるようにしたいハンドルであるかどうかをチェックしますのWin32APIを使用してこの機能を書きました! - >勝利10 strObjectTypeName = Marshal.PtrToStringUni();でSystem.AccessViolationExceptionが保護されたメモリの読み取りまたは書き込みを試み

AcessViolationException(コードの最後の数行)を投げます。これはしばしば、他のメモリが壊れていることを示します。

ここで、win10で管理されていないメモリをどのようにアクセスする必要があるのか​​分かりませんか?

答えて

0

私はちょうど同じ問題に出くわしました。 Win7を試したことはありませんが、Win10(x64)のコードを32ビットとして実行すると(たとえば、アプリケーションの「32ビットフラグを優先」に設定すると)、動作するはずです。 例外が発生した場合は、&を変数 "ipTemp"をVisual Studioの "メモリウィンドウ"にドラッグすると、疑問符または有効なポインタを持たないエラーメッセージだけが表示されます。 私が理解した限り、このAPIで使用される構造体の64ビットバージョンにはパディングバイトがあります。 OBJECT_TYPE_INFORMATIONにはUNICODE_STRINGが含まれ、UNICODE_STRINGには64ビットモードのバッファフィールドの前に4つのパディングバイトがあります。 マイworkaraoundはこのだった:私はすべて私がオープンソースを作成するために検討していますインターネット上でコピーされているので、多くのこのトピックに関する質問とサンプルコード の基本的に2種類を発見した私の研究中に

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
public struct UNICODE_STRING 
{ 
    private IntPtr _dummy; // the two ushorts seem to be padded with 4 bytes in 64bit mode only 

    /// <summary> 
    /// The length, in bytes, of the string stored in Buffer. If the string is null-terminated, Length does not include the trailing null character. 
    /// </summary> 
    public ushort Length 
    { 
     get { return (ushort)Marshal.ReadInt16(this, 0); } 
    } 

    /// <summary> 
    /// The length, in bytes, of Buffer. 
    /// </summary> 
    public ushort MaximumLength 
    { 
     get { return (ushort)Marshal.ReadInt16(this, 2); } 
    } 

    public IntPtr Buffer; 
} 

WinKernelObjectsDotNetという名前のライブラリ。

更新:ライブラリは現在利用可能ですhere。 1行のコードでファイルまたはシリアルポート(COM)をロックしているプロセスを見つけることができます。

関連する問題