2 // RegistryKey.cs: a single node in the Windows registry
5 // Miguel de Icaza (miguel@ximian.com)
6 // Erik LeBel (eriklebel@yahoo.ca)
10 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Collections;
35 using System.Diagnostics;
36 using System.Runtime.InteropServices;
37 using System.Security;
40 namespace Microsoft.Win32
43 /// Wrapper class for Windows Registry Entry.
45 public sealed class RegistryKey : MarshalByRefObject, IDisposable
48 // This represents the backend data, used when creating the
53 string qname; // the fully qualified registry key name
54 bool isRoot; // is the an instance of a root key?
56 static readonly IRegistryApi RegistryApi;
60 if (Path.DirectorySeparatorChar == '\\')
61 RegistryApi = new Win32RegistryApi ();
63 RegistryApi = new UnixRegistryApi ();
67 /// Construct an instance of a root registry key entry.
69 internal RegistryKey (RegistryHive hiveId, string keyName)
77 /// Construct an instance of a registry key entry.
79 internal RegistryKey (object data, string keyName)
89 /// Dispose of registry key object. Close the
90 /// key if it's still open.
92 void IDisposable.Dispose ()
95 GC.SuppressFinalize (this);
100 /// Final cleanup of registry key object. Close the
101 /// key if it's still open.
110 /// Get the fully qualified registry key name.
113 get { return qname; }
118 /// Flush the current registry state to disk.
122 RegistryApi.Flush (this);
127 /// Close the current registry key. This may not
128 /// flush the state of the registry right away.
135 RegistryApi.Close (this);
141 /// get the number of sub-keys for this key
143 public int SubKeyCount {
145 AssertKeyStillValid ();
147 return RegistryApi.SubKeyCount (this);
153 /// get the number of values for this key
155 public int ValueCount {
157 AssertKeyStillValid ();
159 return RegistryApi.ValueCount (this);
165 /// Set a registry value.
167 public void SetValue (string name, object value)
169 AssertKeyStillValid ();
172 throw new ArgumentNullException ();
175 throw new UnauthorizedAccessException ();
177 RegistryApi.SetValue (this, name, value);
182 /// Open the sub key specified, for read access.
184 public RegistryKey OpenSubKey (string keyName)
186 return OpenSubKey (keyName, false);
191 /// Open the sub key specified.
193 public RegistryKey OpenSubKey (string keyName, bool writtable)
195 AssertKeyStillValid ();
196 AssertKeyNameNotNull (keyName);
198 return RegistryApi.OpenSubKey (this, keyName, writtable);
203 /// Get a registry value.
205 public object GetValue (string name)
207 return RegistryApi.GetValue (this, name, false, null);
212 /// Get a registry value.
214 public object GetValue (string name, object defaultValue)
216 AssertKeyStillValid ();
218 return RegistryApi.GetValue (this, name, true, defaultValue);
223 /// Create a sub key.
225 [MonoTODO("RegistryPermission")]
226 public RegistryKey CreateSubKey (string subkey)
228 AssertKeyStillValid ();
229 AssertKeyNameNotNull (subkey);
230 if (subkey.Length > 255)
231 throw new ArgumentException ("keyName length is larger than 255 characters", subkey);
232 return RegistryApi.CreateSubKey (this, subkey);
237 /// Delete the specified subkey.
239 public void DeleteSubKey(string subkey)
241 DeleteSubKey (subkey, true);
246 /// Delete the specified subkey.
248 public void DeleteSubKey(string subkey, bool throwOnMissingSubKey)
250 AssertKeyStillValid ();
251 AssertKeyNameNotNull (subkey);
253 RegistryKey child = OpenSubKey (subkey);
256 if (throwOnMissingSubKey)
257 throw new ArgumentException ("key missing: " + subkey, "subkey");
261 if (child.SubKeyCount > 0){
262 throw new InvalidOperationException ("key " + subkey + " has sub keys");
267 RegistryApi.DeleteKey (this, subkey, throwOnMissingSubKey);
272 /// Delete a sub tree (node, and values alike).
274 public void DeleteSubKeyTree(string keyName)
276 // Note: this is done by deleting sub-nodes recursively.
277 // The preformance is not very good. There may be a
278 // better way to implement this.
280 AssertKeyStillValid ();
281 AssertKeyNameNotNull (keyName);
283 RegistryKey child = OpenSubKey (keyName, true);
285 throw new ArgumentException ("key " + keyName + " at " + Name);
287 child.DeleteChildKeysAndValues ();
289 DeleteSubKey (keyName, false);
294 /// Delete a value from the registry.
296 public void DeleteValue(string value)
298 DeleteValue (value, true);
303 /// Delete a value from the registry.
305 public void DeleteValue(string value, bool shouldThrowWhenKeyMissing)
307 AssertKeyStillValid ();
308 AssertKeyNameNotNull (value);
310 RegistryApi.DeleteValue (this, value, shouldThrowWhenKeyMissing);
315 /// Get the names of the sub keys.
317 public string[] GetSubKeyNames()
319 AssertKeyStillValid ();
321 return RegistryApi.GetSubKeyNames (this);
326 /// Get the names of values contained in this key.
328 public string[] GetValueNames()
330 AssertKeyStillValid ();
331 return RegistryApi.GetValueNames (this);
336 public static RegistryKey OpenRemoteBaseKey(RegistryHive hKey,string machineName)
338 throw new NotImplementedException ();
343 /// Build a string representation of the registry key.
344 /// Conatins the fully qualified key name, and the Hex
345 /// representation of the registry key handle.
347 public override string ToString()
349 return RegistryApi.ToString (this);
352 #endregion // PublicAPI
356 /// validate that the registry key handle is still usable.
358 private void AssertKeyStillValid ()
361 throw new ObjectDisposedException ("Microsoft.Win32.RegistryKey");
366 /// validate that the registry key handle is still usable, and
367 /// that the 'subKeyName' is not null.
369 private void AssertKeyNameNotNull (string subKeyName)
371 if (subKeyName == null)
372 throw new ArgumentNullException ();
377 /// Utility method to delelte a key's sub keys and values.
378 /// This method removes a level of indirection when deleting
381 private void DeleteChildKeysAndValues ()
386 string[] subKeys = GetSubKeyNames ();
387 foreach (string subKey in subKeys)
389 RegistryKey sub = OpenSubKey (subKey, true);
390 sub.DeleteChildKeysAndValues ();
392 DeleteSubKey (subKey, false);
395 string[] values = GetValueNames ();
396 foreach (string value in values) {
397 DeleteValue (value, false);
402 /// decode a byte array as a string, and strip trailing nulls
404 static internal string DecodeString (byte[] data)
406 string stringRep = Encoding.Unicode.GetString (data);
407 int idx = stringRep.IndexOf ('\0');
409 stringRep = stringRep.Substring (0, idx);