0

Is there a command line tool that tells me whether a given .Net assembly makes use of COM interop services?

Example that does not make use of COM interop:

internal class ServerClass { }

Example that does:

[ComImport]
[Guid("114383E9-1969-47D2-9AA9-91388C961A19")]
internal class ServerClass { }
Evgeniy Berezovsky
  • 18,571
  • 13
  • 82
  • 156
  • Does this answer your question? [How to detect if a dll is a COM dll](https://stackoverflow.com/questions/28305017/how-to-detect-if-a-dll-is-a-com-dll) – Ibrennan208 Jun 08 '22 at 07:34
  • Possibly already answered: https://stackoverflow.com/questions/1420726/how-can-i-detect-the-type-of-a-dll-com-net-win32 – Ibrennan208 Jun 08 '22 at 07:35
  • @Ibrennan208 I may be misunderstaning COM interop (in fact, I am honestly pretty clueless about it), but afaict the questions you list are about providers of COM interop services, not consumers (whatever the correct terminology for these concepts may be). – Evgeniy Berezovsky Jun 08 '22 at 07:41
  • So you're asking if there's a way to tell if an assembly is calling another assembly that uses COM interop? – Ibrennan208 Jun 08 '22 at 07:47
  • Maybe this: https://stackoverflow.com/a/3011431/3579174 – Ibrennan208 Jun 08 '22 at 07:49
  • @Ibrennan208 The links you are throwing at me seem to be about detecting whether a dll exports such services, not imports them. – Evgeniy Berezovsky Jun 08 '22 at 07:51
  • Do you have the source code for these assemblies you are working with? Would you be able to use a tool to scan all of their attributes to find the ones that are using COM related attributes? – Ibrennan208 Jun 08 '22 at 07:55
  • If not, then you would probably have to look at the reference links they have to any packages that are COM based and inspect the files created with the assemblies at compile time. If that's the case, refer to the links I posted. – Ibrennan208 Jun 08 '22 at 07:57
  • You have to load that assembly and then scan all classes for the given attributes. – Oliver Jun 08 '22 at 07:58

2 Answers2

1

I suspect the answer is no.

But you could build one. Start with the output of a decompiler and look for use of types and methods unique to COM interop (eg. Type.GetTypeFromProgID).

Richard
  • 106,783
  • 21
  • 203
  • 265
1

It seems that class and interfaces imported from COM - and that is all that can be COM imported - can be grepped with a simple regular expression (or what findstr considers a regular expression - note the escaped space, which would otherwise be taken for an "OR" - i.e. a | in most regex languages):

> ildasm /text NetClient.exe | findstr "\.class.*\ import "
.class interface private abstract auto ansi import NetClient.IServer
.class interface private abstract auto ansi import NetClient.Server
.class private auto ansi import beforefieldinit NetClient.ServerClass

I've tested this with a bunch of dlls already and there was no false positive - I only hope there were no false negatives either...

Also - thanks Simon in the comments - CreateInstance() can be used to load dlls dynamically at runtime, so it should be checked as well (using grep this time instead of findstr, due to the latter's unusual and limited regexp syntax):

> ildasm /text file.dll \
| grep -E 'call.*System.Activator|Reflection.Assembly)::CreateInstance'

N.B. ildasm should come installed with Visual Studio, and is easiest to call when using the Visual Studio Developer Command Prompt.

Evgeniy Berezovsky
  • 18,571
  • 13
  • 82
  • 156
  • 1
    Type.GetTypeFromCLSID/GetTypeFromProgID + Activator.CreateInstance can be used to create COM objects. You can also DllImport CoCreateInstance. Not sure what you're trying to do. – Simon Mourier Jun 08 '22 at 09:27
  • @SimonMourier Using COM services are one possible cause of ".Net internal error"s. I want to see which dlls do not use COM services (and unmanaged or unsafe code, and pinvoke, and native libraries), and which do, so that I can concentrate on the latter for finding the culprit. – Evgeniy Berezovsky Jun 08 '22 at 09:57
  • You can certainly determine a .dll is using "something" with greps but if greps gives you nothing, it doesn't mean it's not using it, ie: false negative are always possible. Worst if the .dll wants to hide things or not. – Simon Mourier Jun 08 '22 at 10:50
  • @SimonMourier I will have to look into your suggestions in the first comment and see if my current solution can be extended. As the dlls are all selected by us, I'm not suspecting the dlls in question to be actively trying to hide something from us, but the ways to import dlls you mention look like legit ways, judging from the names, so they may be used for legitimate reasons... – Evgeniy Berezovsky Jun 08 '22 at 10:56
  • @SimonMourier I have also checked the dlls for Activator.CreateInstance() and Assembly.CreateInstance(). As for CoCreateInstance, that cannot be called from managed code without pinvoke, which I am already checking, so I don't need a special case for this. – Evgeniy Berezovsky Jun 08 '22 at 12:13
  • There is a lot of COM usage that you can't see this way. Beyond late binding, any indirect dependency isn't obvious. There is a lot of it. If the assembly starts a thread then it uses COM. If it throws an exception then it uses COM. Lots of .NET framework assemblies use COM (System.Management, System.DirectoryServices, System.Automation, System.Windows.Forms, PresentationFramework, etc). It just isn't special. – Hans Passant Jun 08 '22 at 13:07
  • 1
    The better mousetrap is to use the [portability analyzer](https://learn.microsoft.com/en-us/dotnet/standard/analyzers/portability-analyzer). When it says that there is a problem then odds are pretty high that there's a COM interface under the floor mat. – Hans Passant Jun 08 '22 at 13:14
  • @HansPassant Thanks for the portability analyzer tip! Very useful! Regarding .Net framework usage of COM, we kind of take this as a "given", nothing we can do about really, short of switching to Java (which we have done for some of our projects). – Evgeniy Berezovsky Jun 08 '22 at 13:48