How to check the application path installed with ClickOnce - c#

Install three applications, A, B, and C, on one PC as ClickOnce.
And is there a way to know the installation path for B and C when you run application A?
My final goal is to get the installation paths of B and C from A and run these two programs from A.
Thanks.

You can start your ClickOnce application from windows start menu path, for that you need application's publisher name, suite name and product name. You can set those information from project property page -> publish section -> click on options button and set publisher name, suite name and product name.
Now you can use below code to start any ClickOnce application.
string StartMenuProgramDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Programs);
string Publisher = "<<Publisher Name>>";
string SuiteName = "<<Suite Name>>";
string ProductName = "<<Product Name>>.appref-ms";
Process.Start(Path.Combine(StartMenuProgramDirectory, Publisher, SuiteName, ProductName));
If you still want to know installation location of ClickOnce application, I am using below way (not sure this is ideal way or not)
You need to set your application display icon with below Code. (This will used to display icon in Control Panel -> Programs and Features)
private void Application_Startup(object sender, StartupEventArgs e)
{
if (ApplicationDeployment.IsNetworkDeployed && ApplicationDeployment.CurrentDeployment.IsFirstRun)
{
string IconPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources", "MyIcon.ico");
if (File.Exists(IconPath))
{
RegistryKey registryKey = Registry.CurrentUser.OpenSubKey(#"Software\Microsoft\Windows\CurrentVersion\Uninstall");
string[] subKeys = registryKey.GetSubKeyNames();
for (int i = 0; i < subKeys.Length; i++)
{
RegistryKey subRegistryKey = registryKey.OpenSubKey(subKeys[i], true);
object DisplayName = subRegistryKey.GetValue("DisplayName");
if (DisplayName != null && (DisplayName + "").ToUpper() == ("<<Product Name>>").ToUpper())
{
subRegistryKey.SetValue("DisplayIcon", IconPath);
break;
}
}
}
}
}
Now, Application's ClickOnce registry file is set with icon's path and your icon is available in installation directory, later you can fetch display icon's path with below code and based on that you can also able to find installation location.
string DisplayIconPath;
RegistryKey InstalledClickOncesRegistryKey = null;
RegistryKey InstalledProgramRegistryKey = null;
InstalledClickOncesRegistryKey = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
if (InstalledClickOncesRegistryKey != null && InstalledClickOncesRegistryKey.SubKeyCount > 0)
{
string[] InstalledClickOncesList = InstalledClickOncesRegistryKey.GetSubKeyNames();
if (InstalledClickOncesList != null && InstalledClickOncesList.Length > 0)
{
foreach (var InstalledClickOnces in InstalledClickOncesList)
{
InstalledProgramRegistryKey = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + InstalledClickOnces);
if (InstalledProgramRegistryKey != null && InstalledProgramRegistryKey.ValueCount > 0)
{
string RegistryApplicationName = Convert.ToString(InstalledProgramRegistryKey.GetValue("DisplayName"));
if (string.Equals(RegistryApplicationName, "<<Product Name>>"))
DisplayIconPath = Convert.ToString(InstalledProgramRegistryKey.GetValue("DisplayIcon"));
}
}
}
}

Related

Persisting file path between runs in c#

I have an app in which the user needs to access certain files in a user set and selected folder.
The folder and files paths need to be easily accessed (short simple path).
I use the Properties Settings to hold the Folder and File paths, but for some reason each time I re-start the program the Folder and File paths are lost.
I have followed and checked the program and all seems to be OK (except something I am missing, apparently).
I attach here the program snippet in two parts: The search for path and the setting in case path / file not found. (removed exception handling to save on lines)
public Main() //part of Main, stripped off exception handling)
{
//..........
dataFolder = Properties.Settings.Default.dataFolder;
if (!Directory.Exists(dataFolder))
{
SetDataFolder();
}
configFile = Properties.Settings.Default.configFile;
if (!File.Exists(configFile))
{
SetConfigFile();
}
dataFile = Properties.Settings.Default.dataFile;
if (!File.Exists(dataFile))
{
SetDataFile();
}
loadParamsFromFile(configFile); //Load the previously saved controls.
public String SetDataFolder()
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
DialogResult folder = dialog.ShowDialog();
if (folder == DialogResult.OK)
{
dataFolder = dialog.SelectedPath;
Directory.CreateDirectory(dataFolder);
dataFolder = Path.GetFullPath(dataFolder);
Properties.Settings.Default.dataFolder = dataFolder;
Properties.Settings.Default.Save();
return dataFolder;
}
else return null;
}
private string SetDataFile()
{
dataFile = $"{dataFolder}\\{textBoxSampleID.Text.Replace("/r", "").Trim()}.txt";
File.Create(dataFile).Close();
Properties.Settings.Default.dataFile = dataFile;
Properties.Settings.Default.Save();
return dataFile;
}
private string SetConfigFile()
{
configFile = $"{dataFolder}\\electroplating.cfg";
File.Create(configFile).Close();
Properties.Settings.Default.configFile = configFile;
Properties.Settings.Default.Save();
return configFile;
}
Check out this question:
How to change application settings (Settings) while app is open?
I would suggest using Path.Combine() for the construction of the file paths.
If it still doesn't work, you could also try using the registry for storing the values.
string dataFilePath = Path.Combine(dataFolder, textBoxSampleID.Text.Replace("/r", "").Trim());
RegistryKey key = Registry.LocalMachine.CreateSubKey(#"SOFTWARE\Company");
if (key != null)
{
key.SetValue("dataFilePath", dataFilePath);
}
You could then use string dataFilePath = (string)key.GetValue("dataFilePath") to get the value out of the registry.

getting a list of installed browsers on the computer

I would like to know is there are any possibility to get a list of installed browsers on the computer using c#?
I'm using Selenium WebDriver in my task and I need to know which browsers are installed because in Selenium I can only run a specific browser, for example for Firefox it will be:
IWebDriver driver = new FirefoxDriver();
I will appreciate any help.
Look at localmachine registry...
Microsoft.Win32.RegistryKey key =
Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Clients\StartMenuInternet");
var browsers = key.GetSubKeyNames();
You also need to take into account the machine architecture (x64 vs x86) and the fact that Microsoft Edge will not be under the specified key. Here is what I ended up using (based on multiple solutions found online):
private List<Browser> GetBrowsers()
{
RegistryKey browserKeys;
browserKeys = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\WOW6432Node\Clients\StartMenuInternet");
if (browserKeys == null)
browserKeys = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Clients\StartMenuInternet");
string[] browserNames = browserKeys.GetSubKeyNames();
List<Browser> browsers = new List<Browser>();
for (int i = 0; i < browserNames.Length; i++)
{
Browser browser = new Browser();
RegistryKey browserKey = browserKeys.OpenSubKey(browserNames[i]);
browser.Name = (string)browserKey.GetValue(null);
RegistryKey browserKeyPath = browserKey.OpenSubKey(#"shell\open\command");
browser.Path = browserKeyPath.GetValue(null).ToString().StripQuotes();
browsers.Add(browser);
if (browser.Path != null)
browser.Version = FileVersionInfo.GetVersionInfo(browser.Path).FileVersion;
else
browser.Version = "unknown";
}
Browser edgeBrowser = GetEdgeVersion();
if (edgeBrowser != null)
{
browsers.Add(edgeBrowser);
}
return browsers;
}
private Browser GetEdgeVersion()
{
RegistryKey edgeKey =
Registry.CurrentUser.OpenSubKey(
#"SOFTWARE\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\SystemAppData\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\Schemas");
if (edgeKey != null)
{
string version = edgeKey.GetValue("PackageFullName").ToString().StripQuotes();
Match result = Regex.Match(version, "(((([0-9.])\\d)+){1})");
if (result.Success)
{
return new Browser
{
Name = "MicrosoftEdge",
Version = result.Value
};
}
}
return null;
}
And the object returned is a simple DTO:
public class Browser{
public string Name { get; set; }
public string Path { get; set; }
public string Version { get; set; }
}
I've written a NuGet package for this:
https://www.nuget.org/packages/MintPlayer.PlatformBrowser/ targetting .net core.
You can get a list of all installed webbrowsers (including Edge) and the default webbrowser. I've also written a package with a dialog to let you pick a browser: https://www.nuget.org/packages/MintPlayer.BrowserDialog/
As far as I know there is no list of browsers in Windows.
However you could check for browser's existence by simply testing the *.exe file's existence:
if (File.Exists(#"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe") ||
File.Exists(#"C:\Program Files\Google\Chrome\Application\chrome.exe")) {
// chrome is installed
}
if (File.Exists(#"C:\Program Files (x86)\Mozilla Firefox\firefox.exe") ||
File.Exists(#"C:\Program Files\Mozilla Firefox\firefox.exe") {
// firefox is installed
}

Check for prerequisite from a .NET Windows Form application

I want to check for the installation of a third party application during the installation of my .NET Windows Form application or when it is opened. My Windows Form application doesn't require the third party application to run but it does need it for a feature to work. For example, My Windows Form application opens up the third party application such as a mail program.
I don't know if Click Once is the right strategy for this? I would need it to check for the prerequisite during installation and if it's not there notify the user to install it first. If Click Once isn't the right strategy for this is there another way? Maybe I need to install my Windows Form application first then when it is opened it checks for the third party application? The problem with that is, the installation path could vary from machine to machine. I'm not really sure how to go about this.
This link explains how to include prerequisites in Click Once but that's not what I want to do.
Another link that talks about including the prerequisites but not just detecting them.
One possible solution is to check registry with this method that returns bool value indicating whether the registry record with application name exists :
public static bool IsApplictionInstalled(string p_name)
{
string displayName;
RegistryKey key;
// search in: CurrentUser
key = Registry.CurrentUser.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
foreach (String keyName in key.GetSubKeyNames())
{
RegistryKey subkey = key.OpenSubKey(keyName);
displayName = subkey.GetValue("DisplayName") as string;
if (p_name.Equals(displayName, StringComparison.OrdinalIgnoreCase) == true)
{
return true;
}
}
// 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 = subkey.GetValue("DisplayName") as string;
if (p_name.Equals(displayName, StringComparison.OrdinalIgnoreCase) == true)
{
return true;
}
}
// 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 = subkey.GetValue("DisplayName") as string;
if (p_name.Equals(displayName, StringComparison.OrdinalIgnoreCase) == true)
{
return true;
}
}
// NOT FOUND
return false;
}

Programmatically open a page in IIS/IIS Express in the default browser on click of a button

I want to open a html page (in AppData/Roaming folder and not in the project/solution) with IIS/IIS Express in the default browser on click of a button. I have been able to find the default browser using the following:-
//This method is used to get the default browser
private static string GetDefaultBrowserPath()
{
string urlAssociation = #"Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http";
string browserPathKey = #"$BROWSER$\shell\open\command";
RegistryKey userChoiceKey = null;
string absBrowserPath = "";
const string exeSuffix = ".exe";
FileInfo browserPath;
try
{
//reading default browser path from userChoiceLKey
userChoiceKey = Registry.CurrentUser.OpenSubKey(urlAssociation + #"\UserChoice", false);
//If user choice was not found, try machine default
if (userChoiceKey == null)
{
//reading default browser path from Win XP registry key
var browserKey = Registry.ClassesRoot.OpenSubKey(#"HTTP\shell\open\command", false);
//if browser path not found, try Win Vista (and newer) registry key
if (browserKey == null)
{
browserKey =
Registry.CurrentUser.OpenSubKey(
urlAssociation, false);
}
var path = browserKey.GetValue(null);
browserKey.Close();
return path.ToString();
}
else
{
//if user defined browser choice was found
string progId = (userChoiceKey.GetValue("ProgId").ToString());
userChoiceKey.Close();
//looking up the path of the executable
string concreteBrowserKey = browserPathKey.Replace("$BROWSER$", progId);
var kp = Registry.ClassesRoot.OpenSubKey(concreteBrowserKey, false);
try
{
absBrowserPath = kp.GetValue(null).ToString().ToLower().Replace("\"", "");
if (!absBrowserPath.EndsWith(exeSuffix))
{
absBrowserPath = absBrowserPath.Substring(0, absBrowserPath.LastIndexOf(exeSuffix, StringComparison.Ordinal) + exeSuffix.Length);
browserPath = new FileInfo(absBrowserPath);
}
}
catch (Exception)
{
throw;
}
kp.Close();
return absBrowserPath;
}
}
catch(Exception ex)
{
return "";
}
}
After locating the default browser, I want to open a html page located in AppData/Roaming folder with IIS. How can this be achieved?
Edit: I am thinking of first publishing the pages with the IIS using ServerManager class of Microsoft.Web.Administration and then trying to open it.
is this a right approach? Once published, how would it be possible to open that page(a locally published site now) on click of some button?

C# code to change browser download options

I am trying to do following with c#.
1) Open Firefox Browser-->Tools-->Options-->General Tab--->Downloads--->Always ask me where to save file.
I want to do this whole process in my application with c#. I want that when download window opens, the radio button in "Always ask me where to save file" option gets checked automatically.
I have tried from various links, but all is in vain.
Here is the full code, console application.
Summary: preferences file is located in application roaming folder, something like this on windows 7:
C:\Users\MYNAME\AppData\Roaming\Mozilla\Firefox\Profiles\d9i9jniz.default\prefs.js
We alter this file so that it includes "user_pref("browser.download.useDownloadDir", false);"
Restart firefox, and done. Only run this application when firefox is not running.
static void Main(string[] args)
{
if (isFireFoxOpen())
{
Console.WriteLine("Firefox is open, close it");
}
else
{
string pathOfPrefsFile = GetPathOfPrefsFile();
updateSettingsFile(pathOfPrefsFile);
Console.WriteLine("Done");
}
Console.ReadLine();
}
private static void updateSettingsFile(string pathOfPrefsFile)
{
string[] contentsOfFile = File.ReadAllLines(pathOfPrefsFile);
// We are looking for "user_pref("browser.download.useDownloadDir", true);"
// This needs to be set to:
// "user_pref("browser.download.useDownloadDir", false);"
List<String> outputLines = new List<string>();
foreach (string line in contentsOfFile)
{
if (line.StartsWith("user_pref(\"browser.download.useDownloadDir\""))
{
Console.WriteLine("Found it already in file, replacing");
}
else
{
outputLines.Add(line);
}
}
// Finally add the value we want to the end
outputLines.Add("user_pref(\"browser.download.useDownloadDir\", false);");
// Rename the old file preferences for safety...
File.Move(pathOfPrefsFile, Path.GetDirectoryName(pathOfPrefsFile) + #"\" + Path.GetFileName(pathOfPrefsFile) + ".OLD." + Guid.NewGuid().ToString());
// Write the new file.
File.WriteAllLines(pathOfPrefsFile, outputLines.ToArray());
}
private static string GetPathOfPrefsFile()
{
// Get roaming folder, and get the profiles.ini
string iniFilePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Mozilla\Firefox\profiles.ini";
// Profiles.ini tells us what folder the preferences file is in.
string contentsOfIni = File.ReadAllText(iniFilePath);
int locOfPath = contentsOfIni.IndexOf("Path=Profiles");
int endOfPath = contentsOfIni.IndexOf(".default", locOfPath);
int startOfPath = locOfPath + "Path=Profiles".Length + 1;
int countofCopy = ((endOfPath + ".default".Length) - startOfPath);
string path = contentsOfIni.Substring(startOfPath, countofCopy);
string toReturn = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Mozilla\Firefox\Profiles\" + path + #"\prefs.js";
return toReturn;
}
public static bool isFireFoxOpen()
{
foreach (Process proc in Process.GetProcesses())
{
if (proc.ProcessName == "firefox")
{
return true;
}
}
return false;
}
What have you tried?
Firefox settings are stored in your profile, so I'd guess you can change the contents of the given file. Type about:config to find the setting you're looking for, I guess it's in the browser.download tree, alter it (after you made sure the browser isn't running) and you should be good to go.

Categories

Resources