我嘗試創建一個程序,它將以編程方式設置Windows顏色管理以歸檔類似f.lux的效果作爲業餘愛好項目。AccessViolationException當嘗試從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試圖讀取或寫保護的內存。這通常表明其他內存已損壞。
如何能夠讀取該指針處的內存?
我首先嚐試分配的內存由nvoigt
建議從IntPtr SizePointer
更改爲IntPtr SizePointer = Marshal.AllocHGlobal(4);
但它仍然拋出同樣的異常
完整的代碼如下這裏。
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;
}
}
我們需要更大膽的文字。 – Dennis
對不起,我現在已經解決了這個問題,使其更具可讀性。 – Suttisak