14

I want to create a manifest file for my VB 6.0 program, so that when I launch my application, the OS should ask the user for administrator privilege.

I also want to know how it can be embedded in the application?

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
nightfire001
  • 759
  • 3
  • 20
  • 50

2 Answers2

27

You don't actually create the manifest file in VB. A Windows application manifest is a standard text document, formatted as XML. You can create it in Notepad and save it with the appropriate file name in your application's directory (YourAppName.exe.manifest).

Microsoft has more information available here: Application Manifests. It even includes a sample manifest that you can simply copy and paste into a blank text file to get started.

The important thing, if you want your application to prompt the user for elevation, is to set the requestedExecutionLevel to requireAdministrator, rather than asInvoker. Specific information on using manifests with UAC is available here.

So a full sample might look something like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
  <assemblyIdentity
     version="1.0.0.0"
     processorArchitecture="*"
     name="MyMagicalApplication"
     type="win32"
  /> 
  <description>Sample manifest for your super cool application</description> 

  <!-- Request version 6 of the common controls. -->
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
        type="win32"
        name="Microsoft.Windows.Common-Controls"
        version="6.0.0.0"
        processorArchitecture="*"
        publicKeyToken="6595b64144ccf1df"
        language="*"
      />
    </dependentAssembly>
 </dependency>

  <!-- Identify the application security requirements. -->
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="requireAdministrator"
          uiAccess="false"
        />
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

The traditional way to embed a manifest into an executable is using the mt.exe utility, available as part of the Windows SDK.

The VBAccelerator site also has some information about embedding manifests in a VB 6 application. Specifically, it says:

There are two ways to provide the manifest: the simplest (but least elegant) way is to provide the manifest on disk for an executable. Let's say your application is called TimeSlot.exe. Then if you save the manifest XML above as

TimeSlot.exe.manifest

in the same directory as the executable, TimeSlot.exe will automatically get the XP styles. VB5 and VB6 examples are provided. If you rename the .manifest file prior to running the app, you can switch off the XP styles.

A more robust method is to compile the manifest as a resource in your application. To do this, the manifest must appear as resource type RT_MANIFEST (24) with id CREATEPROCESS_MANIFEST_RESOURCE_ID (1). For some bizarre reason, you must also ensure that the resulting XML file is an even multiple of 4 bytes long. So for example, if your file is actually 597 bytes you need to add padding spaces to make up the file size to 600 bytes before compiling. The Resource examples demonstrate how to create this resource file using a resource compiler script (.rc file) and RC.exe.

But if you want to embed the manifest automatically when you build your application from the VB 6 IDE, you're in for a little more difficulty. The VB 6 IDE doesn't support post-build steps, so you can't simply run mt.exe on the command line to do it for you. There are a couple of utilities I've seen around the web that claim to automatically embed manifests for you, but I believe most of these are older utilities that only handle requesting v6 of ComCtl32.dll. I'm not sure if they're easily extensible to include the UAC permissions as well, but it's worth a shot. Here are some links to check out:

Community
  • 1
  • 1
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • MMM can create manifests that go beyond CC6 and execution level selection to create the entries for reg-free COM and DLL redirection as well. UMMM attempts to clone its operation and in large part succeeds. MMM definately can embed the manifest. There are also 3rd party commercial tools. – Bob77 Apr 22 '11 at 14:55
  • 2
    @Bob: If you know more about the details of embedding manifests with these tools, please feel free to post an answer. You won't be stealing my thunder. I haven't built an app in VB 6 that required elevation, so I've never put any of these tools through their paces. I vaguely remembered using something like MMM to make my testing cycles easier back in the days of XP, but I always fell back to `mt.exe` before deployment. – Cody Gray - on strike Apr 22 '11 at 14:56
  • 1
    @Cody Gray: You are absolutey right. By using mt.exe we can easily embed the manifest. – nightfire001 Apr 22 '11 at 15:52
  • @Cody: No, I think you covered it well enough for the purpose at hand. There are lots of other issues but they relate to specific cases other than process elevation. For example selecting CC6 means you need to load first shell32.dll and then comctl32.dll prior to first Form load to avoid fatal conflicts. That's another topic though. – Bob77 Apr 22 '11 at 16:22
  • @Bob: You mean that you have to *explicitly* load shell32.dll? I didn't know that. I've never had any trouble with projects where I didn't do that. I'd have thought that DLL was automatically placed in the import table for VB 6 applications because it's used by the runtime behind-the-scenes. – Cody Gray - on strike Apr 23 '11 at 08:24
  • @Cody: Loading shell32 prevents crashes on process shut-down only on XP prior to SP2. On latest OSes doesn't hurt to call `LoadLibrary` just in case. Also, the easiest way to embed manifest file is just to include it in the project's .res file (with proper resource editor). To VB6 compiler the .res file is "opaque" and it's passed to linker "as is". I'm always doing it this way for my "regular" builds and no post-build step is needed. For portable builds UMMM takes care of calling `mt.exe` to embed generated manifest for reg-free activation. – wqw Apr 23 '11 at 08:51
  • @Cody: XP SP3 can have the same problems. This was discussed and beaten to death in http://www.vbforums.com/showthread.php?t=628956 Remember that we're doing SxS selection of libraries so the sequence they get loaded can be critical. You don't need to use LoadLibrary, just call a no-op entrypoint like IsUserAnAdmin. – Bob77 Apr 23 '11 at 20:01
7

Here's a way to include the manifest at build time of your VB6 app:

  1. Save your manifest file, maybe call it "my.manifest".

  2. Make sure the file size is a multiple of four, as Cody already mentioned. If necessary, pad it with blanks at the end.
    See also: Embedding an application manifest into a VB6 exe

  3. Generate a resource-file "my.rc" with the following content:

     #define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
     #define RT_MANIFEST 24
     CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "my.manifest"
    

    You can find more information on the constants used at the msdn blogs. Seems you'd need to use

     #define ISOLATIONAWARE_MANIFEST_RESOURCE_ID 2
    

    for a dll project.

  4. Use rc.exe to compile this .rc file to a .res file.

  5. Add the resulting .res file to your VB6 project.

I've been using this for the last few months without problems, on two old legacy applications that needed to run on Windows 7. You may need to experiment on how you save your manifest file though, for me only saving it as UTF8 without BOM worked properly.

To check what exactly gets embedded as manifest this way, you can also use mt.exe to extract the manifest from your compiled exe/dll. That was what helped me finding the BOM problem ...

takrl
  • 6,356
  • 3
  • 60
  • 69