2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.Collections.Generic;
20 using System.Runtime.InteropServices;
22 namespace Tizen.Applications
25 /// Represents the control message to exchange between applications.
29 /// public class AppControlExample : UIApplication
32 /// protected override void OnAppControlReceived(AppControlReceivedEventArgs e)
34 /// AppControl appControl = new AppControl();
35 /// appControl.ApplicationId = "org.tizen.calculator";
36 /// AppControl.SendLaunchRequest(appControl, (launchRequest, replyRequest, result) => {
43 public class AppControl
45 private const string LogTag = "Tizen.Applications";
47 private static Dictionary<int, Interop.AppControl.ReplyCallback> s_replyNativeCallbackMaps = new Dictionary<int, Interop.AppControl.ReplyCallback>();
48 private static int s_replyNativeCallbackId = 0;
50 private readonly SafeAppControlHandle _handle;
52 private string _operation = null;
53 private string _mime = null;
54 private string _uri = null;
55 private string _category = null;
56 private string _applicationId = null;
57 private ExtraDataCollection _extraData = null;
60 /// Initializes the instance of the AppControl class.
62 /// <exception cref="InvalidOperationException">Thrown when failed to create AppControl handle.</exception>
65 Interop.AppControl.ErrorCode err = Interop.AppControl.Create(out _handle);
66 if (err != Interop.AppControl.ErrorCode.None)
68 throw new InvalidOperationException("Failed to create the appcontrol handle. Err = " + err);
73 /// Initializes the instance of the AppControl class with parameter.
75 /// <param name="enableAppStartedResultEvent">The flag value to receive an additional launch result event on launch request.</param>
76 /// <exception cref="InvalidOperationException">Thrown when failed to create AppControl handle.</exception>
77 public AppControl(bool enableAppStartedResultEvent)
79 Interop.AppControl.ErrorCode err = Interop.AppControl.Create(out _handle);
80 if (err != Interop.AppControl.ErrorCode.None)
82 throw new InvalidOperationException("Failed to create the appcontrol handle. Err = " + err);
85 if (enableAppStartedResultEvent)
87 err = Interop.AppControl.EnableAppStartedResultEvent(_handle);
88 if (err != Interop.AppControl.ErrorCode.None)
90 throw new InvalidOperationException("Failed to set EnableAppStartedResultEvent");
96 /// Initializes the instance of the AppControl class with the SafeAppControlHandle.
98 /// <param name="handle"></param>
99 public AppControl(SafeAppControlHandle handle)
103 throw new ArgumentNullException("handle");
106 Interop.AppControl.ErrorCode err = Interop.AppControl.DangerousClone(out _handle, handle.DangerousGetHandle());
107 if (err != Interop.AppControl.ErrorCode.None)
109 throw new InvalidOperationException("Failed to clone the appcontrol handle. Err = " + err);
113 private AppControl(IntPtr handle)
115 Interop.AppControl.ErrorCode err = Interop.AppControl.DangerousClone(out _handle, handle);
116 if (err != Interop.AppControl.ErrorCode.None)
118 throw new InvalidOperationException("Failed to clone the appcontrol handle. Err = " + err);
122 #region Public Properties
125 /// Gets the SafeAppControlHandle instance.
127 public SafeAppControlHandle SafeAppControlHandle
136 /// Gets and sets the operation to be performed.
139 /// The operation is the mandatory information for the launch request. If the operation is not specified,
140 /// AppControlOperations.Default is used for the launch request. If the operation is AppControlOperations.Default,
141 /// the package information is mandatory to explicitly launch the application.
142 /// (if the operation is null for setter, it clears the previous value.)
146 /// AppControl appControl = new AppControl();
147 /// appControl.Operation = AppControlOperations.Default;
148 /// Log.Debug(LogTag, "Operation: " + appControl.Operation);
151 public string Operation
155 if (String.IsNullOrEmpty(_operation))
157 Interop.AppControl.ErrorCode err = Interop.AppControl.GetOperation(_handle, out _operation);
158 if (err != Interop.AppControl.ErrorCode.None)
160 Log.Warn(LogTag, "Failed to get the operation from the appcontrol. Err = " + err);
167 Interop.AppControl.ErrorCode err = Interop.AppControl.SetOperation(_handle, value);
168 if (err == Interop.AppControl.ErrorCode.None)
174 Log.Warn(LogTag, "Failed to set the operation to the appcontrol. Err = " + err);
180 /// Gets and sets the explicit MIME type of the data.
183 /// (if the mime is null for setter, it clears the previous value.)
187 /// AppControl appControl = new AppControl();
188 /// appControl.Mime = "image/jpg";
189 /// Log.Debug(LogTag, "Mime: " + appControl.Mime);
196 if (String.IsNullOrEmpty(_mime))
198 Interop.AppControl.ErrorCode err = Interop.AppControl.GetMime(_handle, out _mime);
199 if (err != Interop.AppControl.ErrorCode.None)
201 Log.Warn(LogTag, "Failed to get the mime from the appcontrol. Err = " + err);
208 Interop.AppControl.ErrorCode err = Interop.AppControl.SetMime(_handle, value);
209 if (err == Interop.AppControl.ErrorCode.None)
215 Log.Warn(LogTag, "Failed to set the mime to the appcontrol. Err = " + err);
221 /// Gets and sets the URI of the data.
224 /// Since Tizen 2.4, if the parameter 'uri' is started with 'file://' and
225 /// it is a regular file in this application's data path which can be obtained
226 /// by property DataPath in ApplicationInfo class,
227 /// it will be shared to the callee application.
228 /// Framework will grant a temporary permission to the callee application for this file and
229 /// revoke it when the callee application is terminated.
230 /// The callee application can just read it.
231 /// (if the uri is null for setter, it clears the previous value.)
235 /// public class AppControlExample : UIApplication
238 /// protected override void OnAppControlReceived(AppControlReceivedEventArgs e)
241 /// AppControl appControl = new AppControl();
242 /// appContrl.Uri = this.ApplicationInfo.DataPath + "image.jpg";
243 /// Log.Debug(LogTag, "Set Uri: " + appControl.Uri);
252 if (String.IsNullOrEmpty(_uri))
254 Interop.AppControl.ErrorCode err = Interop.AppControl.GetUri(_handle, out _uri);
255 if (err != Interop.AppControl.ErrorCode.None)
257 Log.Warn(LogTag, "Failed to get the uri from the appcontrol. Err = " + err);
264 Interop.AppControl.ErrorCode err = Interop.AppControl.SetUri(_handle, value);
265 if (err == Interop.AppControl.ErrorCode.None)
271 Log.Warn(LogTag, "Failed to set the uri to the appcontrol. Err = " + err);
277 /// Gets and sets the explicit category.
280 /// (if the category is null for setter, it clears the previous value.)
282 public string Category
286 if (String.IsNullOrEmpty(_category))
288 Interop.AppControl.ErrorCode err = Interop.AppControl.GetCategory(_handle, out _category);
289 if (err != Interop.AppControl.ErrorCode.None)
291 Log.Warn(LogTag, "Failed to get the category from the appcontrol. Err = " + err);
298 Interop.AppControl.ErrorCode err = Interop.AppControl.SetCategory(_handle, value);
299 if (err == Interop.AppControl.ErrorCode.None)
305 Log.Warn(LogTag, "Failed to set the category to the appcontrol. Err = " + err);
311 /// Gets and sets the application id to explicitly launch.
314 /// (if the application id is null for setter, it clears the previous value.)
318 /// AppControl appControl = new AppControl();
319 /// appControl.ApplicationId = "org.tizen.calculator";
320 /// Log.Debug(LogTag, "ApplicationId: " + appControl.ApplicationId);
323 public string ApplicationId
327 if (String.IsNullOrEmpty(_applicationId))
329 Interop.AppControl.ErrorCode err = Interop.AppControl.GetAppId(_handle, out _applicationId);
330 if (err != Interop.AppControl.ErrorCode.None)
332 Log.Warn(LogTag, "Failed to get the application id from the AppControl. Err = " + err);
335 return _applicationId;
339 Interop.AppControl.ErrorCode err = Interop.AppControl.SetAppId(_handle, value);
340 if (err == Interop.AppControl.ErrorCode.None)
342 _applicationId = value;
346 Log.Warn(LogTag, "Failed to set the application id to the AppControl. Err = " + err);
352 /// Gets and sets the launch mode of the application.
355 /// Although LaunchMode were set as AppControlLaunchMode.Group,
356 /// callee application would be launched as single mode
357 /// if the manifest file of callee application defined the launch mode as "single".
358 /// This property can just set the preference of caller application to launch an application.
359 /// Sub-applications which were launched as group mode always have own process.
360 /// Since Tizen 3.0, if launch mode not set in the caller app control,
361 /// this property returns AppControlLaunchMode.Single launch mode.
365 /// AppControl appControl = new AppControl();
366 /// appControl.LaunchMode = AppControlLaunchMode.Group;
369 public AppControlLaunchMode LaunchMode
374 Interop.AppControl.ErrorCode err = Interop.AppControl.GetLaunchMode(_handle, out value);
375 if (err != Interop.AppControl.ErrorCode.None)
377 Log.Warn(LogTag, "Failed to get the LaunchMode from the AppControl. Err = " + err);
379 return (AppControlLaunchMode)value;
383 Interop.AppControl.ErrorCode err = Interop.AppControl.SetLaunchMode(_handle, (int)value);
384 if (err != Interop.AppControl.ErrorCode.None)
386 Log.Warn(LogTag, "Failed to set the LaunchMode to the AppControl. Err = " + err);
392 /// Gets the collection of the extra data.
395 /// Extra data for communication between AppControls.
399 /// AppControl appControl = new AppControl();
400 /// appControl.ExtraData.Add("key", "value");
404 public ExtraDataCollection ExtraData
408 if (_extraData == null)
409 _extraData = new ExtraDataCollection(_handle);
414 #endregion // Public Properties
417 /// Retrieves all applications that can be launched to handle the given app_control request.
419 /// <param name="control">The AppControl</param>
420 /// <returns>ApplicationIds</returns>
421 /// <exception cref="InvalidOperationException">Thrown when failed because of invalid parameter</exception>
424 /// IEnumerable<string> applicationIds = AppControl.GetMatchedApplicationIds(control);
425 /// if (applicationIds != null)
427 /// foreach (string id in applicationIds)
434 public static IEnumerable<string> GetMatchedApplicationIds(AppControl control)
438 throw new ArgumentNullException("control");
441 List<string> ids = new List<string>();
442 Interop.AppControl.AppMatchedCallback callback = (handle, applicationId, userData) =>
444 if (applicationId == null)
449 ids.Add(applicationId);
453 Interop.AppControl.ErrorCode err = Interop.AppControl.ForeachAppMatched(control._handle, callback, IntPtr.Zero);
454 if (err != Interop.AppControl.ErrorCode.None)
456 throw new InvalidOperationException("Failed to get matched application ids. err = " + err);
463 /// Sends the launch request.
466 /// The operation is mandatory information for the launch request.
467 /// If the operation is not specified, AppControlOperations.Default is used by default.
468 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application. \n
469 /// Since Tizen 2.4, the launch request of the service application over out of packages is restricted by the platform.
470 /// Also, implicit launch requests are NOT delivered to service applications since 2.4.
471 /// To launch a service application, an explicit launch request with application ID given by property ApplicationId MUST be sent.
473 /// <param name="launchRequest">The AppControl</param>
474 /// <exception cref="ArgumentNullException">Thrown when failed because of a null arguament</exception>
475 /// <exception cref="InvalidOperationException">Thrown when failed because of invalid operation</exception>
476 /// <exception cref="TimeoutException">Thrown when failed because of timeout</exception>
477 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
480 /// AppControl appControl = new AppControl();
481 /// appControl.ApplicationId = "org.tizen.calculator";
482 /// AppControl.SendLaunchRequest(appControl);
485 public static void SendLaunchRequest(AppControl launchRequest)
487 SendLaunchRequest(launchRequest, null);
491 /// Sends the launch request.
494 /// The operation is mandatory information for the launch request.
495 /// If the operation is not specified, AppControlOperations.Default is used by default.
496 /// If the operation is AppControlOperations.Default, the application ID is mandatory to explicitly launch the application. \n
497 /// Since Tizen 2.4, the launch request of the service application over out of packages is restricted by the platform.
498 /// Also, implicit launch requests are NOT delivered to service applications since 2.4.
499 /// To launch a service application, an explicit launch request with application ID given by property ApplicationId MUST be sent.
501 /// <param name="launchRequest">The AppControl</param>
502 /// <param name="replyAfterLaunching">The callback function to be called when the reply is delivered</param>
503 /// <exception cref="ArgumentException">Thrown when failed because of arguament is invalid</exception>
504 /// <exception cref="InvalidOperationException">Thrown when failed because of invalid operation</exception>
505 /// <exception cref="TimeoutException">Thrown when failed because of timeout</exception>
506 /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
509 /// AppControl appControl = new AppControl();
510 /// appControl.ApplicationId = "org.tizen.calculator";
511 /// AppControl.SendLaunchRequest(appControl, (launchRequest, replyRequest, result) => {
516 public static void SendLaunchRequest(AppControl launchRequest, AppControlReplyCallback replyAfterLaunching)
518 if (launchRequest == null)
520 throw new ArgumentNullException("launchRequest");
523 Interop.AppControl.ErrorCode err;
525 if (replyAfterLaunching != null)
528 lock (s_replyNativeCallbackMaps)
530 id = s_replyNativeCallbackId++;
531 s_replyNativeCallbackMaps[id] = (launchRequestHandle, replyRequestHandle, result, userData) =>
533 if (replyAfterLaunching != null)
535 Log.Debug(LogTag, "Reply Callback is launched");
536 replyAfterLaunching(new AppControl(launchRequestHandle), new AppControl(replyRequestHandle), (AppControlReplyResult)result);
537 if (result != Interop.AppControl.AppStartedStatus)
539 lock (s_replyNativeCallbackMaps)
541 s_replyNativeCallbackMaps.Remove(id);
547 err = Interop.AppControl.SendLaunchRequest(launchRequest._handle, s_replyNativeCallbackMaps[id], IntPtr.Zero);
551 err = Interop.AppControl.SendLaunchRequest(launchRequest._handle, null, IntPtr.Zero);
554 if (err != Interop.AppControl.ErrorCode.None)
558 case Interop.AppControl.ErrorCode.InvalidParameter:
559 throw new ArgumentException("Invalid Arguments");
560 case Interop.AppControl.ErrorCode.TimedOut:
561 throw new TimeoutException("Timed out");
563 throw new InvalidOperationException("Error = " + err);
569 /// Sends the terminate request to the application that is launched by AppControl.
572 /// You are not allowed to terminate other general applications using this API.
573 /// This API can be used to terminate sub-applications which were launched as group mode by caller application.
574 /// Once callee application is being terminated by this API,
575 /// other applications which were launched by callee application as group mode will be terminated as well
577 /// <param name="terminateRequest">The AppControl</param>
578 /// <exception cref="ArgumentException">Thrown when failed because of arguament is invalid</exception>
579 /// <exception cref="InvalidOperationException">Thrown when failed because of invalid operation</exception>
580 /// <exception cref="TimeoutException">Thrown when failed because of timeout</exception>
583 /// AppControl terminateRequest = new AppControl();
584 /// terminateRequest.ApplicationId = "org.tizen.calculator";
585 /// AppControl.SendTerminateRequest(terminateRequest);
588 public static void SendTerminateRequest(AppControl terminateRequest)
590 if (terminateRequest == null)
592 throw new ArgumentNullException("terminateRequest");
594 Interop.AppControl.ErrorCode err;
596 err = Interop.AppControl.SendTerminateRequest(terminateRequest._handle);
598 if (err != Interop.AppControl.ErrorCode.None)
602 case Interop.AppControl.ErrorCode.InvalidParameter:
603 throw new ArgumentException("Invalid Arguments");
604 case Interop.AppControl.ErrorCode.TimedOut:
605 throw new TimeoutException("Timed out");
607 throw new InvalidOperationException("Error = " + err);
613 /// Class for Extra Data
615 public class ExtraDataCollection
617 private readonly SafeAppControlHandle _handle;
619 internal ExtraDataCollection(SafeAppControlHandle handle)
628 /// The function replaces any existing value for the given key.
630 /// <param name="key">The name of the extra data</param>
631 /// <param name="value">The value associated with the given key</param>
632 /// <exception cref="ArgumentNullException">Thrown when key or value is a zero-length string</exception>
633 /// <exception cref="ArgumentException">Thrown when the application tries to use the same key with system-defined key</exception>
636 /// AppControl appControl = new AppControl();
637 /// appControl.ExtraData.Add("myKey", "myValue");
640 public void Add(string key, string value)
642 if (string.IsNullOrEmpty(key))
644 throw new ArgumentNullException("key");
646 if (string.IsNullOrEmpty(value))
648 throw new ArgumentNullException("value");
650 Interop.AppControl.ErrorCode err = Interop.AppControl.AddExtraData(_handle, key, value);
651 if (err != Interop.AppControl.ErrorCode.None)
655 case Interop.AppControl.ErrorCode.InvalidParameter:
656 throw new ArgumentException("Invalid parameter: key or value is a zero-length string");
657 case Interop.AppControl.ErrorCode.KeyRejected:
658 throw new ArgumentException("Key is rejected: the key is system-defined key.");
660 throw new InvalidOperationException("Error = " + err);
669 /// The function replaces any existing value for the given key.
671 /// <param name="key">The name of the extra data</param>
672 /// <param name="value">The value associated with the given key</param>
673 /// <exception cref="ArgumentNullException">Thrown when key or value is a zero-length string</exception>
674 /// <exception cref="ArgumentException">Thrown when the application tries to use the same key with system-defined key</exception>
677 /// AppControl appControl = new AppControl();
678 /// string[] myValues = new string[] { "first", "second", "third" };
679 /// appControl.ExtraData.Add("myKey", myValues);
682 public void Add(string key, IEnumerable<string> value)
684 if (string.IsNullOrEmpty(key))
686 throw new ArgumentNullException("key");
690 throw new ArgumentNullException("value");
692 string[] valueArray = value.ToArray();
693 Interop.AppControl.ErrorCode err = Interop.AppControl.AddExtraDataArray(_handle, key, valueArray, valueArray.Length);
694 if (err != Interop.AppControl.ErrorCode.None)
698 case Interop.AppControl.ErrorCode.InvalidParameter:
699 throw new ArgumentException("Invalid parameter: key or value is a zero-length string");
700 case Interop.AppControl.ErrorCode.KeyRejected:
701 throw new ArgumentException("Key is rejected: the key is system-defined key.");
703 throw new InvalidOperationException("Error = " + err);
709 /// Gets the extra data.
711 /// <typeparam name="T">Only string and IEnumerable<string></typeparam>
712 /// <param name="key">The name of extra data</param>
713 /// <returns>The value associated with the given key</returns>
714 /// <exception cref="ArgumentNullException">Thrown when the key is invalid parameter</exception>
715 /// <exception cref="KeyNotFoundException">Thrown when the key is not found</exception>
716 /// <exception cref="ArgumentException">Thrown when the key is rejected</exception>
719 /// AppControl appControl = new AppControl();
720 /// string myValue = appControl.ExtraData.Get<string>("myKey");
723 public T Get<T>(string key)
725 object ret = Get(key);
730 /// Gets the extra data.
732 /// <param name="key">The name of extra data</param>
733 /// <returns>The value associated with the given key</returns>
734 /// <exception cref="ArgumentNullException">Thrown when the key is invalid parameter</exception>
735 /// <exception cref="KeyNotFoundException">Thrown when the key is not found</exception>
736 /// <exception cref="ArgumentException">Thrown when the key is rejected</exception>
739 /// AppControl appControl = new AppControl();
740 /// string myValue = appControl.ExtraData.Get("myKey") as string;
741 /// if (myValue != null)
747 public object Get(string key)
749 if (IsCollection(key))
751 return GetDataCollection(key);
760 /// Gets all keys in extra data.
762 /// <returns>The keys in the AppControl</returns>
763 /// <exception cref="InvalidOperationException">Thrown when invalid parameter</exception>
766 /// AppControl appControl = new AppControl();
767 /// IEnumerable<string> keys = appControl.GetKeys();
768 /// if (keys != null)
770 /// foreach (string key in keys)
777 public IEnumerable<string> GetKeys()
779 List<string> keys = new List<string>();
780 Interop.AppControl.ExtraDataCallback callback = (handle, key, userData) =>
791 Interop.AppControl.ErrorCode err = Interop.AppControl.ForeachExtraData(_handle, callback, IntPtr.Zero);
792 if (err != Interop.AppControl.ErrorCode.None)
794 throw new InvalidOperationException("Failed to get keys. err = " + err);
801 /// Tries getting the extra data.
803 /// <param name="key">The name of extra data</param>
804 /// <param name="value">The value associated with the given key</param>
805 /// <returns>The result whether getting the value is done</returns>
806 /// <exception cref="ArgumentNullException">Thrown when the key is invalid parameter</exception>
807 /// <exception cref="KeyNotFoundException">Thrown when the key is not found</exception>
808 /// <exception cref="ArgumentException">Thrown when the key is rejected</exception>
811 /// AppControl appControl = new AppControl();
812 /// string myValue = string.Empty;
813 /// bool result = appControl.ExtraData.TryGet("myKey", out myValue);
814 /// if (result != null)
820 public bool TryGet(string key, out string value)
822 if (string.IsNullOrEmpty(key))
824 throw new ArgumentNullException("key");
826 Interop.AppControl.GetExtraData(_handle, key, out value);
833 value = default(string);
839 /// Tries getting the extra data.
841 /// <param name="key">The name of extra data</param>
842 /// <param name="value">The value associated with the given key</param>
843 /// <returns>The result whether getting the value is done</returns>
844 /// <exception cref="ArgumentNullException">Thrown when the key is invalid parameter</exception>
845 /// <exception cref="KeyNotFoundException">Thrown when the key is not found</exception>
846 /// <exception cref="ArgumentException">Thrown when the key is rejected</exception>
849 /// AppControl appControl = new AppControl();
850 /// IEnumerable<string> myValue = null;
851 /// bool result = appControl.ExtraData.TryGet("myKey", out myValue);
854 /// foreach (string value in myValue)
861 public bool TryGet(string key, out IEnumerable<string> value)
863 if (string.IsNullOrEmpty(key))
865 throw new ArgumentNullException("key");
867 IntPtr valuePtr = IntPtr.Zero;
869 Interop.AppControl.ErrorCode err = Interop.AppControl.GetExtraDataArray(_handle, key, out valuePtr, out len);
870 if (err == Interop.AppControl.ErrorCode.None && valuePtr != IntPtr.Zero)
872 List<string> stringList = new List<string>();
873 for (int i = 0; i < len; ++i)
875 IntPtr charArr = Marshal.ReadIntPtr(valuePtr, IntPtr.Size * i);
876 stringList.Add(Marshal.PtrToStringAnsi(charArr));
877 Interop.Libc.Free(charArr);
879 Interop.Libc.Free(valuePtr);
885 value = default(IEnumerable<string>);
891 /// Removes the extra data.
893 /// <param name="key">The name of the extra data</param>
894 /// <exception cref="ArgumentNullException">Thrown when the key is a zero-length string</exception>
895 /// <exception cref="KeyNotFoundException">Thrown when the key is not found</exception>
896 /// <exception cref="ArgumentException">Thrown when the key is rejected</exception>
899 /// AppControl appControl = new AppControl();
900 /// appControl.ExtraData.Remove("myKey");
903 public void Remove(string key)
905 if (string.IsNullOrEmpty(key))
907 throw new ArgumentNullException("key");
909 Interop.AppControl.ErrorCode err = Interop.AppControl.RemoveExtraData(_handle, key);
910 if (err != Interop.AppControl.ErrorCode.None)
914 case Interop.AppControl.ErrorCode.InvalidParameter:
915 throw new ArgumentException("Invalid parameter: key is a zero-length string");
916 case Interop.AppControl.ErrorCode.KeyNotFound:
917 throw new KeyNotFoundException("Key is not found"); ;
918 case Interop.AppControl.ErrorCode.KeyRejected:
919 throw new ArgumentException("Key is rejected: the key is system-defined key.");
921 throw new InvalidOperationException("Error = " + err);
927 /// Counts keys in the extra data.
929 /// <returns>The number of counting keys</returns>
930 /// <exception cref="InvalidOperationException">Thrown when invalid parameter</exception>
933 /// AppControl appControl = new AppControl();
934 /// int numberOfKeys = appControl.ExtraData.Count();
939 return GetKeys().Count();
943 /// Checks whether the extra data associated with the given key is of collection data type.
945 /// <param name="key">The name of the extra data</param>
946 /// <returns>If true the extra data is of array data type, otherwise false</returns>
947 /// <exception cref="ArgumentNullException">Thrown when the key is a zero-length string</exception>
948 /// <exception cref="InvalidOperationException">Thrown when failed to check the key</exception>
951 /// AppControl appControl = new AppControl();
952 /// bool result = appControl.ExtraData.IsCollection("myKey");
955 public bool IsCollection(string key)
957 if (string.IsNullOrEmpty(key))
959 throw new ArgumentNullException("key");
961 bool isArray = false;
962 Interop.AppControl.ErrorCode err = Interop.AppControl.IsExtraDataArray(_handle, key, out isArray);
963 if (err != Interop.AppControl.ErrorCode.None)
965 throw new InvalidOperationException("Error = " + err);
970 private string GetData(string key)
972 if (string.IsNullOrEmpty(key))
974 throw new ArgumentNullException("key");
976 string value = string.Empty;
977 Interop.AppControl.ErrorCode err = Interop.AppControl.GetExtraData(_handle, key, out value);
978 if (err != Interop.AppControl.ErrorCode.None)
982 case Interop.AppControl.ErrorCode.InvalidParameter:
983 throw new ArgumentException("Invalid parameter: key is a zero-length string");
984 case Interop.AppControl.ErrorCode.KeyNotFound:
985 throw new KeyNotFoundException("Key is not found"); ;
986 case Interop.AppControl.ErrorCode.InvalidDataType:
987 throw new ArgumentException("Invalid data type: value is data collection type");
988 case Interop.AppControl.ErrorCode.KeyRejected:
989 throw new ArgumentException("Key is rejected: the key is system-defined key.");
991 throw new InvalidOperationException("Error = " + err);
997 private IEnumerable<string> GetDataCollection(string key)
999 if (string.IsNullOrEmpty(key))
1001 throw new ArgumentNullException("key");
1003 IntPtr valuePtr = IntPtr.Zero;
1005 Interop.AppControl.ErrorCode err = Interop.AppControl.GetExtraDataArray(_handle, key, out valuePtr, out len);
1006 if (err != Interop.AppControl.ErrorCode.None)
1010 case Interop.AppControl.ErrorCode.InvalidParameter:
1011 throw new ArgumentException("Invalid parameter: key is a zero-length string");
1012 case Interop.AppControl.ErrorCode.KeyNotFound:
1013 throw new KeyNotFoundException("Key is not found"); ;
1014 case Interop.AppControl.ErrorCode.InvalidDataType:
1015 throw new ArgumentException("Invalid data type: value is data collection type");
1016 case Interop.AppControl.ErrorCode.KeyRejected:
1017 throw new ArgumentException("Key is rejected: the key is system-defined key.");
1019 throw new InvalidOperationException("Error = " + err);
1023 List<string> valueArray = new List<string>();
1024 if (valuePtr != IntPtr.Zero)
1026 for (int i = 0; i < len; ++i)
1028 IntPtr charArr = Marshal.ReadIntPtr(valuePtr, IntPtr.Size * i);
1029 valueArray.Add(Marshal.PtrToStringAnsi(charArr));
1030 Interop.Libc.Free(charArr);
1032 Interop.Libc.Free(valuePtr);