0

This is probably a noob question but seems that despite checking 15+ resources I'm still missing one thing in working with COM interfaces in .NET.

I'd like to unzip a file using Windows Shell. (My goals: works with Windows XP and higher, no 3rd party Zip libraries, no .DLL coming along with my exe, .) Simply instantiate Shell.Application COM object and call its methods. (Minimalistic approach.)

I can handle it using early binding (source, builds OK):

Dim sc As New Shell32.ShellClass()
Dim SrcFlder As Shell32.Folder = sc.NameSpace(sourceFilename)
Dim DestFlder As Shell32.Folder = sc.NameSpace(destinationDirName)
Dim Items As Shell32.FolderItems = SrcFlder.Items()
DestFlder.CopyHere(Items, 16) '16 = Respond with "Yes to All"

I can also handle it using late binding in , where I'm experienced. But I'm not sure how to use late binding in when it comes to types inside the COM module. First two lines of the following converted code work, but how to create variable of type Shell32.folder? It is not a public type (registered in Windows Registry) like Shell.Application is.

Dim st As Type = Type.GetTypeFromProgID("Shell.Application", True)
Dim sc As Object = Activator.CreateInstance(st, True)

'how to instantiate the following 'Shell32.Folder' and 'Shell32.FolderItems' types?
'Dim SrcFlder As Shell32.Folder = sc.NameSpace("d:\test.zip")
'Dim DestFlder As Shell32.Folder = sc.NameSpace("d:\test")
'Dim Items As Shell32.FolderItems = SrcFlder.Items()

'this will be called probably through the reflection, correct?
'DestFlder.CopyHere(Items, 16)  '16 = Respond with "Yes to All"

Reagrding this example: I'm not primarily asking about unzipping (although I need it), but I'd like to correctly work with COM objects in .NET using late binding (not only using early binding).

Matt Wilko
  • 26,994
  • 10
  • 93
  • 143
miroxlav
  • 11,796
  • 5
  • 58
  • 99

1 Answers1

1

You need to use CreateObject and define each object as just Object

Example (untested):

Dim sc As Object = CreateObject("Shell32.ShellClass")
Dim SrcFlder As Object = sc.NameSpace(sourceFilename)
Dim DestFlder As Object = sc.NameSpace(destinationDirName)
Dim Items As Object= SrcFlder.Items()
DestFlder.CopyHere(Items, 16) '16 = Respond with "Yes to All"

Note that this won't compile with Option Strict On

However I will say that you should try and do early binding wherever possible.

Matt Wilko
  • 26,994
  • 10
  • 93
  • 143
  • I've already tried this before and I'm still getting "Cannot create ActiveX component." at line 1 during runtime. The only approach that worked for me was that `GetTypeFromProdID` followed by `CreateInstance` – miroxlav Oct 06 '14 at 12:02
  • As you say, I prefer early binding, too, but in this case requested functionality seems minimal, so I don't want to attach DLL to the tool, which was intended as single exe. – miroxlav Oct 06 '14 at 12:04
  • Both early binding and late binding require the appropriate DLL to be in place on the target machine. – Matt Wilko Oct 06 '14 at 12:08
  • So if I understand correctly, is it enough to reference the one in Windows folder? It is always present on Windows XP and higher. – miroxlav Oct 06 '14 at 12:19
  • Thank you for the answer. **For the record I'm noting here that unzipping approach using the shell library doesn't work properly for on my Windows 8 computer, there are strange errors during the extraction and files cannot be extracted.** I must find some other approach. – miroxlav Oct 06 '14 at 12:44
  • For whoever may read this, one important addition. Due to some reason, the program compiled correctly, but it was false positive. Few hours later, it was giving the following error instead: `Interop type 'ShellClass' cannot be embedded. Use the applicable interface instead.` That finally revealed true problem of strange behavior and after [changing object name from ShellClass to Shell](http://blogs.msdn.com/b/mshneer/archive/2009/12/07/interop-type-xxx-cannot-be-embedded-use-the-applicable-interface-instead.aspx) the COM object started working correctly. – miroxlav Oct 06 '14 at 22:28