4

When using something like DotPeek to decompile a DLL, how do I tell whether it was originally coded in VB.Net or C#?

I gather there's no easy way to tell, but that there may be tell-tale signs (ie. clues) in some of the decompiled code?

codeulike
  • 22,514
  • 29
  • 120
  • 167

6 Answers6

7

You can look for a reference to the Microsoft.VisualBasic library. If that is present, it's very probable that the code was made using VB. The library is sometimes included in C# projects also, but that is not very common. If the reference is not there, it's certainly not VB.

(Well, it's possible to compile VB without the library using the command line compiler and special compiler switches, but that is extremely rare.)

You can also check how frequently the VisualBasic library is used. In a regular VB program it would be used often, but in a C# program it would typically only be used for some specific task that isn't available in other libraries, like a DateDiff call.

Any VB specific commands, like CInt or Mid will show up as calls to the VisualBasic library, and even the = operator when used on strings, will use the library. This code (where a and b are strings):

If a = b Then

will actually make a library call to do the comparison, and shows up like this when decompiled as C#:

if (Operators.CompareString(a, b, false) == 0) {
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • Ah, thats a great answer, thanks. Like you say, people sometimes reference this Assembly from C#, but then they would typically only use specific bits of it – codeulike Mar 03 '13 at 11:02
  • 2
    *If the reference is not there, it's [almost] certainly not VB.* If you're just trying to decide between VB and C#, thats a very strong clue – codeulike Mar 03 '13 at 11:26
3

One posible route might be to look for Named Indexers; It isn't allowed in C# i.e. you can only have the following in c#

object this [int index] {get;set;}

but in managed C++ and VB.Net (I believe, will delete this if I'm wrong) it appears you can have named indexers.

So at least you could narrow it down to whether or not it was C#

Meirion Hughes
  • 24,994
  • 12
  • 71
  • 122
  • But what if the original code doesn't use this rare feature of named indexers? I say rare because, well, C# doesn't support it. – Darin Dimitrov Mar 03 '13 at 10:50
  • Well it wouldn't work, but at least it is a specific language restriction. Maybe the are more obscure ones? I don't know. – Meirion Hughes Mar 03 '13 at 10:54
  • @David Thanks, this is exactly the sort of clue I'm looking for. I suspect there are many other specifics like this that might be clues. – codeulike Mar 03 '13 at 10:55
2

For completeness, I'll post the clue that I'm aware of:

If you decompile to C# and find invalid member names starting with $static$:

private short $STATIC$Report_Print$20211C1280B1$nHeight;

... that means it was probably VB.Net, because the compiler uses those to implement the 'Static' VB keyword.

Hans Passant and Jon Skeet explain it better over here: https://stackoverflow.com/a/7311567/22194 https://stackoverflow.com/a/7310497/22194

Community
  • 1
  • 1
codeulike
  • 22,514
  • 29
  • 120
  • 167
2

I'm surprised noone has mentioned the My namespace yet. It is very hard to get the VB.NET compiler to not include some of its helper classes in the output.

Mark Hurd
  • 10,665
  • 10
  • 68
  • 101
1

how do I tell whether it was originally coded in VB.Net or C#?

You can't tell that in a reliable manner. Well of course IL compiled with the VB.NET compiler will include references to some VB specific assemblies (such as Microsoft.VisualBasic), but there's nothing preventing a C# project also reference and use those assemblies.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • I believe there may be ways, e.g. see http://stackoverflow.com/questions/7310331/decompiling-vb-net-assembly-produces-code-with-invalid-member-variable-names-na – codeulike Mar 03 '13 at 10:43
  • Those are implementation details of the compiler you should never rely upon as they might change in future releases of the compiler. – Darin Dimitrov Mar 03 '13 at 10:44
  • I would be happy to accept answers based on implementation details that may change. I'm looking for clues, not a sure-fire method that works forever. – codeulike Mar 03 '13 at 10:46
  • Hmm, what are these VB-specific assemblies you mention? That sounds like a good clue. – codeulike Mar 03 '13 at 10:56
  • 1
    @codeulike, it's the `Microsoft.VisualBasic` assembly. I repeat once again - there's absolutely nothing preventing a C# project to reference and use this assembly as it contains some useful methods. – Darin Dimitrov Mar 03 '13 at 10:58
  • Right, but if someone uses it from C#, they'll probably use it in specific ways. See great answer by Guffa here: http://stackoverflow.com/a/15184955/22194 – codeulike Mar 03 '13 at 11:14
0

To build on the ideas introduced in the other answers, the assembly does not report what language was used to write it, but you may look for non-cls compliant code

Being CLS compliant means that the code is written against features available to all CLS compliant languages. Which means that there are no public nested classes or named indexers and probably a number of other features that IL may support but any particular language may not.

If it is an option, you could probably just look at the PDBs.

Phillip Scott Givens
  • 5,256
  • 4
  • 32
  • 54
  • this sounds promising, but is there some difference between VB.Net and C# that will show up here? Don't both of them use public nested classes, for example? – codeulike Mar 03 '13 at 11:03
  • 2
    That is true; they both do. Since IL is designed to be language agnostic, it is left as a exercise for the reader to find all of the features supported by one language and not another. At the end of the day, you cannot be sure that the assembly had a language at all and was created purely in ILAsm. – Phillip Scott Givens Mar 03 '13 at 11:16
  • 2
    *At the end of the day, you cannot be sure that the assembly had a language at all and was created purely in ILAsm.* Thats a very good point! I see that this can never be deterministic – codeulike Mar 03 '13 at 11:27