WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Manifest

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

External Manifest with WinBatch


Question:

I'm a long time WinBatch user/fan but have hit a brick wall.

I have a compiled script that calls an external DLL that has a dependency on the MS Visual C 8.0 libraries: msvcp80.dll & msvcr80.dll. This library includes a manifest file.

When I was using an older version of Winbatch (without an embedded Manifest in the EXE) this was not a problem. I simply used the msvcrt .manifest file for the exe and it ran fine under XP & Vista.

However, I recently upgraded to WB 2007 and it includes an embedded manifest when compiling an EXE. In this situation, Vista ignores the external .manifest and uses the embedded one - which does not include the information for the msvcrt dlls. Then, when I run the script under Vista, the thing crashes.

I have tried using the MT.EXE tool to merge the two manifests without success. I found another tool "genman32" to try to remove the embedded manifest - with no luck.

I'm running out of options and need help.

Answer:

I believe the next release (2007D) of the WinBatch+Compiler will have the option to NOT include a manifest in the compile. Perhaps just use a fully qualified name in the DllLoad statement to make sure it uses the correct file

User Reply:

Thanks for the quick responses! I have tried the "NoUAC Info" option in the 2007D compiler. This still appears to insert a very striped down version of a manifest file. Use Microsoft's MT.EXE tool to extract it and you'll see what I mean. I already specify an explicit path in my DLLCall statement in the WinBatch script (which opens the pointer to DLLLoad.)

Answer:

Hmmm. Interesting case. So what problem does having the manifest solve for you. Are there different versions of the run time files and the code prefers a certain version of them? And other processes prefer a different version? How many machines does this need to run on?

Asked the developers and no quick fixes seemed apparent. Some comments regarding Vista presenting it in an unfavorable context were made.

User Reply:

Personally, I wouldn't use the manifest if it wasn't needed. Apparently they are required to use the Visual C library. In XP, the manifest files (for the library) must be linked to both the DLLs and the EXE for the script to run. To confirm this, download the sample I posted, and run under XP. If you remove either Manifest file, it crashes. This works because XP does not support embedded manifest files.

Now Vista, on the other hand, IGNORES external manifest files if there is one embedded in the DLL/EXE. So, the manifest for the DLL (linked to the EXE) never gets loaded. This causes the DLL to crash, etc. (just as if the exe manifest was removed under XP.)

Thus, I suspect that the solution is that the WinBatch compiler needs the ability to either substitute an external manifest file rather than making its own, or needs the ability to compile without any manifest whatsoever.

Unfortunately, I'm handed these files and told to make it work. I don't think there are any alternatives I can use, since these DLLs are shared by our other (mainstream) applications.

The exe will run on hundreds of thousands. The script is for our GPS Setup Wizard: Winbatch handles the UI and registry/file interaction; I call some external DLLs (used by our release application) to do specialized tasks related to our GPS driver library. For example, in the sample I sent (which is a SMALL snippet of the much larger GPS Setup Wizard) I am calling a routine (in the external DLL) that determines the number and type of COM ports on the PC.

If I *have to* I can use the older compiled version of this script. Fortunately, I was only recompiling the wizard with WB 2007 (I think it was last compiled with WB 2003) to be consistent with the other WB scripts we use for Setup Routines (that can't be done with MSI) and our CD AutoRun application.

Answer:

Well, depending, you might be able to write a short script that completely replaces the Manifest that is build into a compiled WinBatch exe with your own.

One limitation is that you cannot "codesign" your exe in the compiler step. However, if needed, you can codesign the exe after the mainifest it replaced.

Assuming that you compile a small model exe, you can find the default manifest near the end of the exe. You will note that a wee tad of extra space is available and you may be able to patch your mainifest in the allocated space.

; Handy constants
;nFixManSize = 432           ; Fixed size of manifest resource WB 2007
;nOffset     = 139576        ; File offset to manifest WB 2007.
nFixManSize = 1057 ; Fixed size of manifest resource in WB 2010c (6.10cjc.)
nOffset = 141116 ; File offset to manifest in WB 2010c (6.10cjc.)

sEndTag     = '</assembly>' ; Manifest end tag.
nEndLen     = StrLen(sEndTag)

; Manifest for c++/c runtime.
sManifest = ""
sManifest = sManifest : '<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">'
sManifest = sManifest : '<noInheritable></noInheritable>'
sManifest = sManifest : '<assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50608.0" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>'
sManifest = sManifest : '<file name="msvcr80.dll"></file>'
sManifest = sManifest : '<file name="msvcp80.dll"></file>'
sManifest = sManifest : '<file name="msvcm80.dll"></file>'

; Sanity check
If (StrLen(sManifest) + nEndlen) > nFixManSize
   Message("Error", "Manifest too Long:": " Maximum manifest size is " : nFixManSize)
   Exit
EndIf

; Pad to size and append end tag.
sManifest = StrFix(sManifest, " ", nFixManSize-nEndLen)
sManifest = sManifest : sEndTag

; Adjust paths and names as needed.
sPath         = "C:\Projects\Webboard\ManifestMayhem\"
sExeName      = "CountPorts.exe"
sOutExeName   = "Test_CountPorts.exe"
sFullExe      = sPath:sExeName

; Boilerplate to modify the exe.
nExeSize      = FileSize(sFullExe)
hBinExe       = BinaryAlloc(nExeSize)
BinaryRead(hBinExe, sFullExe)
BinaryPokeStr(hBinExe, nOffset, sManifest)
BinaryWrite(hBinExe, sPath:sOutExeName)
BinaryFree(hBinExe)
Exit

Article ID:   W17428
File Created: 2010:09:20:09:00:14
Last Updated: 2010:09:20:09:00:14