首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Shell32获取文件扩展属性时出现异常

使用Shell32获取文件扩展属性时出现异常
EN

Stack Overflow用户
提问于 2015-07-14 18:22:42
回答 3查看 12.6K关注 0票数 21

我正在尝试使用Shell32来获取c#中的扩展文件属性。

我的代码如下所示。

代码语言:javascript
复制
        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);
        }

我得到的异常如下。

消息-无法将类型为'Shell32.ShellClass‘的COM对象强制转换为接口类型'Shell32.IShellDispatch6’。此操作失败,原因是由于以下错误,对COM组件的QueryInterface调用失败:不支持此类接口(来自HRESULT的异常: 0x80004002 (E_NOINTERFACE))。

堆栈跟踪-在System.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc,IntPtr pCPCMD,IntPtr& ppTarget,Boolean& pfNeedsRelease)在Shell32.ShellClass.NameSpace(Object vDir)在PBSWebApplication.Test.Button1_OnClick(Object sender,e)在System.Web.UI.WebControls.Button.OnClick(EventArgs e)在System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)在System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)在System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl,字符串eventArgument) at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint,Boolean includeStagesAfterAsyncPoint)

如何解决这个问题?

谢谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-02-22 00:19:52

正如您所确定的,这是因为Shell32需要STA线程。如果你不能像在你的解决方案中那样简单地配置你的应用程序使用STA线程运行,那么作为替代方案,你可以创建一个单独的STA线程,使用它来运行Shell32代码,然后继续执行。例如,this是我在编写SSIS脚本任务时得到的结果,据我所知,它总是在MTA线程上运行。在我的例子中,我调用了一个不同的Shell32方法(CopyHere),但同样的逻辑也适用于您想调用的任何方法:

代码语言:javascript
复制
    /// <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); 
        }
    }
票数 23
EN

Stack Overflow用户

发布于 2015-07-14 19:16:55

事实证明,向我的类添加STAThread属性是一个简单的解决方案,这个问题神奇地消失了。

这是我更新后的完整代码。

注意:这是一个简单的控制台应用程序。

代码语言:javascript
复制
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));
            }
        }
     }
}
票数 7
EN

Stack Overflow用户

发布于 2017-11-13 19:59:25

我有类似的问题,jeronevw在这个论坛上的回答为我解决了这个问题:https://social.msdn.microsoft.com/Forums/vstudio/en-US/b25e2b8f-141a-4a1c-a73c-1cb92f953b2b/instantiate-shell32shell-object-in-windows-8?forum=clr

代码语言:javascript
复制
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 });
}

jeronevw的所有学分

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31403956

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档