Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

287
Vistas
Excepción al usar Shell32 para obtener propiedades extendidas de archivo

Estoy tratando de usar Shell32 para obtener propiedades de archivo extendidas en C#.

Mi código para esto es el siguiente.

 var file = FileUpload1.PostedFile; List<string> arrHeaders = new List<string>(); Shell shell = new ShellClass(); //Exception is thrown at next line Folder rFolder = shell.NameSpace(Path.GetDirectoryName(file.FileName)); FolderItem rFiles = rFolder.ParseName(Path.GetFileName(file.FileName)); for (int i = 0; i < short.MaxValue; i++) { string value = rFolder.GetDetailsOf(rFiles, i).Trim(); arrHeaders.Add(value); }

Recibo una excepción de la siguiente manera.ingrese la descripción de la imagen aquí

Mensaje: no se puede convertir el objeto COM del tipo 'Shell32.ShellClass' al tipo de interfaz 'Shell32.IShellDispatch6'. Esta operación falló porque la llamada QueryInterface en el componente COM para la interfaz con IID '{286E6F1B-7113-4355-9562-96B7E9D64C54}' falló debido al siguiente error: No se admite dicha interfaz (Excepción de HRESULT: 0x80004002 (E_NOINTERFACE)) .

Seguimiento de pila: en System.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc, IntPtr pCPCMD, IntPtr& ppTarget, Boolean& pfNeedsRelease) en Shell32.ShellClass.NameSpace(Object vDir) en PBSWebApplication.Test.Button1_OnClick(Object sender, EventArgs e) en c: \Projects\PBSWebApplication\PBSWebApplication\PBSWebApplication\Test.aspx.cs:line 33 en System.Web.UI.WebControls.Button.OnClick(EventArgs e) en System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) en System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) en System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) en System.Web.UI.Page.RaisePostBackEvent (NameValueCollection postData) en System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

¿Cómo arreglar esto?

Gracias.

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Como identificó, esto se debe a que Shell32 requiere un subproceso STA. Si no puede simplemente configurar su aplicación para que se ejecute con un subproceso STA como en su solución, entonces, como alternativa, puede crear un subproceso STA separado, usarlo para ejecutar el código Shell32 y luego continuar con la ejecución. por ejemplo, esto es con lo que terminé al escribir una tarea de secuencia de comandos SSIS que, según tengo entendido, siempre se ejecuta en el subproceso MTA. En mi caso, estoy llamando a un método diferente de Shell32 (CopyHere), pero la misma lógica se aplicaría al método que desee llamar:

 /// <summary> /// Ugh! SSIS runs script tasks on MTA threads but Shell32 only wants to /// run on STA thread. So start a new STA thread to call UnZip, block /// till it's done, then return. /// We use Shell32 since .net 2 doesn't have ZipFile and we prefer not to /// ship other dlls as they normally need to be deployed to the GAC. So this /// is easiest, although not very pretty. /// </summary> /// <param name="zipFile">File to unzip</param> /// <param name="folderPath">Folder to put the unzipped files</param> public static void UnZipFromMTAThread(string zipFile, string folderPath) { object[] args = new object[] { zipFile, folderPath }; if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA) { UnZip(args); } else { Thread staThread = new Thread(new ParameterizedThreadStart(UnZip)); staThread.SetApartmentState(ApartmentState.STA); staThread.Start(args); staThread.Join(); } } /// <summary> /// From http://www.fluxbytes.com/csharp/unzipping-files-using-shell32-in-c/ but with /// args packed in object array so can be called from new STA Thread in UnZipFromMTAThread(). /// </summary> /// <param name="param">object array containing: [string zipFile, string destinationFolderPath]</param> private static void UnZip(object param) { object[] args = (object[]) param; string zipFile = (string)args[0]; string folderPath = (string)args[1]; if (!File.Exists(zipFile)) throw new FileNotFoundException(); if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath); Shell32.Shell objShell = new Shell32.Shell(); Shell32.Folder destinationFolder = objShell.NameSpace(folderPath); Shell32.Folder sourceFile = objShell.NameSpace(zipFile); foreach (var file in sourceFile.Items()) { // Flags are: No progress displayed, Respond with 'Yes to All' for any dialog, no UI on error // I added 1024 although not sure it's relevant with Zip files. // See https://msdn.microsoft.com/en-us/library/windows/desktop/bb787866%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 destinationFolder.CopyHere(file, 4 | 16 | 1024); } }
over 4 years ago · Santiago Trujillo Denunciar

0

Resultó ser una solución simple agregar el atributo STAThread a mi clase y el problema desapareció mágicamente.

Aquí está mi código completo después de la actualización.

Nota: Es una aplicación de consola simple.

 class Program { [STAThread] static void Main(string[] args) { Console.Title = "Extended file properties."; List<string> arrHeaders = new List<string>(); Shell32.Shell shell = new Shell32.Shell(); Shell32.Folder objFolder; objFolder = shell.NameSpace(@"C:\Users\Admin\Pictures\PBS Docs"); for (int i = 0; i < short.MaxValue; i++) { string header = objFolder.GetDetailsOf(null, i); if (String.IsNullOrEmpty(header)) break; arrHeaders.Add(header); } foreach (Shell32.FolderItem2 item in objFolder.Items()) { for (int i = 0; i < arrHeaders.Count; i++) { Console.WriteLine("{0}\t{1}: {2}", i, arrHeaders[i], objFolder.GetDetailsOf(item, i)); } } } }
over 4 years ago · Santiago Trujillo Denunciar

0

Tuve un problema similar y la respuesta de jeronevw en este foro me lo solucionó: https://social.msdn.microsoft.com/Forums/vstudio/en-US/b25e2b8f-141a-4a1c-a73c-1cb92f953b2b/instantiate-shell32shell -objeto-en-windows-8?forum=clr

 public Shell32.Folder GetShell32NameSpaceFolder(Object folder) { Type shellAppType = Type.GetTypeFromProgID("Shell.Application"); Object shell = Activator.CreateInstance(shellAppType); return (Shell32.Folder)shellAppType.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, shell, new object[] { folder }); }

Todos los creditos de jeronevw

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda