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
);
304 if (Directory
.Exists (full_path
)) {
305 // Wipe out the directory. This way we ensure old assemblies
306 // config files, and AOTd files are removed.
307 Directory
.Delete (full_path
, true);
309 Directory
.CreateDirectory (full_path
);
311 WriteLine (string.Format (failure_msg
, name
) +
312 "gac directories could not be created, " +
313 "possibly permission issues.");
317 Copy (name
, asmb_path
, true);
319 foreach (string ext
in siblings
) {
320 string sibling
= String
.Concat (name
, ext
);
321 if (File
.Exists (sibling
))
322 Copy (sibling
, String
.Concat (asmb_path
, ext
), true);
325 foreach (ManifestResourceInfo resource_info
in resources
) {
327 Copy (resource_info
.FileName
, Path
.Combine (full_path
, Path
.GetFileName (resource_info
.FileName
)), true);
329 WriteLine ("ERROR: Could not install resource file " + resource_info
.FileName
);
330 Environment
.Exit (1);
334 if (package
!= null) {
335 string ref_dir
= Path
.Combine (libdir
, package
);
336 string ref_path
= Path
.Combine (ref_dir
, asmb_file
);
338 if (File
.Exists (ref_path
))
339 File
.Delete (ref_path
);
341 Directory
.CreateDirectory (ref_dir
);
343 WriteLine ("ERROR: Could not create package dir file.");
344 Environment
.Exit (1);
346 if (Path
.DirectorySeparatorChar
== '/') {
347 string pkg_path
= "../gac/" + an
.Name
+ "/" + version_token
+ "/" + asmb_file
;
348 symlink (pkg_path
, ref_path
);
350 foreach (string ext
in siblings
) {
351 string sibling
= String
.Concat (pkg_path
, ext
);
352 string sref
= String
.Concat (ref_path
, ext
);
353 if (File
.Exists (sibling
))
354 symlink (sibling
, sref
);
359 // Ignore error, just delete files that should not be there.
363 WriteLine ("Package exported to: {0} -> {1}", ref_path
, pkg_path
);
365 // string link_path = Path.Combine (Path.Combine (link_gacdir, an.Name), version_token);
367 // We can't use 'link_path' here, since it need not be a valid path at the time 'gacutil'
368 // is run, esp. when invoked in a DESTDIR install.
369 Copy (name
, ref_path
, true);
370 WriteLine ("Package exported to: " + ref_path
);
374 WriteLine ("Installed {0} into the gac ({1})", name
,
380 private static void Uninstall (string name
, string package
, string gacdir
, string libdir
, bool listMode
, ref int uninstalled
, ref int failures
)
382 string [] assembly_pieces
= name
.Split (new char[] { ',' }
);
383 Hashtable asm_info
= new Hashtable ();
385 foreach (string item
in assembly_pieces
) {
386 if (item
== String
.Empty
) continue;
387 string[] pieces
= item
.Trim ().Split (new char[] { '=' }
, 2);
388 if(pieces
.Length
== 1)
389 asm_info
["assembly"] = pieces
[0];
391 asm_info
[pieces
[0].Trim ().ToLower (CultureInfo
.InvariantCulture
)] = pieces
[1];
394 string assembly_name
= (string) asm_info
["assembly"];
395 string asmdir
= Path
.Combine (gacdir
, assembly_name
);
396 if (!Directory
.Exists (asmdir
)) {
399 WriteLine ("Assembly: " + name
);
401 WriteLine ("No assemblies found that match: " + name
);
405 string searchString
= GetSearchString (asm_info
);
406 string [] directories
= Directory
.GetDirectories (asmdir
, searchString
);
408 if (directories
.Length
== 0) {
411 WriteLine ("Assembly: " + name
);
412 WriteLine ("No assemblies found that match: " + name
);
417 for (int i
= 0; i
< directories
.Length
; i
++) {
418 if (listMode
&& i
> 0)
421 string dir
= directories
[i
];
423 AssemblyName an
= AssemblyName
.GetAssemblyName (
424 Path
.Combine (dir
, assembly_name
+ ".dll"));
425 WriteLine ("Assembly: " + an
.FullName
);
427 Directory
.Delete (dir
, true);
428 if (package
!= null) {
429 string link_dir
= Path
.Combine (libdir
, package
);
430 string link
= Path
.Combine (link_dir
, assembly_name
+ ".dll");
434 // The file might not exist, happens with
435 // the debugger on make uninstall
438 if (Directory
.GetFiles (link_dir
).Length
== 0) {
439 WriteLine ("Cleaning package directory, it is empty.");
441 Directory
.Delete (link_dir
);
443 // Workaround: GetFiles does not list Symlinks
449 WriteLine ("Uninstalled: " + an
.FullName
);
452 if (Directory
.GetDirectories (asmdir
).Length
== 0) {
453 WriteLine ("Cleaning assembly dir, it is empty");
455 Directory
.Delete (asmdir
);
457 // Workaround: GetFiles does not list Symlinks
462 private static bool UninstallSpecific (string name
, string package
,
463 string gacdir
, string libdir
)
465 string failure_msg
= "Failure to remove assembly from the cache: ";
467 if (!File
.Exists (name
)) {
468 WriteLine (failure_msg
+ "The system cannot find the file specified.");
472 AssemblyName an
= null;
475 an
= AssemblyName
.GetAssemblyName (name
);
477 WriteLine (failure_msg
+ "The file specified is not a valid assembly.");
481 int uninstallCount
= 0;
482 int uninstallFailures
= 0;
483 Uninstall (an
.FullName
.Replace (" ", String
.Empty
),
484 package
, gacdir
, libdir
, true, ref uninstallCount
,
485 ref uninstallFailures
);
486 WriteLine ("Assemblies uninstalled = {0}", uninstallCount
);
487 WriteLine ("Failures = {0}", uninstallFailures
);
488 return (uninstallFailures
== 0);
491 private static void List (string name
, string gacdir
)
493 WriteLine ("The following assemblies are installed into the GAC:");
496 FilteredList (name
, gacdir
);
501 DirectoryInfo gacinfo
= new DirectoryInfo (gacdir
);
502 foreach (DirectoryInfo parent
in gacinfo
.GetDirectories ()) {
503 foreach (DirectoryInfo dir
in parent
.GetDirectories ()) {
504 string asmb
= Path
.Combine (Path
.Combine (parent
.FullName
, dir
.Name
), parent
.Name
) + ".dll";
505 if (File
.Exists (asmb
)) {
506 WriteLine (AsmbNameFromVersionString (parent
.Name
, dir
.Name
));
511 WriteLine ("Number of items = " + count
);
514 private static void FilteredList (string name
, string gacdir
)
516 string [] assembly_pieces
= name
.Split (new char[] { ',' }
);
517 Hashtable asm_info
= new Hashtable ();
519 foreach (string item
in assembly_pieces
) {
520 string[] pieces
= item
.Trim ().Split (new char[] { '=' }
, 2);
521 if(pieces
.Length
== 1)
522 asm_info
["assembly"] = pieces
[0];
524 asm_info
[pieces
[0].Trim ().ToLower (CultureInfo
.InvariantCulture
)] = pieces
[1];
527 string asmdir
= Path
.Combine (gacdir
, (string) asm_info
["assembly"]);
528 if (!Directory
.Exists (asmdir
)) {
529 WriteLine ("Number of items = 0");
532 string search
= GetSearchString (asm_info
);
533 string [] dir_list
= Directory
.GetDirectories (asmdir
, search
);
536 foreach (string dir
in dir_list
) {
537 string asmb
= Path
.Combine (dir
, (string) asm_info
["assembly"]) + ".dll";
538 if (File
.Exists (asmb
)) {
539 WriteLine (AsmbNameFromVersionString ((string) asm_info
["assembly"],
540 new DirectoryInfo (dir
).Name
));
544 WriteLine ("Number of items = " + count
);
547 private static bool InstallFromList (bool check_refs
, string list_file
, string package
,
548 string gacdir
, string link_gacdir
, string libdir
, string link_libdir
)
550 StreamReader s
= null;
551 int processed
, failed
;
552 string listdir
= Path
.GetDirectoryName (
553 Path
.GetFullPath (list_file
));
555 processed
= failed
= 0;
558 s
= new StreamReader (list_file
);
561 while ((line
= s
.ReadLine ()) != null) {
562 string file
= line
.Trim ();
563 if (file
.Length
== 0)
566 string assemblyPath
= Path
.Combine (listdir
,
569 if (!Install (check_refs
, assemblyPath
, package
, gacdir
,
570 link_gacdir
, libdir
, link_libdir
))
575 WriteLine ("Assemblies processed = {0}", processed
);
576 WriteLine ("Assemblies installed = {0}", processed
- failed
);
577 WriteLine ("Failures = {0}", failed
);
579 return (failed
== 0);
580 } catch (IOException
) {
581 WriteLine ("Failed to open assemblies list file " + list_file
+ ".");
589 private static bool UninstallFromList (string list_file
, string package
,
590 string gacdir
, string libdir
)
592 StreamReader s
= null;
593 int failed
, uninstalled
;
595 failed
= uninstalled
= 0;
598 s
= new StreamReader (list_file
);
601 while ((line
= s
.ReadLine ()) != null) {
602 string name
= line
.Trim ();
603 if (name
.Length
== 0)
605 Uninstall (line
, package
, gacdir
, libdir
,
606 true, ref uninstalled
, ref failed
);
609 WriteLine ("Assemblies processed = {0}", uninstalled
+failed
);
610 WriteLine ("Assemblies uninstalled = {0}", uninstalled
);
611 WriteLine ("Failures = {0}", failed
);
613 return (failed
== 0);
614 } catch (IOException
) {
615 WriteLine ("Failed to open assemblies list file " + list_file
+ ".");
623 private static bool CheckReferencedAssemblies (AssemblyName an
)
627 Assembly a
= Assembly
.LoadFrom (an
.CodeBase
);
628 AssemblyName corlib
= typeof (object).Assembly
.GetName ();
630 foreach (AssemblyName ref_an
in a
.GetReferencedAssemblies ()) {
631 if (ref_an
.Name
== corlib
.Name
) // Just do a string compare so we can install on diff versions
633 byte [] pt
= ref_an
.GetPublicKeyToken ();
634 if (pt
== null || pt
.Length
== 0) {
635 WriteLine ("Assembly " + ref_an
.Name
+ " is not strong named.");
639 } catch (Exception e
) {
640 WriteLine (e
.ToString ()); // This should be removed pre beta3
645 AppDomain
.Unload (d
);
653 private static string GetSearchString (Hashtable asm_info
)
655 if (asm_info
.Keys
.Count
== 1)
657 string version
, culture
, token
;
659 version
= asm_info
["version"] as string;
660 version
= (version
== null ? "*" : version
+ "*");
661 culture
= asm_info
["culture"] as string;
662 culture
= (culture
== null ? "*" : (culture
== "neutral") ? String
.Empty
: culture
.ToLower (CultureInfo
.InvariantCulture
));
663 token
= asm_info
["publickeytoken"] as string;
664 token
= (token
== null ? "*" : token
.ToLower (CultureInfo
.InvariantCulture
));
666 return String
.Format ("{0}_{1}_{2}", version
, culture
, token
);
669 private static string AsmbNameFromVersionString (string name
, string str
)
671 string [] pieces
= str
.Split ('_');
672 return String
.Format ("{0}, Version={1}, Culture={2}, PublicKeyToken={3}",
673 name
, pieces
[0], (pieces
[1] == String
.Empty
? "neutral" : pieces
[1]),
677 static bool LoadConfig (bool quiet
)
679 MethodInfo config
= typeof (System
.Environment
).GetMethod ("GetMachineConfigPath",
680 BindingFlags
.Static
| BindingFlags
.NonPublic
);
682 if (config
!= null) {
683 string path
= (string) config
.Invoke (null, null);
685 bool exist
= File
.Exists (path
);
686 if (!quiet
&& !exist
)
687 Console
.WriteLine ("Couldn't find machine.config");
689 StrongNameManager
.LoadConfig (path
);
692 Console
.WriteLine ("Couldn't resolve machine.config location (corlib issue)");
698 // modified copy from sn
699 private static VerificationResult
VerifyStrongName (AssemblyName an
, string assemblyFile
)
701 byte [] publicKey
= StrongNameManager
.GetMappedPublicKey (an
.GetPublicKeyToken ());
702 if ((publicKey
== null) || (publicKey
.Length
< 12)) {
704 publicKey
= an
.GetPublicKey ();
705 if ((publicKey
== null) || (publicKey
.Length
< 12))
706 return VerificationResult
.WeakNamed
;
709 // Note: MustVerify is based on the original token (by design). Public key
710 // remapping won't affect if the assembly is verified or not.
711 if (StrongNameManager
.MustVerify (an
)) {
712 RSA rsa
= CryptoConvert
.FromCapiPublicKeyBlob (publicKey
, 12);
713 StrongName sn
= new StrongName (rsa
);
714 if (sn
.Verify (assemblyFile
)) {
715 return VerificationResult
.StrongNamed
;
717 return VerificationResult
.DelaySigned
;
720 return VerificationResult
.Skipped
;
724 private static bool IsSwitch (string arg
)
726 return (arg
[0] == '-' || (arg
[0] == '/' && !arg
.EndsWith(".dll") && arg
.IndexOf('/', 1) < 0 ) );
729 private static Command
GetCommand (string arg
)
731 Command c
= Command
.Unknown
;
741 case "--install-from-list":
742 c
= Command
.InstallFromList
;
748 c
= Command
.Uninstall
;
752 case "--uninstall-from-list":
753 c
= Command
.UninstallFromList
;
757 case "--uninstall-specific":
758 c
= Command
.UninstallSpecific
;
774 [DllImport ("libc", SetLastError
=true)]
775 public static extern int symlink (string oldpath
, string newpath
);
777 private static string GetGacDir () {
778 PropertyInfo gac
= typeof (System
.Environment
).GetProperty ("GacPath",
779 BindingFlags
.Static
|BindingFlags
.NonPublic
);
781 WriteLine ("ERROR: Mono runtime not detected, please use " +
782 "the mono runtime for gacutil.exe");
783 Environment
.Exit (1);
785 MethodInfo get_gac
= gac
.GetGetMethod (true);
786 return (string) get_gac
.Invoke (null, null);
789 private static string GetLibDir () {
790 MethodInfo libdir
= typeof (System
.Environment
).GetMethod ("internalGetGacPath",
791 BindingFlags
.Static
|BindingFlags
.NonPublic
);
792 if (libdir
== null) {
793 WriteLine ("ERROR: Mono runtime not detected, please use " +
794 "the mono runtime for gacutil.exe");
795 Environment
.Exit (1);
797 return Path
.Combine ((string)libdir
.Invoke (null, null), "mono");
800 private static string GetStringToken (byte[] tok
)
802 StringBuilder sb
= new StringBuilder ();
803 for (int i
= 0; i
< tok
.Length
; i
++)
804 sb
.Append (tok
[i
].ToString ("x2"));
805 return sb
.ToString ();
808 private static string EnsureLib (string dir
)
810 DirectoryInfo d
= new DirectoryInfo (dir
);
813 return Path
.Combine (dir
, "lib");
816 private static void WriteLine ()
820 Console
.WriteLine ();
823 private static void WriteLine (string line
)
827 Console
.WriteLine (line
);
830 private static void WriteLine (string line
, params object [] p
)
834 Console
.WriteLine (line
, p
);
837 private static void Usage ()
840 Environment
.Exit (1);
843 private static void ShowHelp (bool detailed
)
845 WriteLine ("Usage: gacutil.exe <commands> [ <options> ]");
846 WriteLine ("Commands:");
848 WriteLine ("-i <assembly_path> [-check_refs] [-package NAME] [-root ROOTDIR] [-gacdir GACDIR]");
849 WriteLine ("\tInstalls an assembly into the global assembly cache.");
851 WriteLine ("\t<assembly_path> is the name of the file that contains the " +
852 "\tassembly manifest\n" +
853 "\tExample: -i myDll.dll");
857 WriteLine ("-il <assembly_list_file> [-check_refs] [-package NAME] [-root ROOTDIR] [-gacdir GACDIR]");
858 WriteLine ("\tInstalls one or more assemblies into the global assembly cache.");
860 WriteLine ("\t<assembly_list_file> is the path to a test file containing a list of\n" +
861 "\tassembly file paths on separate lines.\n" +
862 "\tExample -il assembly_list.txt\n" +
863 "\t\tassembly_list.txt contents:\n" +
864 "\t\tassembly1.dll\n" +
865 "\t\tassembly2.dll");
869 WriteLine ("-u <assembly_display_name> [-package NAME] [-root ROOTDIR] [-gacdir GACDIR]");
870 WriteLine ("\tUninstalls an assembly from the global assembly cache.");
872 WriteLine ("\t<assembly_display_name> is the name of the assembly (partial or\n" +
873 "\tfully qualified) to remove from the global assembly cache. If a \n" +
874 "\tpartial name is specified all matching assemblies will be uninstalled.\n" +
875 "\tExample: -u myDll,Version=1.2.1.0");
879 WriteLine ("-ul <assembly_list_file> [-package NAME] [-root ROOTDIR] [-gacdir GACDIR]");
880 WriteLine ("\tUninstalls one or more assemblies from the global assembly cache.");
882 WriteLine ("\t<assembly_list_file> is the path to a test file containing a list of\n" +
883 "\tassembly names on separate lines.\n" +
884 "\tExample -ul assembly_list.txt\n" +
885 "\t\tassembly_list.txt contents:\n" +
886 "\t\tassembly1,Version=1.0.0.0,Culture=en,PublicKeyToken=0123456789abcdef\n" +
887 "\t\tassembly2,Version=2.0.0.0,Culture=en,PublicKeyToken=0123456789abcdef");
891 WriteLine ("-us <assembly_path> [-package NAME] [-root ROOTDIR] [-gacdir GACDIR]");
892 WriteLine ("\tUninstalls an assembly using the specifed assemblies full name.");
894 WriteLine ("\t<assembly path> is the path to an assembly. The full assembly name\n" +
895 "\tis retrieved from the specified assembly if there is an assembly in\n" +
896 "\tthe GAC with a matching name, it is removed.\n" +
897 "\tExample: -us myDll.dll");
901 WriteLine ("-l [assembly_name] [-root ROOTDIR] [-gacdir GACDIR]");
902 WriteLine ("\tLists the contents of the global assembly cache.");
904 WriteLine ("\tWhen the <assembly_name> parameter is specified only matching\n" +
905 "\tassemblies are listed.");
910 WriteLine ("\tDisplays a detailed help screen");
916 WriteLine ("Options:");
917 WriteLine ("-package <NAME>");
918 WriteLine ("\tUsed to create a directory in prefix/lib/mono with the name NAME, and a\n" +
919 "\tsymlink is created from NAME/assembly_name to the assembly on the GAC.\n" +
920 "\tThis is used so developers can reference a set of libraries at once.");
923 WriteLine ("-gacdir <GACDIR>");
924 WriteLine ("\tUsed to specify the GACs base directory. Once an assembly has been installed\n" +
925 "\tto a non standard gacdir the MONO_GAC_PREFIX environment variable must be used\n" +
926 "\tto access the assembly.");
929 WriteLine ("-root <ROOTDIR>");
930 WriteLine ("\tUsed by developers integrating this with automake tools or packaging tools\n" +
931 "\tthat require a prefix directory to be specified. The root represents the\n" +
932 "\t\"libdir\" component of a prefix (typically prefix/lib).");
935 WriteLine ("-check_refs");
936 WriteLine ("\tUsed to ensure that the assembly being installed into the GAC does not\n" +
937 "\treference any non strong named assemblies. Assemblies being installed to\n" +
938 "\tthe GAC should not reference non strong named assemblies, however the is\n" +
939 "\tan optional check.");
942 WriteLine ("Ignored Options:");
944 WriteLine ("\tThe Mono gacutil ignores the -f option to maintain commandline compatibility with");
945 WriteLine ("\tother gacutils. gacutil will always force the installation of a new assembly.");
948 WriteLine ("-r <reference_scheme> <reference_id> <description>");
949 WriteLine ("\tThe Mono gacutil has not implemented traced references and will emit a warning");
950 WriteLine ("\twhen this option is used.");