5 // Todd Berman <tberman@sevenl.net>
6 // Jackson Harper <jackson@ximian.com>
8 // Copyright 2003, 2004 Todd Berman
9 // Copyright 2004 Novell, Inc (http://www.novell.com)
15 using System.Diagnostics;
17 using System.Reflection;
18 using System.Collections;
19 using System.Globalization;
20 using System.Runtime.InteropServices;
21 using System.Security.Cryptography;
24 using Mono.Security.Cryptography;
26 namespace Mono.Tools {
30 private enum Command {
41 private enum VerificationResult
49 private static bool silent;
50 static bool in_bootstrap;
52 public static int Main (string [] args)
57 Command command = Command.Unknown;
58 string command_str = null;
61 string name, package, gacdir, root;
62 name = package = root = gacdir = null;
63 bool check_refs = false;
65 // Check for silent arg first so we can suppress
66 // warnings during command line parsing
67 if (Array.IndexOf (args, "/silent") > -1 || Array.IndexOf (args, "-silent") > -1)
70 for (int i=0; i<args.Length; i++) {
71 if (IsSwitch (args [i])) {
73 // for cmd line compatibility with other gacutils
74 // we always force it though
75 if (args [i] == "-f" || args [i] == "/f")
78 // Ignore this option for now, although we might implement it someday
79 if (args [i] == "/r") {
80 WriteLine ("WARNING: gacutil does not support traced references." +
81 "This option is being ignored.");
86 // This is already handled we just dont want to choke on it
87 if (args [i] == "-silent" || args [i] == "/silent")
90 if (args [i] == "-check_refs" || args [i] == "/check_refs") {
95 if (args [i] == "-bootstrap" || args [i] == "/bootstrap") {
100 if (command == Command.Unknown) {
101 command = GetCommand (args [i]);
102 if (command != Command.Unknown) {
103 command_str = args [i];
108 if (i + 1 >= args.Length) {
109 Console.WriteLine ("Option " + args [i] + " takes 1 argument");
116 package = args [++i];
128 // we currently don't display a
129 // logo banner, so ignore it
130 // for command-line compatibility
141 if (command == Command.Unknown && IsSwitch (args [0])) {
142 Console.WriteLine ("Unknown command: " + args [0]);
144 } else if (command == Command.Unknown) {
146 } else if (command == Command.Help) {
151 if (gacdir == null) {
152 gacdir = GetGacDir ();
153 libdir = GetLibDir ();
155 gacdir = EnsureLib (gacdir);
156 libdir = Path.Combine (gacdir, "mono");
157 gacdir = Path.Combine (libdir, "gac");
160 string link_gacdir = gacdir;
161 string link_libdir = libdir;
163 libdir = Path.Combine (root, "mono");
164 gacdir = Path.Combine (libdir, "gac");
170 case Command.Install:
172 WriteLine ("Option " + command_str + " takes 1 argument");
175 if (!Install (check_refs, name, package, gacdir, link_gacdir, libdir, link_libdir))
178 case Command.InstallFromList:
180 WriteLine ("Option " + command_str + " takes 1 argument");
183 if (!InstallFromList (check_refs, name, package, gacdir, link_gacdir, libdir, link_libdir))
186 case Command.Uninstall:
188 WriteLine ("Option " + command_str + " takes 1 argument");
191 int uninstallCount = 0;
192 int uninstallFailures = 0;
193 Uninstall (name, package, gacdir, libdir, false,
194 ref uninstallCount, ref uninstallFailures);
195 WriteLine ("Assemblies uninstalled = {0}", uninstallCount);
196 WriteLine ("Failures = {0}", uninstallFailures);
197 if (uninstallFailures > 0)
200 case Command.UninstallFromList:
202 WriteLine ("Option " + command_str + " takes 1 argument");
205 if (!UninstallFromList (name, package, gacdir, libdir))
208 case Command.UninstallSpecific:
210 WriteLine ("Option " + command_str + " takes 1 argument");
213 if (!UninstallSpecific (name, package, gacdir, libdir))
224 static void Copy (string source, string target, bool v)
227 File.Delete (target);
229 File.Copy (source, target, v);
232 private static bool Install (bool check_refs, string name, string package,
233 string gacdir, string link_gacdir, string libdir, string link_libdir)
235 string failure_msg = "Failure adding assembly {0} to the cache: ";
238 if (!File.Exists (name)) {
239 WriteLine (string.Format (failure_msg, name) + "The system cannot find the file specified.");
243 Assembly assembly = null;
244 AssemblyName an = null;
247 assembly = Assembly.LoadFrom (name);
249 WriteLine (string.Format (failure_msg, name) + "The file specified is not a valid assembly.");
253 an = assembly.GetName ();
255 switch (VerifyStrongName (an, name)) {
256 case VerificationResult.StrongNamed:
257 case VerificationResult.Skipped:
259 case VerificationResult.WeakNamed:
260 WriteLine (string.Format (failure_msg, name) + "Attempt to install an assembly without a strong name"
261 + (in_bootstrap ? "(continuing anyway)" : string.Empty));
265 case VerificationResult.DelaySigned:
266 WriteLine (string.Format (failure_msg, name) + "Strong name cannot be verified for delay-signed assembly"
267 + (in_bootstrap ? "(continuing anyway)" : string.Empty));
273 resources = new ArrayList ();
274 foreach (string res_name in assembly.GetManifestResourceNames ()) {
275 ManifestResourceInfo res_info = assembly.GetManifestResourceInfo (res_name);
277 if ((res_info.ResourceLocation & ResourceLocation.Embedded) == 0) {
278 if (!File.Exists (res_info.FileName)) {
279 WriteLine (string.Format (failure_msg, name) + "The system cannot find resource " + res_info.FileName);
283 resources.Add (res_info);
287 if (check_refs && !CheckReferencedAssemblies (an)) {
288 WriteLine (string.Format (failure_msg, name) +
289 "Attempt to install an assembly that " +
290 "references non strong named assemblies " +
291 "with -check_refs enabled.");
295 string [] siblings = { ".config", ".mdb" };
296 string version_token = an.Version + "_" +
297 an.CultureInfo.Name.ToLower (CultureInfo.InvariantCulture) + "_" +
298 GetStringToken (an.GetPublicKeyToken ());
299 string full_path = Path.Combine (Path.Combine (gacdir, an.Name), version_token);
300 string asmb_file = Path.GetFileName (name);
301 string asmb_path = Path.Combine (full_path, asmb_file);
302 string asmb_name = assembly.GetName ().Name;
304 if (Path.GetFileNameWithoutExtension (asmb_file) != asmb_name) {
305 WriteLine (string.Format (failure_msg, name) +
306 string.Format ("the filename \"{0}\" doesn't match the assembly name \"{1}\"",
307 asmb_file, asmb_name));
312 if (Directory.Exists (full_path)) {
313 // Wipe out the directory. This way we ensure old assemblies
314 // config files, and AOTd files are removed.
315 Directory.Delete (full_path, true);
317 Directory.CreateDirectory (full_path);
319 WriteLine (string.Format (failure_msg, name) +
320 "gac directories could not be created, " +
321 "possibly permission issues.");
325 Copy (name, asmb_path, true);
327 var name_pdb = Path.ChangeExtension (name, ".pdb");
328 if (File.Exists (name_pdb)) {
329 Copy (name_pdb, Path.ChangeExtension (asmb_path, ".pdb"), true);
332 foreach (string ext in siblings) {
333 string sibling = String.Concat (name, ext);
334 if (File.Exists (sibling))
335 Copy (sibling, String.Concat (asmb_path, ext), true);
338 foreach (ManifestResourceInfo resource_info in resources) {
340 Copy (resource_info.FileName, Path.Combine (full_path, Path.GetFileName (resource_info.FileName)), true);
342 WriteLine ("ERROR: Could not install resource file " + resource_info.FileName);
343 Environment.Exit (1);
347 if (package != null) {
348 string ref_dir = Path.Combine (libdir, package);
349 string ref_path = Path.Combine (ref_dir, asmb_file);
351 if (File.Exists (ref_path))
352 File.Delete (ref_path);
354 Directory.CreateDirectory (ref_dir);
356 WriteLine ("ERROR: Could not create package dir file.");
357 Environment.Exit (1);
359 if (Path.DirectorySeparatorChar == '/') {
360 string pkg_path_abs = Path.Combine (gacdir, Path.Combine (an.Name, Path.Combine (version_token, asmb_file)));
361 string pkg_path = AbsoluteToRelativePath (ref_dir, pkg_path_abs);
362 symlink (pkg_path, ref_path);
364 var pdb_pkg_path = Path.ChangeExtension (pkg_path, ".pdb");
365 var pdb_ref_path = Path.ChangeExtension (ref_path, ".pdb");
367 if (File.Exists (pdb_pkg_path)) {
368 symlink (pdb_pkg_path, pdb_ref_path);
371 File.Delete (pdb_ref_path);
373 // Ignore error, just delete files that should not be there.
377 foreach (string ext in siblings) {
378 string sibling = String.Concat (pkg_path, ext);
379 string sref = String.Concat (ref_path, ext);
381 if (File.Exists (sibling))
382 symlink (sibling, sref);
387 // Ignore error, just delete files that should not be there.
391 WriteLine ("Package exported to: {0} -> {1}", ref_path, pkg_path);
393 // string link_path = Path.Combine (Path.Combine (link_gacdir, an.Name), version_token);
395 // We can't use 'link_path' here, since it need not be a valid path at the time 'gacutil'
396 // is run, esp. when invoked in a DESTDIR install.
397 Copy (name, ref_path, true);
398 WriteLine ("Package exported to: " + ref_path);
402 WriteLine ("Installed {0} into the gac ({1})", name,
408 //from MonoDevelop.Core.FileService
409 unsafe static string AbsoluteToRelativePath (string baseDirectoryPath, string absPath)
411 if (!Path.IsPathRooted (absPath) || string.IsNullOrEmpty (baseDirectoryPath))
414 absPath = Path.GetFullPath (absPath);
415 baseDirectoryPath = Path.GetFullPath (baseDirectoryPath).TrimEnd (Path.DirectorySeparatorChar);
417 fixed (char* bPtr = baseDirectoryPath, aPtr = absPath) {
418 var bEnd = bPtr + baseDirectoryPath.Length;
419 var aEnd = aPtr + absPath.Length;
420 char* lastStartA = aEnd;
421 char* lastStartB = bEnd;
424 // search common base path
430 if (IsSeparator (*a)) {
438 if (a >= aEnd || IsSeparator (*a)) {
449 if (lastStartA >= aEnd)
452 // handle case a: some/path b: some/path/deeper...
454 if (IsSeparator (*b)) {
460 // look how many levels to go up into the base path
462 while (lastStartB < bEnd) {
463 if (IsSeparator (*lastStartB))
467 var size = goUpCount * 2 + goUpCount + aEnd - lastStartA;
468 var result = new char [size];
469 fixed (char* rPtr = result) {
472 for (int i = 0; i < goUpCount; i++) {
475 *(r++) = Path.DirectorySeparatorChar;
477 // copy the remaining absulute path
478 while (lastStartA < aEnd)
479 *(r++) = *(lastStartA++);
481 return new string (result);
485 static bool IsSeparator (char ch)
487 return ch == Path.DirectorySeparatorChar || ch == Path.AltDirectorySeparatorChar || ch == Path.VolumeSeparatorChar;
490 private static void Uninstall (string name, string package, string gacdir, string libdir, bool listMode, ref int uninstalled, ref int failures)
492 string [] assembly_pieces = name.Split (new char[] { ',' });
493 Hashtable asm_info = new Hashtable ();
495 foreach (string item in assembly_pieces) {
496 if (item == String.Empty) continue;
497 string[] pieces = item.Trim ().Split (new char[] { '=' }, 2);
498 if(pieces.Length == 1)
499 asm_info ["assembly"] = pieces [0];
501 asm_info [pieces[0].Trim ().ToLower (CultureInfo.InvariantCulture)] = pieces [1];
504 string assembly_name = (string) asm_info ["assembly"];
505 string asmdir = Path.Combine (gacdir, assembly_name);
506 if (!Directory.Exists (asmdir)) {
509 WriteLine ("Assembly: " + name);
511 WriteLine ("No assemblies found that match: " + name);
515 string searchString = GetSearchString (asm_info);
516 string [] directories = Directory.GetDirectories (asmdir, searchString);
518 if (directories.Length == 0) {
521 WriteLine ("Assembly: " + name);
522 WriteLine ("No assemblies found that match: " + name);
527 for (int i = 0; i < directories.Length; i++) {
528 if (listMode && i > 0)
531 string dir = directories [i];
532 string extension = null;
534 if (File.Exists (Path.Combine (dir, assembly_name + ".dll"))) {
536 } else if (File.Exists (Path.Combine (dir, assembly_name + ".exe"))) {
540 WriteLine("Cannot find the assembly: " + assembly_name);
544 string assembly_filename = assembly_name + extension;
546 AssemblyName an = AssemblyName.GetAssemblyName (
547 Path.Combine (dir, assembly_filename));
548 WriteLine ("Assembly: " + an.FullName);
550 Directory.Delete (dir, true);
551 if (package != null) {
552 string link_dir = Path.Combine (libdir, package);
553 string link = Path.Combine (link_dir, assembly_filename);
558 // The file might not exist, happens with
559 // the debugger on make uninstall
562 if (Directory.GetFiles (link_dir).Length == 0) {
563 WriteLine ("Cleaning package directory, it is empty.");
565 Directory.Delete (link_dir);
567 // Workaround: GetFiles does not list Symlinks
573 WriteLine ("Uninstalled: " + an.FullName);
576 if (Directory.GetDirectories (asmdir).Length == 0) {
577 WriteLine ("Cleaning assembly dir, it is empty");
579 Directory.Delete (asmdir);
581 // Workaround: GetFiles does not list Symlinks
586 private static bool UninstallSpecific (string name, string package,
587 string gacdir, string libdir)
589 string failure_msg = "Failure to remove assembly from the cache: ";
591 if (!File.Exists (name)) {
592 WriteLine (failure_msg + "The system cannot find the file specified.");
596 AssemblyName an = null;
599 an = AssemblyName.GetAssemblyName (name);
601 WriteLine (failure_msg + "The file specified is not a valid assembly.");
605 int uninstallCount = 0;
606 int uninstallFailures = 0;
607 Uninstall (an.FullName.Replace (" ", String.Empty),
608 package, gacdir, libdir, true, ref uninstallCount,
609 ref uninstallFailures);
610 WriteLine ("Assemblies uninstalled = {0}", uninstallCount);
611 WriteLine ("Failures = {0}", uninstallFailures);
612 return (uninstallFailures == 0);
615 private static void List (string name, string gacdir)
617 WriteLine ("The following assemblies are installed into the GAC:");
620 FilteredList (name, gacdir);
625 DirectoryInfo gacinfo = new DirectoryInfo (gacdir);
626 foreach (DirectoryInfo parent in gacinfo.GetDirectories ()) {
627 foreach (DirectoryInfo dir in parent.GetDirectories ()) {
628 string asmb = Path.Combine (Path.Combine (parent.FullName, dir.Name), parent.Name) + ".dll";
629 if (File.Exists (asmb)) {
630 WriteLine (AsmbNameFromVersionString (parent.Name, dir.Name));
635 WriteLine ("Number of items = " + count);
638 private static void FilteredList (string name, string gacdir)
640 string [] assembly_pieces = name.Split (new char[] { ',' });
641 Hashtable asm_info = new Hashtable ();
643 foreach (string item in assembly_pieces) {
644 string[] pieces = item.Trim ().Split (new char[] { '=' }, 2);
645 if(pieces.Length == 1)
646 asm_info ["assembly"] = pieces [0];
648 asm_info [pieces[0].Trim ().ToLower (CultureInfo.InvariantCulture)] = pieces [1];
651 string asmdir = Path.Combine (gacdir, (string) asm_info ["assembly"]);
652 if (!Directory.Exists (asmdir)) {
653 WriteLine ("Number of items = 0");
656 string search = GetSearchString (asm_info);
657 string [] dir_list = Directory.GetDirectories (asmdir, search);
660 foreach (string dir in dir_list) {
661 string asmb = Path.Combine (dir, (string) asm_info ["assembly"]) + ".dll";
662 if (File.Exists (asmb)) {
663 WriteLine (AsmbNameFromVersionString ((string) asm_info ["assembly"],
664 new DirectoryInfo (dir).Name));
668 WriteLine ("Number of items = " + count);
671 private static bool InstallFromList (bool check_refs, string list_file, string package,
672 string gacdir, string link_gacdir, string libdir, string link_libdir)
674 StreamReader s = null;
675 int processed, failed;
676 string listdir = Path.GetDirectoryName (
677 Path.GetFullPath (list_file));
679 processed = failed = 0;
682 s = new StreamReader (list_file);
685 while ((line = s.ReadLine ()) != null) {
686 string file = line.Trim ();
687 if (file.Length == 0)
690 string assemblyPath = Path.Combine (listdir,
693 if (!Install (check_refs, assemblyPath, package, gacdir,
694 link_gacdir, libdir, link_libdir))
699 WriteLine ("Assemblies processed = {0}", processed);
700 WriteLine ("Assemblies installed = {0}", processed - failed);
701 WriteLine ("Failures = {0}", failed);
703 return (failed == 0);
704 } catch (IOException) {
705 WriteLine ("Failed to open assemblies list file " + list_file + ".");
713 private static bool UninstallFromList (string list_file, string package,
714 string gacdir, string libdir)
716 StreamReader s = null;
717 int failed, uninstalled;
719 failed = uninstalled = 0;
722 s = new StreamReader (list_file);
725 while ((line = s.ReadLine ()) != null) {
726 string name = line.Trim ();
727 if (name.Length == 0)
729 Uninstall (line, package, gacdir, libdir,
730 true, ref uninstalled, ref failed);
733 WriteLine ("Assemblies processed = {0}", uninstalled+failed);
734 WriteLine ("Assemblies uninstalled = {0}", uninstalled);
735 WriteLine ("Failures = {0}", failed);
737 return (failed == 0);
738 } catch (IOException) {
739 WriteLine ("Failed to open assemblies list file " + list_file + ".");
747 private static bool CheckReferencedAssemblies (AssemblyName an)
751 Assembly a = Assembly.LoadFrom (an.CodeBase);
752 AssemblyName corlib = typeof (object).Assembly.GetName ();
754 foreach (AssemblyName ref_an in a.GetReferencedAssemblies ()) {
755 if (ref_an.Name == corlib.Name) // Just do a string compare so we can install on diff versions
757 byte [] pt = ref_an.GetPublicKeyToken ();
758 if (pt == null || pt.Length == 0) {
759 WriteLine ("Assembly " + ref_an.Name + " is not strong named.");
763 } catch (Exception e) {
764 WriteLine (e.ToString ()); // This should be removed pre beta3
769 AppDomain.Unload (d);
777 private static string GetSearchString (Hashtable asm_info)
779 if (asm_info.Keys.Count == 1)
781 string version, culture, token;
783 version = asm_info ["version"] as string;
784 version = (version == null ? "*" : version + "*");
785 culture = asm_info ["culture"] as string;
786 culture = (culture == null ? "*" : (culture == "neutral") ? String.Empty : culture.ToLower (CultureInfo.InvariantCulture));
787 token = asm_info ["publickeytoken"] as string;
788 token = (token == null ? "*" : token.ToLower (CultureInfo.InvariantCulture));
790 return String.Format ("{0}_{1}_{2}", version, culture, token);
793 private static string AsmbNameFromVersionString (string name, string str)
795 string [] pieces = str.Split ('_');
796 return String.Format ("{0}, Version={1}, Culture={2}, PublicKeyToken={3}",
797 name, pieces [0], (pieces [1] == String.Empty ? "neutral" : pieces [1]),
801 static bool LoadConfig (bool quiet)
803 MethodInfo config = typeof (System.Environment).GetMethod ("GetMachineConfigPath",
804 BindingFlags.Static | BindingFlags.NonPublic);
806 if (config != null) {
807 string path = (string) config.Invoke (null, null);
809 bool exist = File.Exists (path);
810 if (!quiet && !exist)
811 Console.WriteLine ("Couldn't find machine.config");
813 StrongNameManager.LoadConfig (path);
816 Console.WriteLine ("Couldn't resolve machine.config location (corlib issue)");
822 // modified copy from sn
823 private static VerificationResult VerifyStrongName (AssemblyName an, string assemblyFile)
825 byte [] publicKey = StrongNameManager.GetMappedPublicKey (an.GetPublicKeyToken ());
826 if ((publicKey == null) || (publicKey.Length < 12)) {
828 publicKey = an.GetPublicKey ();
829 if ((publicKey == null) || (publicKey.Length < 12))
830 return VerificationResult.WeakNamed;
833 // Note: MustVerify is based on the original token (by design). Public key
834 // remapping won't affect if the assembly is verified or not.
835 if (StrongNameManager.MustVerify (an)) {
836 RSA rsa = CryptoConvert.FromCapiPublicKeyBlob (publicKey, 12);
837 StrongName sn = new StrongName (rsa);
838 if (sn.Verify (assemblyFile)) {
839 return VerificationResult.StrongNamed;
841 return VerificationResult.DelaySigned;
844 return VerificationResult.Skipped;
848 private static bool IsSwitch (string arg)
850 return (arg [0] == '-' || (arg [0] == '/' && !arg.EndsWith (".dll") && !arg.EndsWith (".exe") && arg.IndexOf ('/', 1) < 0 ) );
853 private static Command GetCommand (string arg)
855 Command c = Command.Unknown;
865 case "--install-from-list":
866 c = Command.InstallFromList;
872 c = Command.Uninstall;
876 case "--uninstall-from-list":
877 c = Command.UninstallFromList;
881 case "--uninstall-specific":
882 c = Command.UninstallSpecific;
898 [DllImport ("libc", SetLastError=true)]
899 public static extern int symlink (string oldpath, string newpath);
901 private static string GetGacDir () {
902 PropertyInfo gac = typeof (System.Environment).GetProperty ("GacPath",
903 BindingFlags.Static|BindingFlags.NonPublic);
905 WriteLine ("ERROR: Mono runtime not detected, please use " +
906 "the mono runtime for gacutil.exe");
907 Environment.Exit (1);
909 MethodInfo get_gac = gac.GetGetMethod (true);
910 return (string) get_gac.Invoke (null, null);
913 private static string GetLibDir () {
914 MethodInfo libdir = typeof (System.Environment).GetMethod ("internalGetGacPath",
915 BindingFlags.Static|BindingFlags.NonPublic);
916 if (libdir == null) {
917 WriteLine ("ERROR: Mono runtime not detected, please use " +
918 "the mono runtime for gacutil.exe");
919 Environment.Exit (1);
921 return Path.Combine ((string)libdir.Invoke (null, null), "mono");
924 private static string GetStringToken (byte[] tok)
926 StringBuilder sb = new StringBuilder ();
927 for (int i = 0; i < tok.Length ; i++)
928 sb.Append (tok[i].ToString ("x2"));
929 return sb.ToString ();
932 private static string EnsureLib (string dir)
934 DirectoryInfo d = new DirectoryInfo (dir);
937 return Path.Combine (dir, "lib");
940 private static void WriteLine ()
944 Console.WriteLine ();
947 private static void WriteLine (string line)
951 Console.WriteLine (line);
954 private static void WriteLine (string line, params object [] p)
958 Console.WriteLine (line, p);
961 private static void Usage ()
964 Environment.Exit (1);
967 private static void ShowHelp (bool detailed)
969 WriteLine ("Usage: gacutil.exe <commands> [ <options> ]");
970 WriteLine ("Commands:");
972 WriteLine ("-i <assembly_path> [-check_refs] [-package NAME] [-root ROOTDIR] [-gacdir GACDIR]");
973 WriteLine ("\tInstalls an assembly into the global assembly cache.");
975 WriteLine ("\t<assembly_path> is the name of the file that contains the " +
976 "\tassembly manifest\n" +
977 "\tExample: -i myDll.dll");
981 WriteLine ("-il <assembly_list_file> [-check_refs] [-package NAME] [-root ROOTDIR] [-gacdir GACDIR]");
982 WriteLine ("\tInstalls one or more assemblies into the global assembly cache.");
984 WriteLine ("\t<assembly_list_file> is the path to a test file containing a list of\n" +
985 "\tassembly file paths on separate lines.\n" +
986 "\tExample -il assembly_list.txt\n" +
987 "\t\tassembly_list.txt contents:\n" +
988 "\t\tassembly1.dll\n" +
989 "\t\tassembly2.dll");
993 WriteLine ("-u <assembly_display_name> [-package NAME] [-root ROOTDIR] [-gacdir GACDIR]");
994 WriteLine ("\tUninstalls an assembly from the global assembly cache.");
996 WriteLine ("\t<assembly_display_name> is the name of the assembly (partial or\n" +
997 "\tfully qualified) to remove from the global assembly cache. If a \n" +
998 "\tpartial name is specified all matching assemblies will be uninstalled.\n" +
999 "\tExample: -u myDll,Version=1.2.1.0");
1003 WriteLine ("-ul <assembly_list_file> [-package NAME] [-root ROOTDIR] [-gacdir GACDIR]");
1004 WriteLine ("\tUninstalls one or more assemblies from the global assembly cache.");
1006 WriteLine ("\t<assembly_list_file> is the path to a test file containing a list of\n" +
1007 "\tassembly names on separate lines.\n" +
1008 "\tExample -ul assembly_list.txt\n" +
1009 "\t\tassembly_list.txt contents:\n" +
1010 "\t\tassembly1,Version=1.0.0.0,Culture=en,PublicKeyToken=0123456789abcdef\n" +
1011 "\t\tassembly2,Version=2.0.0.0,Culture=en,PublicKeyToken=0123456789abcdef");
1015 WriteLine ("-us <assembly_path> [-package NAME] [-root ROOTDIR] [-gacdir GACDIR]");
1016 WriteLine ("\tUninstalls an assembly using the specifed assemblies full name.");
1018 WriteLine ("\t<assembly path> is the path to an assembly. The full assembly name\n" +
1019 "\tis retrieved from the specified assembly if there is an assembly in\n" +
1020 "\tthe GAC with a matching name, it is removed.\n" +
1021 "\tExample: -us myDll.dll");
1025 WriteLine ("-l [assembly_name] [-root ROOTDIR] [-gacdir GACDIR]");
1026 WriteLine ("\tLists the contents of the global assembly cache.");
1028 WriteLine ("\tWhen the <assembly_name> parameter is specified only matching\n" +
1029 "\tassemblies are listed.");
1034 WriteLine ("\tDisplays a detailed help screen");
1040 WriteLine ("Options:");
1041 WriteLine ("-package <NAME>");
1042 WriteLine ("\tUsed to create a directory in prefix/lib/mono with the name NAME, and a\n" +
1043 "\tsymlink is created from NAME/assembly_name to the assembly on the GAC.\n" +
1044 "\tThis is used so developers can reference a set of libraries at once.");
1047 WriteLine ("-gacdir <GACDIR>");
1048 WriteLine ("\tUsed to specify the GACs base directory. Once an assembly has been installed\n" +
1049 "\tto a non standard gacdir the MONO_GAC_PREFIX environment variable must be used\n" +
1050 "\tto access the assembly.");
1053 WriteLine ("-root <ROOTDIR>");
1054 WriteLine ("\tUsed by developers integrating this with automake tools or packaging tools\n" +
1055 "\tthat require a prefix directory to be specified. The root represents the\n" +
1056 "\t\"libdir\" component of a prefix (typically prefix/lib).");
1059 WriteLine ("-check_refs");
1060 WriteLine ("\tUsed to ensure that the assembly being installed into the GAC does not\n" +
1061 "\treference any non strong named assemblies. Assemblies being installed to\n" +
1062 "\tthe GAC should not reference non strong named assemblies, however the is\n" +
1063 "\tan optional check.");
1066 WriteLine ("Ignored Options:");
1068 WriteLine ("\tThe Mono gacutil ignores the -f option to maintain commandline compatibility with");
1069 WriteLine ("\tother gacutils. gacutil will always force the installation of a new assembly.");
1072 WriteLine ("-r <reference_scheme> <reference_id> <description>");
1073 WriteLine ("\tThe Mono gacutil has not implemented traced references and will emit a warning");
1074 WriteLine ("\twhen this option is used.");