有没有办法从结构中删除未使用的变量?

时间:2018-11-15 21:00:09

标签: c# struct pinvoke

我有一个这样的结构

[StructLayout(LayoutKind.Sequential)]
internal struct Context
{
    internal uint ContextFlags;

    private readonly IntPtr Dr0;
    private readonly IntPtr Dr1;
    private readonly IntPtr Dr2;
    private readonly IntPtr Dr3;
    private readonly IntPtr Dr6;
    private readonly IntPtr Dr7;

    private readonly FloatingSaveArea FloatingSave;

    private readonly IntPtr SegGs;
    private readonly IntPtr SegFs;
    private readonly IntPtr SegEs;
    private readonly IntPtr SegDs;

    private readonly IntPtr Edi;
    private readonly IntPtr Esi;
    private readonly IntPtr Ebx;
    private readonly IntPtr Edx;
    private readonly IntPtr Ecx;
    private readonly IntPtr Eax;

    private readonly IntPtr Ebp;
    internal IntPtr Eip;
    private readonly IntPtr SegCs;
    private readonly IntPtr EFlags;
    private readonly IntPtr Esp;
    private readonly IntPtr SegSs;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
    private readonly byte[] ExtendedRegisters;
}

使用以下pinvoke方法填充数据

[DllImport("kernel32.dll")]
internal static extern bool GetThreadContext(IntPtr hThread, ref Context lpContext);

我只需要访问变量ContextFlagsEip

理想情况下,我想从不需要的结构中删除所有其他变量,但是,当我这样做时,Eip变量将不再填充正确的值。

我也尝试了以下方法

[StructLayout(LayoutKind.Explicit)]
internal struct Context
{
    [FieldOffset(0)]
    internal uint ContextFlags;

    [FieldOffset(184)]
    internal IntPtr Eip;
}

字段偏移量184来自

uint offsetEip = (uint) Marshal.OffsetOf(typeof(Context), "Eip");

这也不起作用

有没有办法做到这一点?也许通过使用类而不是结构?

2 个答案:

答案 0 :(得分:1)

它当然可以工作,最后,它只是一个不透明的字节数组,但是您必须确保整个结构大小相同并且匹配当前的硬件/软件上下文,因此,只需为x86进程定义如下:

[StructLayout(LayoutKind.Explicit, Size = 716)] // size is 716 for x86
internal struct X86Context
{
    [FieldOffset(0)]
    internal uint ContextFlags;

    [FieldOffset(184)]
    internal IntPtr Eip;
}

答案 1 :(得分:0)

该结构在Windows头文件中定义,以与Windows API函数相对应,并且假定您将地址传递给与完整结构相同大小的已分配/拥有的内存位置。由于Windows API函数仅获得一个指针,因此尽管您将只使用其中两个成员,但它必须假定您已将指针传递给整个结构。您可以创建自己的相同大小的结构,以仅显示所需的两个成员。