//-------------------------------------------------------------
// GACTest.cs
//
// This is a test application for Managed GAC API Wrappers
//-------------------------------------------------------------
using System;
using System.GACManagedAccess;

public class GACTest
{
    public static int Main(String[] args)
    {
        if (args.Length == 0) {
            ShowUsage();
            return 1;
        }

        try {
            Run(args);
        }
        catch(Exception e) {
            Console.WriteLine("Unhandled Exception: {0}:{1}", e.GetType(), e.Message);
            Console.WriteLine(e.StackTrace);
            return 1;
        }

        return 0;
    }

    internal static void ShowUsage()
    {
        Console.WriteLine("Usage: GACtest [options]");
        Console.WriteLine("Options:");
        Console.WriteLine("\t/L[ist] assemblyName. use \"*\" to show all assemblies.");
        Console.WriteLine("\t/L[ist]R[eference] assemblyName. use \"*\" to show all assemblies.");
        Console.WriteLine("\t/L[ist]P[ath] assemblyName. use \"*\" to show all assemblies.");
        Console.WriteLine("\t/I[nstall] assemblyPath [/f[orce]].");
        Console.WriteLine("\t/I[nstall]R[eference] assemblyPath Guidscheme identity description [/f[orce]].");
        Console.WriteLine("\t/U[ninstall] assemblyFullName.");
        Console.WriteLine("\t/U[ninstall]R[eference] AssemblyFullName Guidscheme identity description.");
        Console.WriteLine("\tGuidscheme can be one of the three: OPAQUE, UNINSTALL_KEY, or FILEPATH.");
    }

    private static void Run(String[] args)
    {
        AssemblyCacheUninstallDisposition disp;

        if (String.Compare(args[0], "/list", true) == 0 || String.Compare(args[0], "/l", true) == 0 ||
            String.Compare(args[0], "-list", true) == 0 || String.Compare(args[0], "-l", true) == 0) {
            if (args.Length != 2) {
                ShowUsage();
                return;
            }

            String name = args[1];
            if (name == "*") {
                name = null;
            }
          
            Console.WriteLine("The following assemblies are found in GAC:\n");
            EnumAssembly(name, false, false);
        }
        else if (String.Compare(args[0], "/listpath", true) == 0 || String.Compare(args[0], "/lp", true) == 0 ||
            String.Compare(args[0], "-listpath", true) == 0 || String.Compare(args[0], "-lp", true) == 0) {
            if (args.Length != 2) {
                ShowUsage();
                return;
            }

            String name = args[1];
            if (name == "*") {
                name = null;
            }
          
            Console.WriteLine("The following assemblies are found in GAC:\n");
            EnumAssembly(name, true, false);
        }
        else if (String.Compare(args[0], "/listreference", true) == 0 || String.Compare(args[0], "/lr", true) == 0 ||
            String.Compare(args[0], "-listreference", true) == 0 || String.Compare(args[0], "-lr", true) == 0) {
            if (args.Length != 2) {
                ShowUsage();
                return;
            }

            String name = args[1];
            if (name == "*") {
                name = null;
            }
          
            Console.WriteLine("The following assemblies are found in GAC:\n");
            EnumAssembly(name, false, true);
        }
        else if (String.Compare(args[0], "/install", true) == 0 || String.Compare(args[0], "/i", true) == 0
               || String.Compare(args[0], "-install", true) == 0 || String.Compare(args[0], "-i", true) == 0) {
            if (args.Length != 2 && args.Length != 3) {
                ShowUsage();
                return;
            }
            String assemblyPath = args[1];
            bool force = false;
            if (args.Length == 3) {
                if (String.Compare(args[2], "/force ", true) == 0 || String.Compare(args[2], "/f", true) == 0
                    || String.Compare(args[2], "-force", true) == 0 || String.Compare(args[2], "-f", true) == 0) {
                    force = true;
                }
                else {
                    ShowUsage();
                    return;
                }
            }

            InstallAssembly(assemblyPath, null, null, null, force);

            Console.WriteLine("Assembly {0} is successfully installed.", assemblyPath);
        }
        else if (String.Compare(args[0], "/installreference", true) == 0 || String.Compare(args[0], "/ir", true) == 0
               || String.Compare(args[0], "-installreference", true) == 0 || String.Compare(args[0], "-ir", true) == 0) {
            if (args.Length != 5 && args.Length != 6) {
                ShowUsage();
                return;
            }
            String assemblyPath = args[1];
            bool force = false;
            if (args.Length == 3) {
                if (String.Compare(args[2], "/force ", true) == 0 || String.Compare(args[2], "/f", true) == 0
                    || String.Compare(args[2], "-force", true) == 0 || String.Compare(args[2], "-f", true) == 0) {
                    force = true;
                }
                else {
                    ShowUsage();
                    return;
                }
            }

            InstallAssembly(assemblyPath, args[2], args[3], args[4], force);

            Console.WriteLine("Assembly {0} is successfully installed.", assemblyPath);
        }
        else if (String.Compare(args[0], "/uninstall", true) == 0 || String.Compare(args[0], "/u", true) == 0
               || String.Compare(args[0], "-uninstall", true) == 0 || String.Compare(args[0], "-u", true) == 0) {
            if (args.Length != 2) {
                ShowUsage();
                return;
            }

            UninstallAssembly(args[1], null, null, null, out disp);

            ShowUninstallResult(args[1], disp);
        }
        else if (String.Compare(args[0], "/uninstallreference", true) == 0 || String.Compare(args[0], "/ur", true) == 0
               || String.Compare(args[0], "-uninstallreference", true) == 0 || String.Compare(args[0], "-ur", true) == 0) {
            if (args.Length != 5) {
                ShowUsage();
                return;
            }

            UninstallAssembly(args[1], args[2], args[3], args[4], out disp);

            ShowUninstallResult(args[1], disp);
        }
        else {
            ShowUsage();
            return;
        }
    }

    private static void EnumAssembly(String asmName, bool showPath, bool showReference)
    {
        if (asmName == "*") {
            asmName = null;
        }

        int total = 0;
        AssemblyCacheEnum asmEnum = new AssemblyCacheEnum(asmName);
        while (true) {
            String nextAsm = asmEnum.GetNextAssembly();
            if (nextAsm != null) {
                total++;
                Console.WriteLine("{0}: {1}", total, nextAsm);
                if (showPath) {
                    Console.WriteLine("Path in GAC:");
                    Console.WriteLine(AssemblyCache.QueryAssemblyInfo(nextAsm));
                    Console.WriteLine();
                }
                if (showReference) {
                    AssemblyCacheInstallReferenceEnum refEnum = new AssemblyCacheInstallReferenceEnum(nextAsm);
                    while(true){
                        InstallReference instRef = refEnum.GetNextReference();
                        if (instRef != null) {
                            String guid;
                            if (instRef.GuidScheme == InstallReferenceGuid.UninstallSubkeyGuid) {
                                guid = "UNINSTALL_KEY";
                            }
                            else if (instRef.GuidScheme == InstallReferenceGuid.FilePathGuid) {
                                guid = "FILEPATH";
                            }
                            else if (instRef.GuidScheme == InstallReferenceGuid.OpaqueGuid) {
                                guid = "OPAQUE";
                            }
                            else if (instRef.GuidScheme == InstallReferenceGuid.MsiGuid) {
                                guid = "WINDOWS_INSTALLER";
                            }
                            else if (instRef.GuidScheme == InstallReferenceGuid.OsInstallGuid) {
                                guid = "OS_INSTALL";
                            }
                            else {
                                guid = "UNKNOWN";
                            }

                            Console.WriteLine("\tSCHEME: <{0}> ID: <{1}> DESCRIPTION: <{2}>", guid, instRef.Identifier, instRef.Description);
                        }
                        else {
                            break;
                        }
                    }
                }
            }
            else {
                break;
            }
        }
      
        Console.WriteLine();
        Console.WriteLine("Totally {0} assemblies found.", total);
    }

    private static void InstallAssembly(String assemblyPath, String scheme, String id, String descp, bool force)
    {
        InstallReference reference = null;

        if (scheme != null) {
            Guid guidscheme;
            if (String.Compare(scheme, "OPAQUE", true) == 0) {
                guidscheme = InstallReferenceGuid.OpaqueGuid;
            }
            else if (String.Compare(scheme, "UNINSTALL_KEY", true) == 0) {
                guidscheme = InstallReferenceGuid.UninstallSubkeyGuid;
            }
            else if (String.Compare(scheme, "FILEPATH", true) == 0) {
                guidscheme = InstallReferenceGuid.FilePathGuid;
            }
            else {
                ShowUsage();
                return;
            }

            reference = new InstallReference(guidscheme, id, descp);
        }

        AssemblyCache.InstallAssembly(assemblyPath, reference, force ? AssemblyCommitFlags.Force : AssemblyCommitFlags.Default);
    }

    private static void UninstallAssembly(String assemblyPath, String scheme, String id, String descp, out AssemblyCacheUninstallDisposition disp)
    {
        InstallReference reference = null;
        disp = AssemblyCacheUninstallDisposition.Unknown;

        if (scheme != null) {
            Guid guidscheme;
            if (String.Compare(scheme, "OPAQUE", true) == 0) {
                guidscheme = InstallReferenceGuid.OpaqueGuid;
            }
            else if (String.Compare(scheme, "UNINSTALL_KEY", true) == 0) {
                guidscheme = InstallReferenceGuid.UninstallSubkeyGuid;
            }
            else if (String.Compare(scheme, "FILEPATH", true) == 0) {
                guidscheme = InstallReferenceGuid.FilePathGuid;
            }
            else {
                ShowUsage();
                return;
            }

            reference = new InstallReference(guidscheme, id, descp);
        }

        AssemblyCacheUninstallDisposition m_disp;
        AssemblyCache.UninstallAssembly(assemblyPath, reference, out m_disp);

        disp = m_disp;
    }
  
    private static void ShowUninstallResult(String name, AssemblyCacheUninstallDisposition disp)
    {
        switch (disp) {
            case AssemblyCacheUninstallDisposition.Uninstalled:
                Console.WriteLine("Assembly \"{0}\" is successfully uninstalled.", name);
                break;
            case AssemblyCacheUninstallDisposition.AlreadyUninstalled:
                Console.WriteLine("Assembly \"{0}\" does not exist in GAC.", name);
                break;
            case AssemblyCacheUninstallDisposition.HasInstallReference:
                Console.WriteLine("Assembly \"{0}\" is required by one or more applications.", name);
                break;
            case AssemblyCacheUninstallDisposition.ReferenceNotFound:
                Console.WriteLine("The reference to Assembly \"{0}\" is not found.", name);
                break;
        }
    }
}

<update date="2004/9/28"> Add "listreference" option to GacTest. </update>