How to use a manifest embedded as a resource? (Windows XP/Vista-style controls) - winapi

I have a manifest embedded as a Windows resource. But what's the right way to apply it?
More specifically:
I have my .manifest file. It's the standard one to make an app use controls in the Windows XP/Vista visual style. When applied by being in the same directory as the .exe and suitably named, it works.
However, this approach is rather cumbersome. I'd like my .exe to be self-contained. Clearly it can be done, given that many of the apps on my computer manage to use the modern style without a separate manifest file.
So I had a look around, and finally found embedding the manifest as a resource. So I've added this line to my .rc file:
1 RT_MANIFEST "mdiedit.exe.manifest"
But what do I do next?
Edit: If it helps you to know, my program is written in D and built using the Digital Mars D and resource compilers. No IDE. But I'd expect any solution that works in C(++), when built using command-line tools, to work in D as well.

RT_MANIFEST is a define, so make sure your resource file includes the correct header, or just replace RT_MANIFEST with 24

Did you add the .rc file to your project yet? Alternatively, use your development environment's resource compiler, such as brcc32.exe or rc.exe, to compile the .rc file into a .res file, and then add that file to your project.

Related

GetVersionEx function for Windows 8.1 and upper (fasm)

I am writting application in fasm and have problem with determinating Windows version 8.1 and upper. Functions GetVersionEx and Version Helper give me Windows 8. As MSDN says, I must target my application via changing manifest file in Visual Studio, but I'm not using VS, so what should I do?
Any programming environment that allows you to link resources into the compiled executable can be used to create a manifest resource. All you have to do is write a suitable .manifest file for your app that contains the desired XML values, and then link that file's content directly into your application's resources, making sure the resource type is 24 and the resource ID is 1, 2, or 3 (see this page for details about when to use which ID). You are not required to use VisualStudio for this.
If, for some reason, you cannot link the manifest directly into your app's resources, you can alternatively save the XML into a file named <myappname>.exe.manifest (where <myappname> is the actual name of your EXE file) and put it in the same folder as your app. This is not the preferred approach to manifestation, but it does work.
That being said, there are alternative APIs you can use instead of GetVersion/Ex() or VerifyVersionInfo()-based helpers to get the correct OS version without dealing with manifestation at all. Namely, RtlGetVersion(), NetServerGetInfo(), and NetWkstaGetInfo() can be used instead (and all of them have been tested as working in Windows 8.1 and 10).
The manifest file is XML file embedded as Win32 resource. It can also be external file with the name your.exe.manifest. Search for examples in internet for sample contents.

How to view and/or edit the manifest of a Setup.exe file

This question might seem to be duplicated with this and this that are similar. But it is not! First- I am getting this error from the setup file and not from the program that I am distributing Second -the version is different, the directories in Installshield 2009 an 10.5 differ. .
I'm trying to fix an error caused by Windows compatibility mode in my setup, which is built with Installshield 10.5. So far my research led me to a conclusion that i need to add [this][3] to my manifest file. I saw that Microsoft's tool mt.exe could extract a manifest file from a dll, however I did not see anywhere that it can extract it from an executable file.
So my questions are the following:
Is there any way to view the manifest file of a Setup.exe built with Installshield?
Is there any way to configure this manifest file for the certain project in Installshield?
[3]Can one edit an InstallShield setup.exe's manifest file?
As far as I know, mt.exe will work fine on EXE files; both EXE and DLL files are Portable Executable (PE) files, and PE files use the exact same structure for resources such as the manifest. Visual Studio, CFF explorer, and countless other tools (including raw resource APIs) will also work to view and possibly update manifests in general.
However for a built InstallShield setup.exe, there is a twist. InstallShield uses areas in the file to store information that are not described in the PE format. Tools that update the resources on an EXE can inadvertently destroy this data as they do not expect it to be there, nor do they know how to detect or adjust it.
InstallShield 12 or so and later allow you to specify a manifest, and it selects the manifest from files it ships that you can update before it adds them to the setup.exe. In addition, there is a tool called ISReMan that is aware of the extra information and can update the manifest correctly when that data is present.
By the way, it's generally helpful to mention the actual problem you're trying to solve, in case the method you've chosen (in this case updating the manifest) is not the correct solution. Note as well that InstallShield 10.5 is over 10 years old, and knows nothing about UAC, PCA, and other Vista and later technologies; adjusting the manifest may not help fix, say, an elevation-related problem.
Note as well that I am paid to work on InstallShield, so I may be biased when I recommend things like upgrading. :)

How to link a compiled resource (.res) file into an executable

What I want to do is to programmatically update resources of an executable file.
I have a binary resource (.res) file containg bitmaps, icons, version info and a manifest, created with a resource editor, and a PE file compiled with AutoHotkey to which I want to copy the resources from the .res file.
Until now I used to do this with ResourceHacker in command prompt, but ResourceHacker can't be redistributed and besides I want to do this more elegantly.
So I was looking in the WinAPI functions and there seems to be a way to do this: http://msdn.microsoft.com/en-us/library/windows/desktop/ms648008%28v=vs.85%29.aspx
But the problem is that the article describes how to copy resources from an executable file to another, and you can't import non-executable files (the .res file) with LoadLibrary/LoadLibraryEx.
There also seems to be a way to do this with tools from Visual Studio, particularly LINK.exe. But I'm not sure if it can be used outside of the VS enviroment. I have no idea how it works.
You can programmatically update resources with the UpdateResource function
RES files are not involved. RES files are used by the project makefile system to enable minimal rebuild of resources... they don't have to be recompiled every time the application is relinked, just embedded. But you aren't relinking the application and losing the existing resources, so updating just the resources you want to change is the way to go.
If your source assets are already encoded in RES files, then this page describing "Resource File Formats" can help you extract them. It also describes use of LINK.exe for resource embedding. LINK.exe is installed as part of Visual Studio, but it is also available in many versions of the Platform SDK and Windows DDK.

Program to static-link VB6 executable to it's dependencies (like PowerRap)

I read something about PowerWrap which is supposed to allow you to static-link a vb6 .exe to it's dependent files (.OCX, etc.)
However, the website for the product appears to be just a squatter.
Anyone know anything more about the product or something similar that's still being supported?
I discovered another solution called UMM (Universal Make My Manifest). You give it a list of files and some options, and out comes a manifest ready-to-go. I've been using it for a half-million line VB project with dozens of ActiveX modules, and it works well. Requires tlbinf32.dll.

Embedding an application manifest into a VB6 exe

I have recently gone through a bunch of standalone utility apps written in VB6 to make sure that registry virtualization is turned off for Windows Vista and above. I created a standalone manifest file for each exe, set the requestedExecutionLevel appropriately (some of them need to modify HKEY_LOCAL_MACHINE registry keys, others do not), and tested them. They all appear to work correctly.
I have only one small problem remaining. Since they are standalone utilities, people are used to just copying them around the network and running them manually. If anyone forgets to copy the manifest file as well as the exe, then the exe will silently write to the virtualized registry key instead of the real one and cause hard-to-debug problems.
The obvious solution is to embed the manifest into the exe as a resource. All the articles I have read on the net tell you to embed the resource like this:
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#define RT_MANIFEST 24
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "app.manifest"
This should work just fine, except that the VB compiler always creates the application icon with resource ID = 1. When I tried the above code, Windows refused to run the exe, complaining about a resource error (I'll update this post with the details later). I tried changing the resource ID to another number, after which Windows ran the program successfully but did not recognise the manifest contents.
Does anyone know of a way to get an embedded manifest to work in a VB6 exe, or should I just stick with an external file?
UPDATE 1
The text given above is the whole content of the .rc file. I compile it to a .res file like this:
"%ProgramFiles%\Microsoft Visual Studio\VB98\Wizards\rc.exe" /r /fo "Resources.res" "Resources.rc"
And embed it in the VB6 project file like this:
Type=Exe
Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\..\..\..\..\WINDOWS\system32\stdole2.tlb#OLE Automation
Form=Main.frm
ResFile32="Resources.res"
IconForm="FMain"
Startup="FMain"
HelpFile=""
Title="Windows Vista Registry Test - VB6"
ExeName32="RegistryTestVB6.exe"
Path32=""
Command32=""
Name="RegistryTestVB6"
HelpContextID="0"
CompatibleMode="0"
MajorVer=1
MinorVer=0
RevisionVer=0
AutoIncrementVer=0
ServerSupportFiles=0
VersionComments="Windows Vista Registry Test - VB6"
VersionCompanyName=""
VersionFileDescription="Windows Vista Registry Test - VB6"
VersionLegalCopyright=""
VersionProductName="Windows Vista Registry Test - VB6"
CondComp=""
CompilationType=0
OptimizationType=0
FavorPentiumPro(tm)=0
CodeViewDebugInfo=0
NoAliasing=0
BoundsCheck=0
OverflowCheck=0
FlPointCheck=0
FDIVCheck=0
UnroundedFP=0
StartMode=0
Unattended=0
Retained=0
ThreadPerObject=0
MaxNumberOfThreads=1
When I read the compiled exe into the VS2008 resource editor, it looks like this:
RegistryTestVB6.exe
Icon
1 [Neutral]
RT_MANIFEST
1 [English (United States)]
Version
1 [English (United States)]
When I construct an exact equivalent VB.NET test app in VS2008, then load that into the resource editor, it looks like this instead:
RegistryTestNET.exe
Icon
32512 [Neutral]
RT_MANIFEST
1 [Neutral]
Version
1 [Neutral]
UPDATE 2
Testing - the .NET exe runs fine on both Windows XP and Windows 7. However, the VB6 exe produces the following error on XP:
This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem.
and the following error on 7:
The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.
Looking in the event log I see the following entry:
Activation context generation failed for "RegistryTestVB6.exe". Error in manifest or policy file "RegistryTestVB6.exe" on line 10. Invalid Xml syntax.
Needless to say the XML isn't invalid, it's exactly the same file with the same encoding that I used for the .NET exe, and that one works.
RESOLUTION
The VB6 compiler does indeed require that an arbitrary text file included in a resource must be an exact multiple of 4 bytes. I simply added spaces to the XML until Notepad++ told me that the total file size including BOM was a multiple of 4.
Thanks to both Michael and Jim for pointing me in the correct direction. Just a pity I can't mark you both as the answer!
Interestingly enough, I had to do the exact same thing recently. Following the steps Christian described, I got it to work the first time through. For prosperity, here is the entire workflow I followed:
Created a RC file as described in the orginal question
Created a app.manifest, preserving whitespace characters, which are VERY IMPORTANT for this to work. As stated in previous answers, the file size must be a multiple of 4.
Ran RC.EXE as described in the original question against the rc to generate the .res file
Edited my Project.VBP file to include the following line near the top:
ResFile32="Resources.res"
Built EXE in standard vb6 environment. When deployed on a vista or win7 machine, the shield shows up and the user is prompted to run as administrator. When opening the EXE file in studio, I verified the resources.
Notepad++ tells me that the encoding on my app.manifest file is ANSI. It did not include an byte order mark at the start of the file.
If you are still having troubles, let me know and I'll share whatever I can with you. Other than that, I'm not sure what to tell you other than Works on my Machine!
VB6 has a quirk in that any resource element must be an exact multiple of 4 in length. Try padding the manifest file out with spaces to ensure this, and see if that changes the behavior.
This quirk was documented in Microsoft article Q297112 (archive).
Also, you might add the resource using the VB6 IDE instead of editing the VBP. The effect may be the same, but the resource editor is the standard means for doing this.
Using the Resource Compiler (rc.exe) is going the long way around. There is a much simpler option for embedding an application manifest within an executable, whether C++ or VB6 or just about any other language. The Manifest Tool (mt.exe) was written specifically to embed manifests within binaries and is provided free of charge with the Windows SDK. The added benefit of using mt.exe is that it automatically handles any necessary padding.
Simply run the following command line after the binary has been compiled. I have used the naming convention used internally by the Visual C++ 2005 compiler, where the manifest filename contains the full program name with ".intermediate.manifest" appended.
mt.exe -nologo -manifest "program.exe.intermediate.manifest" -outputresource:"program.exe;#1
Update: I have personally been using this in an automated build process with VB6 executables for over two years now. It has been so successful that we have eliminated OS compatibility tests - specific to manifests - from our regression testing.

Resources