It could be that this is no strictly speaking a WIX issue, but it should be a well known problem related to setup with well established best practices. I just can't find these practices on Google. Using WiX 3.6, Windows 7, Visual Studio 2008, but the installation must support Windows from XP to newer.
I'm installing a COM object that depends on some third party DLLs. The object itself is registered okay, and all the DLLs are installed in installation folder, and setup adds this folder to system's PATH environment variable. The code looks like this:
<Component Id="RequiredLibraries" Guid="$(var.RequiredLibrariesGUID)">
<?include redist.wxi?>
<Environment Id="PATH" Name="PATH" Value="[INSTALLDIR]" Permanent="no" Part="last" Action="set" System="yes" />
</Component>
On my machine I can use the object immediately after installation, but on some machines I must reboot the computer. This reboot is a pain, and I don't know why is it necessary, nor why only on some machines. I can <ScheduleReboot After="InstallFinalize"/>, but I'm hoping for some better solution. So, feel free to answer any of these questions:
What is the best common practice for this issue? I can't pack everything to a single DLL, so I need a solution for several DLLs.
What I could I do to enable the use of the COM object (by making the change to PATH visible to the rest of the system), without resorting to reboot, or user relogin, or Explorer restart? Does Windows Installer broadcasts WM_SETTINGCHANGE message? Should I broadcast it in custom action?
How could I detect and ask the user to reboot/relogin only if it is required, and not always? (reboot is not required on some machines)
How can I schedule something less painful than reboot that works just as well?
There are two scenarios I know of:
1) Application doesn't honor WM_SETTINGCHANGE broadcasts ( typically anything hosted by service control manager )
2) A behavior in MSI when it chooses not to send the broadcast. Per WriteEnvironmentStrings Action:
(emphasis added)
Environment variables do not change for the installation in progress
when the WriteEnvironmentStrings action or RemoveEnvironmentStrings
action are run. On Windows 2000, Windows Server 2003, Windows XP, and
Windows Vista this information is stored in the registry and a
WM_SETTINGCHANGE message is sent to notify the system of the changes
when the installation completes. Another process can receive
notification of the changes by handling these messages. No message is
sent if a restart of the system is pending. A package can use the
MsiSystemRebootPending property to check whether a system restart is
pending.
I've worked around #2 by writing a .NET custom action (using Environment class) that makes a meaningless change just to get the broadcast to occur after MSI has done it's thing.
Related
I have two installers created using wix(version 3.11). The installers are sharing few dll/ocx files(Old VB modules).
The installers are working fine, when installed alone. Or when both installers installed. But if i uninstalled any one application, then other one is not start (not even starting).
I am using following kind of Component tag.
<Component Id="cmpFF2764B47716F09AAAEBF0C6DC2324E9" Guid="{6A11D493-3293-45DE-B169-B624A26B6D98}" Shared="yes" SharedDllRefCount="yes">
<File Id="filB539B5FD161C1FA29A10F82339F88A83" KeyPath="yes" Source="$(var.SourceBasePath)\COMMON_FILES\Common\Servers\libsrv.dll" SelfRegCost="1"/>
</Component>
I couldn't able to harvest dll using heat.exe due to error error CNDL0047 : The TypeLib element is non-advertised and therefore requires a
parent File element. (https://github.com/wixtoolset/issues/issues/3412/) .
So I made it as SelfReg. Now i stuck with this issue. Any clues to resolve this issue??
Virtualization: Are you in a corporate environment with these applications? Can you use a modern App-V package instead? This is a package that is basically installed on demand (on launch) and allows the appliation it deploys to run "sandboxed" or isolated from other applications on the system. Interference problems should be gone. You can also use a virtual machine via systems such as VMWare to run the problematic application(s) in their own operating system. Virtual machines also allow you to run certain applications with admin rights if that is desired. If there is a packaging team in your company, have a word with them?
The reason I suggest the above is that I know VB6 applications are basically hopeless to deploy. They have all kinds of weird problems that take forever to fix and the fix is never that good.
I have an installer package for a 32-bit Application (built with MakeMsi, originally for Windows XP, and simplicisticly maintained since then), that fails registering a COM server on modern (64-bit) Windows systems (7, 8, 10). This is what I see when trying to install my MSI normally:
Application Error
Exception EOleSysError in module xyz at 000F0B01. Error accessing the OLE registry.
If I bring the MSI in compatibility mode Previous version of Windows, the COM server registers successfully. Since "it's working" somehow, I didn't invest much time in exploring the reasons so far. But finally, I'm exhausted to remember our customers (and sometimes also me) again and again of this precondition, so I wish to fix this issue.
The registration (and de-registration) is done via CustomActions, as I see looking into it using Orca:
"[INSTALLDIR.MYAPP]\placeholder.exe" -regserver
"[INSTALLDIR.MYAPP]\placeholder.exe" -unregserver
For each of those entries, Type is 1122 and Source is INSTALLDIR.MYAPP.
I could imagine that the COM server is started with insufficient privileges in the installation procedure, but aren't installers run automatically with administrator rights? I mean, when I (as a standard user) start the installer by double-clicking it, it shows the UAC prompt before the actual installation takes place. Why are the COM servers not run with elevated rights for their registration and de-registration? It's confusing...
How should I change my MSI to make Windows installer process it successfully?
I assume you know that the problem is in the executable that you're running as a custom action, not anything in Windows Installer. That means the issue will be the code in the executable, and it's probably old and incompatible with later OS versions. You'll need to look at the code to see what it's doing that is unsupported.
Many installs don't bother with self-registration. That data is all static data that can be extracted once and included in the MSI file in registry entries and other COM class tables. This means that there is no need to run code at all during the install.
After learning how to register COM servers the right way, I still was interested to understand, why my MSI package worked before. In other words: what is the crucial change after Windows XP? ...I meanwhile also checked that the MSI works when I run it as an administrator...
As I figured out reading the WiX toolset documentation, there is an attribute Impersonate for CustomAction that controls if the CA is executed with elevated privileges:
This attribute specifies whether the Windows Installer, which executes as LocalSystem, should impersonate the user context of the installing user when executing this custom action. Typically the value should be 'yes', except when the custom action needs elevated privileges to apply changes to the machine.
It refers to the msidbCustomActionTypeNoImpersonateflag in the Type field of the CustomAction Table. The value 1122 I observed in my MSI is decompiled into this:
1024 (flag): msidbCustomActionTypeInScript, or, deferred execution, runs in installation script
64 (flag): msidbCustomActionTypeContinue, or, ignore exit code and continue
34: Custom Action Type 34, or, launch executable via commandline
What I used to "fix" the problem the fast way is, enable the msidbCustomActionTypeNoImpersonate flag (2048) in the CA type (in WiX this would be Impersonate="no").
Translated into my MakeMsi script, I had to use the System attribute in the Type of the ExeCa command as to make self registration work as before:
Type="Deferred Sync AnyRc System"
I'm fully aware that this is only a workaround, since running a COM server for (un-)register is dangerous. And so the solution mentioned in the second section of PhilDWs answer should be preferred: manage COM related static information via registry entries in the MSI. But sometimes you need a fast solution, and sometimes there is no other option, see Euro Micellis comment.
I'm trying to deploy some Vb6 components on a Windows Server 2003 Standard x64 R2. I normally run these in a com+ application and I went through the normal routine of creating the COM+ application and adding all the components. Everything seemed to work fine until I actually tried to use any of the components. I would some kind of "ActiveX component can't create object" or "Application-defined or object-defined error" or something similar to that.
To remove as many variables a possible I created a very simple VB form to consume the simpliest of the components and tried that. Nope. So I created a simple install to install the component, and whooo hoooo it worked. So I tried one of the more envolved components with high hopes ... but no after the install I still can't call the component successfully. Using Dependency Walker I discovered that for some reason the msvbvm60.dll is not properly registerd.
I've downloaded VBRUN60.exe and VBRUN60SP6.exe and tried installing them. Even going so far as to do a run as with the administrator account and removing the check box for "Run this program with restricted access". I've tried to manually register the msvbvm60.dll in the SysWow64 directory.
Nothing seems to work. It just won't register. Does anybody have any suggestions? At this point I'll try just about anything.
Thanks
If you are registering the components manually you need to pay extra attention. As you are on a 64-bit OS there are two versions of regsvr32.exe. When registering VB6 components you must make sure to use the 32-bit version of regsvr32, which is located under the following location:
%WINDIR%\SysWOW64\regsvr32.exe
If you just type regsvr32 on the command prompt, normally the 64-bit version is chosen (because %WINDIR%\system32 is contained in the %PATH% environment variable), so please make sure to use the full path as above.
If you are using a 32-bit MSI to install your components, this version will be selected automatically and the registration should work just fine.
In case you haven't already done, you should give a try to Process Monitor - one of the best tools I have used on dll registering problems.
The following links will provide some usufull clues:
An excelent tutorial on using Process Monitor for problem solving;
ActiveX component can't create an object
RESOLVED! ActiveX Component Can't Create Object: Cube build failure against SQL Server 2005 Analysis Services
Hope it helps :D
I've had trouble with unregistered components for Visual Basic 6 - although not tried to use the same one as you are mentioning. Manually registering never resolved things, no matter which reg server was used
The problem (eventually) turns out to be Internet Explorer 10. Uninstalling that (due to the way Windows 7 handles IE as Windows updates, this meant unistalling newer versions first to expose the older ones) worked. Afterwards, reinstalling the latest IE brings no problem.
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.
I just noticed that Chromium was installed in AppData in both Vista and XP. If Google does that and if other applications does this, than is that becuase there is some form of protection? Should we write installers that does the same thing as Google?
Windows still lacks a convention for per-user installation.
When an installer asks whether to install for the current user or all users, it really only refers to shortcut placement (Start Menu; Desktop). The actual application files still go in the system-wide %PROGRAMFILES%.
Microsoft's own ClickOnce works around this by creating a completely non-standard %USERPROFILE%\Local Settings\Apps (%USERPROFILE%\AppData\Roaming on Vista / Server 2008) directory, with both program files and configuration data in there.
(I'm at a loss why Microsoft couldn't add a per-user Program Files directory in Vista. For example, in OS X, you can create a ~/Applications, and the Finder will give it an appropriate icon. Apps like CrossOver and Adobe AIR automatically use that, defaulting to per-user apps. Thus, no permissions issues.)
What you probably should do: if the user is not an admin, install in the user directory; if they do, give them both options.
One advantage nobody mentioned are silent auto-updates. Chrome has an updater process that runs all the time and immediately updates your chrome installation.
I think their use-case is non-standard. They need a way to fix vulnerability issues (since it's a browser) as soon as possible. Waiting for admins approving every single update company-wide, is simply not good enough.
As far as I can tell, the only reason why Chrome installs into the Application Data folder is so that non-admin users can install it.
The Chrome installer currently does not allow the user to pick where the application is to be installed. Don't do that – instead, give the user a choice between a per-user (somewhere like App Data) and computer-wide (Program Files) installation.
Windows 7 and Windows Installer 5.0 provide real per-user installation capabilities now.
http://msdn.microsoft.com/en-us/library/dd408068%28VS.85%29.aspx
You can sort of fudge it in Vista and XP by using ~/AppData/Local or the equivalent like Chrome does. Microsoft themselves use this for the ClickOnce installers.
So at least on Windows 7 and beyond the solution is simple.
Frankly, I have yet to see the first installer that really allows both per-user and per-machine installations. Many installers offer this option in their GUI, but the setting only affects where the shortcuts etc. go -- the binaries always fo to %ProgramFiles%.
In fact, it is pretty hard to create Windows Installer packages that allow both kinds of installs, to say the least. With the advent of UAC, I'd say its is impossible: Per user installations must not require elevation, per machine installations have to. But whether an MSI package requires elevation is controlled via a bit in the summary information stream -- there is no way to have user input have impact on that.
Whether per-user or per-machine is the better choice greatly deoends on the application. For small packages, however, I tend to prefer per-user installations. Besides being slightly more user-friendly by not requiring an UAC prompt or runas, they also signalize the user that the setup will not do much harm to the computer (assuming he is a non-admin).
The Chrome installer really ought to allow global installation (with elevation) in addition to per-user. I don't want to have to maintain an installation for every user; I want to be able to centrally manage upgrades and so on. Chrome doesn't allow that.
That said, the option to install per-user is quite nice, as it means no permissions issues.
Just so you people know, Google has created an MSI installer for global system installation and management. It's located here:
https://www.google.com/intl/en/chrome/business/browser/
I do not see anything in %PROGRAMFILES% on Win7. Looks like Chrome must be installed for each user on the machine.
Perhaps the true reason of doing this is faking number of Chrome installations by few times ! Thus making it first browser in the world !