I Have a Three EXE's
EXE1 build with 3.5 net framework
EXE2 build with 4.5 net framework
EXE3 build with 4.6 net framework
I want to run exe after detect which.Net version already installed and according to that start exe
if 3.5 installed
RUN(EXE1)
if 4.5 installed
RUN(EXE2)
if 4.6 installed
RUN(EXE3)
i think about wix setup, iexpress but didnt get any thing so how can we do this ?
or its is possible? if yes then how and if no then so can we do this with the help of third party software?
so I need a way to run exe as per platform because each platform has
their own .Net framework
there is 2 way: using bath file to detect .net version after that run exe for this version
or build a porogram exe depend .net 2 after that this exe decide witch file must run
Update:
this samples give you version of .net freamwork are inistaled
for.net 4 and older
private static void GetVersionFromRegistry()
{
// Opens the registry key for the .NET Framework entry.
using (RegistryKey ndpKey =
RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, "").
OpenSubKey(#"SOFTWARE\Microsoft\NET Framework Setup\NDP\"))
{
// As an alternative, if you know the computers you will query are running .NET Framework 4.5
// or later, you can use:
// using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
// RegistryView.Registry32).OpenSubKey(#"SOFTWARE\Microsoft\NET Framework Setup\NDP\"))
foreach (string versionKeyName in ndpKey.GetSubKeyNames())
{
if (versionKeyName.StartsWith("v"))
{
RegistryKey versionKey = ndpKey.OpenSubKey(versionKeyName);
string name = (string)versionKey.GetValue("Version", "");
string sp = versionKey.GetValue("SP", "").ToString();
string install = versionKey.GetValue("Install", "").ToString();
if (install == "") //no install info, must be later.
Console.WriteLine(versionKeyName + " " + name);
else
{
if (sp != "" && install == "1")
{
Console.WriteLine(versionKeyName + " " + name + " SP" + sp);
}
}
if (name != "")
{
continue;
}
foreach (string subKeyName in versionKey.GetSubKeyNames())
{
RegistryKey subKey = versionKey.OpenSubKey(subKeyName);
name = (string)subKey.GetValue("Version", "");
if (name != "")
sp = subKey.GetValue("SP", "").ToString();
install = subKey.GetValue("Install", "").ToString();
if (install == "") //no install info, must be later.
Console.WriteLine(versionKeyName + " " + name);
else
{
if (sp != "" && install == "1")
{
Console.WriteLine(" " + subKeyName + " " + name + " SP" + sp);
}
else if (install == "1")
{
Console.WriteLine(" " + subKeyName + " " + name);
}
}
}
}
}
}
}
and for get .net 4.5 and upper
using System;
using Microsoft.Win32;
public class GetDotNetVersion
{
public static void Get45PlusFromRegistry()
{
const string subkey = #"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(subkey))
{
if (ndpKey != null && ndpKey.GetValue("Release") != null) {
Console.WriteLine(".NET Framework Version: " + CheckFor45PlusVersion((int) ndpKey.GetValue("Release")));
}
else {
Console.WriteLine(".NET Framework Version 4.5 or later is not detected.");
}
}
}
// Checking the version using >= will enable forward compatibility.
private static string CheckFor45PlusVersion(int releaseKey)
{
if (releaseKey >= 460798) {
return "4.7 or later";
}
if (releaseKey >= 394802) {
return "4.6.2";
}
if (releaseKey >= 394254) {
return "4.6.1";
}
if (releaseKey >= 393295) {
return "4.6";
}
if ((releaseKey >= 379893)) {
return "4.5.2";
}
if ((releaseKey >= 378675)) {
return "4.5.1";
}
if ((releaseKey >= 378389)) {
return "4.5";
}
// This code should never execute. A non-null release key should mean
// that 4.5 or later is installed.
return "No 4.5 or later version detected";
}
}
// Calling the GetDotNetVersion.Get45PlusFromRegistry method produces
// output like the following:
// .NET Framework Version: 4.6.1
and by this sample you can run exe file
using System;
using System.Diagnostics;
using System.ComponentModel;
namespace MyProcessSample
{
class MyProcess
{
public static void Main()
{
Process myProcess = new Process();
try
{
myProcess.StartInfo.UseShellExecute = false;
// You can start any process, HelloWorld is a do-nothing example.
myProcess.StartInfo.FileName = "C:\\HelloWorld.exe";
myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start();
// This code assumes the process you are starting will terminate itself.
// Given that is is started without a window so you cannot terminate it
// on the desktop, it must terminate itself or you can do it programmatically
// from this application using the Kill method.
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
Update2:
by this Update you get latest version of .net at batch File
#echo off
setlocal
#SET INSTALLUTILDIR=
#for /F "tokens=1,2*" %%i in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5" /v "Version"') DO (
if "%%i"=="Version" (
SET .NetVer=%%k
)
)
#for /F "tokens=1,2*" %%i in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" /v "Version"') DO (
if "%%i"=="Version" (
SET .NetVer=%%k
)
)
ECHO The most current version of Net in use is %.NetVer%
and by this code you can run program but dont forget the bat file must be in folder the exe files are there
start myProgram.exe
exit
If you use Windows Installer (such as through wix), you can use the MsiNetAssemblySupport property to condition a custom action that launches your executable. If you use wix specifically, the WixNetfxExtension can be asked to set other properties that may be easier to use. Here is wix's list of .NET properties.
However I suspect this is the wrong approach. It should be much easier to write a single .NET executable that targets the lowest framework version you support, and include a .config file1 with a supportedRuntime element that enables it to run on a wider spread of frameworks. (See How to: Configure an App to Support .NET Framework 4 or 4.5.
Also, depending on what the executable does, you may be better off writing a C++ executable, a C++ DLL (so it can interact with Windows Installer), or even leveraging native Windows Installer functionality instead of custom actions. (If applicable, the last option is ideal.)
1Note that Windows Installer EXE custom action support for temporary files will only extract a single file to the temp folder, so your .config file would not be found in these configurations. Alternate approaches would be required; various Windows Installer tools have their own approaches for mitigating this problem.
Related
I have a small subroutine to check for the existence of a required server program, as follows:
private bool IsProgramInstalled(string programDisplayName)
{
string logstr = string.Format("Checking install status of {0}....", programDisplayName);
RegistryKey rk = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Bridge Club Utilities");
foreach (string s in rk.GetSubKeyNames())
{
Console.WriteLine(s);
if (s != null)
{
if (s.Equals(programDisplayName))
{
AppendToLog(logstr + " INSTALLED");
return true;
}
}
}
AppendToLog(logstr + " NOT INSTALLED", Color.Red);
return false;
}
I have installed the program containing the above subroutine on many Windows boxes with no problems, but one customer receives an 'Unhandled Exception' error on program startup, as shown below:
When I loaded VS2022 on the customer's machine and ran it in debug mode, the exception appears on the line that sets RegistryKey rk, as shown below:
So I thought this user had maybe installed the required server program (BridgeComposer) in the wrong place, or the registry was screwed up somehow, or there was a permissions issue. I tried running my app in 'administrative mode', but this did not solve the problem.
Next, I tried to see if the user's PC had the same registry entries as my PC, and it appears that they do. If I manually navigate to 'Computer\HKEY_LOCAL_MACHINE\SOFTWARE\RegisteredApplications' on both machines, I see the same entry for 'BridgeComposer' as shown below:
Clearly I'm doing something wrong/stupid, but I have no clue what it is. Any pointers/clues would be appreciated.
Most likely your program is running as 32-bit on a 64-bit computer and is therefore searching in HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node.
There are a number of ways one can approach this:
Use Registry.OpenBaseKey and specify the desired Registry View.
Compile for AnyCPU, but uncheck Prefer 32-bit (Project => <project name> Properties... => Build => Uncheck Prefer 32-bit)
Compile for 64-bit
Option 1:
Note: The following is untested, but should work - it's a slight modification of the code in your OP.
private bool IsProgramInstalled(string programDisplayName, RegistryView regView = RegistryView.Registry64)
{
string logstr = string.Format("Checking install status of {0}....", programDisplayName);
using (RegistryKey localKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, regView))
{
if (localKey != null)
{
using (RegistryKey rk = localKey.OpenSubKey(#"SOFTWARE\Bridge Club Utilities"))
{
if (rk != null)
{
foreach (string s in rk.GetSubKeyNames())
{
Console.WriteLine(s);
if (s != null)
{
if (s.Equals(programDisplayName))
{
AppendToLog(logstr + " INSTALLED");
return true;
}
}
}
}
}
}
}
AppendToLog(logstr + " NOT INSTALLED", Color.Red);
return false;
}
When launch clickonce setup of CefSharp Winform Application return an error installing vc++ 2019 redist (vc++ is in deployment requirements). It's generate an empty directory during install.
"C:\Users\xxxxxx\AppData\Local\Temp\VSD66FC.tmp\vcredist_x86\vcredist_x86.exe has changed since it was initially published."
Both on Windows 7 and 10, same error. I need to install manually package.
I've removed Visual C++ "14" from requirements, but I don't know how include c++ library in the Application code.
I found a workaround. I'm using a service, but it should work in a winform:
private void InstallVCredist()
{
string exe = #"path to exe\VC_redist.x86.exe"; //set path
string stp = #"\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"; //set subkey
using (RegistryKey reg = Registry.LocalMachine.OpenSubKey(stp)) //recall registry
{
if (reg != null)
{
foreach (string dname in reg.GetSubKeyNames()) //loop search
{
using (RegistryKey sreg = reg.OpenSubKey(dname))
{
if (sreg.GetValue("DisplayName").ToString() == "Microsoft Visual C++ 2015-2019 Redistributable (x86) - 14.23.27820") //set dispayname of version
{
vcredist = "1"; //it's mine control variable
break;
}
}
}
}
}
if (vcredist == "0") //now testing if it was found
{
Process vc = new Process();
vc.StartInfo.FileName = exe;
//silent install
vc.StartInfo.Arguments = "/install /passive /norestart";
vc.StartInfo.UseShellExecute = false;
vc.StartInfo.CreateNoWindow = true;
//silent install
vc.Start();
vc.WaitForExit(); //as he says ;)
}
}
I'm trying to uninstall a program with this code.. But it doesn't seem to work. I've tried the other answers but didn't seem to work either.. Can someone help me with this? I'm trying to uninstall the program by a given name(displayName)
For example I give the displayName = Appname then this code should uninstall the Appname program from my computer.
public static void UninstallApplictionInstalled(string p_name)
{
string displayName;
string uninstlString;
RegistryKey key;
ProcessStartInfo info = new ProcessStartInfo();
Process uninstallProcess = new Process();
string temp;
// search in: CurrentUser
key = Registry.CurrentUser.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
foreach (String keyName in key.GetSubKeyNames())
{
RegistryKey subkey = key.OpenSubKey(keyName);
displayName = Convert.ToString(subkey.GetValue("DisplayName"));
uninstlString = Convert.ToString(subkey.GetValue("UninstallString"));
if (p_name.Equals(displayName, StringComparison.OrdinalIgnoreCase) == true)
{
uninstallProcess.StartInfo.FileName = "MsiExec.exe";
uninstallProcess.StartInfo.Arguments = " /x " + uninstlString + " /quiet /norestart";
uninstallProcess.Start();
uninstallProcess.WaitForExit();
break;
//Console.WriteLine(subkey.GetValue("UninstallString"));
}
}
// search in: LocalMachine_32
key = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
foreach (String keyName in key.GetSubKeyNames())
{
RegistryKey subkey = key.OpenSubKey(keyName);
displayName = Convert.ToString(subkey.GetValue("DisplayName"));
uninstlString = Convert.ToString(subkey.GetValue("UninstallString"));
if (p_name.Equals(displayName, StringComparison.OrdinalIgnoreCase) == true)
{
uninstallProcess.StartInfo.FileName = "MsiExec.exe";
uninstallProcess.StartInfo.Arguments = " /x " + uninstlString + " /quiet /norestart";
uninstallProcess.Start();
uninstallProcess.WaitForExit();
break;
//Console.WriteLine(subkey.GetValue("UninstallString"));
}
}
// search in: LocalMachine_64
key = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall");
foreach (String keyName in key.GetSubKeyNames())
{
RegistryKey subkey = key.OpenSubKey(keyName);
displayName = Convert.ToString(subkey.GetValue("DisplayName"));
uninstlString = Convert.ToString(subkey.GetValue("UninstallString"));
if (p_name.Equals(displayName, StringComparison.OrdinalIgnoreCase) == true)
{
//string prdctId = uninstlString.Substring((uninstlString.IndexOf("{")));
uninstallProcess.StartInfo.FileName = "MsiExec.exe";
uninstallProcess.StartInfo.Arguments = " /x " + uninstlString + " /quiet /norestart";
uninstallProcess.Start();
uninstallProcess.WaitForExit();
break;
//Console.WriteLine(subkey.GetValue("UninstallString"));
}
}
}
Only this pops up..
Duplicates: Welcome to Stackoverflow. Just to mention to you that I see this question asked in at least 3 different flavors. We will have to close some of your questions since the duplication scatters replies and can waste a lot of time if people answer the (seemingly) unanswered duplicates.
In short: please don't post the same question several times. Here are the other questions:
MsiExec.exe product id uninstall
MSI installer option- uninstalling an application
C#: Using C# for this can be clunky - no matter how you do it. I would not push a command line to msiexec.exe, but go directly via the MSI API. This API can be accessed via Win32 functions or COM automation.
Uninstall Appraches for MSI: For your reference, there is a myriad of ways to kick of an MSI
uninstall:
Uninstalling an MSI file from the command line without using msiexec.
Section 14 from the link above shows how to uninstall using C++ - if that is an option. However:, there are changes in the Visual Studio 2017 templates again, so it might need a tune-up to work "out-of-the-box".
However, I would use the MSI API - as already stated - and I would recommend you go via the native Win32 functions and that you use DTF (Deployment Tools Foundation) which is part of the WiX toolkit. It is a .NET wrapper for the MSI API - which will save you a lot of boilerplate code, at the expense of having to deploy the DTF DLL: Microsoft.Deployment.WindowsInstaller.dll along with your product. I do not know if this is acceptable. I have code that does not depend on DTF if need be, but it is much longer.
Mock-up C# Sample. Project reference to Microsoft.Deployment.WindowsInstaller.dll needed. Then try the below code in a fresh C# .NET project. You can get that DLL by installing the WiX toolkit - the open source toolkit to create MSI files. After installation check in %ProgramFiles(x86)%\WiX Toolset v3.11\bin (adjust for WiX version - current as of September 2018).
Installer GUI: Important note first: the setup's UI level is set via the Installer.SetInternalUI function. If you run in silent mode, then you need to run the executable elevated for the uninstall to work properly, or an access exception occurs. When you run in Full GUI mode, you need to elevate the install yourself - provided you have the rights to do so.
Run Elevated: How to check for admin rights: Check if the current user is administrator.
using System;
using Microsoft.Deployment.WindowsInstaller;
namespace UninstallMsiViaDTF
{
class Program
{
static void Main(string[] args)
{
// Update this name to search for your product. This sample searches for "Orca"
var productcode = FindProductCode("orca");
try
{
if (String.IsNullOrEmpty(productcode)) { throw new ArgumentNullException("productcode"); }
// Note: Setting InstallUIOptions to silent will fail uninstall if uninstall requires elevation since UAC prompt then does not show up
Installer.SetInternalUI(InstallUIOptions.Full); // Set MSI GUI level (run this function elevated for silent mode)
Installer.ConfigureProduct(productcode, 0, InstallState.Absent, "REBOOT=\"ReallySuppress\"");
// Check: Installer.RebootInitiated and Installer.RebootRequired;
}
catch (Exception e)
{
Console.WriteLine("Exception: " + e.Message);
}
Console.ReadLine(); // Keep console open
}
// Find product code for product name. First match found wins
static string FindProductCode(string productname)
{
var productcode = String.Empty;
var productname = productname.ToLower();
foreach (ProductInstallation product in ProductInstallation.AllProducts)
{
if (product.ProductName.ToLower().Contains(productname))
{
productcode = product.ProductCode;
break;
}
}
return productcode;
}
}
}
With the following code:
static void Main()
{
try
{
var context = uno.util.Bootstrap.bootstrap();
}
catch (Exception ex)
{
Console.WriteLine(ex.toString());
}
}
I can start Writer of LibreOffice. This works fine with Version 4.4.4 but after installing version 5.0.0 and with new SDK Bootstrap.bootstrap() throws the exception:
"External component has thrown an exception"
Has anyone faced the same problem or some solution?
(.NET 4.0, Windows 7 64-bit, LibreOffice 5.0 Lite)
I have managed to solve the problem by setting the UNO_PATH environment variable before starting the soffice.exe server:
using static System.Environment;
var unoPath = #"C:\Program Files\LibreOffice 5\program"
// when running 32-bit LibreOffice on a 64-bit system, the path will be in Program Files (x86)
// var unoPath = #"C:\Program Files (x86)\LibreOffice 5\program"
SetEnvironmentVariable("UNO_PATH", unoPath, EnvironmentVariableTarget.Process);
SetEnvironmentVariable("PATH", GetEnvironmentVariable("PATH") + #";" + unoPath, EnvironmentVariableTarget.Process);
This was required because LibreOffice 5's program directory does not have "URE" subdirectory anymore (previous versions did) which is required for UNO layer.
To get the path to the LibreOffice installation you can ask e.g. the Windows registry. In C# this is smoething like that:
String unoPath = "";
// access 32bit registry entry for latest LibreOffice for Current User
Microsoft.Win32.RegistryKey hkcuView32 = Microsoft.Win32.RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.CurrentUser, Microsoft.Win32.RegistryView.Registry32);
Microsoft.Win32.RegistryKey hkcuUnoInstallPathKey = hkcuView32.OpenSubKey(#"SOFTWARE\LibreOffice\UNO\InstallPath", false);
if (hkcuUnoInstallPathKey != null && hkcuUnoInstallPathKey.ValueCount > 0)
{
unoPath = (string)hkcuUnoInstallPathKey.GetValue(hkcuUnoInstallPathKey.GetValueNames()[hkcuUnoInstallPathKey.ValueCount - 1]);
}
else
{
// access 32bit registry entry for latest LibreOffice for Local Machine (All Users)
Microsoft.Win32.RegistryKey hklmView32 = Microsoft.Win32.RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, Microsoft.Win32.RegistryView.Registry32);
Microsoft.Win32.RegistryKey hklmUnoInstallPathKey = hklmView32.OpenSubKey(#"SOFTWARE\LibreOffice\UNO\InstallPath", false);
if (hklmUnoInstallPathKey != null && hklmUnoInstallPathKey.ValueCount > 0)
{
unoPath = (string)hklmUnoInstallPathKey.GetValue(hklmUnoInstallPathKey.GetValueNames()[hklmUnoInstallPathKey.ValueCount - 1]);
}
}
Then you can use the answer of Funbit [ https://stackoverflow.com/a/31937114/2936206 ]
The most easiest way I found is just copy the URE folder from previous LibreOffice version to LibreOffice 5.
I tried this,this to uninstall the application programmatically. I am not getting any error or exception but the application is not uninstalled from my machine. Please see tried code also
public static string GetUninstallCommandFor(string productDisplayName)
{
RegistryKey localMachine = Registry.LocalMachine;
string productsRoot = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products";
RegistryKey products = localMachine.OpenSubKey(productsRoot);
string[] productFolders = products.GetSubKeyNames();
foreach (string p in productFolders)
{
RegistryKey installProperties = products.OpenSubKey(p + #"\InstallProperties");
if (installProperties != null)
{
string displayName = (string)installProperties.GetValue("DisplayName");
if ((displayName != null) && (displayName.Contains(productDisplayName)))
{
string uninstallCommand =(string)installProperties.GetValue("UninstallString");
return uninstallCommand;
}
}
}
return "";
}
Please help me to uninstall the application programmatically using C#.
The above routine will return a string, assuming it found a match that may look like:
MsiExec.exe /X{02DA0248-DB55-44A7-8DC6-DBA573AEEA94}
You need to take that and run it as a process:
System.Diagnostics.Process.Start(uninstallString);
Note that it may not be always msiexec, it can be anything that the program chooses to specify. In case of msiexec, you can append /q parameter to your uninstallString to make it uninstall silently (and it won't show those Repair/Remove dialogs).
Update: If you're using Windows installer 3.0 or above, you can also use /quiet for silent install/uninstall. It's basically same as /qn (if you're on older versions). Source. Thanks #JRO for bringing it up!