I am using a C# code to install a program using a process which runs the msiexec, giving it the path to the MSI file.
This is the code I use:
string pathtoMsiFile = "\"" + msiPath + msiName + "\"";
Process p = new Process();
p.StartInfo.FileName = "msiexec.exe";
p.StartInfo.Arguments = "/i " + pathtoMsiFile + " /quiet";
p.Start();
p.WaitForExit();
The strange thing is that when I try to install the program, for a certain version it installs it to the correct location I would expect to on C:\path but a different version it installs to D:\path for some reason. If I open the MSI itself manually, the default location there is C:\path. Any idea why?
Eventually it appears the problem is with the program the msiexec tried to install.
I am not that program's developer so I couldn't know the problem in advanced on my own.
The program had a custom action in its installation that set a variable representing the drive to install on as the one where the OS is installed. The problem is, that this action was invoked only through the installation's UI (when double clicking the MSI), but not when using a quiet CLI command to install it.
Related
At work I have to uninstall the same application several times per day (and reinstall new versions). I'm trying to make a C# program that I can run that will do this all for me. Right now, I'm stuck on the uninstall process.
The code I have runs and attempts to uninstall the application, but Windows gives me an error during this.
Here's what I have right now:
static void Main(string[] args)
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
const string prodName = "myApp";
Console.WriteLine("searching...");
foreach (ManagementObject wmi in searcher.Get())
{
if (wmi["Name"].ToString() == prodName)
{
Console.WriteLine("found");
string productCode = "/x {" + wmi.Properties["IdentifyingNumber"].Value.ToString() + "}";
Process p = new Process();
p.StartInfo.FileName = "msiexec.exe";
p.StartInfo.Arguments = productCode;
p.Start();
Console.WriteLine("Uninstalled");
break;
}
}
Console.ReadLine();
}
This is the error I get when it tries to do the uninstall:
"This installation package could not be opened. Verify that the package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer package"
Uninstall Reference: This old answer might have what you need: Uninstalling an MSI file from the command line without using msiexec. It shows various ways to uninstall an MSI.
DTF: The DTF (Desktop Tools Foundation) included with the WiX toolset can be used to uninstall. Here is some sample C# code:
Uninstalling program
- run elevated, quick link to sample.
VBScript / COM: Here are some links to VBScript samples and various ways to uninstall (uninstall by product name, uninstall by upgrade code, etc...): WIX (remove all previous versions) - the uninstall by upgrade code (sample code towards bottom) is interesting because it generally works for all versions and incarnations of your installer (upgrade code tends to remain stable across releases).
CMD.EXE: Personally I might just use an install and an uninstall batch file. More of these samples in section 3 here. Just create two different files:
Install: msiexec.exe /i "c:\Setup.msi" /QN /L*V "C:\msi.log" REBOOT=ReallySuppress
Uninstall: msiexec.exe /x "c:\Setup.msi" /QN /L*V "C:\msi.log" REBOOT=ReallySuppress
I have a .exe file which checks the system architecture and based on the system architecture it calls the corresponding msi file.
I am trying to run this exe file from C# using the code below
Process process = new Process();
process.StartInfo.FileName = "my.exe";
process.StartInfo.Arguments = "/quiet";
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.WorkingDirectory = "path//to//exe//directory";
Console.WriteLine(process.StartInfo.WorkingDirectory);
process.Start();
process.WaitForExit();
The exe is getting invoked. i can see the application logs and there are no errors in the logs.
But the msi is not getting started or installed.
When I try to run the same exe file manually the msi is installed.
Note: There are other dependency files for this my.exe which are placed in the same directory.
Why am i not able to install the msi from C# program while i am able to do this manually.
I am running the VisualStudios in administrator mode.
You need to execute .exe (and msi) as an administrator.
To ensure that, use:
process.StartInfo.Verb = "runas"
Also, try it removing quiet arguments to see any possible errors.
Is "my.exe" installing your MSI if you call it, isn't it?
I got this resolved after i added Thread.Sleep(). before "process.WaitForExit()"
Running install programs from the c# code I can successfuly install .exe files and uninstall both exe and msi files... however whenever launching an msi for installation it just sits there and never does anything....
start = new ProcessStartInfo("msiexec.exe", "/i \"" + tempDir + "/" + s.executable + "\"");
start.WindowStyle = ProcessWindowStyle.Hidden;
start.CreateNoWindow = true;
Process.Start(start).WaitForExit();
can anyone spot my mistake. I understand the wait for exit will wait indefinatly and that is fine as there will be 10-12 installs going synchronously but It never actually installs.....
I had a look of msiexec.exe document. It seems that it only works with *.msi file. I tried your code with msi file, it works well.
There is a minor problem with your code. The directory path should be the other way around.
start = new ProcessStartInfo("msiexec.exe", "/i \"" + tempDir + "\\" + s.executable + "\"")
You have to tweak your command line on several issues to be optimal, and mainly to be supportable.
Don't use the ProcessWindowStyle.Hidden Option here. You don't need to.
As long as you are testing , use the "/qb" parameter.
For release, if you want no dialog, just use "/qn"
I think using not /qn but forbidding to open the window can be the source of the problem.
Assure that your program is already started with admin rights, otherwise you will have a more complicated UAC situation under Vista, Win7 ff. and you really need the dialog to allow the UAC dialog. If your program is already started with admin rights, you can use "/qn" and have other simplifications of scenarios which I would recommend for beginners to MSI.
Use logging.
Using backslashes in Windows is safer although slashes may work sometimes too.
=> I would recommend a resulting command line like this.
string msicmd;
msicmd="msiexec.exe /i \"" + tempDir + #"\" + msifile + #"\" /qb /L*v \"tempDir\mylogfile\"");
// Show a trace of this command line to debug it in case of errors :-)
...
I've been looking around for a while for a possible solution and explanation, but I can't find anything really.
The following command is being run from a windows service. The same command does function if used directly in cmd.
It does not return any errors or anything else for that matter.
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C lpr.exe –S " + printerIP + " –P " + deviceName + " –o l " + fInfo.DirectoryName + #"\" + fInfo.Name;
process.StartInfo = startInfo;
process.Start();
It might just be some minor thing I'm missing, but I just can't see it. If it's possible to go around using the lpr-command with an easy alternative I'd love that, but I havent seen anything yet.
Edit:
Forgot to add that the file I'm trying to send to the printer is a pcl file.
Edit2:
When I run the command without the Hidden windowstyle and WaitForExit(5000) applied to the process then I can't seem to see any commandline written - all that appears is the empty command prompt.
Edit 3:
Been toying a bit around with this now and I've come up with the following:
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "lpr";
startInfo.Arguments = " –S " + printerIP + " –P " + deviceName + " –o l " + fInfo.DirectoryName + #"\" + fInfo.Name;
process.StartInfo = startInfo;
process.Start();
The above code works if it is executed by a user clicking a button in a form. So I decided to change my code into running as a tray application, seeing as I thought this might solve the issues - yet it still seems to refuse being run. Could it be some sort of issue with it being run by a triggered timer or another thread? Or perhaps something to do with the rights of those methods?
Change your code to this:
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C C:\windows\Sysnative\lpr.exe –S " + printerIP + " –P " + deviceName + " –o l " + fInfo.DirectoryName + #"\" + fInfo.Name;
process.StartInfo = startInfo;
process.Start();
The issue is that you are trying to access a 64 bit application (lpr) from a 32 bit cmd.exe application. The simple solution is to use the sysnative directory.
http://www.samlogic.net/articles/sysnative-folder-64-bit-windows.htm
The 'Sysnative' folder is invisible in Windows Explorer If you
start Windows Explorer and open the Windows folder on your hard disk,
you may notice that the Sysnative folder is not shown. The main reason
to this is that Windows Explorer is a 64-bit program (when run in a
64-bit Windows), and the Sysnative folder is only visible and
accessible from 32-bit software. If 64-bit software need access to the
64-bit system folder in Windows, the only option is to use the
System32 folder name (for example: C:\Windows\System32).
Using the 'Sysnative' folder will help you access 64-bit tools from
32-bit code Some tools in a 64-bit Windows only exist in a 64-bit
version; there is no 32-bit version available. And some of these tools
are located in the 64-bit System32 folder. One example is the nbtstat
tool that is used to help troubleshoot NetBIOS name resolution
problems. If you try to run the nbtstat tool from 32-bit code (for
example from an application or from script) and use a path like
C:\Windows\System32, you will get a "File not found" error. The file
can not be found; although Windows Explorer shows that the nbtstat
program file actually is located in the C:\Windows\System32 folder.
The solution to this (somewhat confusing) problem is to include the
virtual Sysnative folder in the folder path when you want to run the
tool. For example like this: C:\Windows\Sysnative\nbtstat.exe The
file path above will give you access to the 64-bit nbtstat tool from a
32-bit application or from a 32-bit script. We recommend you to read
this article / blog post (at Scottie’s Tech.Info) to get more details
about this.
I'm having an issue with running slui.exe from a method in c#. I'm using the code:
ProcessStartInfo startInfo = new ProcessStartInfo(#"C:\Windows\System32\slui.exe");
Process p = new Process();
p.StartInfo = startInfo;
p.Start();
p.WaitForExit();
but I keep getting a Win32Exception: 'The system cannot find the file specified'.
If I change the ProcessStartInfo to: (#"C:\Windows\System32\cmd.exe") it will launch just fine.
Is there something with running slui.exe in this context that is breaking?
I'm certain that the file is in the directory specified, so I'm stumped as to what may be going wrong here.
Any ideas how to call slui.exe from a c# method?
Slui.exe is only available as a 64-bit program on Windows x64. Your hard-coded path c:\windows\system32 will get re-directed to c:\windows\syswow64 when you run as a 32-bit process. And thus won't find the file.
Project + Properties, Compile tab, change the Platform target setting to "AnyCPU". Repeat for the Release configuration. And use Environment.GetFolderPath() to ensure it still works when Windows isn't installed to c:\windows.