2011-07-12 43 views
-1

我們有一些.NET代碼可以調用COM組件(dnsapi.dll)來查詢某個域是否有與其關聯的MX記錄來驗證輸入到我們網站的電子郵件地址。如何更新一些COM編組代碼以在64位系統上工作?

問題是我們已經從32位系統升級到64位系統,並且COM類型和.NET類型之間編組的代碼(並在之後清理)不再正常工作。

COM調用將結果放入內存並返回指向它們的位置的指針。將結果編組爲.NET結構的代碼仍能正常工作,但是在破壞堆並使IIS應用程序池崩潰之後清理內存的代碼仍然正常工作。

這絕對是一個64/32位的問題,因爲我創建了一個調用相同代碼的小控制檯應用程序,並且在我爲32位編譯時工作正常,但在編譯爲64位時顯示相同的堆損壞行爲。

我發現有同樣的問題別人的stackoverflow post,他們說的解決辦法是:

解決的辦法是儘量確保在Win32結構和C#的結構是位(大小)的映射。這可以通過爲win32類型使用精確的c#類型來實現。

我之前沒有做過太多的互操作,也不確定需要改變什麼。下面是MSDN documentation說什麼天然結構是這樣的:

typedef struct _DnsRecord { 
    DNS_RECORD *pNext; 
    PWSTR  pName; 
    WORD  wType; 
    WORD  wDataLength; 
    union { 
    DWORD   DW; 
    DNS_RECORD_FLAGS S; 
    } Flags; 
    DWORD  dwTtl; 
    DWORD  dwReserved; 
    union { 
    DNS_A_DATA  A; 
    DNS_SOA_DATA SOA, Soa; 
    DNS_PTR_DATA PTR, Ptr, NS, Ns, CNAME, Cname, DNAME, Dname, MB, Mb, MD, Md, MF, Mf, MG, Mg, MR, Mr; 
    DNS_MINFO_DATA MINFO, Minfo, RP, Rp; 
    DNS_MX_DATA  MX, Mx, AFSDB, Afsdb, RT, Rt; 
    DNS_TXT_DATA HINFO, Hinfo, ISDN, Isdn, TXT, Txt, X25; 
    DNS_NULL_DATA Null; 
    DNS_WKS_DATA WKS, Wks; 
    DNS_AAAA_DATA AAAA; 
    DNS_KEY_DATA KEY, Key; 
    DNS_SIG_DATA SIG, Sig; 
    DNS_ATMA_DATA ATMA, Atma; 
    DNS_NXT_DATA NXT, Nxt; 
    DNS_SRV_DATA SRV, Srv; 
    DNS_NAPTR_DATA NAPTR, Naptr; 
    DNS_OPT_DATA OPT, Opt; 
    DNS_DS_DATA  DS, Ds; 
    DNS_RRSIG_DATA RRSIG, Rrsig; 
    DNS_NSEC_DATA NSEC, Nsec; 
    DNS_DNSKEY_DATA DNSKEY, Dnskey; 
    DNS_TKEY_DATA TKEY, Tkey; 
    DNS_TSIG_DATA TSIG, Tsig; 
    DNS_WINS_DATA WINS, Wins; 
    DNS_WINSR_DATA WINSR, WinsR, NBSTAT, Nbstat; 
    DNS_DHCID_DATA DHCID; 
    } Data; 
} DNS_RECORD, *PDNS_RECORD; 

這裏是我們的.NET結構:

[StructLayout(LayoutKind.Sequential)] 
private struct DNSRecord 
{ 
    public IntPtr pNext; 
    public string pName; 
    public Int16 wType; 
    public Int16 wDataLength; 
    public Int32 dwflags; 
    public Int32 dwTtl; 
    public Int32 dwReserved; 
    public IntPtr pNameExchange; 
    public Int16 wPreference; 
    public Int16 Pad; 
} 

我知道IntPtr的是取決於應用程序是否在運行64位或不同的尺寸32位,但似乎並不是我可以專門控制的東西。我不確定我是否需要製作更大或更小的字段。理想情況下,我真的很想了解發生了什麼,以及爲什麼這是一個問題。

我知道另一種選擇是使用純粹通過CLR代碼完成此操作的第三方庫。不幸的是,這是一個.NET1.1庫,現在很難升級,所以我們不能只插入一個.NET庫。我查看了一個可以查詢MX記錄的.NET庫,它們都需要更新版本的.NET。

+0

您應該發佈在本機應用程序中定義的結構。 – tinman

回答

0

是的,你的結構太短,你沒有正確處理數據字段。該結構在32位模式下需要爲64個字節,在64位模式下爲88個字節。內存在32位版本的IIS中也被損壞,你只是沒有注意到它。

使用Marshal.SizeOf(typeof(DNSRecord))進行驗證。通過將以下字段添加到結構中,您可以獲得所需的大小:

[StructLayout(LayoutKind.Sequential)] 
struct DNSRecord { 
    public IntPtr pNext; 
    // etc.. 
    public Int16 Pad; 
    private int Pad1; 
    private int Pad2; 
    private int Pad3; 
    private int Pad4; 
    private int Pad5; 
    private IntPtr Pad6; 
    private IntPtr Pad7; 
    private IntPtr Pad8; 
} 
+0

你怎麼知道它應該是多大? – Helephant

+0

我在C程序中使用sizeof(DNS_RECORD),爲x86和x64構建它。 –

相關問題