50% OFF!!!

Wednesday, December 8, 2010

C# | Check if app is installed for “All users” or "Just me"

Today I bring a very HARD-to-find topic about getting an installed application "Installation context".
An installation context may be Per-Machine Installation Context (ALLUSERS=1) and Per-User Installation Context (ALLUSERS="").

When installing an application, the user may select one of two options:
a. Install [APP] for yourself
b. or for anyone who uses this computer

[a] installs only for the current user(just me) while [b] installs for the Local System user which is for all-users(everyone).

In this post I will give a code for checking is an installed application was installed for "Everyone" or "Just me".

The validation process is check if the APPLICATION-NAME exists in the registry keys under UserData.
(*) Everyone - check under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\ (S-1-5-18 represents the Local System user)

(*) Just me (Current user) - check under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-?!?!?!?!\Products\ (S-?!?!?!?! represents the Current user. this value found by the code: WindowsIdentity.GetCurrent().User.Value.

[Code] Method's return type:
private enum InstallationContexts { NotInstalled, Everyone, JustMe };

[Code] Method declaration:
private InstallationContexts GetInstalledContext(string p_appDisplayName)
    //The S-1-5-18  =
Local System user (Everyone) | HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\

    //The S-XXXXXX  =
Current user (Just me)       |

    string key;
    string keyFormat = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\{0}\Products\";
    // Check if installed for -> Everyone
    key = string.Format(keyFormat, "S-1-5-18");
    bool res = GetInstalledContext_IsRegKeyExists(key, p_appDisplayName, StringComparison.OrdinalIgnoreCase);
    if (res == true)
        return InstallationContexts.Everyone;
    // Check if installed for -> Just me
    key = string.Format(keyFormat, WindowsIdentity.GetCurrent().User.Value);
    res = GetInstalledContext_IsRegKeyExists(key, p_appDisplayName, StringComparison.OrdinalIgnoreCase);
    if (res == true)
        return InstallationContexts.JustMe;
    return InstallationContexts.NotInstalled;
private bool GetInstalledContext_IsRegKeyExists(string p_regKey, string p_appDisplayName, StringComparison p_scompare)
    using (RegistryKey regkey = Registry.LocalMachine.OpenSubKey(p_regKey))
        if (regkey != null)
            RegistryKey rk;
            string[] arrProducs = regkey.GetSubKeyNames();
            for (int i = 0; i < arrProducs.Length; i++)

               using (rk = regkey.OpenSubKey(arrProducs[i] + @"\InstallProperties"))
if (rk != null &&
                        p_appDisplayName.Equals(rk.GetValue("DisplayName").ToString(), p_scompare) == true)
                        return true;
    return false;

[Code] Method's usage example:
InstallationContexts appContext = GetInstalledContext("APP-DISPLAY-NAME");

This code gives the ability to detect previously installed application or previously installed software is installed to ALLUSERS (everyone) or only to CURRENT USER (just me).

Addition on 19.12.2010:
(*) This checking operation is valid ONLY for an application and software which were installed using Microsoft's Windows Installer.
For general checking for installed application, check my post about check if program/application is installed.


Thursday, December 2, 2010

C# | check if program/application is installed on remote computer

As an advance to my previous post about checking if a program or an application is installed on my comptuer, I bringing a code for doing this validation on a remote computer.

The code is the same as checking for installed app in local comptuer (as described here) except that checking remote machine registry.
The remote machine registry checking is preformed using the static method OpenRemoteBaseKey of the class RegistryKey.

The code:
public static bool IsAppInstalled(string p_machineName, string p_name)
   string keyName;
   // search in: CurrentUser
   keyName = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
   if (ExistsInRemoteSubKey(p_machineName, RegistryHive.CurrentUser, keyName, "DisplayName", p_name) == true)
      return true;
   // search in: LocalMachine_32
   keyName = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
   if (ExistsInRemoteSubKey(p_machineName, RegistryHive.LocalMachine, keyName, "DisplayName", p_name) == true)
      return true;
   // search in: LocalMachine_64
   keyName = @"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall";
   if (ExistsInRemoteSubKey(p_machineName, RegistryHive.LocalMachine, keyName, "DisplayName", p_name) == true)
      return true;
   return false;
private static bool ExistsInRemoteSubKey(string p_machineName, RegistryHive p_hive, string p_subKeyName, string p_attributeName, string p_name)
   RegistryKey subkey;
   string displayName;
   using (RegistryKey regHive = RegistryKey.OpenRemoteBaseKey(p_hive, p_machineName))
      using (RegistryKey regKey = regHive.OpenSubKey(p_subKeyName))
         if (regKey != null)
            foreach (string kn in regKey.GetSubKeyNames())
               using (subkey = regKey.OpenSubKey(kn))
                  displayName = subkey.GetValue(p_attributeName) as string;
                  if (p_name.Equals(displayName, StringComparison.OrdinalIgnoreCase) == true) // key found!
                     return true;
   return false;

How to use this code:
bool isAppInstalled = IsAppInstalled(MACHINE_NAME, APPLICATION_NAME);
  string msg = string.Format("Application '{0}' is {1} on the remote-machine '{2}'!",
isAppInstalled ? "installed" : "NOT installed",
catch (Exception ex)


Sunday, November 28, 2010

c# | Check if VcRedist installed (x86/x64/IA64)

The following code checks if vcredist (Microsoft Visual C++ 2008 SP1 Redistributable Package) is installed.
This check is used when we want to assure that the Visual C++ 2008 SP1 is INSTALLED perior to the application launch.

The code is using the MsiQueryProductState function from the msi.dll.

We check the product codes of vcredist_x86, vcredist_x64 and vcredist_IA64 using MsiQueryProductState to validate if the product is installed or not!
(vcredist product codes are listed HERE)

The Code:
public enum INSTALLSTATE
   INSTALLSTATE_NOTUSED = -7,  // component disabled
   INSTALLSTATE_BADCONFIG = -6,  // configuration datacorrupt
   INSTALLSTATE_INCOMPLETE = -5,  // installationsuspended or in progress
   INSTALLSTATE_SOURCEABSENT = -4,  // run from source,source is unavailable
   INSTALLSTATE_MOREDATA = -3,  // return bufferoverflow
   INSTALLSTATE_INVALIDARG = -2,  // invalid functionargument
   INSTALLSTATE_UNKNOWN = -1,  // unrecognized productor feature
   INSTALLSTATE_BROKEN = 0,  // broken
   INSTALLSTATE_ADVERTISED = 1,  // advertised feature
   INSTALLSTATE_REMOVED = 1,  // component being removed(action state, not settable)
   INSTALLSTATE_ABSENT = 2,  // uninstalled (or actionstate absent but clients remain)
   INSTALLSTATE_LOCAL = 3,  // installed on local drive
   INSTALLSTATE_SOURCE = 4,  // run from source, CD ornet
   INSTALLSTATE_DEFAULT = 5,  // use default, local orsource
private static extern INSTALLSTATE MsiQueryProductState(string product);
public static boolIsVCRedistInstalled()
   string[] strCodes = newstring[]
       //vcredist_x86 - ProductCode
       //vcredist_x64 - ProductCode
       //vcredist_IA64 - ProductCode
   for (int i = 0;i < strCodes.Length; i++)
       state = MsiQueryProductState(strCodes[i]);
           return true;
   return false;

You may also extent and improve this method to check only those Product Codes that matching current architecture (x86/x64/IA64).

Hope it helps,

Wednesday, November 24, 2010

Bootstrapper Package | detect vcredist installed | Microsoft Visual C++ 2008 SP1 Redistributable Package

As a countinue post of my previous http://mdb-blog.blogspot.com/2010/11/bootstrapper-package-visual-studio-2010.html about Bootstrapper Package ( Visual Studio 2010) of Microsoft .NET Framework Version 2.0 Redistributable, i give an example for:
Bootstrapper Package for Microsoft Visual C++ 2008 SP1 Redistributable Package
(also known as Visual C++ 9.0 runtime redistributable package)

As I searched for many sites, I couldn't find any GOOD article about detecting this resi package.
So, I built a bootstrapper package using the information I found on Aaron's post: "How to detect the presence of the Visual C++ 9.0 runtime redistributable package" at http://blogs.msdn.com/b/astebner/archive/2009/01/29/9384143.aspx.

First of all, we have to detect if one of (vcredist_x86, vcredist_x64, vcredist_IA64) is INSTALLED!
To do so, we will use the MsiQueryProductState API inside our Product.xml in the bootstrapper package folder. (for more information about bootstrapper package files watch my previous post.
Because there is a difference in the Product-Code between the localized versions of the redistributables for VC++ 2008, i checked and write down all the product codes in the following table:

UpgradeCode for all {AA783A14-A7A3-3D33-95F0-9A351D530011}

UpgradeCode for all {AA783A14-A7A3-3D33-95F0-9A351D530011}

Russian[Installer NOT exists!]
UpgradeCode for all {AA783A14-A7A3-3D33-95F0-9A351D530011}

All left is to create the bootstrapper folder (name it Vcredist2008sp1):
(*) en (FOLDER)
    (*) package.xml
(*) Product.xml
(*) redist.txt
(*) vcredist_x86.exe (download here)
(*) vcredist_x64.exe (download here)
(*) vcredist_IA64.exe (download here)

package.xml file:
<?xml version="1.0" encoding="utf-8"?>
<Package Name="DisplayName" Culture="Culture" xmlns="http://schemas.microsoft.com/developer/2004/01/bootstrapper">
    <String Name="Culture">en</String>
    <String Name="DisplayName">Microsoft Visual C++ 2008 SP1 Redistributable Package</String>
    <String Name="AdminRequired">Administrator permissions are required to install the Microsoft Visual C++ 2008 SP1 Redistributable Package Contact your administrator.</String>
    <String Name="CancelledInstall">The user has cancelled the installation. The Microsoft Visual C++ 2008 SP1 Redistributable Package has not been installed.</String>
    <String Name="GeneralFailure">A failure occurred attempting to install the Microsoft Visual C++ 2008 SP1 Redistributable Package.</String>
    <String Name="ErrorDownloading">A failure occurred while downloading Microsoft Visual C++ 2008 SP1 Redistributable Package.</String>

Product.xml file:
1. PackageFiles (installation files):
<PackageFiles CopyAllPackageFiles="false">
  <PackageFile Name="vcredist_x86.exe" />
  <PackageFile Name="vcredist_x64.exe" />
  <PackageFile Name="vcredist_IA64.exe" />

2. InstallChecks (valiadation prefurmed):
  <!--VCRedistx86 - ProductCodes-->
  <MsiProductCheck Property="VCRedistx86_English_Installed" Product="{9A25302D-30C0-39D9-BD6F-21E6EC160475}" />
  <MsiProductCheck Property="VCRedistx86_ChineseSimplified_Installed" Product="{86CE1746-9EFF-3C9C-8755-81EA8903AC34}" />
  <MsiProductCheck Property="VCRedistx86_ChineseTraditional_Installed" Product="{CA8A885F-E95B-3FC6-BB91-F4D9377C7686}" />
  <MsiProductCheck Property="VCRedistx86_French_Installed" Product="{820B6609-4C97-3A2B-B644-573B06A0F0CC}" />
  <MsiProductCheck Property="VCRedistx86_German_Installed" Product="{6AFCA4E1-9B78-3640-8F72-A7BF33448200}" />
  <MsiProductCheck Property="VCRedistx86_Italian_Installed" Product="{F03CB3EF-DC16-35CE-B3C1-C68EA09E5E97}" />
  <MsiProductCheck Property="VCRedistx86_Japanese_Installed" Product="{402ED4A1-8F5B-387A-8688-997ABF58B8F2}" />
  <MsiProductCheck Property="VCRedistx86_Korean_Installed" Product="{887868A2-D6DE-3255-AA92-AA0B5A59B874}" />
  <MsiProductCheck Property="VCRedistx86_Russian_Installed" Product="{527BBE2F-1FED-3D8B-91CB-4DB0F838E69E}" />
  <MsiProductCheck Property="VCRedistx86_Spanish_Installed" Product="{57660847-B1F7-35BD-9118-F62EB863A598}" />

  <!--VCRedistx64 - ProductCodes-->
  <MsiProductCheck Property="VCRedistx64_English_Installed" Product="{8220EEFE-38CD-377E-8595-13398D740ACE}" />
  <MsiProductCheck Property="VCRedistx64_ChineseSimplified_Installed" Product="{56F27690-F6EA-3356-980A-02BA379506EE}" />
  <MsiProductCheck Property="VCRedistx64_ChineseTraditional_Installed" Product="{14297226-E0A0-3781-8911-E9D529552663}" />
  <MsiProductCheck Property="VCRedistx64_French_Installed" Product="{9B3F0A88-790D-3AD9-9F96-B19CF2746452}" />
  <MsiProductCheck Property="VCRedistx64_German_Installed" Product="{D285FC5F-3021-32E9-9C59-24CA325BDC5C}" />
  <MsiProductCheck Property="VCRedistx64_Italian_Installed" Product="{092EE08C-60DE-3FE6-B113-90076EC06D0D}" />
  <MsiProductCheck Property="VCRedistx64_Japanese_Installed" Product="{A96702F7-EFC8-3EED-BE46-22C809D4EBE5}" />
  <MsiProductCheck Property="VCRedistx64_Korean_Installed" Product="{92B8FD1F-C1AE-3750-8577-631B0AA85DF5}" />
  <MsiProductCheck Property="VCRedistx64_Russian_Installed" Product="{2DFD8316-9EF1-3210-908C-4CB61961C1AC}" />
  <MsiProductCheck Property="VCRedistx64_Spanish_Installed" Product="{E34002C7-8CE7-3F76-B36C-09FA973BC4F6}" />

  <!--VCRedistIA64 - ProductCodes-->
  <MsiProductCheck Property="VCRedistIA64_English_Installed" Product="{5827ECE1-AEB0-328E-B813-6FC68622C1F9}" />
  <MsiProductCheck Property="VCRedistIA64_ChineseSimplified_Installed" Product="{9363B366-8370-34F7-8164-25052EBF35FD}" />
  <MsiProductCheck Property="VCRedistIA64_ChineseTraditional_Installed" Product="{4EC84186-70BB-3121-9C1B-C63512D7126E}" />
  <MsiProductCheck Property="VCRedistIA64_French_Installed" Product="{1F7B9797-A3C8-3B98-85C4-00620F221CE8}" />
  <MsiProductCheck Property="VCRedistIA64_German_Installed" Product="{6BE0A7C7-3462-30EE-8B77-D21D7848D967}" />
  <MsiProductCheck Property="VCRedistIA64_Italian_Installed" Product="{BF58DC07-38AB-3887-8000-70173F9650EA}" />
  <MsiProductCheck Property="VCRedistIA64_Japanese_Installed" Product="{D289009A-2728-3D0A-833E-F08E0E58934C}" />
  <MsiProductCheck Property="VCRedistIA64_Korean_Installed" Product="{9476DC14-00C3-3C36-A435-00D714CF77B8}" />
  <!--RUSSIAN installer not exists -->
  <MsiProductCheck Property="VCRedistIA64_Spanish_Installed" Product="{678835D7-D524-3C0E-9C33-1D3767FDA6BF}" />

3. for each installation check if any localized installed:
<BypassIf Property="VCRedistx86_English_Installed" Compare="ValueEqualTo" Value="5" />
<BypassIf Property="VCRedistx86_ChineseSimplified_Installed" Compare="ValueEqualTo" Value="5" />
<BypassIf Property="VCRedistx86_ChineseTraditional_Installed" Compare="ValueEqualTo" Value="5" />
<BypassIf Property="VCRedistx86_French_Installed" Compare="ValueEqualTo" Value="5" />
<BypassIf Property="VCRedistx86_German_Installed" Compare="ValueEqualTo" Value="5" />
<BypassIf Property="VCRedistx86_Italian_Installed" Compare="ValueEqualTo" Value="5" />
<BypassIf Property="VCRedistx86_Japanese_Installed" Compare="ValueEqualTo" Value="5" />
<BypassIf Property="VCRedistx86_Korean_Installed" Compare="ValueEqualTo" Value="5" />
<BypassIf Property="VCRedistx86_Russian_Installed" Compare="ValueEqualTo" Value="5" />
<BypassIf Property="VCRedistx86_Spanish_Installed" Compare="ValueEqualTo" Value="5" />

Download link for the full bootstrapper package is here:
download full package here

Hope it helps,

Tuesday, November 23, 2010

How to determine the Windows version by using Visual C# | windows 7 windows vista

Here is a good code includes Windows 7 and Windows Vista recognaizer.

internal enum WindowsVersions { UnKnown, Win95, Win98, WinMe, WinNT3or4, Win2000, WinXP, WinServer2003, WinVista, Win7, Win8, MacOSX, Unix, Xbox };
internal static WindowsVersions GetCurrentWindowsVersion()
    // Get OperatingSystem information from the system namespace.
    System.OperatingSystem osInfo = System.Environment.OSVersion;
    // Determine the platform.
    if (osInfo.Platform == System.PlatformID.Win32Windows)
        // Platform is Windows 95, Windows 98, Windows 98 Second Edition, or Windows Me.
        switch (osInfo.Version.Minor)
            case 0:
                //Console.WriteLine("Windows 95");
                return WindowsVersions.Win95;
            case 10:
                //if (osInfo.Version.Revision.ToString() == "2222A")
                //    Console.WriteLine("Windows 98 Second Edition");
                //    Console.WriteLine("Windows 98");
                return WindowsVersions.Win98;
            case 90:
                //Console.WriteLine("Windows Me");
                return WindowsVersions.WinMe;
    else if (osInfo.Platform == System.PlatformID.Win32NT)
        // Platform is Windows NT 3.51, Windows NT 4.0, Windows 2000, or Windows XP.
        switch (osInfo.Version.Major)
            case 3:
            case 4:
                //Console.WriteLine("Windows NT 3.51"); // = 3
                //Console.WriteLine("Windows NT 4.0");  // = 4
                return WindowsVersions.WinNT3or4;
            case 5:
                switch (osInfo.Version.Minor)
                    case 0:
                        //name = "Windows 2000";
                        return WindowsVersions.Win2000;
                    case 1:
                        //name = "Windows XP";
                        return WindowsVersions.WinXP;
                    case 2:
                        //name = "Windows Server 2003";
                        return WindowsVersions.WinServer2003;
            case 6:
                switch (osInfo.Version.Minor)
                    case 0:
                        // Windows Vista or Windows Server 2008 (distinct by rpoduct type)
                        return WindowsVersions.WinVista;
                    case 1:
                        return WindowsVersions.Win7;
                    case 2:
                        return WindowsVersions.Win8;
    else if (osInfo.Platform == System.PlatformID.Unix)
        return WindowsVersions.Unix;
    else if (osInfo.Platform == System.PlatformID.MacOSX)
        return WindowsVersions.MacOSX;
    else if (osInfo.Platform == PlatformID.Xbox)
        return WindowsVersions.Xbox;
    return WindowsVersions.UnKnown;
2013/07/02: added WIN8 support

Monday, November 22, 2010

Bootstrapper Package | Visual Studio 2010 | Microsoft .NET Framework Version 2.0 Redistributable

After long searching & reading, I created Bootstrapper package for using prerequisites on my setup project for my dot.net 2.0 application.

First of all, there must exist the Microsoft .NET Framework Version 2.0 Redistributable packages installation files:
1. dotnetfx.exe - for x86 (download here)
2. NetFx64.exe - for x64 (download here)
3. NetFx64.exe - for IA64-Itanium (download here)

Let's rename the files (respectively) so they will be more readable:
1. dotnetfx_x86.exe (for x86)
2. NetFx64_x64.exe (for x64)
3. NetFx64_IA64.exe (for IA64-Itanium)

Now, we have to create new Bootstrapper Package for this cause Visual Studio 2010 not contains in its setup prerequisites the Microsoft .NET Framework Version 2.0.

First we create a folder on C:\ and then copy the finished folder to the Bootstrapper folder.

Step 1
Create a folder under C:\ and name it DotNetFx20
Inside DotNetFx20, create:
a. copy the 3 downloaded Redistributable files to it (dotnetfx_x86.exe, NetFx64_x64.exe, NetFx64_IA64.exe)
b. create an (empty) XML file named Product.xml (will be edited later)
c. create a folder named en (for english locale) and create an (empty) XML file named package.xml

Step 2
[Expand/Collapse] Edit file Product.xml:

Step 3
[Expand/Collapse] Edit file package.xml:

Step 4
Copy the folder DotNetFx20 to the Bootstrapper packages folder which is under:
C:\Program Files\Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages\

Step 5
That's it.. :)

Here is the whole Bootstrapper Package ready-to-use folder to download without (dotnetfx_x86.exe, NetFx64_x64.exe, NetFx64_IA64.exe) which can be downloaded from MSDN directly (links above):
download here (updated file)

Update (29.11.2010):
There was problem with the Product.xml file, so file updated and also zip file for downloading. The filenames did NOT match...