How to set wix msi to run advertised by admin - wix

I have a program that auto-updates itself when it finds a newer version MSI. I used to create the MSI with a VS2008 Setup project. I migrated the development to VS2013, lost the Setup project, tried IS and got extremely frustrated and finally landed with WIX.
The MSI created with WIX does all I need but fails in the auto-update logic:
Because the program can be running under a limited user account, when it detects a newer MSI, it first Advertises it with the credentials of an Administrator. These credentials are stored encrypted in an XML file.
Then, once the MSI has been advertised, it is launched with the current user. The code (in short)
Process^ advertise = this->advertiseMSI(shortpath,mydomain,myusername,mypassword);
advertise->WaitForExit();
Process^ install = this->installMSI(shortpath);
Where advertiseMSI is:
Process^ process = gcnew Process();
process->StartInfo->UseShellExecute = false;
process->StartInfo->FileName = "C:\\Windows\\System32\\msiexec.exe";
process->StartInfo->Arguments = "/jm " + "\"" + msiPath + "\"";
process->StartInfo->WorkingDirectory = Environment::GetEnvironmentVariable("WINDIR");
process->StartInfo->UserName = userName;
process->StartInfo->Password = this->getSecureString(Password);
process->StartInfo->Domain = userDomain;
process->StartInfo->Verb = "runas";
process->Start();
return process;
and installMSI just launches the Msiexec in a silent install with the current user.
This worked fine with the MSI created with VS2008 but it fails with the WIX MSI.
The log of the msiexec is:
"Error 1730. You must be an Administrator to remove this application..."
If I run the MSI manually, it works when logged as admin but when logged as user it fails and doesn't ask for elevating privileges.
I have set InstallPrivileges="elevated" InstallScope="perMachine" in the Package section and does not make a difference (I have tried every possible combination of those). It seems to me that the MSI is not advertised but the code does not fail. Looks like the MSI is always run with limited privileges.
I have also tried to set AllowAdvertise="yes" in the only one Feature of the product.
One main difference I can see with the MSI produced with VS2008 is that the later had two features, Admin and user.

I don't know if you're still struggling with this problem, but I've come across a similar problem with an installer built with NSIS, so perhaps this will help you or others. I was able to overcome this in my situation by using command shell indirection as follows (C# code):
ProcessStartInfo processInfo = new ProcessStartInfo("cmd", "/C myapp_installer.exe /S /D"); // Options /S /D apply to myapp_installer.exe.
processInfo.UseShellExecute = false;
processInfo.Domain = domain;
processInfo.UserName = username;
processInfo.Password = password; // Obtain securely not hard-coded.
Process process = Process.Start(processInfo);
I can't fully explain why this works, when directly calling the installer fails to pass the required credentials, but I'm pretty certain that it has to do with what is explained by Chris Jackson on the MSDN Blog, which incidentally was referenced in the answer to your related question.
I hope this helps!

Related

Wix FindRelatedProducts has found a product which is not installed

After testing many of install/uninstall of my product in the machine I've ended up a scenario where I don't have my product installed, at least I cannot see it in the control panel, but when I try to install it again, Wix is trying to Update a product which is not installed.
I've executed the msi with the logs, then I found that FindRelatedProducts is found a GUID and populating the WIX property WIX_UPGRADE_DETECTED.
part of the log:
FindRelatedProducts: Found application: {MY-GUID}
MSI (c) (24:8C) [07:21:36:885]: PROPERTY CHANGE: Adding WIX_UPGRADE_DETECTED property. Its value is '{MY-GUID}'.
As I'm using WIX_UPGRADE_DETECTED to select with dialog (Install or Upgrade) to show, It's showing a upgrade dialog, but no product is installed.
If I test in another machine, doing the same scenario, FindRelatedProducts doesn't find any product, which is the correct case.
I'm suspecting of some entry in the windows Registry(regedit) was not cleaned.
Do you know how Wix detects FindRelatedProducts? Or why Wix is populating the WIX_UPGRADE_DETECTED with no product installed?
Thanks!
Short Answer: The answer below is probably too elaborate, just do an uninstall of what your upgrade setup finds and then try to
install again.
From a command prompt (Windows Key + Tap R +
Type: cmd.exe + Enter) run the following command:
msiexec.exe /x {GUID-FROM-LOG-FILE}
The GUID is (most likely) the one from your log file: WIX_UPGRADE_DETECTED. Then try
installing again.
Failing Uninstall: If the uninstall fails, try running this Microsoft FixIt tool. Sometimes it can sort out setups that don't uninstall properly. Alternative, under the hood fix (not recommended).
UpgradeTable: The first thing I would do is to verify what is in the UpgradeTable in the compiled MSI file that shows the problem. Does the upgrade code there match the upgrade code for your setup? (UpgradeCode entry in the Property Table).
The content of the UpgradeTable determines what existing installations (if any) are detected as related to your new installation. If you configure weird stuff here you could even end up uninstalling competitive products erroneously detected as related to yours - I wouldn't try that :-). Too much paperwork.
Uninstall: Now, how to get rid of the problem installation? You need to get hold of the ProductCode GUID. There are numerous ways to obtain this information. It should be the product GUID you see in your MSI log for WIX_UPGRADE_DETECTED, so try that first:
msiexec.exe /x {GUID}
Here is an answer on uninstalling MSI setups in a general sense (all kinds of different options - have a quick read?): Uninstalling an MSI file from the command line without using msiexec.
ProductCode (GUID): Rob has already mentioned the right MSI API to list installed products, I will just add that I have this answer here that can help: How can I find the product GUID of an installed MSI setup? It lists several options to see what is installed on your box.
VBScript / COM Automation: I will just inline the VBScript option from the first link above (there are several options listed in that linked answer):
' Retrieve all ProductCodes (with ProductName and ProductVersion)
Set fso = CreateObject("Scripting.FileSystemObject")
Set output = fso.CreateTextFile("msiinfo.csv", True, True)
Set installer = CreateObject("WindowsInstaller.Installer")
On Error Resume Next ' we ignore all errors
For Each product In installer.ProductsEx("", "", 7)
productcode = product.ProductCode
name = product.InstallProperty("ProductName")
version=product.InstallProperty("VersionString")
output.writeline (productcode & ", " & name & ", " & version)
Next
output.Close
PowerShell: Throwing in the PowerShell option as well. In some cases this can trigger unexpected self-repair.
get-wmiobject Win32_Product | Format-Table IdentifyingNumber, Name, LocalPackage -AutoSize
The Windows Installer has registration spread about the registry. It provides an API to introspect over that registration. In this case, you want ::MsiEnumRelatedProducts(). It will get you all the products related via that UpgradeCode.
You can then uninstall those products by doing:
msiexec /x {PRODUCT-CODE-GUID}
You should find {PRODUCT-CODE-GUID} is the same as what you redacted as {MY-GUID}.
Note: this has nothing to do with the WiX Toolset. Is 100% Windows Installer behavior (aka: MSI).
FindRelatedProducts is executed by Windows Installer not WiX. Your assertion that the behavior is incorrect is most certainly incorrect. You have a dirty machine and MSI has artifacts indicating that it's installed. Your other machine is clean and does not.
I was able to identify what were the registry entries left on the machine which was causing the errors that I mentioned.
They are in the following location:
- HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\UpgradeCodes\{OTHER-GUID}
- HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Products\{OTHER-GUID}
Note that, the {OTHER-GUID} is not my product code, but a generated one, my product code is one of a values present into those registry entries.
Just removing them makes my installer working again.
Tks #stein-Åsmul this command: get-wmiobject Win32_Product is very helpful.

Why installer runs after click on shortcut?

I created a simple bootstrapper for my application using WixSharp.
namespace TestBootstrapper
{
class Program
{
static void Main()
{
var package = new MsiPackage("../testmsi.msi")
{
DisplayInternalUI = true,
Id = "MyId",
Compressed = true,
Visible = true
};
var bootstrapper = new Bundle("MyTestInstaller", package)
{
Version = new Version("1.0.0.0"),
UpgradeCode = new Guid("1FCC927B-7BB0-4FB0-B81E-2D87012E470B"),
PreserveTempFiles = true,
DisableModify = "yes",
DisableRemove = true
};
bootstrapper.Build("Installer.exe");
}
}
}
I logged as admin and installed the application (using Installer.exe) and there were no errors in Event Viewer during installation. When I clicked shortcut the application runs as expected.
If I run testmsi.msi as standard user or admin it installed without any errors and if I clicked shortcut the application runs as expected.
I logged as standard user and installed the application (using Installer.exe). There were no errors in Event Viewer during installation. But when I clicked shortcut installer runs again.
So, why installer runs and how to prevent this behavior?
It's a repair, which may be good or bad depending on what is being re-installed. The application event log should have MsiInstaller entries that say something about what is being repaired. It's not necessarily a bad thing that needs to be prevented.
Assuming you did a per-machine install, if you installed (for example) a file into the User's Application Data folder from your MSI, and then you log on as another user and run the app, then the file is obviously missing for that user. So Windows Installer will do an install for that missing part of the app. The file is probably required for all users of the system, yes? Windows assumes that if you install a file (or registry entry) into a user profile location then everyone that logs on needs this file, so it gets installed by "repair" when another user logs on and uses the shortcut.
There are other scenarios where a repair is not so good. If you do something to remove a file that you installed then Windows will attempt to restore it. If you do a per-user install but then log on as another user and try to use the app that's not an intended use of the product - installer per machine to do that.
I just discovered something that might help -
If you are not installing any programs to the Application directory (for example only installing to Local App data), Windows Installer generates an error message because the Application directory doesn't exist.
If you add ANY file to the Application directory, or create it manually, the shortcut will work properly.

WIX 3.8 msiexec.exe /quiet Error 1603

I am using WIX 3.8, Windows 8 Pro, Visual Studio 2013, and I am doing a Silent Installation.
When I run with no /quiet arguments, Ir runs OK. But when I put "/quiet", nothin happend.
There is some problems with /qn Arguments... Any other Arguments Runs OK.
string arg = " SetupWIX.msi";
Process p = new Process();
p.StartInfo.FileName = "msiexec.exe";
p.StartInfo.CreateNoWindow = true;
p.StartInfo.Arguments = "/i " + arg +" /quiet /l*v log.txt";
p.Start();
And it give error 3.
MainEngineThread is returning 1603.
Any Ideas?
Tahnks
Based on the log you sent me, your MSI need to be elevated.
Not all MSI's do. Most do. If you are installer in a per-machine context and/or writing to restricted areas ( Program Files, HKLM, Windows an so on ) you'll need elevation. Typically when you double click an MSI the UI sequence runs as standard user and then when it transitions to the Execute sequence it'll prompt for elevation if required. However when you run /quiet it can't do that so it just fails instead. The two ways around this are to elevate the calling process or first 'advertise' the MSI so that the system trusts it. In that case the UI->Exec elevation happens automatically without a UAC request.
I SOLVE IT!! Thanks yopu all for your time
I was MIssing
p.StartInfo.Verb = "runas";
I did not know I need Administrator Privilegies to execute "/quiet".

RestartManager fails to restart application during update

I'm using c#, .net 4, WIX 3.5, Windows Vista.
I have made my application compatible with RestartManager by p/invoking the RegisterApplicationRestart method and by handling the WM_QUERYENDSESSION and WM_ENDSESSION window messages (I return new IntPtr(1);).
If I try to update my application manually, then everything works as it should:
Launch application;
Launch msi file containing new app version;
During the installation/update, I'm prompted to close the running application;
Upon continuing the running app is closed, install completes, and the app is restarted;
If I try to update my application from the application itself, then I run into problems:
1) Launch application;
2) Download the new msi file;
3) Launch msi file with:
using (System.Diagnostics.Process p = new System.Diagnostics.Process())
{
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = "msiexec";
p.StartInfo.Arguments = "/i \"" + downloadPath + "\" /passive";
p.StartInfo.UserName = "Administrator";
p.StartInfo.Password = securePassword;
p.Start();
}
4) Because I'm using passive mode, the application is closed automatically;
5) After the installation, my application is not restarted and under Event Viewer I have an
Event 10007 - Application or service 'MyApp' could not be restarted.
I have tried:
Not to use passive mode for msiexec;
Launch msiexec via cmd.exe (cmd.exe /C "msiexec /i ....") - in the hopes that launching msiexec from another process would solve the problem;
Wait for 60+ seconds before launching the msi update (shouldn't be relevant in my scenario, but MSDN documentation has something about it...)
But none of the above has worked (always the same result).
Having to launch the setup with elevated permissions might have something to do with the issue, because during the manual update I get a warning in the Event Viewer - Application MyApp (pid 3220) cannot be restarted - Application SID does not match Conductor SID.
Despite this, restarting the app still works. Googleing the warning yields no good/specific results, only that this warning is probably caused by running the msi in an elevated prompt.
How do I fix (or workaround) this issue, so that I can update my application from the application itself and restart my application afterwards?
Edit - extra testing:
There doesn't seem to be a need to respond to WM_QUERYENDSESSION and WM_ENDSESSION messages, because application restart during a manual upgrade works without them, so we can rule them out;
If I don't provide administrator credentials to the application initiated upgrade and instead I type them in during the upgrade, then app restarting works;
If I run an elevated command prompt and initiate an application upgrade from there (manually), then app restarting still works;
In order for application upgrade to work at all under Standard user accounts (so far I tested under an Administrator account with UAC), then I also have to set p.StartInfo.LoadUserProfile = true;. Otherwise nothing happens. (application restart still doesn't work though);
I tried all other process StartInfo parameters that I could set - WorkingDirectory, Redirect, Verb
(= "runas") - no change in results;
I installed Vista SP2 onto the virtual machine that I have been testing on (so far ran SP1), but no change;
I performed an "automatic" application upgrade with verbose logging. In the end there was an error message - RESTART MANAGER: Failed while restarting applications. Error: 352. That error code is very generic (http://msdn.microsoft.com/cs-cz/library/aa373665), inorder to get more detailed info I would have to write my own installer that would call RmGetList after the error, then I might get more details (this though is something I'm not willing to do);
Edit 2 - msi log file:
http://mommi.planet.ee/muu/log.txt
Assuming that the manual process indeed works without any problem it seems that your need for Administrator privileges in combination with the "updating itself" leads to these problems. I see the following options:
create a batch file to execute the update
When you want to update call this batch file (with elevated privileges), make the app close itself... the batch file should wait some seconds, then check whether the app is still running (and close it in case) and then run the commandline you need to run msiexec - don't restart the app from within msiexec but after a successfull run of msiexec from the batch file.
create a batch file which is always used to start the app
When the time comes to update you just end the app. Either the batch file check for an available update and applies it, starting the app after successfull update OR the app set some environment variable which is then accordingly processed by the rest of the batch file.

Trouble with msi exit code 1625 when running msi programmatically

Exit code 1625 is "This installation is forbidden by system policy. Contact your system administrator."
What I'm doing is calling it this way:
Process installProcess = Process.Start(msiPath, "/quiet");
I can run the msi fine if I open it manually. This is on windows server 2008...
The intent of this is to automatically update my .net forms program with the latest version. Anybody have a clue what sort of setting is causing this? I mean, the clients are going to be using vista/7/xp, but I still need to know what kind of security settings will ruin my plan.
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.Arguments = "/i " + "\""+Directory.GetCurrentDirectory()+"\\"+msiPath +"\"" +" /q";
startInfo.FileName = "msiexec.exe";
startInfo.Verb = "runas";
Process installProcess = Process.Start(startInfo);
Calling the msi this way did the trick.
Turned out to be some kind of UAC issue I think. The runas verb somehow elevates the permissions the program has. Even though my UAC prompts were disabled on server 2008 I still had to do this to get around it.. strange huh?