Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 417 Vote(s) - 3.44 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Exception when using Shell32 to get File extended properties

#1
I am trying to use Shell32 to get extended file properties in c#.

My code for this is as follows.

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);
}

I am getting exception as follows.
![enter image description here][1]


[1]:



Message - Unable to cast COM object of type 'Shell32.ShellClass' to interface type 'Shell32.IShellDispatch6'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{286E6F1B-7113-4355-9562-96B7E9D64C54}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

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

How to fix this?

Thanks.
Reply

#2
As you identified this is because Shell32 requires an STA thread. If you can't simply configure your app to run with an STA Thread as in your solution then as an alternative you can create a separate STA Thread, use it to run the Shell32 code, then continue execution. e.g. [this][1] is what I ended up with when writing an SSIS Script Task which as I understand it always runs on MTA thread. In my case I'm calling a different method of Shell32 (CopyHere) but same logic would apply whichever method you want to call:

/// <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

[To see links please register here]

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

[To see links please register here]

destinationFolder.CopyHere(file, 4 | 16 | 1024);
}
}


[1]:

[To see links please register here]

Reply

#3
I had simliar issue and the answer from jeronevw on this forum fixed it for me:

[To see links please register here]


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 });
}

All credits for jeronevw
Reply

#4
It turned out to be simple solution to add `STAThread` attribute to my class and the problem is vanished magically.

Here is my complete code after update.

> Note: It is simple console application.

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));
}
}
}
}
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through