Category: 32bit-64bit

How can I test a Windows DLL file to determine if it is 32 bit or 64 bit?

I’d like to write a test script or program that asserts that all DLL files in a given directory are of a particular build type.

I would use this as a sanity check at the end of a build process on an SDK to make sure that the 64-bit version hasn’t somehow got some 32-bit DLL files in it and vice versa.

Is there an easy way to look at a DLL file and determine its type?

The solution should work on both xp32 and xp64.

Comments:


Gory details

A DLL uses the PE executable format, and it’s not too tricky to read that information out of the file.

See this MSDN article on the PE File Format for an overview. You need to read the MS-DOS header, then read the IMAGE_NT_HEADERS structure. This contains the IMAGE_FILE_HEADER structure which contains the info you need in the Machine member which contains one of the following values

  • IMAGE_FILE_MACHINE_I386 (0x014c)
  • IMAGE_FILE_MACHINE_IA64 (0x0200)
  • IMAGE_FILE_MACHINE_AMD64 (0x8664)

This information should be at a fixed offset in the file, but I’d still recommend traversing the file and checking the signature of the MS-DOS header and the IMAGE_NT_HEADERS to be sure you cope with any future changes.

Use ImageHelp to read the headers…

You can also use the ImageHelp API to do this – load the DLL with LoadImage and you’ll get a LOADED_IMAGE structure which will contain a pointer to an IMAGE_NT_HEADERS structure. Deallocate the LOADED_IMAGE with ImageUnload.

…or adapt this rough Perl script

Here’s rough Perl script which gets the job done. It checks the file has a DOS header, then reads the PE offset from the IMAGE_DOS_HEADER 60 bytes into the file.

It then seeks to the start of the PE part, reads the signature and checks it, and then extracts the value we’re interested in.

#!/usr/bin/perl
#
# usage: petype <exefile>
#
$exe = $ARGV[0];

open(EXE, $exe) or die "can't open $exe: $!";
binmode(EXE);
if (read(EXE, $doshdr, 64)) {

   ($magic,$skip,$offset)=unpack('a2a58l', $doshdr);
   die("Not an executable") if ($magic ne 'MZ');

   seek(EXE,$offset,SEEK_SET);
   if (read(EXE, $pehdr, 6)){
       ($sig,$skip,$machine)=unpack('a2a2v', $pehdr);
       die("No a PE Executable") if ($sig ne 'PE');

       if ($machine == 0x014c){
            print "i386n";
       }
       elsif ($machine == 0x0200){
            print "IA64n";
       }
       elsif ($machine == 0x8664){
            print "AMD64n";
       }
       else{
            printf("Unknown machine type 0x%lxn", $machine);
       }
   }
}

close(EXE);

Answers:

If you have Cygwin installed (which I strongly recommend for a variety of reasons), you could use the ‘file’ utility on the DLL

file <filename>

which would give an output like this:

icuuc36.dll: MS-DOS executable PE  for MS Windows (DLL) (GUI) Intel 80386 32-bit

Answers:

A crude way would be to call dumpbin with the headers option from the Visual Studio tools on each DLL and look for the appropriate output:

dumpbin /headers my32bit.dll

PE signature found

File Type: DLL

FILE HEADER VALUES
             14C machine (x86)
               1 number of sections
        45499E0A time date stamp Thu Nov 02 03:28:10 2006
               0 file pointer to symbol table
               0 number of symbols
              E0 size of optional header
            2102 characteristics
                   Executable
                   32 bit word machine
                   DLL

OPTIONAL HEADER VALUES
             10B magic # (PE32)

You can see a couple clues in that output that it is a 32 bit DLL, including the 14C value that Paul mentions. Should be easy to look for in a script.

Answers:

Dependency Walker tells all(well almost).
http://www.dependencywalker.com/

It does not “install” -just get it, extract it and run the exec.
It works for any x32 or x64 windows module|application.

As I recall it is fairly straightforward to see all dependencies, i.e. the dll modules, and since the appl. is a sum of the dependencies one can ascertain if it is full x64, x32(x86) or a bit of each.

Type of CPU that the module was built for is in the “CPU” column. Most 64-bit aps are still a bit of each but 32-bit ap w/b all x86.

Beautiful program for geeks/programmers and it is free…

Answers:

I have written a very simple tool that does exactly that – it’s called PE Deconstructor.

Simply fire it up and load your DLL file:

enter image description here

In the example above, the loaded DLL is 32-bit.

You can download it here (I only have the 64-bit version compiled ATM):
http://files.quickmediasolutions.com/exe/pedeconstructor_0.1_amd64.exe

An older 32-bit version is available here:
http://dl.dropbox.com/u/31080052/pedeconstructor.zip

Answers:

Running a C# application as 32-bit on a 64-bit machine

How do I force my application to run as 32-bit on a 64-bit machine?

The code is written in C#.

Comments:


Assuming this is a Winforms, console app, or Windows service you have to build the exe for x86 instead of Any CPU. It’s in the Configuration Manager.

Answers:

If you go to Configuration Manager in Visual Studio you can set the platform to x86 or x64.

Answers:

Right click your project, and select properties.

In properties, select the build tab. Under platform target, select x86.

Hit Ctrl+Shift+S to save all files, right click the solution and select “Clean” to get rid of old binaries. Any builds after that should be 32 bit

Answers:

Here’s how I did it when we couldn’t change the existing code from Any CPU to x86 due to a ClickOnce limitation:

Create a 32-bit (x86 must be checked under project properties) ‘launcher’ application (Windows Application but not form):

static void Main(string[] args)
{
    // Load the assembly    
    string directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    string assemblyName = Path.Combine(directory, "YourAnyCPUApplication.exe");
    Assembly assembly = Assembly.LoadFile(assemblyName);
    assembly.EntryPoint.Invoke(null, null);
}

Add the following code to the Main method in the Any CPU project:

if (IntPtr.Size == 4)
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    // etc...
}
else
{
    // Launch application in 32-bit mode
    System.Diagnostics.Process.Start(Path.GetDirectoryName(Application.ExecutablePath)
                                     + @"Your32BitApplicationLauncher.exe");
}

I hope this helps 🙂

Answers:

Command-line form:

corflags application.exe /32BIT+ 

Answers:

Setting the project to x86 will prevent the file from executing on non-x86 platforms such as ARM. Since Visual Studio 11 and .NET framwork 4.5 there’s a new option named Any CPU 32-bit preferred and this was the default since then. The resulting code will run on any platforms but on 64-bit platforms they are run as 32-bit processes

Further reading

Answers: