3 // Author: Todd Berman <tberman@gentoo.org>
5 // (C) 2003 Todd Berman
10 using System.Reflection;
11 using System.Collections;
19 private string gac_path = "/usr/lib/mono/gac/";
21 public static void Main (string[] args)
23 Driver d = new Driver ();
27 public void Run (string[] args)
29 if (args.Length == 0) {
34 if (args[0] == "/user" || args[0] == "--user") {
35 //FIXME: Need to check machine.config to make sure this is legal (potential security hole)
36 gac_path = Path.Combine (Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.Personal), ".mono"), "gac");
37 gac_path += Path.DirectorySeparatorChar;
39 string[] stripped = new string[args.Length - 1];
40 Array.Copy (args, 1, stripped, 0, args.Length - 1);
44 string[] remainder_args = new string[args.Length - 1];
46 if (args.Length >= 2) {
47 Array.Copy (args, 1, remainder_args, 0, args.Length - 1);
57 InstallAssembly (remainder_args);
61 ListAssemblies (remainder_args);
65 UninstallAssemblies (remainder_args);
68 case "--install-from-list":
69 InstallAssembliesFromList (remainder_args);
72 case "--uninstall-from-list":
73 UninstallAssembliesFromList (remainder_args);
81 public void InstallAssembliesFromList (string[] args)
83 if (args.Length == 0) {
84 Console.WriteLine ("ERROR: need a file passed");
88 if (!File.Exists (args[0])) {
89 Console.WriteLine ("ERROR: file '" + args[0] + "' does not exist");
93 string[] perFile = args;
95 using (StreamReader s = File.OpenText (args[0])) {
98 while((line = s.ReadLine()) != null) {
100 InstallAssembly (perFile);
105 public void UninstallAssembliesFromList (string[] args)
107 if (args.Length == 0) {
108 Console.WriteLine ("ERROR: file must be passed.");
112 if (!File.Exists (args[0])) {
113 Console.WriteLine ("ERROR: file '" + args[0] + "' does not exist");
117 using (StreamReader s = File.OpenText (args[0])) {
120 while ((line = s.ReadLine ()) != null) {
121 UninstallAssemblies (new string[] { line } );
126 public void UninstallAssemblies (string[] args)
128 if(args.Length == 0) {
129 Console.WriteLine ("ERROR: need an argument to uninstall");
133 string joinedArgs = String.Join ("", args);
135 string[] assemblyPieces = joinedArgs.Split(new char[] { ',' });
137 Hashtable paramInfo = new Hashtable ();
139 foreach (string item in assemblyPieces) {
140 string[] pieces = item.Trim ().Split (new char[] { '=' }, 2);
141 if(pieces.Length == 1)
142 paramInfo["assembly"] = pieces[0];
144 paramInfo[pieces[0].ToLower ()] = pieces[1];
147 if (!Directory.Exists (Path.Combine (gac_path, (string) paramInfo["assembly"]))) {
148 Console.WriteLine ("ERROR: Assembly not in gac.");
152 string searchString = (string) paramInfo["assembly"] + Path.DirectorySeparatorChar;
154 if (paramInfo.Keys.Count != 1) {
155 if (paramInfo["version"] != null) {
156 searchString += (string) paramInfo["version"] + "*";
162 string[] directories = Directory.GetDirectories (gac_path, searchString);
164 foreach (string dir in directories) {
165 Hashtable info = GetAssemblyInfo (Path.Combine (dir, "__AssemblyInfo__"));
166 if(Convert.ToInt32 (info["RefCount"]) == 1) {
167 Directory.Delete (dir, true);
168 Console.WriteLine ("Assembly removed from the gac.");
170 info["RefCount"] = ((int) Convert.ToInt32 (info["RefCount"]) - 1).ToString ();
171 WriteAssemblyInfo (Path.Combine (dir, "__AssemblyInfo__"), info);
172 Console.WriteLine ("Assembly was not deleted because its still needed by other applications");
175 if(Directory.GetDirectories (Path.Combine (gac_path, (string) paramInfo["assembly"])).Length == 0) {
176 Console.WriteLine ("Cleaning assembly dir, its empty");
177 Directory.Delete (Path.Combine (gac_path, (string) paramInfo["assembly"]));
182 public void ListAssemblies (string[] args)
184 Console.WriteLine ("The following assemblies are installed into the GAC:");
185 DirectoryInfo d = new DirectoryInfo (gac_path);
186 foreach (DirectoryInfo namedDir in d.GetDirectories ()) {
187 foreach (DirectoryInfo assemblyDir in namedDir.GetDirectories ()) {
188 Hashtable assemblyInfo = GetAssemblyInfo (Path.Combine (assemblyDir.FullName, "__AssemblyInfo__"));
189 Console.WriteLine ("\t" + assemblyInfo["DisplayName"]);
194 private Hashtable GetAssemblyInfo (string filename)
196 Hashtable infoHash = new Hashtable ();
197 using (StreamReader s = new StreamReader (filename)) {
200 while ((line = s.ReadLine ()) != null) {
201 string[] splitStr = line.Split (new char[] { '=' }, 2);
202 infoHash[splitStr[0]] = splitStr[1];
208 private void WriteAssemblyInfo (string filename, Hashtable info)
210 using (StreamWriter s = File.CreateText (filename)) {
211 foreach (string key in info.Keys) {
212 s.WriteLine (key + "=" + (string) info[key]);
217 public void InstallAssembly (string[] args)
219 if(args.Length == 0) {
220 Console.WriteLine ("ERROR: You must specify a valid assembly name after the install switch");
224 if(!File.Exists (args[0])) {
225 Console.WriteLine ("ERROR: The assembly: '" + args[0] + "' does not exist");
229 AssemblyName an = AssemblyName.GetAssemblyName (args[0]);
231 byte[] pub_tok = an.GetPublicKeyToken ();
233 if (pub_tok == null || pub_tok.Length == 0) {
234 Console.WriteLine ("ERROR: assembly has no valid public key token");
238 //FIXME: need to ensure strongly named here.
242 if(args.Length == 2 && (args[1] == "/f" || args[1] == "--force"))
246 string version_token = an.Version + "__" + GetStringToken (an.GetPublicKeyToken ());
248 string fullPath = String.Format ("{0}{3}{1}{3}{2}{3}", gac_path, an.Name, version_token, Path.DirectorySeparatorChar);
250 if (File.Exists (fullPath + an.Name + ".dll") && force == false) {
251 Hashtable assemInfo = GetAssemblyInfo (fullPath + "__AssemblyInfo__");
252 assemInfo["RefCount"] = ((int) Convert.ToInt32 (assemInfo["RefCount"]) + 1).ToString ();
253 WriteAssemblyInfo (fullPath + "__AssemblyInfo__", assemInfo);
254 Console.WriteLine ("RefCount of assembly '" + an.Name + "' increased by one.");
258 if(!EnsureDirectories (an.Name, version_token)) {
259 Console.WriteLine ("ERROR: gac directories could not be created, possibly permission issues");
263 File.Copy (args[0], fullPath + an.Name + ".dll", force);
265 Hashtable info = new Hashtable ();
267 info["DisplayName"] = an.FullName;
268 info["RefCount"] = 1.ToString ();
270 WriteAssemblyInfo (fullPath + "__AssemblyInfo__", info);
272 Console.WriteLine ("Assembly installed into the gac");
275 private bool EnsureDirectories (string name, string tok)
277 //FIXME: Workaround for broken DirectoryInfo.CreateSubdirectory
279 DirectoryInfo d = new DirectoryInfo (gac_path);
281 d.CreateSubdirectory (name);
282 d = new DirectoryInfo (Path.Combine (gac_path, name));
283 d.CreateSubdirectory (tok);
290 private string GetStringToken (byte[] tok)
292 StringBuilder sb = new StringBuilder ();
293 for (int i = 0; i < tok.Length ; i++) {
294 sb.Append (tok[i].ToString ("x2"));
296 return sb.ToString ();
299 public void ShowHelp (bool detailed)
301 Console.WriteLine ("help placeholder");