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)       |
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-?!?!?!?!\Products\

    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.


Enjoy...
MDB-Blog

6 comments:

  1. Another good title for this post may be:


    c# get app installation context

    ReplyDelete
  2. What about MSI API method MsiGetProductInfo()?
    It seems like it returns context if you request INSTALLPROPERTY_ASSIGNMENTTYPE. See
    http://msdn.microsoft.com/en-us/library/windows/desktop/aa368279.aspx for details

    ReplyDelete
  3. about `MSI API method MsiGetProductInfo()`:
    ==============================================
    This function available on the `msi.dll` which means that some users might dont have it.
    the required version for this function is:
    :::::
    Windows Installer 5.0 on Windows Server 2012, Windows 8, Windows Server 2008 R2 or Windows 7. Windows Installer 4.0 or Windows Installer 4.5 on Windows Server 2008 or Windows Vista. Windows Installer on Windows Server 2003 or Windows XP. See the Windows Installer Run-Time Requirements for information about the minimum Windows service pack that is required by a Windows Installer version.
    src #1: http://msdn.microsoft.com/en-us/library/windows/desktop/aa370130%28v=vs.85%29.aspx
    src #2: http://msdn.microsoft.com/en-us/library/windows/desktop/cc185688%28v=vs.85%29.aspx

    here you can find which function supported since which version:
    http://msdn.microsoft.com/en-us/library/windows/desktop/aa816406%28v=vs.85%29.aspx


    :::::

    The `registry reading` method is recommended and supported on most OSs.

    anyway, if you still want to use it,
    you can find several examples on google ;)
    example #1: http://www.pinvoke.net/default.aspx/msi.msigetproductinfo
    example #2:

    ReplyDelete
  4. but remember,

    (*) This checking operation is valid ONLY for an application and software which were installed using Microsoft's Windows Installer.

    ReplyDelete
  5. This solution is only for programmers - most people do not write code and have no clue how to run code, so this solution is useless to them. Isn't there some better way?

    ReplyDelete
  6. if you just want to see list of installed applications, you have to open
    [Win7] Control Panel => Programs => list of all installed apps.

    Shortcut for it,
    just click START => and then in the search area, write "Program" and it will find for you
    "Program and features"
    which lists all programs.

    (for win 8.1: http://winsupersite.com/windows-8/windows-81-tip-find-your-installed-apps)


    hope I helped...



    ReplyDelete