2013-08-21 23 views
8

Sto creando una libreria di utilità da utilizzare sia nell'ambiente desktop in un ambiente web.urlmon.dll FindMimeFromData() funziona perfettamente su desktop/console 64 bit ma genera errori su ASP.NET

Contiene diverse funzionalità che credo siano spesso ripetute nelle mie applicazioni, inclusa l'utilità per ottenere il tipo mime di un file dal suo contenuto (non dall'estensione).

I file che dovrò verificare sono i più comuni (jpg, png, pdf, txt), così ho scelto di utilizzare il (link qui sotto) metodo esterno

Using .NET, how can you find the mime type of a file based on the file signature not the extension

Il metodo funziona bene, tranne che per i due tipi mime errati di JPG (image/pjpg) e PNG (image/x-png), risolti facilmente eseguendo un controllo prima dell'istruzione di reso.

La libreria è compilata per la piattaforma AnyCPU, poiché deve essere installata su server/client sia a 32 che a 64 bit.

Al momento del test sull'ambiente desktop tutto funziona correttamente per entrambe le applicazioni compilate per x86 e x64.

al momento del test di un'applicazione ASP.NET (un sito vuoto con un gestore http per il test) si verifica un errore di tipo HRESULT e il debugger mi dice che non può fornire ulteriori informazioni.

Dopo una configurazione di prova pochi, tra cui cambiando l'identità del pool di sistema locale (senza risultato), ho individuato il problema:

la piscina dovrebbe consentire applicazioni a 32-bit (vedi immagine sopra).

IisAllow32BitApplication

Perché?

Non dovrebbe caricare la DLL urlmon.dll del sistema a 64 bit in cui ci troviamo ora?

Questo è un grosso problema, perché il metodo può essere richiamato da tutto il mondo in questa libreria:

il risultato è che un'invocazione di questo metodo con un altro metodo di utilità può lanciare questa eccezione e rendendo difficile la traccia il problema anche attraverso il debug.

Qualche idea/esperienza?

sistemi operativi utilizzati per i test

Desktop:

  1. Windows 8 x64 - funziona
  2. Windows 7 x64 - lavora
  3. Windows Server 2008 Standard R2 x64 - funziona
  4. Windows Server 2008 Standard x86 - funziona
  5. Windows Server 2003 Standard x86 - funziona
  6. Windows XP Professional SP3 - funziona

Web:

  1. Windows 8 x64 - trovato il primo errore, funziona solo con l'applicazione a 32 bit abilitata
  2. Windows Server 2008 Standard R2 x64 - errore confermato, funziona solo con l'applicazione a 32 bit abilitata
  3. Windows Server 2008 Standard x86 - funziona

EDIT 2 (domanda risolto)

Risolto da Noseratio:

Il corretto tipo di parametri ppwzMimeOut e pBC devono essere System.IntPtr anziché System.UInt32.

So che lo System.UInt32 causa problemi a tutte le applicazioni Web a 64 bit, ma non so perché.

Se qualcuno conosce la ragione di questi problemi, può spiegarlo meglio in un commento?

Grazie in anticipo

+1

Ecco perché è utile disporre di un metodo di fallback per "URLMon.dll" come [questo] (http://stackoverflow.com/a/15595571/495455). O nel tuo caso Urlmon folle del tutto a favore di Winista. –

risposta

10

Se utilizzate la firma PInvoke dal answer tua collegato, è definito non in questo modo:

[DllImport(@"urlmon.dll", CharSet = CharSet.Auto)] 
private extern static System.UInt32 FindMimeFromData(
    System.UInt32 pBC, 
    [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl, 
    [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer, 
    System.UInt32 cbSize, 
    [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed, 
    System.UInt32 dwMimeFlags, 
    out System.UInt32 ppwzMimeOut, 
    System.UInt32 dwReserverd 
); 

Avrei preferito utilizzare il defintion da pinvoke.net:

[DllImport("urlmon.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false)] 
static extern int FindMimeFromData(IntPtr pBC, 
    [MarshalAs(UnmanagedType.LPWStr)] string pwzUrl, 
    [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I1, SizeParamIndex=3)] 
    byte[] pBuffer, 
    int cbSize, 
    [MarshalAs(UnmanagedType.LPWStr)] string pwzMimeProposed, 
    int dwMimeFlags, 
    out IntPtr ppwzMimeOut, 
    int dwReserved); 

Notare la differenza nei tipi per il parametro ppwzMimeOut e pBC. Nel primo caso, System.UInt32 non è un tipo corretto per un puntatore a 64 bit in una piattaforma a 64 bit. Per pBC, questo probabilmente non è un problema (purché sia ​​NULL), ma è importante per ppwzMimeOut.

Vedere this implementation che sembra essere corretto.

+1

Hey man ... Dopo aver cambiato il tipo di parametro pBC e ppwzMimeOut, ora funziona ovunque! Grazie molto! –

+1

Nessun problema, lieto di aver aiutato:] BTW, non dimenticare di chiamare 'Marshal.FreeCoTaskMem' su' ppwzMimeOut' (come mostrato [qui] (http://stackoverflow.com/a/2826884/1768303)), altrimenti colerà. – Noseratio

+1

Ovviamente;) grazie ancora –