2016-03-28 8 views
-2

プログラムで、Windowsカラーマネージメントを設定して、ホビープロジェクトとしてf.luxのようなエフェクトをアーカイブしようとしました。Marshalクラスを使用してC#でポインタからメモリを読み込もうとしたとき

** WINAPI WcsGetDefaultColorProfileSizeの定義。 **

BOOL WINAPI WcsGetDefaultColorProfileSize(
    _In_  WCS_PROFILE_MANAGEMENT_SCOPE profileManagementScope, 
    _In_opt_ PCWSTR pDeviceName, 
    _In_  COLORPROFILETYPE cptColorProfileType, 
    _In_  COLORPROFILESUBTYPE cpstColorProfileSubType, 
    _In_  DWORD dwProfileID, 
    _Out_  PDWORD pcbProfileName 
); 

**これは管理対象のWcsGetDefaultColorProfileSizeの署名です。 **

[DllImport("Mscms.dll", EntryPoint = "WcsGetDefaultColorProfileSize", CharSet = CharSet.Unicode)] 
private static extern bool GetDefaultColorProfileSize(
    WCS_PROFILE_MANAGEMENT_SCOPE profileManagementScope, 
    [MarshalAs(UnmanagedType.LPWStr), In] string pDeviceName, 
    COLORPROFILETYPE cptColorProfileType, 
    COLORPROFILESUBTYPE cpstColorProfileSubType, 
    Int32 dwProfileID, 
    out IntPtr pcbProfileSize 
); 

私はMarshalクラスを使用してWINAPIからポインタとしての復帰である文字列を取得しようとすると問題があります。 Marshal.ReadInt32 を使用して、この

// Need to get the size of ICC profile file first 
GetDefaultColorProfileSize(
WCS_PROFILE_MANAGEMENT_SCOPE.WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER, 
monitor_name.DeviceKey, 
COLORPROFILETYPE.CPT_ICC, 
COLORPROFILESUBTYPE.CPST_RGB_WORKING_SPACE, 
1, 
out SizePointer); 
System.Diagnostics.Debug.WriteLine("Size is " + Marshal.ReadInt32(SizePointer)); 

GetDefaultColorProfileSizeリターンTRUEが、私はそれが返すアドレスにアクセスしようとすると、(これは、このアドレス0x0000003eを返す)のようにそれは

System.AccessViolationExceptionを読み取ろうとしました。このエラーをスローまたは書き込み保護されたメモリ。これはしばしば、他のメモリが壊れていることを示します。

どのようにしてそのポインタのメモリを読み取ることができますか?

は私がIntPtr SizePointer = Marshal.AllocHGlobal(4);

IntPtr SizePointerから変更nvoigt

によって示唆された第1のメモリを割り当てようが、それはまだ完全なコードは、ここで以下の通りです同じ例外

を投げます。

Enumnerateのディスプレイデバイス

[DllImport("User32.dll")] 
    private static extern bool EnumDisplayDevices(
     string lpDevice, int iDevNum, 
     ref DISPLAY_DEVICE lpDisplayDevice, int dwFlags); 

    [StructLayout(LayoutKind.Sequential)] 
    public struct DISPLAY_DEVICE 
    { 
     public int cb; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 
     public string DeviceName; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] 
     public string DeviceString; 
     public int StateFlags; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] 
     public string DeviceID; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] 
     public string DeviceKey; 

     public DISPLAY_DEVICE(int flags) { 
      cb = 0; 
      StateFlags = flags; 
      DeviceName = new string((char)32, 32); 
      DeviceString = new string((char)32, 128); 
      DeviceID = new string((char)32, 128); 
      DeviceKey = new string((char)32, 128); 
      cb = Marshal.SizeOf(this); 
     } 
    } 

ウィンドウの色システム

enum WCS_PROFILE_MANAGEMENT_SCOPE 
    { 
     WCS_PROFILE_MANAGEMENT_SCOPE_SYSTEM_WIDE = 0, 
     WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER 
    } 

    enum COLORPROFILETYPE 
    { 
     CPT_ICC = 0x0001, 
     CPT_DMP, 
     CPT_CAMP, 
     CPT_GMMP 
    } 

    enum COLORPROFILESUBTYPE 
    { 
     CPST_NONE = 0x0000, 
     CPST_RGB_WORKING_SPACE = 0x0001, 
     CPST_PERCEPTUAL = 0x0002, 
     CPST_ABSOLUTE_COLORIMETRIC = 0x0004, 
     CPST_RELATIVE_COLORIMETRIC = 0x0008, 
     CPST_SATURATION = 0x0010, 
     CPST_CUSTOM_WORKING_SPACE = 0x0020 
    } 
    [DllImport("Mscms.dll", EntryPoint = "WcsGetDefaultColorProfileSize", CharSet = CharSet.Unicode)] 
    private static extern bool GetDefaultColorProfileSize(
     WCS_PROFILE_MANAGEMENT_SCOPE profileManagementScope, 
     [MarshalAs(UnmanagedType.LPWStr), In] string pDeviceName, 
     COLORPROFILETYPE cptColorProfileType, 
     COLORPROFILESUBTYPE cpstColorProfileSubType, 
     Int32 dwProfileID, 
     out IntPtr pcbProfileSize 
    ); 
    [DllImport("Mscms.dll", EntryPoint = "WcsGetDefaultColorProfile" , CharSet =CharSet.Unicode, SetLastError =true)] 
    private unsafe static extern bool GetDefaultColorProfile(WCS_PROFILE_MANAGEMENT_SCOPE profileManagementScope, 
     [MarshalAs(UnmanagedType.LPWStr), In] string pDeviceName, 
      COLORPROFILETYPE cptColorProfileType, 
      COLORPROFILESUBTYPE cpstColorProfileSubType, 
      Int32 dwProfileID, 
      Int32 cbProfileName, 
      out IntPtr pProfileName); 

    [DllImport("Mscms.dll", EntryPoint = "WcsSetUsePerUserProfiles", CharSet = CharSet.Unicode)] 
    private static extern bool SetUsePerUserProfiles([MarshalAs(UnmanagedType.LPWStr), In]string pDeviceName, Int32 dwDeviceClass, bool usePerUserProfiles); 
    [DllImport("Mscms.dll", EntryPoint = "WcsGetUsePerUserProfiles", CharSet = CharSet.Unicode)] 
    private static extern bool GetUsePerUserProfiles([MarshalAs(UnmanagedType.LPWStr), In]string pDeviceName, Int32 dwDeviceClass, out bool pUsePerUserProfiles); 

実際のコード

public unsafe static void GetProfile() { 
     DISPLAY_DEVICE lpDisplayDevice = new DISPLAY_DEVICE(0);  // OUT 
     DISPLAY_DEVICE monitor_name = new DISPLAY_DEVICE(0);  // OUT 

     int devNum = 0; 
     while (EnumDisplayDevices(null, devNum, ref lpDisplayDevice, 0)) { 
      int devNum2 = 0; 
      while (EnumDisplayDevices(lpDisplayDevice.DeviceName, devNum2, ref monitor_name, 0)) { 
       IntPtr SizePointer; 
       // Need to get the size of ICC profile file first 
       GetDefaultColorProfileSize(
    WCS_PROFILE_MANAGEMENT_SCOPE.WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER, 
        monitor_name.DeviceKey, 
        COLORPROFILETYPE.CPT_ICC, 
        COLORPROFILESUBTYPE.CPST_RGB_WORKING_SPACE, 
        1, 
        out SizePointer); 
       System.Diagnostics.Debug.WriteLine("Size is " + Marshal.ReadInt32(SizePointer)); 
      // Try to get a location of ICC profile file. 
      // Not Implement Yet 
       break; 
      } 
      break; 
     } 
    } 
+0

int size = 4; // 4 byte = 32 bit IntPtr p = Marshal.AllocHGlobal(size); 

が後でそれを解放することを忘れないでください、これはごみ収集ではありません。 – Dennis

+0

申し訳ありませんが、私は今質問を読みやすくするために修正しました。 – Suttisak

答えて

1

あなたSizePointerは、あなたが使用したことがないローカル変数です。 が起こると予想していますが、これはうまくいかないでしょう。あなたはおそらくprofileSizeを使うつもりです。

今後は、警告を最初に修正する必要があります。彼らは重要です。


さて、あなたは少なくとも正しい変数を渡しています。あなたはまだそれを何かに初期化していません。そこに書き込むはずのメソッドにNULLポインタを渡しています。それはできません。私はあなたが実際にその方法からTRUEを得たとは想像できません。そして、NULLポインタからの読み取りは明らかに失敗します。ポインタが実際に書き込めるメモリ内の部分を指していることを確認する必要があります。

DWORDが必要です。 ReadInt32を使用しているので、私はあなたが32bitであると仮定します。あなたが最初のメモリを割り当てる必要が

:私たちは、もっと大胆なテキストが必要

Marshal.FreeHGlobal(p); 
+0

申し訳ありませんが、コードをStackOverflowにコピーして重要でない行を切り取ったときは、誤植です。 VS2015で実行した実際のコードが修正されました。私はあなたがすでに言及したようにタイプミスを修正しました。 – Suttisak

+0

あなたが偽のコードを投稿し、それが私たちの間違いであるかのように間違った質問に答えていることを伝えれば、誰も手助けしたくありません。率直に言えば、あなたのコードが実際に何であるか気にしません。我々は私たちの目の前にある質問だけに気をつけます。あなたの前にコードと関係のないコードを投稿すると、それはあなたのものです。偽のコードを投稿しないでください。 –

+0

@nvoigt私は試しましたが、それでも例外はスローされます。 'TRUE'を返す 'WcsGetDefaultColorProfileSize'が' Out IntPtr SizePointer'を返すポインタは常に "0x0000003e"です。私はVSでメモリウィンドウを開いて、このアドレスを検索します。それだけを示して?? ?? ?? ?? – Suttisak

関連する問題