question

YitongPhou-7639 avatar image
0 Votes"
YitongPhou-7639 asked YitongPhou-7639 answered

Can the Shell32.dll be used in the IIS environment?

I have a console exe program that used shell32.dll (compiled in dotnetCore 5). It works. However, when I used it in IIS environment (called it from CONTROLLERS) and it doesn't work.

I wonder that is a restriction especially for the shell32.dll?
If there is a restriction, what would be the other DLLs that have features like shell32.dll I can use?

Here is the message I got.
System.InvalidCastException
HResult=0x80004002
Message=Unable to cast COM object of type 'System.__ComObject' to interface type 'Shell32.Shell'. 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 (0x80004002 (E_NOINTERFACE)).
Source=System.Private.CoreLib
StackTrace:
at System.Runtime.CompilerServices.CastHelpers.ChkCastAny(Void* toTypeHnd, Object obj)

dotnet-aspnet-core-webapi
· 6
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi @YitongPhou-7639,

I have a console exe program that used shell32.dll (compiled in dotnetCore 5). It works. However, when I used it in IIS environment (called it from CONTROLLERS) and it doesn't work.

From your description, I assume there have two applications: the console application used the shell32.dll and the API/MVC application (which have the controller). Then, in the API/MVC application, you will call the console application, right? In this scenario, when the API/MVC application running in the local, whether it can call the console exe program successful?

Besides, in the IIS environment, try to set the application pool identity as the Administrator.

142283-image.png


0 Votes 0 ·
image.png (20.4 KiB)

It still did not work.

0 Votes 0 ·

Here is the code controllers:

public JsonResult xxxx()
{
List<ClassMediaMetaData> list = new();
FILE_PATH = @"D:\medias";
string Folder = FILE_PATH.TrimEnd(Path.DirectorySeparatorChar).Split(Path.DirectorySeparatorChar).Last();
//UpdateMenuAmericanMusicItems(Folder);
list = Helpers.MediaMetaData.SingleDir(FILE_PATH);
foreach (ClassMediaMetaData d in list) {
Console.WriteLine(d.FullFileName);
}
return new JsonResult("pass xxxx");
}

0 Votes 0 ·

.code In HELPERS:
class MediaMetaData
{
[STAThread]
public static List<ClassMediaMetaData> SingleDir(string folder)
{
return GetFilesSingleDir(folder);
}
private static List<ClassMediaMetaData> GetFilesSingleDir(String folder)
{
TimeSpan dur = TimeSpan.Zero;
Shell32.Shell shell = new Shell32.Shell();
Shell32.Folder objFolder = shell.NameSpace(folder);
List<ClassMediaMetaData> list = new();
list.Clear();
foreach (FolderItem2 item in objFolder.Items())
{
if (!item.IsFolder)
{
ClassMediaMetaData md = new ClassMediaMetaData();
dur = TimeSpan.FromSeconds(item.ExtendedProperty("System.Media.Duration") / 10000000);
md.Duration = dur.Duration();
md.FullFileName = item.Name;
md.FullPath = folder;
list.Add(md);
}
}
return list;
}


0 Votes 0 ·

I did write a console app and the console app is working. Then I use the class that is working and put it in Helpers folder (MVC environment).

But it doesn't work in the MVC (IIS environment).

i hope I make it clear.

Thank you.

0 Votes 0 ·

I have a sample app that works with Shell32.dll. Here is my git https://github.com/d052057/TestShellAPI. This app does work with VS2019 (dotnet core 5).




0 Votes 0 ·
cooldadtx avatar image
0 Votes"
cooldadtx answered YitongPhou-7639 commented

Yes it can work but the issue isn't with shell32 which is where the bulk of the Shell APIs reside. For example ShellExecute resides there and that is used when you call Process.Start with UseShellExecute set. Problems occur when you try to use APIs that are designed for desktop users in a web app that doesn't have such a thing. Where the actual problem is depends upon exactly what you're trying to call and since you didn't tell us that it is hard to say.

Out of the box your app pool is probably not loading the user profile of the user account under which it runs. Hence there is no user profile loaded and none of the APIs relying on that works. Setting the app pool to load the user profile has a negative impact on performance but can solve issues in some cases.

The web app itself is running in a non-interactive environment and therefore most APIs related to the UI will also not work. This appears to be what you might be doing here. You're trying to get the Shell object which may or may not be available. Posting the code you wrote that you are trying to get working would be helpful for us.

You mentioned a console app so I suspect you might be trying to start the process from a web app and it is then failing. That could just be related to you not passing the right startup options (or you might need to ensure the user profile for the app pool is loaded).

· 12
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

i have written a console application and use this class

class MediaMetaData

{
[STAThread]
public static List<ClassMediaMetaData> SingleDir(string folder)
{
return GetFilesSingleDir(folder);
}
private static List<ClassMediaMetaData> GetFilesSingleDir(String folder)
{
TimeSpan dur = TimeSpan.Zero;
Shell32.Shell shell = new Shell32.Shell();
Shell32.Folder objFolder = shell.NameSpace(folder);
List<ClassMediaMetaData> list = new();
list.Clear();
foreach (FolderItem2 item in objFolder.Items())
{
if (!item.IsFolder)
{
ClassMediaMetaData md = new ClassMediaMetaData();
dur = TimeSpan.FromSeconds(item.ExtendedProperty("System.Media.Duration") / 10000000);
md.Duration = dur.Duration();
md.FullFileName = item.Name;
md.FullPath = folder;
list.Add(md);
}
}
return list;
}

...
and the console app is working (it retrieves files in a directory with duration and name and path).
Now, I know this piece of code is working and give right information. Then I used this piece of code in MVC controllers.
When I debug it it stop at Shell32.Shell shell = new Shell32.Shell();

In the project, I did add COM reference the same way I did it in the console application.

I hope I this will make sense.

Thank you.


0 Votes 0 ·

i have written a console application and use this class

class MediaMetaData

{
[STAThread]
public static List<ClassMediaMetaData> SingleDir(string folder)
{
return GetFilesSingleDir(folder);
}
private static List<ClassMediaMetaData> GetFilesSingleDir(String folder)
{
TimeSpan dur = TimeSpan.Zero;
Shell32.Shell shell = new Shell32.Shell();
Shell32.Folder objFolder = shell.NameSpace(folder);
List<ClassMediaMetaData> list = new();
list.Clear();
foreach (FolderItem2 item in objFolder.Items())
{
if (!item.IsFolder)
{
ClassMediaMetaData md = new ClassMediaMetaData();
dur = TimeSpan.FromSeconds(item.ExtendedProperty("System.Media.Duration") / 10000000);
md.Duration = dur.Duration();
md.FullFileName = item.Name;
md.FullPath = folder;
list.Add(md);
}
}
return list;
}

...
and the console app is working (it retrieves files in a directory with duration and name and path).
Now, I know this piece of code is working and give right information. Then I used this piece of code in MVC controllers.
When I debug it it stop at Shell32.Shell shell = new Shell32.Shell();

In the project, I did add COM reference the same way I did it in the console application.

I hope I this will make sense.
Thank you.


0 Votes 0 ·

Since this is a separate console app, bitness shouldn't be an issue. I assume you are pointing to a folder that your web app has read/write access to? Note that web apps run in a sandbox so you generally have to grant them access to folders outside the current web directory.

Have you enabled the "Load User Profile" option in the app pool for your web app?

0 Votes 0 ·

I don't think read/write permission would be the issue based upon the error message (the issue is the Shell32.dll).
I tried to the 'Load User Profile' (see the image attached), however I still have the same problem.
142764-authen.png


0 Votes 0 ·
authen.png (6.7 KiB)
Show more comments
YitongPhou-7639 avatar image
0 Votes"
YitongPhou-7639 answered
 using System;
 using System.Collections.Generic;
 using Shell32;
 using System.Threading;
    
 namespace ShellTestAPI.Helpers
 {
     class MediaMetaData
     {
         //[STAThread]
         public static List<FileMetaData> SingleDir(string folder)
         {
             List<FileMetaData> results = null;
    
             var thread = new System.Threading.Thread(() => {
                 results = GetFilesSingleDir(folder);
             });
    
 #pragma warning disable CA1416 // Validate platform compatibility
             thread.SetApartmentState(ApartmentState.STA);
 #pragma warning restore CA1416 // Validate platform compatibility
             thread.Start();
             thread.Join();
    
             return results;
         }
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

YitongPhou-7639 avatar image
0 Votes"
YitongPhou-7639 answered

Please view https://github.com/d052057/ShellTestAPI for the answer. It works with VS2019 - dotnet core 5.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.