I have two executable files, the first one should run the second one. The second one comes with different types of manifests: asInvoker, requireAdministrator, etc.
Is it possible to change the manifest of executable file? I'm searching a simple solution on C.
I would like not to keep few copies of executable with different types of manifests, and not to keep third party tool that could change it. BTW, it is possible and this tool exists: MT (manifest tool) from visual studio package, link.
Yes, you can change the manifest file using mt.exe from the Win32 SDK. But that is only something you should do during development or testing. You cannot deploy this tool to customer's machine, so you can't use it to dynamically change the manifest back and forth.
But that's okay, because you don't ever need to change the manifest file back and forth at runtime. The executable's manifest file should specify the minimum required privileges for that EXE. Thus, if it's possible for the user to run the EXE without administrative privileges (i.e., without elevation)—even if it means the app runs with limited functionality—the app's manifest should specify "asInvoker". The user can always choose to run the app with administrative privileges if they need those extra features.
And, of course, you can launch the EXE programmatically with elevation. You do this using ShellExecuteEx, specifying the "runas" verb for the lpVerb parameter. This will have the same effect as setting the permissions level in the application's manifest to "requireAdministrator".
It is not entirely clear from your question how your application is set up. Normally, the first EXE has "asInvoker" set in its manifest so that any user can run it. It doesn't need administrative privileges in order to do anything. However, if there is something it might need to do that requires administrative privileges, it displays some bit of UI with the UAC shield icon, and clicking on that will launch a second EXE (with "requireAdministrator" set in its manifest) that performs whatever task requires elevation. This second app doesn't need to be distributed in an "asInvoker" form because what it does always requires elevation. You'll notice that this is how all of Microsoft's apps are set up, including the bits shipped with the operating system.
Thanks #RbMm for his comment.
Also I found later that my question is duplicate. Sorry for that, I haven't found this earlier.
So, the solution (error handling and includes omitted):
HANDLE handle = BeginUpdateResourceW(file, TRUE);
UpdateResourceW(handle, RT_MANIFEST, CREATEPROCESS_MANIFEST_RESOURCE_ID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), manifest, strlen(manifest));
EndUpdateResourceW(handle, FALSE);
Notes for further generations:
Manifest should be in short chars - char * instead of wchar *
Errors (e.g. incorrect XML syntax) could be tracked in Event Viewer, section Windows Logs -> Application
Some tools (Resource Hacker) could open and show manifests, but they show unicode manifests without error too...
Related
I'm using Inno Setup 5, and to enbody an customizable .exe file, it's name is changed in the [Files] section using the parameter DestName. But, we're talking about an .exe file.
I noticed that when it's running, the name in Task Manager is the old file name, the DestName parameter only changes it's actual name, not the file Description, which is shown in Task Manager. Somebody has had any experience like this?
I'm using Windows 10, running as administrator (if makes any difference).
The file description is a part of the file header.
You cannot change it easily. It's possible. But only with unsigned binaries. Changing a description of a signed binary would invalidate the signature, as any other change would. And nowadays all binaries should be signed.
If you sign the binary as part of the installer build, you can modify the description before that. You can use Resource Hacker command-line. There are various way to invoke a tool like Resource Hacker as part of the installer build:
If you build your installer from command-line, you can modify the description even before you run the Inno Setup compiler. See Run a [Code] or PowerShell script in Inno Setup compiler.
You can use Exec preprocessor function. This is also covered in Run a [Code] or PowerShell script in Inno Setup compiler.
Or you can do it as part of the signing. For some information see Inno Setup - How to change the icon of the shortcut of uninstaller without separate icon file? and Microsoft SmartScreen - suspended using Inno Setup installer?.
For an example on how to use Resource Hacker to modify a binary description, see Inno Setup change Task Manager Description for Setup.tmp – It's about a manual modification, but you will need some of the information even for your automated (command-line) modification.
Though I believe that way easier is to automate and customize your application build process, so you can easily produce the binaries with custom description, instead of hacking it into the installer build process.
[Setup]: VersionInfoDescription
Default value: "AppName Setup" if AppName doesn't include constants, an empty string otherwise
Description:
Specifies the file description value for the Setup version info.
This setting has no effect if UseSetupLdr is set to no.
Code Sample:
VersionInfoDescription = "This is my awesome app description"
There is a solution I found.
Go to the direction of Inno Setup, then open Default.isl file. This file includes all setup descriptions & other components.
You can open this file with any text editor, then press Ctrl + F and search for whatever you want to change.
After you saved this file, compile your setup file and execute it again.
My description was already changed.
There is an example I did previously.
I'm deploying a .NET application with VS2010. My application creates .txt file in the logs folder in the same directory with .exe:
app.exe
add.exe.config
logs (folder)
I used setup project to create a MSI installer. When I installed in the client machine C: drive or any drives I have no problem to create the .txt file, but when I installed in C:\Program File\myAppFolder or C:\Program File(x86)\myAppFolder I cannot to create the .txt file.
It is a poor design to write to install location for your application. It is better to write to the ApplicationDataFolder. The ApplicationDataFolder is under the user profile and the application will have access to write there when run as that user. #Ken White provided a very good pointer to an existing StackOverflow answer about this.
If this is a legacy application that must write to that folder, then you'll need to modify the permissions on the log folder such that all users can write to the folder. This is possible to do with the Windows Installer (aka: MSI) but I'm not sure that the Visual Studio setup projects expose it. The WiX toolset definitely supports doing such things.
An old post but I needed to do similar recently so I guess it is still valid! While I don't advocate bad design, in the real world sometimes we have to bend to requirement.
Writing to the application folder is possibly under Win7 and it is possible to set this up via an installer class in an MSI created by VS2010. You just need to give a relevant group (suggest either the "Users" group, or if you want to give more control over who gets what, supply a selection screen) Write-Data access.
Using DirectoryInfo on a path you can then get the security data from GetAccessControl.
When you have your Group known, get the SID for the group and AddAccessRule also supplying the required ControlType value.
Then set the access control on the DirectoryInfo object (SetAccessControl) using the security data object.
You can get the SID from the Groups principal object if you do a search with PrincipalSearcher.
Hope this helps
paul
This generally all depends on:
Whether your app requires to be run as administrator for other reasons and..
Whether your app is provided for limited users.
If the app requires elevation for a bunch of other reasons (and not just updating files in restricted locations) then the normal way is to have an elevation manifest embedded in your app. This isn't a good thing from the security point of view, but if you absolutely need admin privilege then this is the way to do it.
If the only operation requiring elevation is updating/creating data in the Program Files folder then don't put the file there. Every case of this that I've seen has been lazy programming where the code just refers to the file name and consequently it goes in the Program Files folder (more accurately in the same folder that the app runs in). The cure for this is to put the data file in the correct location (such as User's Application Data folder). As Rob Mensching says, you should alter the permissions on the install folder only if this is a legacy app that you cannot change.
My installer requires there be two files in the same directory in order for it to install.
The installer (.msi file)
An organization specific config file that the installer copies. (This file is customized by the organization and then distributed to it's end users).
Since there are two files, the file has to be distributed as a zip file. Which presents the issue of if a user tries running the .msi without actually extracting the zip... only the msi file gets extracted. I am able to detect the issue in the install process and tell the user they need to unzip the file... but you know how noone actually reads error messages.
So, I'd like to make it more foolproof and so i was wondering if there was a simple tool that i could let my customers (ie the organization) be able to make modifications to the config file and when finished create a .exe file which when clicked would extract to a temp folder and then run the msi. I know there are solutions for this which require commercial software. I'm wondering if a simple freeware tool exists that can do this.
Edit: Accepted Solution Notes:
The one issue i ran into is the iexpress wasn't designed to be used for .msi files. As a result on the step that asks you for the Install Program. It's a combo box which if you had added a .exe file in the previous step could just select the .exe file from. Instead you have to manually type in
msiexec /i yourinstaller.msi
I was very pleased to find such a simple solution that's built in to windows. The only way this could be better is if it allowed for wildcards so that your iexpress project would be able to handle changes in the msi file's name which occur with each version. And defaulting the Install Program to the .msi file. These minor inconveniences are offset by the fact that end user wouldn't need to install any new software to create the package so I have stopped looking for other tools.
You could try using iexpress.
It enables you to package up a set of files which can be extracted, with the option of running an installation command automatically after extraction. It also has options to enable you to prompt users about things, show a EULA, restart the computer, etc..
I believe it comes as part of Windows (part of IE?) - try running iexpress.exe from the run dialog to get the UI.
The Wix project has a bootstrapper and packager for dealing with this kind of thing.
I've used wix a lot but haven't really looked at the bootstrapper/packager much - last time I had a quick look it wasn't really usable but that was a long time ago so it may be better now.
I'm guessing that the config file is something like a properties file, and that you want users to set the values of the properties "foo" and "bar". You don't need a separate tool to update the file.
I would do this:
Put one or more dialogs in the install that ask the user what the values of foo and bar should be, and set a couple public properties accordingly.
Write a custom action that writes the config file out to whatever location you want, including whatever values you want for foo and bar. This would be pretty easy in vbscript.
Put the custom action somewhere in the execute sequence (ideally as a deferred execution action, since you're making changes to the system).
Add an entry to the RemoveFile table, so the config file is removed on uninstall (assuming you don't want it to be left behind.)
Add an entry to the LaunchCondition table, to prevent users from doing a silent install. Or if you want silent install to be allowed, make the names of the public properties that hold the config data known, and make them part of the LaunchCondition. You would block "msiexec /i myapp.msi", but you could choose to allow "msiexec /i myapp.msi FOO=Something BAR=SomethingElse".
We have an installer for our application that must be downloaded and run with administrator privileges, like many other installers. However, the installer isn't named "setup.exe", so Windows doesn't automatically detect it as requiring elevation to run.
Changing the installer name to make things elevate properly sounds pretty messy, frankly. This article talks a lot about UAC and elevation, and it says that you can use a manifest to make something require authorization.
So, we'd just love to create a manifest for our installer. However, how do we ensure the manifest is present? If the user just downloads our_application_v13.exe, how do we ensure they get the manifest too? AFAIK the manifest would have to be a file named "our_application_v13.exe.manifest" in that case.
Since they're just downloading a file from our web site, how do we make sure they get the manifest too? Can we build it into the executable in some way, or otherwise flag the executable as requiring elevation? We are using an installer tool from hundreds of years ago that we can't change, so it doesn't have any capabilities relevant to this.
Thanks!
If the installer tool allows you to change/attach/edit the resources of the generated EXE file, you can add the manifest file as a resource with a resource type of 24 (RT_MANIFEST in the windows headers) and a resource id of 1.
If The installer tool does not have the built in facility to insert resources, then you might have to write a tool to post-process your install.exe file to insert the resource. Look up the Windows APIs BeginUpdateResouce and EndUpdateResource. They have some limitations - they tend not to work if the EXE doesn't already contain any resource files at all, but most install tool generated exe files contain at least a version info resource.
Also, if the install is digitally signed that will have to be done after insertion of the manifest resource.
Also, mt.exe included with the Platform SDK and most versions of visual studio has options to embed, extract and merge manifest resources.
The manifest can also be in the application's native resource section (inside the EXE).
There is Resource Tuner Console from Heaventools Software.
Resource Tuner Console is a command-line tool that enables developers to automate post-processing of your install exe file and insert the manifest resource. See specifically the Adding Application Manifest page for greater details:
http://www.heaventools.com/rtconsole-embed-manifest.htm
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.