Starting with Windows Vista, Microsoft added a class of compatibility shims that will allow an application that assumes it has administrative file and registry access to continue to function.
In other words: An application that failed on Windows XP would run on Windows Vista.
These OS provided bug-fixes can be disabled by adding a section to the application manifest, declaring the application should run asInvoker:
<!-- Disable Windows Vista standard user compatability heuristics -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker"/>
</requestedPrivileges>
</security>
</trustInfo>
Ideally, a developer would test their application to ensure that it doesn't (needlessly) require administrative privelages. In order for me to test this, i would need to manifest it asInvoker.
But when it comes down to it, i'm not going to release the application to the customer manifested asInvoker. If i did miss something, i don't want the user to be impacted. i want Microsoft's operating system to fix my mistakes. Problem with this solution is:
i have to modify the manfiest before release
i'll never know about the things i missed, becuase they're just work on Windows Vista.
A similar conundrum comes up with Windows 7's supportedOS manifiest entires. You can add a manifest to the application indicating which version of Windows you were designed and tested for:
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!--The ID below indicates application support for Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!--The ID below indicates application support for Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
</application>
</compatibility>
In the case of the supportedOS items, the operating system knows up front which OS you were designed for. This will place your application in the context of Windows Vista if you do not say that you support Windows 7:
(source: msdn.com)
This action is similar to running an application in some Compatibility Mode, e.g.:
Windows Server 2008 (Service Pack 1)
Windows Vista (Service Pack 2)
Windows Vista (Service Pack 1)
Windows Vista
Windows Server 2003 (Service Pack 1)
Windows XP (Service Pack 2)
Windows 2000
Windows NT 4.0 (Service Pack 5)
Windows 98 / Windows Me
Windows 95
where you will get a schmorgasboard of compatibilty shims applied, and Windows will emulate old undocumented behaviour in order to help your app from crashing when it depended on that undocumented behaviour.
An example of compatibility shims that Windows 7 will provide for an application running in the Windows Vista context:
RPC will use the old private thread pool, rather than the OS thread pool
you will be able to Lock the primary video desktop display buffer
you will be able to Blit to the primary desktop video buffer without specifying a clipping window
you will be vulnerable to a GetOverlappedResult race condition (if you depended on it)
you will continue to get Program Compatibilty Assistant (PCA) mitigation
And once again, in order to test my application properly under Windows 7, i have to add the supportsOS manifest entry. But, again, i'm not going to ship the application with that flag, because i don't want to lose the benefit of these shims (e.g. PCA). And, again, if an app has problems that were fixed because it was running in the Vista context: i'll never know about it from our customers - because the app is just working.
Thoughts? Guidance? Best practices?
i'm not going to release the application to the customer manifested asInvoker. If i did miss something, i don't want the user to be impacted.
I think this is a bad approach. My advice is to manifest correctly from the start and test what you deploy.
Microsoft is not going to bend over backwards for everyone's compatibility. They're going to target the most common, high-impact mistakes made by the biggest vendors. If you miss some small issue, the chance of them providing a shim in the future is small.
Every time Microsoft adds a compatibility shim, we all pay a price. There are APIs that don't work the way they should because they had to handle some case in a brain dead way to achieve compatibility with somebody else's bug. This means long, painful debugging sessions, it means wading through longer (or less complete) documentation, and it means little inefficiencies in the OS for everyone. It also means Windows developers are wasting time fixing other people's mistakes instead of improving the OS.
Sometimes these compatibility changes are big hammers that penalize developers who do it right. Many applications don't handle high DPI correctly, so--in the name of compatibility--Vista assumes that no applications handle it correctly (unless they explicitly claim otherwise). Vista applies UI scaling. Applications that didn't handle high-DPI get improved (but suboptimal) results. Applications that did handle high_DPI get degraded results. (And customers who used the good apps see them get worse when they upgrade to Vista and blame Microsoft.) The developers who didn't pay their taxes get help from Microsoft, the rest of us (including Microsoft) get penalized. The only way to avoid this is for everyone to pay their taxes.
In general, Microsoft is getting better at making these compatibility shims more targeted (though Vista was pretty blunt). Nevertheless, there's a little cost to each one.
Follow the best practice during development. Test what you plan to deploy. If it breaks big, Microsoft might fix it for you. Otherwise, you might have to release an update. That's better than everyone suffering a penalty because some developers didn't do the right thing.
AsInvoker is the correct way to distribute your application!!!
All that says, is run with the user's credentials. It doesn't say 'do something sneaky' or 'use admin rights'.
Without that manifest, you're branding your application as "I'm not aware of UAC, so please provide me whatever hacks you need to make me still maybe function on any system that has UAC"
But if your application doesn't try to do admin-only things - and you can easily test that by simply being logged in as a standard user & then running your app and watching for failures - then AsInvoker is absolutely correct.
This might help you get a handle on it: A Programmer's Exploration of Vista's User Account Control
As I understand it, instead of supplying a manifest file with your distribution it can also be linked directly into your EXE file by adding the following command to your application's resource file: [1,2].
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "YourApp.exe.manifest"
A separate manifest file in the directory containing the EXE file could override this linked-in manifest, but that is up to the customer. You wouldn't supply it.
Now, the "RC" resource compiler from Microsoft accepts preprocessor directives such as #ifdef [3]. Which means, you could instruct your Visual Studio to have two separate build targets defining different preprocessor definitions such as TESTING and DEPLOYMENT.
Then, it is just a matter of using #ifdef directives to use two different manifest files for your testing and deployment build targets, and you can edit the manifest files as you wish. Would this solve your problem?
[1] http://msdn.microsoft.com/en-us/library/ms997646.aspx
[2] http://doc.ddart.net/xmlsdk/htm/sdk_dependencies_5wvi.htm
[3] http://msdn.microsoft.com/en-us/library/aa381033%28VS.85%29.aspx
Related
I have a VB6 Application that I am deploying using Microsoft Development Environment.
The install package is working for Windows 7/10 32/64 bit.
The problem I am having is if a second user logs into windows and runs the installed app some of the controls are not working.
Forms that contain MSCOMCT2.OCX, TABCTL32.OCX and maybe others fail saying:
"Component ... or one of is dependencies not correctly registered: a file is missing or invalid"
But once again for the user that installed the app all is good.
I see in other installs there is a choice to install for only me or all users. I don't see a way to implement that in "Microsoft Development Environment", is this my problem?
What changes if you install an app for All users?
This may have to do with registry virtualization. The application may be running in some kind of compatibility mode so that the controls are not really being installed system-wide.
I'm not too familiar with those settings but it might be possible to adjust them so that the DLLs/OCX files are genuinely registered for all users and the application runs accordingly. There is a risk that if the compatibility settings were set intentionally, this could break something else.
Hopefully this is a useful starting point.
I will add that IMO installing the application not to require registration whatsoever is a much more robust solution. See How can you force VB6 to use the DLLs and OCXs from the app directory?
We have an ERP application which is built in VB6 and it was running just fine till a few of our customer upgraded all their systems to Win7.
This software is programmed in such a way that it registers a few plugins (found in plugin folder) which are COM based at runtime. Now when the software is run by user without setting Compatibility Mode and Run as Administrator setting it fails and crashes.
I know we can manually set both Compatibility Mode as well as Run a Administrator by right clicking on program executable and then going to its properties. But this looks very unprofessional.
I think there will be some way to tell Win 7 to automatically run a software in Compatibility Mode and Run as Administrator.
Please help me.
Compatibility is an administrative function, not a development or deployment function. It is better to fix the application where possible, especially to remove any requirement for elevation.
There are plenty of tools for investigating the issues so you can correct them. However globally registering "plug ins" at runtime is a nasty one. VB6 component self-registration is always global unless registry virtualization can redirect it. Why not create installers for the plug-ins that can run elevated once during installation?
There are ways to set compatibility less manually, even as part of installation - though Microsoft discourages this. Maybe take a look at:
Compatibility Fix Database Management Strategies and Deployment
However the effort required might be better spent on remediating the problem. Support costs will be less over time.
As the other answers have said, you shouldn't need to run all the time elevated.
If you want to register the plugins after its started (as a normal user), you can use ShellExecute() with the "runas" verb to run regsvr32.exe, or use COM elevation which has been discussed many times before.
You can indicate that an application must run as admin by specifying it in the Application Manifest, which in an xml file that you can either embed or deploy with your application.
Once your application is running with admin rights it should be able to register and load the plugins. You should not need to run in compatibility mode to access the COM plugins.
I have a flash drive which has an application whose code is written VC++ 2008 , the application works fine in xp , but the problem arises when i plug in the drive to a windows 7 machine , it doesn't run properly. is there any way that i can make it compatible to windows by writing a code.
i dont want to set the compatibility tab in windows 7 to run the program..
i want to code it in the program , more like a patch.
You can use the Microsoft Application Compatibility Toolkit, which will tell you exactly which Windows XP compatibility shims are used by your code when you run your application under Windows XP mode.
You simply run your application and disable various shims until your code once again behaves incorrectly. The last shim you disabled is the cause of the incorrect behavior. You can then research the exact consequences of each shim as well as exactly what your code will have to do to fix the bugs it has that force it to run in Windows XP Compatibility Mode.
You probably need to add an Application Manifest to your application to request the appropriate security permissions to allow your application to do what it needs to do.
This may cause a UAC prompt to be shown to the user if elevated permissions are needed, but then your code will be allowed to do whatever Windows 7 is currently blocking.
If you know that the problem exists and know that UAC / etc ... / Manifest on Win7 don't solve your problem and that it's not connected with 32/64 bit issues, try a different approach.
I guess you know what goes wrong with your app on Windows 7. If you're not sure exactly, at least you should know where (in which logical block) your problem is located (e.g IO block, Disk read/write block, Gui, etc.
Now stick to the debugger. Hope your program isn't that big that you can't analyze it and find the source of your problem. You could have your problems because of some functions working not as expected or something like that.
Then, I guess, you could rethink / remanage your code and change it the way it works on both platform. If there is no universal solution, use #ifdefs to determine your current platform (the worst case actually, because you would have to have different binary files for different windows versions).
I have an application written in Delphi 2006 that was working fine in Windows XP. I packed the application using Inno Setup, using Program Files as the default folder. A few users migrated to Windows Vista and Windows 7. The issue here is that the application creates some files inside its installation folder by its own. This was working in XP but in Windows Vista the users were having problems with the created files (they don't appear and so on). After investigating the users' reports I discovered KB 927387: "Common file and registry virtualization issues in Windows Vista or in Windows 7."
Running the application with administrator rights just solves the problem, but that is (I think) an awful workaround. I would like to know if there are any directives or tips for making the application compatible with Vista and 7, because more users will migrate to these OS soon.
You need to re-write your application to store its files in the proper locations, even in XP, but especially in Vista onwards, particularly if UAC is enabled. This is becoming more and more important to get right as Microsoft keeps locking down and enforcing its security models with each new OS version. The rules for how to properly manage application- and user-related files is documented on MSDN, for example: "Application Specification for Microsoft Windows 2000 for Desktop Applications, Chapter 4: Data and Settings Management" and "Application Specification for Microsoft Windows 2000 for Desktop Applications Appendix A: Best Practices" (yes, they are old, but are still quite relevant). Look at SHGetSpecialFolderLocation(), SHGetFolderPath(), SHGetKnownFolderPath() and other related functions to help you.
For Vista/Win7, your app can't put the files in a subfolder of Program Files / Programs unless UAC is turned off or the app is running as elevated. Note that "elevated" does not necessarily mean "logged in as Administrator." Non-administrator users can elevate, and Administrator isn't necessarily elevated.
If the app does attempt to write to Program Files but is not elevated, the OS will either block the app or "virtualize" the write (put the files somewhere else), depending upon how UAC is configured. Neither one helps the app succeed at what it was trying to od.
So it needs to put them somewhere else. Where depends on why the files are being created, and you haven't told us that. You can read this article to learn about the options. Note that in addition to the user's AppData and Roaming folders, there is also an "All Users" (shared) profile.
You should probably look at this article and screencast, which discusses UAC in depth from a Delphi point of view.
Files you create for use by your application other than at installation time should go into the ProgramData directory if its global to the workstation, or into the users ApplicationData directory if its specific to the user.
For cases where you absolutely must place a file in the program files directory, you can use com to request elevation. This is discussed in great detail, and delphi specific bits are also available. One example that I have used this is in patching my users installation base. They are warned by UAC that the system needs to make changes, so if your doing this as an automated task, you might need to rethink the logic to be more user driven.
Here is another article, by Zarko Gajic, which shows how to get different system directories. Also have a look at this related question.
I had a similar enquiry here (Stack Overflow).
In the end I realised that I needed to put my application into Program Files at install time (requiring UAC/elevation) and then store my app's data in the user's App Data folder. I had to change the way my program generated 'default' configuration settings and also where I was saving this stuff, but it was worth the effort in the end - we ended up with something that installs and runs fine on XP, Vista and Windows 7.
The only UAC hit we get is at installation time, which makes sense to me (and you get a similar hit at install-time on the Mac too). We didn't have any data that would be common to all users in this particular case but I would have looked at the Program Data special folder if that had been the case.
The installer software we use (Setup Factory) made this fairly straightforward (we just wrote a small bit of code to detect XP versus Vista/Win7 and choose the right special folder accordingly). It would be easy to do this in Inno Setup too, from what limited experience I have of it.
My application needs administrative access and I want it to run without any hassles in Windows 7.
I have the following options
1.Ask the user using the application to turn off UAC. This is a last resort option and would hate to do that.
2.Embed a manifest in the application that says elevate to adminstrator privelege. This will work but it seems that it will bring up a dialog requiring users consent every time a user runs the application.
3. Configure the application to run in Windows XP compatibility mode. This works, but i had to do this using explorer->application properties. if can I do this programmatically during installation time, I would really prefer this option. My question is if there is any way to achieve this.
regards
Ganesh
Try making an application compatibility shim that says your app needs the XP compatibility mode, and distributing it with your app. A shim is a means for administrators to simplify installation of a 3rd party app that needs compatibility settings - it saves them tweaking each PC individually. You can probably roll it into your install program with a little ingenuity.
I've gotten pretty used to dealing with the UAC dialog, running Vista for the last 2 years. If it bugs you, I have to wonder how much experience you have using post-XP OS'es.
As a user I think there are two ways to look at it:
The program inherently requires admin. For these, I very much appreciate the dialog, as I know it means nobody's going to sneakily run that thing in the background on me and modify my system.
The program inherently does not require admin. Most programs only need admin to auto-update themselves (and probably shouldn't need it then). My attitude is that these programs are poorly-designed. Such a program should only invoke AUC if it discovers it needs to update, not every single frigging time I start it up. This is a security issue too, as any buffer overflow someone finds in the entire program puts me at risk.
Localize the need for UAC as much as you possibly can. The best would be to put in a separate executable. (eg: an "updater")