[Adapdev-commits] Adapdev/src/Adapdev Adapdev.csproj,1.13,1.14 AppDomainManager.cs,1.4,1.5 AssemblyC
Status: Beta
Brought to you by:
intesar66
Update of /cvsroot/adapdev/Adapdev/src/Adapdev In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19977/src/Adapdev Added Files: Adapdev.csproj AppDomainManager.cs AssemblyCache.cs AssemblyInfo.cs CommandLineAliasAttribute.cs CommandLineParser.cs CommandLineSwitchAttribute.cs CommandLineSwitchInfo.cs CommandLineSwitchRecord.cs CompositeValidator.cs ICompositeValidator.cs IProgressCallback.cs IValidationRule.cs IValidator.cs LongLivingMarshalByRefObject.cs ObjectComparer.cs ObjectSorter.cs SortableCollectionBase.cs Util.cs ValidationResult.cs Log Message: Reposting to the repository after it got hosed --- NEW FILE: AppDomainManager.cs --- #region Copyright / License Information /* Copyright 2004 - 2005 Adapdev Technologies, LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ============================ Author Log ============================ III Full Name SMM Sean McCormack (Adapdev) ============================ Change Log ============================ III MMDDYY Change */ #endregion using System; using System.IO; using System.Reflection; using System.Runtime.Remoting; using System.Security.Permissions; using System.Security.Policy; using SecurityPermission = System.Security.Permissions.SecurityPermission; namespace Adapdev { using log4net; /// <summary> /// Summary description for Class1. /// </summary> /// public class AppDomainManager : LongLivingMarshalByRefObject { protected string domainName = String.Empty; protected AppDomain domain = null; protected string shadowCopyPath = AppDomain.CurrentDomain.BaseDirectory; protected AppDomainManager remote = null; protected DomainType domainType = DomainType.Local; protected string guid = String.Empty; protected bool unloaded = false; private string basedir = String.Empty; private string configFile = String.Empty; // create the logger private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); /// <summary> /// Creates a new <see cref="AppDomainManager"/> instance. /// </summary> public AppDomainManager() { domain = AppDomain.CurrentDomain; basedir = AppDomain.CurrentDomain.BaseDirectory; } /// <summary> /// Creates a new <see cref="AppDomainManager"/> instance. /// </summary> /// <param name="shadowCopyDirectories">Shadow copy directories.</param> public AppDomainManager(params string[] shadowCopyDirectories) : this(AppDomain.CurrentDomain.BaseDirectory, "Test", String.Empty, shadowCopyDirectories){} /// <summary> /// Creates a new <see cref="AppDomainManager"/> instance. /// </summary> /// <param name="basedir">Basedir.</param> /// <param name="configFile">Name of the configuration file to use.</param> /// <param name="shadowCopyDirectories">Shadow copy directories.</param> public AppDomainManager(string basedir, string configFile, params string[] shadowCopyDirectories) : this(basedir, "Test", configFile, shadowCopyDirectories){} /// <summary> /// Creates a new <see cref="AppDomainManager"/> instance. /// </summary> /// <param name="basedir">The base directory to use.</param> /// <param name="shadowCopyDirectories">Shadow copy directories.</param> public AppDomainManager(string basedir, params string[] shadowCopyDirectories) : this(basedir, "Test", shadowCopyDirectories){} /// <summary> /// Creates a new <see cref="AppDomainManager"/> instance. /// </summary> /// <param name="domainName">Name of the domain.</param> /// <param name="configurationFile">Configuration file.</param> /// <param name="shadowCopyDirectories">Shadow copy directories.</param> public AppDomainManager(string basedir, string domainName, string configurationFile, params string[] shadowCopyDirectories) { this.domainName = domainName; this.domainType = DomainType.Remote; this.configFile = configurationFile; if(log.IsDebugEnabled) log.Debug("Loading new AppDomainManager"); Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; Evidence evidence = new Evidence(baseEvidence); AppDomainSetup setup = new AppDomainSetup(); setup.ApplicationBase = basedir; setup.ApplicationName = "Test"; if(configurationFile.Length > 0) setup.ConfigurationFile = configurationFile; if(log.IsDebugEnabled) { log.Debug("ApplicationBase: " + setup.ApplicationBase); log.Debug("ApplicationName: " + setup.ApplicationName); log.Debug("ConfigurationFile: " + setup.ConfigurationFile); } if(shadowCopyDirectories != null && shadowCopyDirectories.Length >= 0) { guid = System.Guid.NewGuid().ToString(); setup.ShadowCopyFiles = "true"; setup.CachePath = this.GetCachePath(); foreach (string shadowCopyDirectory in shadowCopyDirectories) { string dir = String.Empty; if(File.Exists(shadowCopyDirectory)) { // if it's a file, grab the directory name FileInfo f = new FileInfo(shadowCopyDirectory); dir = f.DirectoryName; } else { dir = shadowCopyDirectory; } if(setup.ShadowCopyDirectories != null && setup.ShadowCopyDirectories.Length > 0) { setup.ShadowCopyDirectories += ";" + dir; } else { setup.ShadowCopyDirectories += dir; } } } domain = AppDomain.CreateDomain(this.domainName, evidence, setup); remote = (AppDomainManager)domain.CreateInstanceAndUnwrap(typeof(AppDomainManager).Assembly.FullName, typeof(AppDomainManager).FullName); } /// <summary> /// Adds the assembly. /// </summary> /// <param name="path">Path.</param> public void AddAssembly(string path) { string assemblyDirectory = Path.GetDirectoryName( path ); if(log.IsDebugEnabled)log.Debug("Adding " + path); if(this.domainType == DomainType.Local) { domain.AppendPrivatePath(assemblyDirectory); this.LoadAssembly(path); } else { domain.AppendPrivatePath(assemblyDirectory); remote.LoadAssembly(path); } } /// <summary> /// Adds the assemblies. /// </summary> /// <param name="paths">Paths.</param> public void AddAssemblies(params string[] paths) { foreach (string path in paths) { try { this.AddAssembly(path); } catch(FileNotFoundException){} } } /// <summary> /// Adds all the dlls in the directory to the AppDomain /// </summary> /// <param name="path">Path.</param> public void AddDirectory(string path) { foreach (string file in Directory.GetFiles(path)) { FileInfo f = new FileInfo(file); if(f.Extension == "dll") { this.AddAssembly(file); } } } /// <summary> /// Unloads the AppDomain. /// </summary> public void Unload() { if(!(this.domainName == String.Empty) && !unloaded) { if(log.IsDebugEnabled) { foreach(AssemblyInfo a in this.GetLoadedAssemblies()) { log.Debug("Unloading: " + a.Name + " - " + a.Version + " - " + a.Location); } } // Must unload AppDomain first, before you can delete the shadow copy directory AppDomain.Unload(this.domain); if(this.guid.Length > 0 && Directory.Exists(this.GetCachePath())) { Directory.Delete(this.GetCachePath(), true); } unloaded = true; if(log.IsDebugEnabled) log.Debug("Domain unloaded."); } } /// <summary> /// Gets the domain. /// </summary> /// <value></value> public AppDomain Domain { get { return domain; } } /// <summary> /// Loads the assembly. /// </summary> /// <param name="path">Path.</param> protected void LoadAssembly(string path) { AssemblyCache.Add(path.ToLower(), path); } /// <summary> /// Gets the loaded assemblies. /// </summary> public AssemblyInfo[] GetLoadedAssemblies() { AssemblyInfo[] ass = null; if(this.domainType == DomainType.Local){ ass = new AssemblyInfo[AppDomain.CurrentDomain.GetAssemblies().Length]; int i = 0; foreach (Assembly assembly in domain.GetAssemblies()) { try { AssemblyInfo ai = new AssemblyInfo(); ai.CodeBase = assembly.CodeBase; ai.FullName = assembly.FullName; ai.Location = assembly.Location; ai.Name = assembly.GetName().Name; ai.Version = assembly.GetName().Version.ToString(); ass[i] = ai; i++; } // In case it's a dynamic assembly, it can't be analyzed catch(Exception){} } }else { ass = remote.GetLoadedAssemblies(); } return ass; } /// <summary> /// Determines whether the specified path is loaded. /// </summary> /// <param name="path">Path.</param> /// <returns> /// <c>true</c> if the specified path is loaded; otherwise, <c>false</c>. /// </returns> public bool IsLoaded(string path) { if(this.domainType == DomainType.Local) return AssemblyCache.ContainsByPath(path); else return remote.IsLoaded(path); } /// <summary> /// Gets the cache path. /// </summary> /// <returns></returns> internal string GetCachePath() { if(guid.Length > 0) return Path.Combine(Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "zanebugcache"),guid); return String.Empty; } /// <summary> /// Gets the domain type. /// </summary> /// <value></value> public DomainType DomainType { get { return domainType; } } /// <summary> /// Gets the object by path. /// </summary> /// <param name="path">Path.</param> /// <param name="classname">Classname.</param> /// <returns></returns> public object GetObjectByPath(string path, string classname) { string filename = Path.GetFileNameWithoutExtension(path); return this.GetObjectByName(filename, classname); } /// <summary> /// Gets the object by name. /// </summary> /// <param name="name">Name.</param> /// <param name="classname">Classname.</param> /// <returns></returns> public object GetObjectByName(string name, string classname) { return domain.CreateInstanceAndUnwrap(name, classname); } public string ConfigurationFile { get{return this.configFile;} } } public enum DomainType { Local, Remote } } --- NEW FILE: ICompositeValidator.cs --- using System; namespace Adapdev { /// <summary> /// Summary description for IRuleValidatable. /// </summary> public interface ICompositeValidator : IValidator { void AddRule(IValidationRule rule); } } --- NEW FILE: LongLivingMarshalByRefObject.cs --- (This appears to be a binary file; contents omitted.) --- NEW FILE: SortableCollectionBase.cs --- // Copyright 2004 J. Ambrose - http://dotnettemplar.net/PermaLink.aspx?guid=1d32654f-9ed5-46e2-a815-4f70b762f734 using System; using System.Reflection; using System.CodeDom.Compiler; using Microsoft.CSharp; namespace Adapdev.Collections { /// <summary> /// Base class that provides T-SQL-like sorting capabilities. /// </summary> /// <remarks>This class is not thread safe; it depends on the /// underlying collection to remain static during sorting /// operations, therefore, use the <see cref="GetNewView"/> /// methods to get a shallow copy of the collection before /// attempting sort operations if the collection instance /// could be accessed by more than one thread in your /// application.</remarks> public class SortableCollectionBase : System.Collections.CollectionBase { #region Static Caches /// <summary> /// Comparer cache that stores instances of dynamically-created comparers. /// </summary> protected static System.Collections.Hashtable comparers = new System.Collections.Hashtable(100); /// <summary> /// Table for ensuring that we only generate a unique comparer once. /// </summary> protected static System.Collections.Hashtable comparerLocks = new System.Collections.Hashtable(10); /// <summary> /// Assembly path cache that stores the paths to the referenced assemblies /// to be used when compiling dynamically-created comparers. /// </summary> protected static System.Collections.Hashtable assemblyPaths = new System.Collections.Hashtable(10); #endregion #region GetNewView /// <summary> /// Gets a new <see cref="SortableCollectionBase"/> to /// provide a unique view of the underlying collection. /// </summary> /// <overload>Gets a view of the current collection.</overload> /// <returns>A new view of the underlying collection.</returns> /// <remarks>This would typically be used when needing to modify /// the collection for display purposes, such as sorting and the like. /// <p>It performs a shallow copy of the collection.</p></remarks> public SortableCollectionBase GetNewView() { SortableCollectionBase view = new SortableCollectionBase(); for (int i = 0; i < this.List.Count; i++) { view.List.Add(this.List[i]); } return view; } /// <summary> /// Gets a view of the current collection as /// the collection type specified. /// </summary> /// <overload>Gets a view of the current collection.</overload> /// <param name="collectionType">The type of collection to return.</param> /// <returns>A collection of the specified <i>collectionType</i> /// that contains a shallow copy of the items in this collection.</returns> /// <remarks> /// Constraints: A <see cref="NotSupportedException"/> will /// be thrown if any are not met. /// <ul> /// <li>The <i>collectionType</i> must implement a /// default constructor ("new" constraint).</li> /// <li>The <i>collectionType</i> must implement the /// <see cref="System.Collections.IList"/> interface.</li> /// </ul> /// </remarks> public System.Collections.IList GetNewView(System.Type collectionType) { return this.GetNewView(collectionType, null); } /// <summary> /// Gets a view of the current collection, sorted using the given <i>sortExpression</i>. /// </summary> /// <overload>Gets a view of the current collection.</overload> /// <param name="collectionType">The type of collection to return.</param> /// <param name="sortExpression"></param> /// <returns>A collection of the specified <i>collectionType</i> /// that contains a shallow copy of the items in this collection.</returns> /// <remarks> /// Constraints: A <see cref="NotSupportedException"/> will /// be thrown if any are not met. /// <ul> /// <li>The <i>collectionType</i> must implement a /// default constructor ("new" constraint).</li> /// <li>The <i>collectionType</i> must inherit from the /// <see cref="SortableCollectionBase"/> class.</li> /// </ul> /// </remarks> public System.Collections.IList GetNewView(System.Type collectionType, string sortExpression) { System.Reflection.ConstructorInfo ctor; // retrieve the property info for the specified property ctor = collectionType.GetConstructor(new System.Type[0]); if (ctor == null) throw new NotSupportedException( String.Format("The '{0}' type must have a public default constructor.", collectionType.FullName)); // get an instance of the collection type SortableCollectionBase view = ctor.Invoke(new object[] {}) as SortableCollectionBase; if (view == null) throw new NotSupportedException( String.Format("The '{0}' type must inherit from SortableCollectionBase.", collectionType.FullName)); for (int i = 0; i < this.List.Count; i++) view.InnerList.Add(base.List[i]); if (sortExpression != null) view.Sort(sortExpression); return view; } #endregion #region Sort /// <summary> /// Sorts the list by the given expression. /// </summary> /// <param name="sortExpression">A sort expression, e.g., MyProperty ASC, MyProp2 DESC.</param> /// <remarks> /// Valid sort expressions are comma-delimited lists of properties where each property /// can optionally be followed by a sort direction (ASC or DESC).<br /> /// Sort order is from left to right, i.e., properties to the left are sorted on first. /// <p>All properties sorted on must implement <see cref="IComparable"/> and meaningfully /// override <see cref="Object.Equals"/>.</p> /// <p>If <i>sortExpression</i> is null, an <see cref="ArgumentNullException"/> is thrown.<br /> /// If <i>sortExpression</i> is empty, an <see cref="ArgumentException"/> is thrown.<br /> /// Throws an <see cref="ApplicationException"/> if there are errors compiling the comparer /// or if a new instance of a dynamically-created comparer cannot be created /// for any of the sort properties.</p> /// <p>It is assumed that all objects in the collection are of the same type.</p> /// </remarks> public void Sort(string sortExpression) { #region Parameter Checks if (sortExpression == null) throw new ArgumentNullException("sortExpression", "Argument cannot be null."); #endregion this.InnerList.Sort(this.GetMultiComparer(this.List[0].GetType(), sortExpression)); } /// <summary> /// Gets an <see cref="System.Collections.IComparer"/> for the given type and sort expression. /// </summary> /// <param name="type">The type of object to be sorted.</param> /// <param name="sortExpression">A sort expression, e.g., MyProperty ASC, MyProp2 DESC.</param> /// <returns>An <see cref="System.Collections.IComparer"/> for the given type and sort expression.</returns> protected System.Collections.IComparer GetMultiComparer(System.Type type, string sortExpression) { // split the sort expression string by the commas string[] sorts = sortExpression.Split(','); // if no sorts are present, throw an exception if (sorts.Length == 0) throw new ArgumentException("No sorts were passed in the sort expression.", "sortExpression"); string typeName = type.FullName; // create a unique type name for the comparer based on the type and sort expression string comparerName = sortExpression.Replace(",", "").Replace(" ", "") + "Comparer", dynamicTypeName = typeName + "DynamicComparers." + comparerName; System.Collections.IComparer comparer = null; // check the comparers table for an existing comparer for this type and property if (!comparers.ContainsKey(dynamicTypeName)) // not found { object comparerLock; bool generate = false; // let threads pile up here waiting their turn to look at this collection lock (comparerLocks.SyncRoot) { // First, we see if the comparer lock for this // dynamicTypeName exists. comparerLock = comparerLocks[dynamicTypeName]; if (comparerLock == null) { // This is the first thread in here looking for this // dynamicTypeName, so it gets to be the one to // create the comparer for the dynamicTypeName. generate = true; // Add lock object for any future threads to see and // know that they won't need to generate the comparer. comparerLock = new object(); comparerLocks.Add(dynamicTypeName, comparerLock); } } // comparerLock will be unique per dynamicTypeName and, consequently, // per unique comparer. However, the code above only ensures // that only one thread will do the generation of the comparer. // We now need to lock the comparerLock for each dynamicTypeName to // make non generating threads wait on the thread that is doing the // generation, so we ensure that the comparer is generated for all // threads by the time we exit the following block. lock (comparerLock) { // This ensures only that first thread in actually does any generation. if (generate) { // declare the source code for the dynamic assembly string compareCode = @" using System; namespace [TypeName]DynamicComparers { public sealed class [ComparerName] : System.Collections.IComparer { public int Compare(object first, object second) { [TypeName] firstInstance = first as [TypeName]; if (firstInstance == null) throw new ArgumentNullException(""First object cannot be null."", ""first""); [TypeName] secondInstance = second as [TypeName]; if (secondInstance == null) throw new ArgumentNullException(""Second object cannot be null."", ""second""); int result = 0; [CompareCode] } } } "; System.Text.StringBuilder compareBuilder = new System.Text.StringBuilder(); string propertyName; bool desc; for (int sortIndex = 0; sortIndex < sorts.Length; sortIndex++) { // check current sort for null, continue if null if (sorts[sortIndex] == null) continue; // split current sort by space to distinguish property from asc/desc string[] sortValues = sorts[sortIndex].Trim().Split(' '); // if there are no values after split, leave -- should have at least the prop name if (sortValues.Length == 0) continue; // prop name will be first value propertyName = sortValues[0].Trim(); // ensure property exists on specified type PropertyInfo prop = type.GetProperty(propertyName); if (prop == null) throw new ArgumentException( String.Format("Specified property '{0}' is not a property of type '{1}'.", propertyName, type.FullName), "sortExpression"); // if there, the second will be asc/desc; compare to get whether or not this // sort is descending desc = (sortValues.Length > 1) ? (sortValues[1].Trim().ToUpper() == "DESC") : false; // if property type is reference type, we need to do null checking in the compare code bool checkForNull = !prop.PropertyType.IsValueType; // check for null if the property is a reference type if (checkForNull) compareBuilder.Append("\t\t\tif (firstInstance." + propertyName + " != null)\n\t"); // compare the property compareBuilder.Append("\t\t\tresult = firstInstance." + propertyName + ".CompareTo(secondInstance." + propertyName + ");"); // check for null on the second type, if necessary if (checkForNull) { // if second type is also null, return true; otherwise, the first instance is // less than the second because it is null compareBuilder.Append("\t\t\telse if (secondInstance." + propertyName + " == null)\n"); compareBuilder.Append("\t\t\t\tresult = 0; else result = -1;\n"); } // if the two are not equal, no further comparison is needed, just return the // current compare value and flip the sign, if the current sort is descending compareBuilder.Append("\t\t\tif (result !=0) return " + (desc ? "-" : "") + "(result);\n"); } // if all comparisons were equal, we'll need the next line to return that result compareBuilder.Append("\t\t\treturn result;"); // replace the type and comparer name placeholders in the source with real values // and insert the property comparisons compareCode = compareCode.Replace("[TypeName]", typeName).Replace("[ComparerName]", comparerName) .Replace("[CompareCode]", compareBuilder.ToString()); #if TRACE System.Diagnostics.Debug.WriteLine(compareCode); #endif // create a C# compiler instance ICodeCompiler compiler = new CSharpCodeProvider().CreateCompiler(); // create a compiler parameters collection CompilerParameters parameters = new CompilerParameters(); // add necessary assembly references for the source to compile string primeAssemblyPath = type.Assembly.Location.Replace("file:///", "").Replace("/", "\\"); parameters.ReferencedAssemblies.Add(primeAssemblyPath); foreach (System.Reflection.AssemblyName asm in type.Assembly.GetReferencedAssemblies()) parameters.ReferencedAssemblies.Add(this.GetAssemblyPath(asm)); // tell the compiler to generate the IL in memory parameters.GenerateInMemory = true; // compile the new dynamic assembly using the parameters and source from above CompilerResults compiled = compiler.CompileAssemblyFromSource(parameters, compareCode); // check for compiler errors if (compiled.Errors.HasErrors) { // build error message from compiler errors string message = "Could not generate a comparer for '{0}'. Errors:\n"; for (int i = 0; i < compiled.Errors.Count; i++) message += compiled.Errors[i].ErrorText + "\n"; // throw an exception with the relevant information throw new ApplicationException( String.Format(message, dynamicTypeName)); } // get an instance of the new type as IComparer comparer = compiled.CompiledAssembly.CreateInstance(dynamicTypeName) as System.Collections.IComparer; // throw an exception if getting the new instance fails if (comparer == null) throw new ApplicationException( String.Format("Could not instantiate the dynamic type '{0}'.", dynamicTypeName)); // add the new comparer to the comparers table lock (comparers) comparers.Add(dynamicTypeName, comparer); } // (generate) } // comparer lock } // comparers cache check // At this point, we should be sure that a comparer has been generated for the // requested dynamicTypeName and stuck in the cache. If we're the thread that // did the generating, comparer will not be null, and we can just return it. // If comparer hasn't been assigned (via generating it above), get it from the cache. if (comparer == null) { // get the comparer from the cache comparer = comparers[dynamicTypeName] as System.Collections.IComparer; // throw an exception if the comparer cannot be retrieved if (comparer == null) throw new ApplicationException( String.Format("Could not retrieve the dynamic type '{0}'.", dynamicTypeName)); } // return the comparer return comparer; } /// <summary> /// Loads the given assembly to get its path (for dynamic compilation reference). /// </summary> /// <param name="assembly">AssemblyName instance to load assembly from.</param> /// <returns>The path for the given assembly or an empty /// string if it can't load/locate it.</returns> protected string GetAssemblyPath(System.Reflection.AssemblyName assembly) { string assemblyFullName = assembly.FullName; string path = string.Empty; path = (string)assemblyPaths[assemblyFullName]; if (path == null) { lock (assemblyPaths.SyncRoot) { path = (string)assemblyPaths[assemblyFullName]; if (path == null) { System.Reflection.Assembly asm = System.Reflection.Assembly.Load(assembly); if (asm != null) { path = asm.Location.Replace("file:///", "").Replace("/", "\\"); } assemblyPaths.Add(assemblyFullName, path); } } } return path; } #endregion } } --- NEW FILE: IProgressCallback.cs --- // // This code based on functions from http://www.codeproject.com/cs/miscctrl/progressdialog.asp // Original Author: About Matthew Adams // using System; namespace Adapdev { public enum ProgressMessageTypes { Info, Warning, Critical }; public enum ProgressAutoCloseTypes {AutoClose, WaitOnEnd, WaitOnError} /// <summary> /// This defines an interface which can be implemented by UI elements /// which indicate the progress of a long operation. /// (See ProgressWindow for a typical implementation) /// </summary> public interface IProgressCallback { /// <summary> /// Call this method from the worker thread to initialize /// the progress callback. /// </summary> /// <param name="minimum">The minimum value in the progress range (e.g. 0)</param> /// <param name="maximum">The maximum value in the progress range (e.g. 100)</param> void Begin( int minimum, int maximum ); /// <summary> /// Call this method from the worker thread to initialize /// the progress callback. /// </summary> /// <param name="minimum">The minimum value in the progress range (e.g. 0)</param> /// <param name="maximum">The maximum value in the progress range (e.g. 100)</param> /// <param name="autoClose">Specify to automatically close on End or Pause on End</param> void Begin(ProgressAutoCloseTypes autoClose, int minimum, int maximum ); /// <summary> /// Call this method from the worker thread to initialize /// the progress callback, without setting the range /// </summary> void Begin(); /// <summary> /// Call this method to set the AutoClose flag. True mean to autoclose on completion /// (default) and false means to wait when closing. /// </summary> /// <param name="autoClose">Sets the flag</param> void SetAutoClose( ProgressAutoCloseTypes autoClose ); /// <summary> /// Call this method from the worker thread to reset the range in the progress callback /// </summary> /// <param name="minimum">The minimum value in the progress range (e.g. 0)</param> /// <param name="maximum">The maximum value in the progress range (e.g. 100)</param> /// <remarks>You must have called one of the Begin() methods prior to this call.</remarks> void SetRange( int minimum, int maximum ); /// <summary> /// Call this method from the worker thread to update the progress text. /// </summary> /// <param name="text1">The progress text to display</param> /// <remarks>You must have called one of the Begin() methods prior to this call.</remarks> void SetText( String text1, String text2 ); void SetText( String text ); /// <summary> /// Call this method to add a message to the list box of messages /// </summary> /// <param name="message"></param> void AddMessage( string message ); void AddMessage( ProgressMessageTypes type, string message ); /// <summary> /// Call this method from the worker thread to increase the progress counter by a specified value. /// </summary> /// <param name="val">The amount by which to increment the progress indicator</param> /// <remarks>You must have called one of the Begin() methods prior to this call.</remarks> void StepTo( int val ); /// <summary> /// Call this method from the worker thread to step the progress meter to a particular value. /// </summary> /// <param name="val">The value to which to step the meter</param> /// <remarks>You must have called one of the Begin() methods prior to this call.</remarks> void Increment( int val ); /// <summary> /// If this property is true, then you should abort work /// </summary> /// <remarks>You must have called one of the Begin() methods prior to this call.</remarks> bool IsAborting { get; } /// <summary> /// Call this method from the worker thread to finalize the progress meter /// </summary> /// <remarks>You must have called one of the Begin() methods prior to this call.</remarks> void End(); } } --- NEW FILE: CommandLineParser.cs --- // Original Copyright (c) 2003 Ray Hayes. http://www.codeproject.com/csharp/commandlineparser.asp #region Modified Copyright / License Information /* Copyright 2004 - 2005 Adapdev Technologies, LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ============================ Author Log ============================ III Full Name SMM Sean McCormack (Adapdev) ============================ Change Log ============================ III MMDDYY Change SMM 111504 Renamed class to CommandLineParser */ #endregion using System; using System.Text; using System.Reflection; using System.Text.RegularExpressions; namespace Adapdev { /// <summary> /// A command-line parsing class that is capable of having switches /// programatically registered with it; or, it can use reflection to /// find properties with the <see cref="CommandLineSwitchAttribute" /> /// </summary> public class CommandLineParser { #region Private Variables /// <summary> /// Command line on which the parser operates /// </summary> private string _commandLine = ""; /// <summary> /// String holding the part of the command line that did not match /// any switch definitions /// </summary> private string _workingString = ""; /// <summary> /// Name of the application parsed from the command line /// </summary> private string _applicationName = ""; /// <summary> /// Array of parameters (whitespace separated command line /// elements) parsed from the command line /// </summary> private string[] _splitParameters = null; /// <summary> /// Array of recognized switches parsed from the command line /// </summary> private System.Collections.ArrayList _switches = null; #endregion #region Private Utility Functions /// <summary> /// Extracts the application name from <see cref="_commandLine" /> /// and places it in <see cref="_applicationName" /> /// </summary> private void ExtractApplicationName() { Regex r = new Regex(@"^(?<commandLine>(""[^\""]+""|(\S)+))(?<remainder>.+)", RegexOptions.ExplicitCapture); Match m = r.Match(_commandLine); if ( m != null && m.Groups["commandLine"] != null ) { _applicationName = m.Groups["commandLine"].Value; _workingString = m.Groups["remainder"].Value; } } /// <summary> /// Extracts the parameters from <see cref="_commandLine" /> /// and places them in <see cref="_splitParameters" /> /// </summary> /// <remarks> /// If quotes are used, the quotes are removed but the text between /// the quotes is kept as a single parameter /// </remarks> /// <example>For example: /// if <c>_commandLine</c> has <c>one two three "four five six"</c> /// then <c>_splitParameters</c> would contain /// <list type="table"> /// <item> /// <term>_splitParameters[0]</term><description>one</description> /// </item> /// <item> /// <term>_splitParameters[1]</term><description>two</description> /// </item> /// <item> /// <term>_splitParameters[2]</term><description>three</description> /// </item> /// <item> /// <term>_splitParameters[3]</term><description>four five six</description> /// </item> /// </list> /// </example> private void SplitParameters() { // Populate the split parameters array with the remaining parameters. Regex r = new Regex(@"((\s*(""(?<param>.+?)""|(?<param>\S+))))", RegexOptions.ExplicitCapture); MatchCollection m = r.Matches( _workingString ); if ( m != null ) { _splitParameters = new string[ m.Count ]; for ( int i=0; i < m.Count; i++ ) _splitParameters[i] = m[i].Groups["param"].Value; } } /// <summary> /// Parses the command line looking for switches and setting their /// proper values /// </summary> private void HandleSwitches() { if ( _switches != null ) { foreach ( CommandLineSwitchRecord s in _switches ) { Regex r = new Regex( s.Pattern, RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase ); MatchCollection m = r.Matches( _workingString ); if ( m != null ) { for ( int i=0; i < m.Count; i++ ) { string value = null; if ( m[i].Groups != null && m[i].Groups["value"] != null ) value = m[i].Groups["value"].Value; if ( s.Type == typeof(bool)) { bool state = true; // The value string may indicate what value we want. if ( m[i].Groups != null && m[i].Groups["value"] != null ) { switch ( value ) { case "+": state = true; break; case "-": state = false; break; case "": if ( s.ReadValue != null ) state = !(bool)s.ReadValue; break; default: break; } } s.Notify( state ); break; } else if ( s.Type == typeof(string) ) s.Notify( value ); else if ( s.Type == typeof(int) ) s.Notify( int.Parse( value ) ); else if ( s.Type.IsEnum ) s.Notify( System.Enum.Parse(s.Type,value,true) ); } } _workingString = r.Replace(_workingString, " "); } } } #endregion #region Public Properties /// <summary> /// Gets the string holding the part of the command line that did not match /// any switch definitions /// </summary> public string UnhandledCommandLine { get { return _workingString.TrimStart(' '); } } /// <summary> /// Gets the name of the application parsed from the command line /// </summary> public string ApplicationName { get { return _applicationName; } } /// <summary> /// Gets an array of parameters (whitespace separated command line /// elements) parsed from the command line /// </summary> public string[] UnhandledParameters { get { return _splitParameters; } } /// <summary> /// Gets an array of recognized switches parsed from the command line /// </summary> public CommandLineSwitchInfo[] Switches { get { if ( _switches == null ) return null; else { CommandLineSwitchInfo[] si = new CommandLineSwitchInfo[ _switches.Count ]; for ( int i=0; i<_switches.Count; i++ ) si[i] = new CommandLineSwitchInfo( _switches[i] ); return si; } } } /// <summary> /// Gets the value of the switch at the specified index. /// </summary> public object this[string name] { get { if ( _switches != null ) for ( int i=0; i<_switches.Count; i++ ) if ( string.Compare( (_switches[i] as CommandLineSwitchRecord).Name, name, true )==0 ) return (_switches[i] as CommandLineSwitchRecord).Value; return null; } } /// <summary> /// Gets an array containing the switches the parser has /// recognized but have not been registered. /// </summary> /// <remark> /// The unhandled switches are not removed from the remainder /// of the command-line. /// </remark> public string[] UnhandledSwitches { get { string switchPattern = @"(\s|^)(?<match>(-{1,2}|/)(.+?))(?=(\s|$))"; Regex r = new Regex( switchPattern, RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase ); MatchCollection m = r.Matches( _workingString ); if ( m != null ) { string[] unhandled = new string[ m.Count ]; for ( int i=0; i < m.Count; i++ ) unhandled[i] = m[i].Groups["match"].Value; return unhandled; } else return new string[]{}; } } /// <summary> /// Gets a string that describes the command line usage /// based on the registered switches /// </summary> public string Usage { get { StringBuilder builder = new StringBuilder(); int oldLength; foreach ( CommandLineSwitchRecord s in _switches ) { oldLength = builder.Length; builder.Append(" /"); builder.Append(s.Name); Type valueType = s.Type; if (valueType == typeof(int)) { builder.Append(":<int>"); } else if (valueType == typeof(uint)) { builder.Append(":<uint>"); } else if (valueType == typeof(bool)) { builder.Append("[+|-]"); } else if (valueType == typeof(string)) { builder.Append(":<string>"); } else { builder.Append(":{"); bool first = true; foreach (FieldInfo field in valueType.GetFields()) { if (field.IsStatic) { if (first) first = false; else builder.Append('|'); builder.Append(field.Name); } } builder.Append('}'); } builder.Append("\r\n"); } oldLength = builder.Length; builder.Append(" @<file>"); builder.Append(' ', IndentLength(builder.Length - oldLength)); builder.Append("Read response file for more options"); builder.Append("\r\n"); return builder.ToString(); } } /// <summary> /// Computes the number of characters a line should be indented /// so that it is right justified at 40 characters. /// </summary> /// <remarks> /// If <paramref name="lineLength"/> is over 36 characters, the indent /// is simply set to four. /// </remarks> /// <param name="lineLength">Number of characters in the line</param> /// <returns>Number of spaces to indent</returns> private static int IndentLength(int lineLength) { return Math.Max(4, 40 - lineLength); } #endregion #region Public Methods /// <summary> /// Registers a switch with the command line parser /// </summary> /// <remarks> /// Switches named here should not include a switch prefix character /// such as a slash or minus. This is handled by the parser in /// <see cref="CommandLineSwitchRecord"/>. /// </remarks> /// <example>For example: /// <code> /// parser = new CommandLineParser(System.Environment.CommandLine); /// parser.AddSwitch(@"\?" , "show help"); /// parser.Parse(); /// </code> /// </example> /// <param name="name">The name of the switch.</param> /// <param name="description">Usage description for the switch.</param> public void AddSwitch( string name, string description ) { if ( _switches == null ) _switches = new System.Collections.ArrayList(); CommandLineSwitchRecord rec = new CommandLineSwitchRecord( name, description ); _switches.Add( rec ); } /// <summary> /// Registers an array of synonymous switches (aliases) with the /// command line parser /// </summary> /// <remarks> /// Switches named here should not include a switch prefix character /// such as a slash or minus. This is handled by the parser in /// <see cref="CommandLineSwitchRecord"/>. /// <para> /// The first switch in the array is considered to be the actual /// name of the switch while those that follow create the aliases /// for the switch /// </para> /// </remarks> /// <example>For example: /// <code> /// parser = new CommandLineParser(System.Environment.CommandLine); /// parser.AddSwitch(new string[] { "help", @"usage" }, "show help"); //Add a switch with an alias /// parser.Parse(); /// </code> /// </example> /// <param name="names">Name and aliases of the switch.</param> /// <param name="description">Usage description for the switch.</param> public void AddSwitch( string[] names, string description ) { if ( _switches == null ) _switches = new System.Collections.ArrayList(); CommandLineSwitchRecord rec = new CommandLineSwitchRecord( names[0], description ); for ( int s=1; s<names.Length; s++ ) rec.AddAlias( names[s] ); _switches.Add( rec ); } /// <summary> /// Parses the command line. /// </summary> public void Parse() { ExtractApplicationName(); // Remove switches and associated info. HandleSwitches(); // Split parameters. SplitParameters(); } /// <summary> /// Gets the value of the switch with the specified name /// </summary> /// <param name="name">Name of the switch</param> /// <returns>Value of the named switch</returns> public object InternalValue(string name) { if ( _switches != null ) for ( int i=0; i<_switches.Count; i++ ) if ( string.Compare( (_switches[i] as CommandLineSwitchRecord).Name, name, true )==0 ) return (_switches[i] as CommandLineSwitchRecord).InternalValue; return null; } #endregion #region Constructors /// <summary> /// Initializes a new instance of the CommandLineParser class /// </summary> /// <example>For example: /// <code> /// CommandLineParser clp = new CommandLineParser(System.Environment.CommandLine); /// clp.AddSwitch(@"\?","Show help message"); /// clp.Parse(); /// </code> /// </example> /// <param name="commandLine">The command line to parse when <see cref="Parse"/> is called.</param> public CommandLineParser( string commandLine ) { _commandLine = commandLine; } /// <summary> /// Initializes a new instance of the CommandLineParser class /// </summary> /// <example>For example: /// <code> /// class Class1 /// { /// private bool _bool; /// /// [CommandLineSwitch("bool","Provide boolean value")] /// [CommandLineAlias(new string [] {"boolean","b"})] /// public bool Bool /// { /// get { return _bool; } /// set { this._bool = value; } /// } /// /// [STAThread] /// static void Main(string[] args) /// { /// Class1 c = new Class1(); /// /// CommandLineParser clp = new CommandLineParser(System.Environment.CommandLine,c); /// clp.Parse(); /// /// Console.WriteLine("bool={0}",c.Bool); /// } /// } /// </code> /// </example> /// <param name="commandLine">The command line to parse when <see cref="Parse"/> is called.</param> /// <param name="classForAutoAttributes">The class that contains attributes from which switches are created.</param> public CommandLineParser( string commandLine, object classForAutoAttributes ) { _commandLine = commandLine; Type type = classForAutoAttributes.GetType(); System.Reflection.MemberInfo[] members = type.GetMembers(); for(int i=0; i<members.Length; i++) { object[] attributes = members[i].GetCustomAttributes(false); if(attributes.Length > 0) { CommandLineSwitchRecord rec = null; foreach ( Attribute attribute in attributes ) { if ( attribute is CommandLineSwitchAttribute ) { CommandLineSwitchAttribute switchAttrib = (CommandLineSwitchAttribute) attribute; // Get the property information. We're only handling // properties at the moment! if ( members[i] is System.Reflection.PropertyInfo ) { System.Reflection.PropertyInfo pi = (System.Reflection.PropertyInfo) members[i]; rec = new CommandLineSwitchRecord( switchAttrib.Name, switchAttrib.Description, pi.PropertyType ); // Map in the Get/Set methods. rec.SetMethod = pi.GetSetMethod(); rec.GetMethod = pi.GetGetMethod(); rec.PropertyOwner = classForAutoAttributes; // Can only handle a single switch for each property // (otherwise the parsing of aliases gets silly...) break; } } } // See if any aliases are required. We can only do this after // a switch has been registered and the framework doesn't make // any guarantees about the order of attributes, so we have to // walk the collection a second time. if ( rec != null ) { foreach ( Attribute attribute in attributes ) { if ( attribute is CommandLineAliasAttribute ) { CommandLineAliasAttribute aliasAttrib = (CommandLineAliasAttribute) attribute; foreach(string a in aliasAttrib.Alias) rec.AddAlias(a); } } } // Assuming we have a switch record (that may or may not have // aliases), add it to the collection of switches. if ( rec != null ) { if ( _switches == null ) _switches = new System.Collections.ArrayList(); _switches.Add( rec ); } } } } #endregion } } --- NEW FILE: Adapdev.csproj --- <VisualStudioProject> <CSHARP ProjectType = "Local" ProductVersion = "7.10.3077" SchemaVersion = "2.0" ProjectGuid = "{CC30A321-2569-4B1F-8E1A-781B5509B56D}" > <Build> <Settings ApplicationIcon = "" AssemblyKeyContainerName = "" AssemblyName = "Adapdev" AssemblyOriginatorKeyFile = "" DefaultClientScript = "JScript" DefaultHTMLPageLayout = "Grid" DefaultTargetSchema = "IE50" DelaySign = "false" OutputType = "Library" PreBuildEvent = "" PostBuildEvent = "" RootNamespace = "Adapdev" RunPostBuildEvent = "OnBuildSuccess" StartupObject = "" > <Config Name = "Debug" AllowUnsafeBlocks = "false" BaseAddress = "285212672" CheckForOverflowUnderflow = "false" ConfigurationOverrideFile = "" DefineConstants = "DEBUG;TRACE" DocumentationFile = "" DebugSymbols = "true" FileAlignment = "4096" IncrementalBuild = "false" NoStdLib = "false" NoWarn = "" Optimize = "false" OutputPath = "bin\Debug\" RegisterForComInterop = "false" RemoveIntegerChecks = "false" TreatWarningsAsErrors = "false" WarningLevel = "4" /> <Config Name = "Release" AllowUnsafeBlocks = "false" BaseAddress = "285212672" CheckForOverflowUnderflow = "false" ConfigurationOverrideFile = "" DefineConstants = "TRACE" DocumentationFile = "" DebugSymbols = "false" FileAlignment = "4096" IncrementalBuild = "false" NoStdLib = "false" NoWarn = "" Optimize = "true" OutputPath = "bin\Release\" RegisterForComInterop = "false" RemoveIntegerChecks = "false" TreatWarningsAsErrors = "false" WarningLevel = "4" /> </Settings> <References> <Reference Name = "System" AssemblyName = "System" HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll" /> <Reference Name = "System.Data" AssemblyName = "System.Data" HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll" /> <Reference Name = "System.XML" AssemblyName = "System.Xml" HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll" /> <Reference Name = "System.Runtime.Remoting" AssemblyName = "System.Runtime.Remoting" HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Runtime.Remoting.dll" /> <Reference Name = "System.Runtime.Serialization.Formatters.Soap" AssemblyName = "System.Runtime.Serialization.Formatters.Soap" HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Runtime.Serialization.Formatters.Soap.dll" /> <Reference Name = "Microsoft.VisualBasic" AssemblyName = "Microsoft.VisualBasic" HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\Microsoft.VisualBasic.dll" /> <Reference Name = "log4net" AssemblyName = "log4net" HintPath = "..\..\lib\log4net.dll" /> <Reference Name = "System.EnterpriseServices" AssemblyName = "System.EnterpriseServices" HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.EnterpriseServices.dll" /> </References> </Build> <Files> <Include> <File RelPath = "AdapdevAssemblyInfo.cs" Link = "..\AdapdevAssemblyInfo.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "AppDomainManager.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "AssemblyCache.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "AssemblyInfo.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "CommandLineAliasAttribute.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "CommandLineParser.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "CommandLineSwitchAttribute.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "CommandLineSwitchInfo.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "CommandLineSwitchRecord.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "CompositeValidator.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "ICompositeValidator.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "IProgressCallback.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "IValidationRule.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "IValidator.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "LongLivingMarshalByRefObject.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "ObjectComparer.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "ObjectSorter.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "SortableCollectionBase.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Util.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "ValidationResult.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Attributes\SchemaDataRewritableAttribute.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Commands\ICommand.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Cryptography\Crypto.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Cryptography\Decryptor.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Cryptography\DecryptTransformer.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Cryptography\EncryptionAlgorithm.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Cryptography\Encryptor.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Cryptography\EncryptTransformer.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Cryptography\Hasher.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Diagnostics\CPUMeter.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Diagnostics\HiPerfTimer.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Diagnostics\IPerfTimer.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Diagnostics\MillisecondsPerfTimer.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Diagnostics\MinutesPerfTimer.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Diagnostics\PerfTimerFactory.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Diagnostics\SecondsPerfTimer.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Diagnostics\TicksPerfTimer.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "IO\FileUtil.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "IO\FileWatcher.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Mock\SuppliersEntity.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Reflection\ClassAccessor.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Reflection\ClassAccessorCache.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Reflection\FieldAccessor.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Reflection\FieldAccessorException.cs" SubType = "Code" BuildAction = "Compile" /> <File RelPath = "Reflection\IV... [truncated message content] |