how to check if OpenOffice is installed programatically using c# - c#

how to check if OpenOffice is installed programatically using c#

public bool isOpenofficeInstalled()
{
//The registry key:
string SoftwareKey = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(SoftwareKey))
{
bool flag = false;
//Let's go through the registry keys and get the info we need:
foreach (string skName in rk.GetSubKeyNames())
{
using (RegistryKey sk = rk.OpenSubKey(skName))
{
try
{
//If the key has value, continue, if not, skip it:
// if (((sk.GetValue("DisplayName")).ToString() == "OpenOffice.org 3.2"))
if((sk.GetValue("DisplayName")).ToString() == "OpenOffice.org 3.2")
{
flag = true;
////install location ?
//if (sk.GetValue("InstallLocation") == null)
// Software += sk.GetValue("DisplayName") + " - Install path not known\n"; //Nope, not here.
//else
// Software += sk.GetValue("DisplayName") + " - " + sk.GetValue("InstallLocation") + "\n"; //Yes, here it is...
}
}
catch (Exception)
{
}
}
}
return flag;
}
}

Here is a solution that gets the startup location of the default program to open a odt file. As long as the file association has not been changed this works regardless of what version is installed.
(this is VB.NET)
Dim odt = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(".odt")
Dim linkedValue = odt.GetValue("")
Dim linkedKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(linkedValue)
Dim openWith = linkedKey.OpenSubKey("Shell\Open\Command").GetValue("")
Dim O As String = CStr(openWith)
If O.Contains("swriter.exe") Then
// proceed with code
Else
// error message
End If

Same as in any other language? Search the known locations on the file system for the executable that launches open office? Check for libraries? Parse the output of "which openoffice"?
There are lots of options, and I'd say that most of them would not be reliable.

Related

confusion excel install location in registry

I am required to detect excel install location in registry and open an excel file .I have found an example code .
I have two problems Firstly there is no InstallRoot directorty in the given registry path in that code
RegistryKey rootdir = excelKey.OpenSubKey(currentVersion +
#".0\Excel\InstallRoot");
But It does exist under this path (SOFTWARE\Wow6432Node\MicroSoft\Office)
The Other problem I was getting the the message that says "can't Open in excel
because excel is not installed."So I thought that CurrentVersion returns worng value
in my case (since office 2007) It returns 120.0 instead 12.0
public void OpenInExcel(string filename)
{
string dir = "";
RegistryKey key = Registry.LocalMachine;
RegistryKey excelKey = key.OpenSubKey(#"SOFTWARE\MicroSoft\Office");
if (excelKey != null)
{
foreach (string valuename in excelKey.GetSubKeyNames())
{
int version = 9;
double currentVersion=0;
if (Double.TryParse(valuename, out currentVersion) && currentVersion >= version)
{
RegistryKey rootdir = excelKey.OpenSubKey(currentVersion + #".0\Excel\InstallRoot");
if (rootdir != null)
{
dir = rootdir.GetValue(rootdir.GetValueNames()[0]).ToString();
break;
}
}
}
}
if (dir != "")
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = dir + #"Excel.exe";
startInfo.Arguments = "\"" + fileName + "\"";
startInfo.UseShellExecute = false;
using (Process process = new Process())
{
process.StartInfo = startInfo;
try
{
process.Start();
}
catch (Exception ex)
{
Console.WriteLine("\n\nCould not start Excel process.");
Console.WriteLine(ex);
}
}
}
else
{
MessageBox.Show("Can't Open in excel because excel is not installed.");
}
}
#Edit:I think something goes wrong at this line that returns wrong value because It Works this way
RegistryKey rootdir = excelKey.OpenSubKey(
#"12.0\Excel\InstallRoot");
I dont know why TryParse returns 120.0
This isn't intended to be an answer to your question, but it might help you get the correct version number, and I can't post all this code in a comment.
public const string CProgIdOutlook = "Outlook.Application";
/// <summary>
/// Method to get the Outlook version number, which will presumably be 11 (2003), 12 (2007),
/// 14 (2010) or 15 (2013). (I wonder what happened to version 13?) An exception is thrown if
/// this method is unable to provide an answer.
///
/// The technique used to get the version number of the "current" installed version of Outlook
/// is one of many possible methods that are described in various Internet sources, and is
/// hopefully the most likely to provide the correct answer with the least side-effects.
/// Problems with some of the alternative registry-based methods typically show up when
/// multiple versions of Outlook are installed or have been installed. The registry values can
/// also depend on x86 vs. x64 systems and whether Outlook was installed for one user or for
/// all users. Techniques involving querying the Outlook automation object have the
/// disadvantage of an instance of the Outlook program getting created - this can be seen in
/// Task Manager.
///
/// The idea for this code came from here: http://support.microsoft.com/kb/240794
/// </summary>
/// <returns>11 (2003), 12 (2007), 14 (2010) or 15 (2013)</returns>
private static int GetOutlookVersion()
{
const string CRegistryKey = #"SOFTWARE\Classes\" + GroupwareProgIds.CProgIdOutlook;
int outlookVersion;
using (RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(CRegistryKey))
{
outlookVersion = GetOutlookVersion(registryKey);
if (outlookVersion != -1)
return outlookVersion;
}
using (RegistryKey registryKey = Registry.CurrentUser.OpenSubKey(CRegistryKey))
{
outlookVersion = GetOutlookVersion(registryKey);
if (outlookVersion != -1)
return outlookVersion;
}
throw new MerliniaException(0x2d4a67fu, "No registry entry for " + CRegistryKey);
}
/// <summary>
/// Sub-method of above method to do the work for either HKLM or HKCU.
/// </summary>
/// <returns>11 (2003), 12 (2007), 14 (2010) or 15 (2013), or -1 for error</returns>
private static int GetOutlookVersion(RegistryKey registryKey1)
{
const string CCurVer = "CurVer";
if (registryKey1 == null)
return -1;
using (RegistryKey registryKey2 = registryKey1.OpenSubKey(CCurVer))
{
if (registryKey2 == null)
throw new MerliniaException(0x2d43e5au,
"No registry entry for " + registryKey1 + "\\" + CCurVer);
string currentOutlookAppName = registryKey2.GetValue(null) as string;
if (currentOutlookAppName != null)
{
string[] sa = currentOutlookAppName.Split('.');
if (sa.Length == 3)
{
int outlookVersion;
if (int.TryParse(sa[2], NumberStyles.Integer,
CultureInfo.InvariantCulture, out outlookVersion))
return outlookVersion;
}
}
throw new MerliniaException(0x2d4b29du,
"Invalid registry content for " + registryKey1 + "\\" + CCurVer);
}
}
The problem is about double type and Culture.
I try explain:
You get double 12.0 value.
And ToString convert to 12.0 in Culture en-US and convert to 120.0 in Culture es-ES (decimal separators not the same).
The problem was parsing the version as a double.
Since the computer culture considers , as decimal separator and . as thousands separator
You can changes the code like this (when you tried Double.TryParse):
if (Double.TryParse(valuename, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out currentVersion) && currentVersion >= version)

How to print a PDF file from code? [duplicate]

This question already has answers here:
How can I send a file document to the printer and have it print?
(12 answers)
Windows 8 blows error on c# process for printing pdf file, how?
(1 answer)
Closed 9 years ago.
I've been developing an application in visual c# which needs to print an existing pdf file at the press of a button.
I've been using the System.Diagnostics.Process method to print but it fails to work as desired in a Windows 8 environment as the "Printto" command doesn't seem to work there.
I would like to use an alternative such as possibly the System.Drawing.Printing.PrintDocument which had an example that works with text files but when I tried with a pdf it was printing random characters instead.
My google searches for such seem to come up empty or I'm not entering the right keywords, but I need a solution which not only prints pdf to target printer but can determine if the printer is ready, offline or out of paper as well as an error catch.
Please advise as I'm also willing to look at any SDK or third party routes recommendable.
edit: added code snippet I'm currently using:
string defFile = (Path.Combine(GlobalVars.pdfPath, tkt_no + "_DEF.pdf"));
string rwPrinter = "";
if (GlobalVars.useDefaultPrinter == false)
{
foreach (string strPrinter in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
{
if (strPrinter.StartsWith("ZDesigner"))
{
rwPrinter = strPrinter;
break;
}
}
}
if (jobdo.Equals("print"))
{
Process process = new Process();
//process.StartInfo.CreateNoWindow = true;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.FileName = defFile;
if (rwPrinter.Length > 0)
{
process.StartInfo.Verb = "printto";
//process.StartInfo.Verb = (Path.Combine(System.Windows.Forms.Application.StartupPath, "printto.exe"));
process.StartInfo.Arguments = "\"" + rwPrinter + "\"";
}
else
{
process.StartInfo.Verb = "print";
}
try
{
process.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
process.WaitForInputIdle();
//while (process.MainWindowHandle == IntPtr.Zero)
//{
// Thread.Sleep(20);
// process.Refresh();
//}
Thread.Sleep(7000);
try
{
process.Kill();
}
catch { }
// close any occurrences of Adobe Reader that may not close through a citrix environment regardless
foreach (System.Diagnostics.Process p in System.Diagnostics.Process.GetProcesses())
{
if (p.ProcessName.Equals("AcroRd32"))
{
ObjectQuery sq = new ObjectQuery
("Select * from Win32_Process where ProcessID = '" + p.Id + "'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(sq);
foreach (ManagementObject oReturn in searcher.Get())
{
string[] o = new string[2];
oReturn.InvokeMethod("GetOwner", (object[])o);
if(o[0] != null)
if(o[0].Equals(System.Environment.UserName))
p.Kill();
}
}
}
if (rwPrinter == "")
{
rwPrinter = "the default printer";
}
else
MessageBox.Show("Ticket " + tkt_no + " was printed to " + rwPrinter + ".");
}
Please see this, using iTextSharp library you can easily create PDF file:
http://sourceforge.net/projects/itextsharp/

Unable to read Registry value using PowerShell in C#

I am not able to read specific registry values using PowerShell in C#. Here is the code:
Calling function:
public static string UserDisplayName()
{
// PowerShell Command: (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\SessionData\1').LoggedOnDisplayName
return GetPowerShellOutputString(#"(Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\SessionData\1').LoggedOnDisplayName");
}
Function definition:
private static string GetPowerShellOutputString(string PsCmd)
{
try
{
string PsOut = string.Empty;
Debug.Write("PsCmd: " + PsCmd + "; ");
Runspace rs = RunspaceFactory.CreateRunspace();
rs.Open();
Pipeline pipeline = rs.CreatePipeline();
pipeline.Commands.AddScript(PsCmd);
Collection<PSObject> results = pipeline.Invoke();
rs.Close();
foreach (PSObject obj in results)
if (obj != null) PsOut += obj.ToString() + ", ";
PsOut = (PsOut == string.Empty) ? strUnavailableString : PsOut.TrimEnd(',', ' ');
Debug.WriteLine("PsOut: " + PsOut);
return PsOut;
}
catch (Exception ex)
{
Debug.WriteLine("! " + ex.Message + ex.InnerException + "\n");
return strUnavailableString;
}
}
However, the same Function definition is working perfectly if I am trying to read any other registry value e.g.:
public static string UserOUPath()
{
try
{
if (UserDomain() == SystemInformation.ComputerName) return strUnavailableString; // Non-domain account
//For consistant performance, grab OU from registry instead of AD.
string userSID = WindowsIdentity.GetCurrent().User.ToString();
string ouPath = #"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\" + userSID;
string ou = GetPowerShellOutputString("(Get-ItemProperty -Path '" + ouPath + "').'Distinguished-Name'");
ou = ou.Remove(0, ou.IndexOf(",", 0) + 1); // Drop leading CN stuff
ou = ou.Remove(ou.IndexOf(",DC=", 0), ou.Length - ou.IndexOf(",DC=", 0)); // Drop trailing DC stuff
ou = ou.Replace(",OU=", "/");
ou = ou.Replace("OU=", "/");
ou = FlipOU(ou);
if (ou == null) throw new NullReferenceException();
return ou;
}
catch
{
return strUnavailableString;
}
}
For the first call (UserDisplayName()) when I did Debug mode, the results object is returning null. However if I run the same PowerShell Command in PowerShell window it is giving the value.
I am stumbled upon this as I am not able to get why and what is happening?
A couple of things. First I agree with all the comments about just using the Microsoft.Win32.Registry* classes directly in C#. However to answer your question about doing this from PowerShell, I believe what you are running into a registry virtualization issue. If your C# project is AnyCPU and run under Visual Studio it is likely running 32-bit and that registry path will be virtualized to the SysWow64 registry node. So your reg path won't exist. That can be fixed by making the exe compile as x64. Another option is to use the .NET Registry.OpenBaseKey() method will allows you to specify which reg hive you want to view (32-bit or 64-bit).
Second, you can simplify your code by using the PowerShell class e.g.:
var ps = PowerShell.Create();
ps.AddScript(PsCmd);
var results = ps.Invoke();
foreach (PSObject obj in results)
if (obj != null) PsOut += obj.ToString() + ", ";
Third, with the PowerShell class, after the Invoke() call, check the Error stream for errors like so:
foreach (var error in ps.Streams.Error)
Console.Error.WriteLine(error);

System.IO exception coming while saving XML document in C#

After importing plenty of XML files into application i tried to do modifications on it by using XML document class, for this i created few methods to do modifications.
The thing is the starting method it's working fine and when comes to the second one it's displaying System.IO exception like "File is already using another process".
So any one help me out how can i solve this issue.
Sample code what i'm doing:
Method1(fileList);
Method2(fileList);
Method3(fileList);
private void Method1(IList<RenamedImportedFileInfo> fileList)
{
try
{
string isDefaultAttribute = Resource.Resources.ImportIsDefaultAttribute;
string editorsPath = editorsFolderName + Path.DirectorySeparatorChar + meterType;
string profilesPath = profileFolderName + Path.DirectorySeparatorChar + meterType;
string strUriAttribute = Resource.Resources.ImportUriAttribute;
foreach (RenamedImportedFileInfo renameInfo in fileList)
{
if (renameInfo.NewFilePath.ToString().Contains(editorsPath) && (renameInfo.IsProfileRenamed != true))
{
var xmldoc = new XmlDocument();
xmldoc.Load(renameInfo.NewFilePath);
if (xmldoc.DocumentElement.HasAttribute(isDefaultAttribute))
{
xmldoc.DocumentElement.Attributes[isDefaultAttribute].Value = Resource.Resources.ImportFalse;
}
XmlNodeList profileNodes = xmldoc.DocumentElement.GetElementsByTagName(Resource.Resources.ImportMeasurementProfileElement);
if (profileNodes.Count == 0)
{
profileNodes = xmldoc.DocumentElement.GetElementsByTagName(Resource.Resources.ImportBsMeasurementProfileElement);
}
if (profileNodes.Count > 0)
{
foreach (RenamedImportedFileInfo profileName in oRenamedImportedFileList)
{
if (profileName.NewFilePath.ToString().Contains(profilesPath))
{
if (string.Compare(Path.GetFileName(profileName.OldFilePath), Convert.ToString(profileNodes[0].Attributes[strUriAttribute].Value, CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase) == 0)
{
profileNodes[0].Attributes[strUriAttribute].Value = Path.GetFileName(profileName.NewFilePath);
renameInfo.IsProfileRenamed = true;
break;
}
}
}
}
xmldoc.Save(renameInfo.NewFilePath);
xmldoc = null;
profileNodes = null;
}
}
oRenamedImportedFileList = null;
}
catch (NullReferenceException nullException) { LastErrorMessage = nullException.Message; }
}
Thanks,
Raj
You are probably opening the same file twice in your application. Before you can open it again, you have to close it (or leave it open and work on the same document without opening it again).
For help on how to implement this, please show us more code so we can give you advice.

how to find the execution path of a installed software

How can i find the execution path of a installed software in c# for eg media player ,vlc player . i just need to find their execution path . if i have a vlc player installed in my D drive . how do i find the path of the VLC.exe from my c# coding
Using C# code you can find the path for some excutables this way:
private const string keyBase = #"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths";
private string GetPathForExe(string fileName)
{
RegistryKey localMachine = Registry.LocalMachine;
RegistryKey fileKey = localMachine.OpenSubKey(string.Format(#"{0}\{1}", keyBase, fileName));
object result = null;
if (fileKey != null)
{
result = fileKey.GetValue(string.Empty);
fileKey.Close();
}
return (string)result;
}
Use it like so:
string pathToExe = GetPathForExe("wmplayer.exe");
However, it may very well be that the application that you want does not have an App Paths key.
This method works for any executable located in a folder which is defined in the windows PATH variable:
private string LocateEXE(String filename)
{
String path = Environment.GetEnvironmentVariable("path");
String[] folders = path.Split(';');
foreach (String folder in folders)
{
if (File.Exists(folder + filename))
{
return folder + filename;
}
else if (File.Exists(folder + "\\" + filename))
{
return folder + "\\" + filename;
}
}
return String.Empty;
}
Then use it as follows:
string pathToExe = LocateEXE("example.exe");
Like Fredrik's method it only finds paths for some executables
I used the CurrentVersion\Installer\Folders registry key. Just pass in the product name.
private string GetAppPath(string productName)
{
const string foldersPath = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\Folders";
var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
var subKey = baseKey.OpenSubKey(foldersPath);
if (subKey == null)
{
baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
subKey = baseKey.OpenSubKey(foldersPath);
}
return subKey != null ? subKey.GetValueNames().FirstOrDefault(kv => kv.Contains(productName)) : "ERROR";
}
None of the answers worked for me. After hours of searching online, I was able to successfully get the installation path. Here is the final code.
public static string checkInstalled(string findByName)
{
string displayName;
string InstallPath;
string registryKey = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
//64 bits computer
RegistryKey key64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey key = key64.OpenSubKey(registryKey);
if (key != null)
{
foreach (RegistryKey subkey in key.GetSubKeyNames().Select(keyName => key.OpenSubKey(keyName)))
{
displayName = subkey.GetValue("DisplayName") as string;
if (displayName != null && displayName.Contains(findByName))
{
InstallPath = subkey.GetValue("InstallLocation").ToString();
return InstallPath; //or displayName
}
}
key.Close();
}
return null;
}
you can call this method like this
string JavaPath = Software.checkInstalled("Java(TM) SE Development Kit");
and boom. Cheers
Have a look at MsiEnumProductsEx
This stackoverflow.com article describes how to get the application associated with a particular file extension.
Perhaps you could use this technique to get the application associated with certain extensions, such as avi or wmv - either Medial Player or in your case VLC player?

Categories