2010-05-17 19 views
0

我正嘗試使用編譯爲AnyCPU的.NET 2.0應用程序中的CryptUIWizDigitalSign函數對文件進行數字簽名。該調用在x86上運行時工作正常,但在x64上失敗,在編譯爲x86時,該調用也適用於x64操作系統。任何想法如何更好地marshall或從x64呼叫?在x64上從.NET調用CryptUIWizDigitalSign

返回的Win32exception是「在文件的數字簽名期間遇到錯誤...」,本機錯誤代碼爲-2146762749。

代碼的相關部分是:

[StructLayout(LayoutKind.Sequential)] 
public struct CRYPTUI_WIZ_DIGITAL_SIGN_INFO { 
public Int32 dwSize; 
public Int32 dwSubjectChoice; 
[MarshalAs(UnmanagedType.LPWStr)] 
public string pwszFileName; 
public Int32 dwSigningCertChoice; 
public IntPtr pSigningCertContext; 
[MarshalAs(UnmanagedType.LPWStr)] 
public string pwszTimestampURL; 
public Int32 dwAdditionalCertChoice; 
public IntPtr pSignExtInfo; 
} 

[DllImport("Cryptui.dll", CharSet=CharSet.Unicode, SetLastError=true)] 
public static extern bool CryptUIWizDigitalSign(int dwFlags, IntPtr hwndParent, string pwszWizardTitle, ref CRYPTUI_WIZ_DIGITAL_SIGN_INFO pDigitalSignInfo, ref IntPtr ppSignContext); 

CRYPTUI_WIZ_DIGITAL_SIGN_INFO digitalSignInfo = new CRYPTUI_WIZ_DIGITAL_SIGN_INFO(); 
digitalSignInfo = new CRYPTUI_WIZ_DIGITAL_SIGN_INFO(); 
digitalSignInfo.dwSize = Marshal.SizeOf(digitalSignInfo); 
digitalSignInfo.dwSubjectChoice = 1; 
digitalSignInfo.dwSigningCertChoice = 1; 
digitalSignInfo.pSigningCertContext = pSigningCertContext; 
digitalSignInfo.pwszTimestampURL = timestampUrl; 
digitalSignInfo.dwAdditionalCertChoice = 0; 
digitalSignInfo.pSignExtInfo = IntPtr.Zero; 
digitalSignInfo.pwszFileName = filepath; 
CryptUIWizDigitalSign(1, IntPtr.Zero, null, ref digitalSignInfo, ref pSignContext)); 

這裏是SigningCertContext如何檢索(減去各種錯誤處理)

public IntPtr GetCertContext(String pfxfilename, String pswd) 
IntPtr hMemStore = IntPtr.Zero; 
IntPtr hCertCntxt = IntPtr.Zero; 
IntPtr pProvInfo = IntPtr.Zero; 
uint provinfosize = 0; 
try {     
    byte[] pfxdata = PfxUtility.GetFileBytes(pfxfilename); 
    CRYPT_DATA_BLOB ppfx = new CRYPT_DATA_BLOB(); 
    ppfx.cbData = pfxdata.Length; 
    ppfx.pbData = Marshal.AllocHGlobal(pfxdata.Length); 
    Marshal.Copy(pfxdata, 0, ppfx.pbData, pfxdata.Length); 
    hMemStore = Win32.PFXImportCertStore(ref ppfx, pswd, CRYPT_USER_KEYSET); 
    pswd = null; 
    if (hMemStore != IntPtr.Zero) { 
    Marshal.FreeHGlobal(ppfx.pbData); 
    while ((hCertCntxt = Win32.CertEnumCertificatesInStore(hMemStore, hCertCntxt)) != IntPtr.Zero) { 
    if (Win32.CertGetCertificateContextProperty(hCertCntxt, CERT_KEY_PROV_INFO_PROP_ID, IntPtr.Zero, ref provinfosize)) 
    pProvInfo = Marshal.AllocHGlobal((int)provinfosize); 
    else 
    continue; 
    if (Win32.CertGetCertificateContextProperty(hCertCntxt, CERT_KEY_PROV_INFO_PROP_ID, pProvInfo, ref provinfosize)) 
    break; 
    }    
    } 
finally { 
if (pProvInfo != IntPtr.Zero) 
    Marshal.FreeHGlobal(pProvInfo); 
if (hMemStore != IntPtr.Zero) 
    Win32.CertCloseStore(hMemStore, 0); 
} 
return hCertCntxt; 
} 
+0

我沒有看到任何錯誤。我看不到pSigningCertContext是如何初始化的。描述「失敗」和Marshal.GetLastWin32Error返回值。 – 2010-05-17 17:21:28

回答

0

當應用程序與AnyCPU目標編制,他們會在32位OS上加載爲32位,在64位OS上加載爲64位。您無法從64位進程加載32位DLL。

你曾經說過,它在編譯到x86時「起作用」。你能做到嗎?這使我相信你的搜索路徑中的cryptui.dll是一個32位的DLL。