diff --git a/docs/workflow/resources.md b/docs/workflow/resources.md index ef8323d73..e222e0680 100644 --- a/docs/workflow/resources.md +++ b/docs/workflow/resources.md @@ -10,7 +10,13 @@ We are using our own `Start-ResGen` to generate them. Usually it's called as part of the regular build with ``` -Start-PSBuild -ResGen +PS C:\> Start-PSBuild -ResGen +``` + +If you see compilation errors related to resources, try to call `Start-ResGen` explicitly. + +``` +PS C:\> Start-ResGen ``` ## Editing resx files @@ -20,3 +26,16 @@ It will try to create `.cs` files for you and you will get whole bunch of hard-t To edit resource file, use any **plain text editor**. Resource file is a simple xml, and it's easy to edit. + + +## Convert txt resource files into resx + +`dotnet cli` doesn't support embeeding old-fashioned txt resource. +You can do a one-time convertion of `.txt` resources into `.resx` files with a helper function + +``` +# example, converting all .txt resources under src\Microsoft.WSMan.Management\resources +PS C:\> Convert-TxtResourceToXml -Path src\Microsoft.WSMan.Management\resources +``` + +`.resx` files would be placed next to `.txt` files. diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/AssemblyInfo.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/AssemblyInfo.cs new file mode 100644 index 000000000..c745d8b81 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/AssemblyInfo.cs @@ -0,0 +1,16 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +using System.Diagnostics; +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly:AssemblyFileVersionAttribute("1.0.0.0")] +[assembly:AssemblyVersion("1.0.0.0")] + +[assembly:InternalsVisibleTo("Microsoft.Windows.DSC.CoreConfProviders,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] +[assembly:InternalsVisibleTo("Microsoft.Management.Infrastructure.CimCmdlets.Test,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] +//This is equal to Debuggable(true,true) which enables IsJITTracking and Disable Optimization. CoreCLR does not have constructor Debuggable(true,true) +[assembly: Debuggable(DebuggableAttribute.DebuggingModes.DisableOptimizations)] diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/BinaryMiLogBase.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/BinaryMiLogBase.cs new file mode 100644 index 000000000..fa841f3d2 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/BinaryMiLogBase.cs @@ -0,0 +1,201 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Management.Automation; + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + public abstract class BinaryMiLogBase : PSCmdlet + { + internal const string Noun = "BinaryMiLog"; + + internal BinaryMiLogBase() + { + } + + [Parameter(Mandatory = true, Position = 0)] + [ValidateNotNullOrEmpty] + public string Path { get; set; } + + #region Path utilities copied from internal admin/monad/src/utils/PathUtils.cs + + /* command.Context.ProviderNames.FileSystem is internal */ + private const string FileSystemProviderName = "FileSystem"; + + private static string ResolveFilePath(string filePath, PSCmdlet command, bool isLiteralPath) + { + string path = null; + + try + { + ProviderInfo provider = null; + PSDriveInfo drive = null; + List filePaths = new List(); + + if (isLiteralPath) + { + filePaths.Add(command.SessionState.Path.GetUnresolvedProviderPathFromPSPath(filePath, out provider, out drive)); + } + else + { + filePaths.AddRange(command.SessionState.Path.GetResolvedProviderPathFromPSPath(filePath, out provider)); + } + + /* command.Context.ProviderNames.FileSystem is internal */ + if (!provider.Name.Equals(FileSystemProviderName, StringComparison.OrdinalIgnoreCase)) + { + ReportWrongProviderType(command, provider.Name); + } + + if (filePaths.Count > 1) + { + ReportMultipleFilesNotSupported(command); + } + if (filePaths.Count == 0) + { + ReportWildcardingFailure(command, filePath); + } + + path = filePaths[0]; + } + catch (ItemNotFoundException) + { + if (!isLiteralPath) + { + return ResolveFilePath(filePath, command, isLiteralPath: true); + } + else + { + throw; + } + } + return path; + } + + internal string GetVerifiedFilePath(FileAccess fileAccess) + { + string resolvedPath = ResolveFilePath(this.Path, this, isLiteralPath: false); + + try + { + FileMode fileMode; + FileShare fileShare; + switch (fileAccess) + { + case FileAccess.Read: + fileMode = FileMode.Open; + fileShare = FileShare.Read; + break; + case FileAccess.Write: + fileMode = FileMode.Create; + fileShare = FileShare.None; + break; + default: + throw new ArgumentOutOfRangeException("fileAccess"); + } + + using (new FileStream(resolvedPath, fileMode, fileAccess, fileShare)) + { + /* open and immediately close the file - to get exception in PowerShell style; + * obviously there is a race here - we can still get error from mibincodec.dll later on */ + } + } + catch (ArgumentException e) + { + // NOTE: this call will throw + ReportFileOpenFailure(this, resolvedPath, e); + } + catch (IOException e) + { + // NOTE: this call will throw + ReportFileOpenFailure(this, resolvedPath, e); + } + catch (UnauthorizedAccessException e) + { + // NOTE: this call will throw + ReportFileOpenFailure(this, resolvedPath, e); + } + catch (NotSupportedException e) + { + // NOTE: this call will throw + ReportFileOpenFailure(this, resolvedPath, e); + } + catch (System.Security.SecurityException e) + { + // NOTE: this call will throw + ReportFileOpenFailure(this, resolvedPath, e); + } + + return resolvedPath; + } + + private static void ReportFileOpenFailure(Cmdlet cmdlet, string filePath, Exception e) + { + ErrorRecord errorRecord = new ErrorRecord( + e, + "FileOpenFailure", + ErrorCategory.OpenError, + null); + + cmdlet.ThrowTerminatingError(errorRecord); + } + + + internal static void ReportWrongProviderType(Cmdlet cmdlet, string providerId) + { + string msg = string.Format( + CultureInfo.InvariantCulture, /* providerId is culture invariant */ + Strings.ReadWriteFileNotFileSystemProvider, + providerId); + + var errorRecord = new ErrorRecord ( + new InvalidOperationException(msg), + "ReadWriteFileNotFileSystemProvider", + ErrorCategory.InvalidArgument, + null); + + errorRecord.ErrorDetails = new ErrorDetails(msg); + cmdlet.ThrowTerminatingError(errorRecord); + } + + internal static void ReportMultipleFilesNotSupported(Cmdlet cmdlet) + { + string msg = Strings.MultipleFilesNotSupported; + + var errorRecord = new ErrorRecord ( + new InvalidOperationException(msg), + "ReadWriteMultipleFilesNotSupported", + ErrorCategory.InvalidArgument, + null); + + errorRecord.ErrorDetails = new ErrorDetails(msg); + cmdlet.ThrowTerminatingError(errorRecord); + } + + internal static void ReportWildcardingFailure(Cmdlet cmdlet, string filePath) + { + string msg = string.Format( + CultureInfo.InvariantCulture, /* filePath is culture invariant */ + Strings.DidNotResolveFile, + filePath); + + var errorRecord = new ErrorRecord ( + new FileNotFoundException(msg), + "FileOpenFailure", + ErrorCategory.OpenError, + filePath); + + errorRecord.ErrorDetails = new ErrorDetails(msg); + cmdlet.ThrowTerminatingError(errorRecord); + } + + #endregion + + } +} diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimAsyncOperation.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimAsyncOperation.cs new file mode 100644 index 000000000..ac2221334 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimAsyncOperation.cs @@ -0,0 +1,589 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Management.Automation; +using System.Threading; +using System.Globalization; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// + /// Async operation base class, it will issue async operation through + /// 1...* CimSession object(s), processing the async results, extended + /// pssemantics operations, and manage the lifecycle of created + /// CimSession object(s). + /// + /// + internal abstract class CimAsyncOperation : IDisposable + { + #region Constructor + + /// + /// Constructor + /// + public CimAsyncOperation() + { + this.moreActionEvent = new ManualResetEventSlim(false); + this.actionQueue = new ConcurrentQueue(); + this._disposed = 0; + this.operationCount = 0; + } + + #endregion + + #region Event handler + + /// + /// + /// Handler used to handle new action event from + /// object. + /// + /// + /// + /// object raised the event + /// + /// event argument + protected void NewCmdletActionHandler(object cimSession, CmdletActionEventArgs actionArgs) + { + DebugHelper.WriteLogEx("Disposed {0}, action type = {1}", 0, this._disposed, actionArgs.Action); + + if (this.Disposed) + { + if (actionArgs.Action is CimSyncAction) + { + // unblock the thread waiting for response + (actionArgs.Action as CimSyncAction).OnComplete(); + } + return; + } + + bool isEmpty = this.actionQueue.IsEmpty; + this.actionQueue.Enqueue(actionArgs.Action); + if (isEmpty) + { + this.moreActionEvent.Set(); + } + } + + /// + /// + /// Handler used to handle new operation event from + /// object. + /// + /// + /// + /// object raised the event + /// + /// event argument + protected void OperationCreatedHandler(object cimSession, OperationEventArgs actionArgs) + { + DebugHelper.WriteLogEx(); + + lock (this.myLock) + { + this.operationCount++; + } + } + + /// + /// + /// Handler used to handle operation deletion event from + /// object. + /// + /// + /// + /// object raised the event + /// + /// event argument + protected void OperationDeletedHandler(object cimSession, OperationEventArgs actionArgs) + { + DebugHelper.WriteLogEx(); + + lock (this.myLock) + { + this.operationCount--; + if (this.operationCount == 0) + { + this.moreActionEvent.Set(); + } + } + } + + #endregion + + /// + /// + /// process all actions in the action queue + /// + /// + /// + /// wrapper of cmdlet, for details + /// + public void ProcessActions(CmdletOperationBase cmdletOperation) + { + if (!this.actionQueue.IsEmpty) + { + CimBaseAction action; + while (GetActionAndRemove(out action)) + { + action.Execute(cmdletOperation); + if (this.Disposed) + { + break; + } + } + } + } + + /// + /// + /// process remaining actions until all operations are completed or + /// current cmdlet is terminated by user + /// + /// + /// + /// wrapper of cmdlet, for details + /// + public void ProcessRemainActions(CmdletOperationBase cmdletOperation) + { + DebugHelper.WriteLogEx(); + + while (true) + { + ProcessActions(cmdletOperation); + if (!this.IsActive()) + { + DebugHelper.WriteLogEx("Either disposed or all operations completed.", 2); + break; + } + try + { + this.moreActionEvent.Wait(); + this.moreActionEvent.Reset(); + } + catch (ObjectDisposedException ex) + { + // This might happen if this object is being disposed, + // while another thread is processing the remaining actions + DebugHelper.WriteLogEx("moreActionEvent was disposed: {0}.", 2, ex); + break; + } + } + ProcessActions(cmdletOperation); + } + + #region helper methods + + /// + /// + /// Get action object from action queue + /// + /// + /// next action to execute + /// true indicates there is an valid action, otherwise false + protected bool GetActionAndRemove(out CimBaseAction action) + { + return this.actionQueue.TryDequeue(out action); + } + + /// + /// + /// Add temporary object to cache. + /// + /// + /// Computer name of the cimsession + /// cimsession wrapper object + protected void AddCimSessionProxy(CimSessionProxy sessionproxy) + { + lock (cimSessionProxyCacheLock) + { + if (this.cimSessionProxyCache == null) + { + this.cimSessionProxyCache = new List(); + } + if (!this.cimSessionProxyCache.Contains(sessionproxy)) + { + this.cimSessionProxyCache.Add(sessionproxy); + } + } + } + + /// + /// + /// Are there active operations? + /// + /// + /// true for having active operations, otherwise false. + protected bool IsActive() + { + DebugHelper.WriteLogEx("Disposed {0}, Operation Count {1}", 2, this.Disposed, this.operationCount); + bool isActive = (!this.Disposed) && (this.operationCount > 0); + return isActive; + } + + /// + /// Create object. + /// + /// + protected CimSessionProxy CreateCimSessionProxy(CimSessionProxy originalProxy) + { + CimSessionProxy proxy = new CimSessionProxy(originalProxy); + this.SubscribeEventAndAddProxytoCache(proxy); + return proxy; + } + + /// + /// Create object. + /// + /// + protected CimSessionProxy CreateCimSessionProxy(CimSessionProxy originalProxy, bool passThru) + { + CimSessionProxy proxy = new CimSessionProxySetCimInstance(originalProxy, passThru); + this.SubscribeEventAndAddProxytoCache(proxy); + return proxy; + } + + /// + /// Create object. + /// + /// + protected CimSessionProxy CreateCimSessionProxy(CimSession session) + { + CimSessionProxy proxy = new CimSessionProxy(session); + this.SubscribeEventAndAddProxytoCache(proxy); + return proxy; + } + + /// + /// Create object. + /// + /// + protected CimSessionProxy CreateCimSessionProxy(CimSession session, bool passThru) + { + CimSessionProxy proxy = new CimSessionProxySetCimInstance(session, passThru); + this.SubscribeEventAndAddProxytoCache(proxy); + return proxy; + } + + /// + /// Create object, and + /// add the proxy into cache. + /// + /// + protected CimSessionProxy CreateCimSessionProxy(string computerName) + { + CimSessionProxy proxy = new CimSessionProxy(computerName); + this.SubscribeEventAndAddProxytoCache(proxy); + return proxy; + } + + /// + /// Create object, and + /// add the proxy into cache. + /// + /// + /// + /// + protected CimSessionProxy CreateCimSessionProxy(string computerName, + CimInstance cimInstance) + { + CimSessionProxy proxy = new CimSessionProxy(computerName, cimInstance); + this.SubscribeEventAndAddProxytoCache(proxy); + return proxy; + } + + /// + /// Create object, and + /// add the proxy into cache. + /// + /// + /// + /// + protected CimSessionProxy CreateCimSessionProxy(string computerName, CimInstance cimInstance, bool passThru) + { + CimSessionProxy proxy = new CimSessionProxySetCimInstance(computerName, cimInstance, passThru); + this.SubscribeEventAndAddProxytoCache(proxy); + return proxy; + } + + /// + /// Subscribe event from proxy and add proxy to cache + /// + /// + protected void SubscribeEventAndAddProxytoCache(CimSessionProxy proxy) + { + this.AddCimSessionProxy(proxy); + SubscribeToCimSessionProxyEvent(proxy); + } + + /// + /// + /// Subscribe to the events issued by . + /// + /// + /// + protected virtual void SubscribeToCimSessionProxyEvent(CimSessionProxy proxy) + { + DebugHelper.WriteLogEx(); + + proxy.OnNewCmdletAction += this.NewCmdletActionHandler; + proxy.OnOperationCreated += this.OperationCreatedHandler; + proxy.OnOperationDeleted += this.OperationDeletedHandler; + } + + /// + /// Retrieve the base object out if wrapped in psobject + /// + /// + /// + protected object GetBaseObject(object value) + { + PSObject psObject = value as PSObject; + if (psObject == null) + { + return value; + } + else + { + object baseObject = psObject.BaseObject; + var arrayObject = baseObject as object[]; + if (arrayObject == null) + { + return baseObject; + } + else + { + object[] arraybaseObject = new object[arrayObject.Length]; + for (int i = 0; i < arrayObject.Length; i++) + { + arraybaseObject[i] = GetBaseObject(arrayObject[i]); + } + return arraybaseObject; + } + } + } + + /// + /// Retrieve the reference object or reference array object. + /// The returned object has to be either CimInstance or CImInstance[] type, + /// if not thrown exception. + /// + /// + /// output the cimtype of the value, either Reference or ReferenceArray + /// + protected object GetReferenceOrReferenceArrayObject(object value, ref CimType referenceType) + { + PSReference cimReference = value as PSReference; + if (cimReference != null) + { + object baseObject = GetBaseObject(cimReference.Value); + CimInstance cimInstance = baseObject as CimInstance; + if (cimInstance == null) + { + return null; + } + referenceType = CimType.Reference; + return cimInstance; + } + else + { + object[] cimReferenceArray = value as object[]; + if (cimReferenceArray == null) + { + return null; + } + else if (!(cimReferenceArray[0] is PSReference)) + { + return null; + } + CimInstance[] cimInstanceArray = new CimInstance[cimReferenceArray.Length]; + for (int i = 0; i < cimReferenceArray.Length; i++) + { + PSReference tempCimReference = cimReferenceArray[i] as PSReference; + if (tempCimReference == null) + { + return null; + } + object baseObject = GetBaseObject(tempCimReference.Value); + cimInstanceArray[i] = baseObject as CimInstance; + if (cimInstanceArray[i] == null) + { + return null; + } + } + referenceType = CimType.ReferenceArray; + return cimInstanceArray; + } + } + #endregion + + #region IDisposable + + /// + /// + /// Indicates whether this object was disposed or not + /// + /// + protected bool Disposed + { + get + { + return (Interlocked.Read(ref this._disposed) == 1); + } + } + private long _disposed; + + /// + /// + /// Dispose() calls Dispose(true). + /// Implement IDisposable. Do not make this method virtual. + /// A derived class should not be able to override this method. + /// + /// + public void Dispose() + { + Dispose(true); + // This object will be cleaned up by the Dispose method. + // Therefore, you should call GC.SupressFinalize to + // take this object off the finalization queue + // and prevent finalization code for this object + // from executing a second time. + GC.SuppressFinalize(this); + } + + /// + /// + /// Dispose(bool disposing) executes in two distinct scenarios. + /// If disposing equals true, the method has been called directly + /// or indirectly by a user's code. Managed and unmanaged resources + /// can be disposed. + /// If disposing equals false, the method has been called by the + /// runtime from inside the finalizer and you should not reference + /// other objects. Only unmanaged resources can be disposed. + /// + /// + /// Whether it is directly called + protected virtual void Dispose(bool disposing) + { + if (Interlocked.CompareExchange(ref this._disposed, 1, 0) == 0) + { + if (disposing) + { + // free managed resources + Cleanup(); + } + // free native resources if there are any + } + } + + /// + /// + /// Clean up managed resources + /// + /// + private void Cleanup() + { + DebugHelper.WriteLogEx(); + + // unblock thread that waiting for more actions + this.moreActionEvent.Set(); + CimBaseAction action; + while (GetActionAndRemove(out action)) + { + DebugHelper.WriteLog("Action {0}", 2, action); + + if (action is CimSyncAction) + { + // unblock the thread waiting for response + (action as CimSyncAction).OnComplete(); + } + } + if (this.cimSessionProxyCache != null) + { + List temporaryProxy; + lock (this.cimSessionProxyCache) + { + temporaryProxy = new List(this.cimSessionProxyCache); + this.cimSessionProxyCache.Clear(); + } + // clean up all proxy objects + foreach (CimSessionProxy proxy in temporaryProxy) + { + DebugHelper.WriteLog("Dispose proxy ", 2); + proxy.Dispose(); + } + } + + this.moreActionEvent.Dispose(); + if (this.ackedEvent != null) + { + this.ackedEvent.Dispose(); + } + DebugHelper.WriteLog("Cleanup complete.", 2); + } + + #endregion + + #region private members + + /// + /// lock object + /// + private readonly object myLock = new object(); + + /// + /// number of active operations + /// + private UInt32 operationCount = 0; + + /// + /// Event to notify ps thread that more action is available + /// + private ManualResetEventSlim moreActionEvent; + + /// + /// The following is the definition of action queue. + /// The queue holding all actions to be exected in the context of either + /// ProcessRecord or EndProcessing. + /// + private ConcurrentQueue actionQueue; + + /// + /// lock object + /// + private readonly object cimSessionProxyCacheLock = new object(); + + /// + /// cache all objects related to + /// the current operation. + /// + private List cimSessionProxyCache; + + #endregion + + #region protected members + /// + /// Event to notify ps thread that either a ACK message sent back + /// or a error happened. Currently only used by class + /// . + /// + protected ManualResetEventSlim ackedEvent; + #endregion + + #region const strings + internal const string ComputerNameArgument = @"ComputerName"; + internal const string CimSessionArgument = @"CimSession"; + #endregion + + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimBaseAction.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimBaseAction.cs new file mode 100644 index 000000000..eed2e32a8 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimBaseAction.cs @@ -0,0 +1,201 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System.Threading; +using Microsoft.Management.Infrastructure.Options; +using System; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// Base action class, implemented to write results to pipeline. + /// + internal abstract class CimBaseAction + { + /// + /// Constructor method. + /// + public CimBaseAction() + { + } + + /// + /// + /// Execute the write opration to given cmdlet object + /// + /// + /// + /// cmdlet wrapper object, to which write result. + /// for details. + /// + public virtual void Execute(CmdletOperationBase cmdlet) + { + } + + /// + /// + /// object that related to current action. + /// It may used by action, such as , + /// since later on action may require namspace, and proxy object to reuse + /// , object. + /// + /// + protected XOperationContextBase Context + { + get + { + return this.context; + } + set + { + this.context = value; + } + } + private XOperationContextBase context; + }//End Class + + /// + /// + /// Synchronous action class, implemented to write results to pipeline + /// and block current thread until the action is completed. + /// + /// + internal class CimSyncAction : CimBaseAction, IDisposable + { + /// + /// Constructor + /// + public CimSyncAction() + { + this.completeEvent = new ManualResetEventSlim(false); + this.responseType = CimResponseType.None; + } + + /// + /// + /// Block current thread until action completed + /// + /// + /// Response from user + public virtual CimResponseType GetResponse() + { + this.Block(); + return responseType; + } + + /// + /// + /// Set response result + /// + /// + internal CimResponseType ResponseType + { + set { this.responseType = value; } + } + + /// + /// + /// Call this method when the action is completed or + /// the operation is terminated + /// + /// + internal virtual void OnComplete() + { + this.completeEvent.Set(); + } + + /// + /// + /// block current thread. + /// + /// + protected virtual void Block() + { + this.completeEvent.Wait(); + this.completeEvent.Dispose(); + } + + #region members + + /// + /// action completed event + /// + private ManualResetEventSlim completeEvent; + + /// + /// response result + /// + protected CimResponseType responseType; + + #endregion + + #region IDisposable interface + /// + /// IDisposable interface + /// + private bool _disposed; + + /// + /// + /// Dispose() calls Dispose(true). + /// Implement IDisposable. Do not make this method virtual. + /// A derived class should not be able to override this method. + /// + /// + public void Dispose() + { + Dispose(true); + // This object will be cleaned up by the Dispose method. + // Therefore, you should call GC.SupressFinalize to + // take this object off the finalization queue + // and prevent finalization code for this object + // from executing a second time. + GC.SuppressFinalize(this); + } + + /// + /// + /// Dispose(bool disposing) executes in two distinct scenarios. + /// If disposing equals true, the method has been called directly + /// or indirectly by a user's code. Managed and unmanaged resources + /// can be disposed. + /// If disposing equals false, the method has been called by the + /// runtime from inside the finalizer and you should not reference + /// other objects. Only unmanaged resources can be disposed. + /// + /// + /// Whether it is directly called + protected virtual void Dispose(bool disposing) + { + // Check to see if Dispose has already been called. + if (!this._disposed) + { + // If disposing equals true, dispose all managed + // and unmanaged resources. + if (disposing) + { + // Dispose managed resources. + if (this.completeEvent != null) + { + this.completeEvent.Dispose(); + } + } + + // Call the appropriate methods to clean up + // unmanaged resources here. + // If disposing is false, + // only the following code is executed. + + // Note disposing has been done. + _disposed = true; + } + } + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimCmdletModuleInitialize.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimCmdletModuleInitialize.cs new file mode 100644 index 000000000..c97511ede --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimCmdletModuleInitialize.cs @@ -0,0 +1,116 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using System.Globalization; +using System.Management.Automation; +using System.Management.Automation.Runspaces; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// + /// Initialize the cimcmdlets. + /// + /// + /// + /// Provide a hook to the engine for startup initialization + /// w.r.t compiled assembly loading. + /// + public sealed class CimCmdletsAssemblyInitializer : IModuleAssemblyInitializer + { + /// + /// + /// constructor + /// + /// + public CimCmdletsAssemblyInitializer() + { + } + + /// + /// PowerShell engine will call this method when the cimcmdlets module + /// is loaded. + /// + public void OnImport() + { + DebugHelper.WriteLogEx(); + using (System.Management.Automation.PowerShell invoker = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace)) + { + foreach (CimCmdletAliasEntry alias in Aliases) + { + invoker.AddScript(string.Format(CultureInfo.CurrentUICulture, "Set-Alias -Name {0} -Value {1} -Option {2} -ErrorAction SilentlyContinue", alias.Name, alias.Value, alias.Options)); + DebugHelper.WriteLog(@"Add commands {0} of {1} with option {2} to current runspace.", 1, alias.Name, alias.Value, alias.Options); + } + System.Collections.ObjectModel.Collection psObjects = invoker.Invoke(); + DebugHelper.WriteLog(@"Invoke results {0}.", 1, psObjects.Count); + } + } + + #region readonly string + + /// + /// + /// CimCmdlet alias entry + /// + /// + internal sealed class CimCmdletAliasEntry + { + /// + /// + /// Constructor + /// + /// + /// + /// + internal CimCmdletAliasEntry(string name, string value) + { + this._name = name; + this._value = value; + } + + /// + /// The string defining the name of this alias + /// + internal string Name { get { return this._name; } } + private string _name; + + /// + /// The string defining realy cmdlet name + /// + internal string Value { get { return this._value; } } + private string _value = String.Empty; + + /// + /// The string defining realy cmdlet name + /// + internal ScopedItemOptions Options { get { return this._options; } } + private ScopedItemOptions _options = ScopedItemOptions.AllScope | ScopedItemOptions.ReadOnly; + } + + /// + /// Returns a new array of alias entries everytime it's called. + /// + internal static CimCmdletAliasEntry[] Aliases = new CimCmdletAliasEntry[] { + new CimCmdletAliasEntry("gcim", "Get-CimInstance"), + new CimCmdletAliasEntry("scim", "Set-CimInstance"), + new CimCmdletAliasEntry("ncim", "New-CimInstance "), + new CimCmdletAliasEntry("rcim", "Remove-cimInstance"), + new CimCmdletAliasEntry("icim", "Invoke-CimMethod"), + new CimCmdletAliasEntry("gcai", "Get-CimAssociatedInstance"), + new CimCmdletAliasEntry("rcie", "Register-CimIndicationEvent"), + new CimCmdletAliasEntry("ncms", "New-CimSession"), + new CimCmdletAliasEntry("rcms", "Remove-cimSession"), + new CimCmdletAliasEntry("gcms", "Get-CimSession"), + new CimCmdletAliasEntry("ncso", "New-CimSessionOption"), + new CimCmdletAliasEntry("gcls", "Get-CimClass"), + }; + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimCommandBase.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimCommandBase.cs new file mode 100644 index 000000000..41b4e423d --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimCommandBase.cs @@ -0,0 +1,988 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Management.Automation; +using System.Net; +using System.Text; +using Microsoft.Management.Infrastructure.Options; +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + #region Parameter Set Resolving Classes + + /// + /// + /// Define class ParameterDefinitionEntry. + /// + /// + internal class ParameterDefinitionEntry + { + /// + /// constructor + /// + /// + /// + internal ParameterDefinitionEntry(string parameterSetName, bool mandatory) + { + this.mandatory = mandatory; + this.parameterSetName = parameterSetName; + } + + /// + /// property ParameterSetName + /// + internal string ParameterSetName + { + get + { + return this.parameterSetName; + } + } + private readonly string parameterSetName = null; + + /// + /// Whether the parameter is mandatory to the set + /// + internal bool IsMandatory + { + get + { + return this.mandatory; + } + } + private readonly bool mandatory = false; + } + + /// + /// + /// Define class ParameterSetEntry. + /// + /// + internal class ParameterSetEntry + { + /// + /// constructor + /// + /// + internal ParameterSetEntry(UInt32 mandatoryParameterCount) + { + this.mandatoryParameterCount = mandatoryParameterCount; + this.isDefaultParameterSet = false; + reset(); + } + + /// + /// constructor + /// + /// + internal ParameterSetEntry(ParameterSetEntry toClone) + { + this.mandatoryParameterCount = toClone.MandatoryParameterCount; + this.isDefaultParameterSet = toClone.IsDefaultParameterSet; + reset(); + } + + /// + /// constructor + /// + /// + /// + internal ParameterSetEntry(UInt32 mandatoryParameterCount, bool isDefault) + { + this.mandatoryParameterCount = mandatoryParameterCount; + this.isDefaultParameterSet = isDefault; + reset(); + } + + /// + /// reset the internal status + /// + internal void reset() + { + this.setMandatoryParameterCount = this.setMandatoryParameterCountAtBeginProcess; + this.isValueSet = this.isValueSetAtBeginProcess; + } + + /// + /// property DefaultParameterSet + /// + internal bool IsDefaultParameterSet + { + get + { + return this.isDefaultParameterSet; + } + } + private readonly bool isDefaultParameterSet = false; + + /// + /// property MandatoryParameterCount + /// + internal UInt32 MandatoryParameterCount + { + get + { + return this.mandatoryParameterCount; + } + } + private readonly UInt32 mandatoryParameterCount = 0; + + /// + /// property IsValueSet + /// + internal bool IsValueSet + { + get + { + return this.isValueSet; + } + set + { + this.isValueSet = value; + } + } + private bool isValueSet = false; + + /// + /// property IsValueSetAtBeginProcess + /// + internal bool IsValueSetAtBeginProcess + { + get + { + return this.isValueSetAtBeginProcess; + } + set + { + this.isValueSetAtBeginProcess = value; + } + } + private bool isValueSetAtBeginProcess = false; + + /// + /// property SetMandatoryParameterCount + /// + internal UInt32 SetMandatoryParameterCount + { + get + { + return this.setMandatoryParameterCount; + } + set + { + this.setMandatoryParameterCount = value; + } + } + private UInt32 setMandatoryParameterCount = 0; + + /// + /// property SetMandatoryParameterCountAtBeginProcess + /// + internal UInt32 SetMandatoryParameterCountAtBeginProcess + { + get + { + return this.setMandatoryParameterCountAtBeginProcess; + } + set + { + this.setMandatoryParameterCountAtBeginProcess = value; + } + } + private UInt32 setMandatoryParameterCountAtBeginProcess = 0; + } + + /// + /// Define class ParameterBinder. + /// + internal class ParameterBinder + { + /// + /// constructor + /// + /// + /// + internal ParameterBinder( + Dictionary> parameters, + Dictionary sets) + { + this.CloneParameterEntries(parameters, sets); + } + + #region Two dictionaryies used to determine the bound parameter set + + /// + /// Define the parameter definition entries, + /// each parameter may belong a set of parameterSets, each parameter set + /// are defined by a . + /// + private Dictionary> parameterDefinitionEntries; + + /// + /// + /// Define parameter set entries, + /// each cmdlet has a list of parameter set, each has number of mandatory parameters, etc. + /// This data structure is used to track the number of mandatory parameter has been set for + /// current parameterset, whether the parameter set was been set by user. + /// + /// + private Dictionary parameterSetEntries; + + #endregion + + /// + /// + /// Used to remember the set of parameterset were set + /// if any conflition occurred with current parameter, + /// throw exception + /// + /// + private List parametersetNamesList = new List(); + + /// + /// Parameter names list + /// + private List parameterNamesList = new List(); + + /// + /// + /// Used to remember the set of parameterset were set before begin process + /// if any conflition occurred with current parameter, + /// throw exception + /// + /// + private List parametersetNamesListAtBeginProcess = new List(); + + /// + /// Parameter names list befre begin process + /// + private List parameterNamesListAtBeginProcess = new List(); + + /// + /// + /// Reset the status of parameter set entries + /// + /// + internal void reset() + { + foreach (KeyValuePair setEntry in parameterSetEntries) + { + setEntry.Value.reset(); + } + + this.parametersetNamesList.Clear(); + foreach (string parametersetName in this.parametersetNamesListAtBeginProcess) + { + this.parametersetNamesList.Add(parametersetName); + } + + this.parameterNamesList.Clear(); + foreach (string parameterName in this.parameterNamesListAtBeginProcess) + { + this.parameterNamesList.Add(parameterName); + } + } + + /// + /// + /// A given parameter's value was set by cmdlet caller, + /// check and change the status of parameter set, + /// throw exception if confliction occurred + /// + /// + /// + /// throw if conflict parameter was set + internal void SetParameter(string parameterName, bool isBeginProcess) + { + DebugHelper.WriteLogEx("ParameterName = {0}, isBeginProcess = {1}", 0, parameterName, isBeginProcess); + + if (this.parameterNamesList.Contains(parameterName)) + { + DebugHelper.WriteLogEx("ParameterName {0} is already bound ", 1, parameterName); + return; + } + else + { + this.parameterNamesList.Add(parameterName); + if (isBeginProcess) + { + this.parameterNamesListAtBeginProcess.Add(parameterName); + } + } + + if (this.parametersetNamesList.Count == 0) + { + List nameset = new List(); + foreach (ParameterDefinitionEntry parameterDefinitionEntry in this.parameterDefinitionEntries[parameterName]) + { + DebugHelper.WriteLogEx("parameterset name = '{0}'; mandatory = '{1}'", 1, parameterDefinitionEntry.ParameterSetName, parameterDefinitionEntry.IsMandatory); + ParameterSetEntry psEntry = this.parameterSetEntries[parameterDefinitionEntry.ParameterSetName]; + if (psEntry == null) + continue; + + if (parameterDefinitionEntry.IsMandatory) + { + psEntry.SetMandatoryParameterCount++; + if (isBeginProcess) + { + psEntry.SetMandatoryParameterCountAtBeginProcess++; + } + DebugHelper.WriteLogEx("parameterset name = '{0}'; SetMandatoryParameterCount = '{1}'", 1, parameterDefinitionEntry.ParameterSetName, psEntry.SetMandatoryParameterCount); + } + if (!psEntry.IsValueSet) + { + psEntry.IsValueSet = true; + if (isBeginProcess) + { + psEntry.IsValueSetAtBeginProcess = true; + } + } + nameset.Add(parameterDefinitionEntry.ParameterSetName); + } + this.parametersetNamesList = nameset; + if (isBeginProcess) + { + this.parametersetNamesListAtBeginProcess = nameset; + } + } + else + { + List nameset = new List(); + foreach (ParameterDefinitionEntry entry in this.parameterDefinitionEntries[parameterName]) + { + if (this.parametersetNamesList.Contains(entry.ParameterSetName)) + { + nameset.Add(entry.ParameterSetName); + if (entry.IsMandatory) + { + ParameterSetEntry psEntry = this.parameterSetEntries[entry.ParameterSetName]; + psEntry.SetMandatoryParameterCount++; + if (isBeginProcess) + { + psEntry.SetMandatoryParameterCountAtBeginProcess++; + } + DebugHelper.WriteLogEx("parameterset name = '{0}'; SetMandatoryParameterCount = '{1}'", + 1, + entry.ParameterSetName, + psEntry.SetMandatoryParameterCount); + } + } + } + if (nameset.Count == 0) + { + throw new PSArgumentException(Strings.UnableToResolvePareameterSetName); + } + else + { + this.parametersetNamesList = nameset; + if (isBeginProcess) + { + this.parametersetNamesListAtBeginProcess = nameset; + } + } + } + } + + /// + /// Get the parameter set name based on current binding results + /// + /// + internal string GetParameterSet() + { + DebugHelper.WriteLogEx(); + + string boundParameterSetName = null; + string defaultParameterSetName = null; + List noMandatoryParameterSet = new List(); + + // Looking for parameter set which have mandatory parameters + foreach (string parameterSetName in this.parameterSetEntries.Keys) + { + ParameterSetEntry entry = this.parameterSetEntries[parameterSetName]; + DebugHelper.WriteLogEx( + "parameterset name = {0}, {1}/{2} mandatory parameters.", + 1, + parameterSetName, + entry.SetMandatoryParameterCount, + entry.MandatoryParameterCount); + + // Ignore the parameter set which has no mandatory parameter firstly + if (entry.MandatoryParameterCount == 0) + { + if (entry.IsDefaultParameterSet) + { + defaultParameterSetName = parameterSetName; + } + if (entry.IsValueSet) + { + noMandatoryParameterSet.Add(parameterSetName); + } + continue; + } + if ((entry.SetMandatoryParameterCount == entry.MandatoryParameterCount) && + this.parametersetNamesList.Contains(parameterSetName)) + { + if (boundParameterSetName != null) + { + throw new PSArgumentException(Strings.UnableToResolvePareameterSetName); + } + boundParameterSetName = parameterSetName; + } + } + + // Looking for parameter set which has no mandatory parameters + if (boundParameterSetName == null) + { + // throw if there are > 1 parameter set + if (noMandatoryParameterSet.Count > 1) + { + throw new PSArgumentException(Strings.UnableToResolvePareameterSetName); + } + else if (noMandatoryParameterSet.Count == 1) + { + boundParameterSetName = noMandatoryParameterSet[0]; + } + } + + // Looking for default parameter set + if (boundParameterSetName == null) + { + boundParameterSetName = defaultParameterSetName; + } + + // throw if still can not find the parameter set name + if (boundParameterSetName == null) + { + throw new PSArgumentException(Strings.UnableToResolvePareameterSetName); + } + return boundParameterSetName; + } + + /// + /// Deep clone the parameter entries to member variable + /// + private void CloneParameterEntries( + Dictionary> parameters, + Dictionary sets) + { + this.parameterDefinitionEntries = parameters; + this.parameterSetEntries = new Dictionary(); + foreach (KeyValuePair parameterSet in sets) + { + this.parameterSetEntries.Add(parameterSet.Key, new ParameterSetEntry(parameterSet.Value)); + } + } + } + + #endregion + + /// + /// Base command for all cim cmdlets + /// + public class CimBaseCommand : Cmdlet, IDisposable + { + + #region resolve parameter set name + /// + /// + /// Check set parameters and set ParameterSetName + /// + /// + /// Following are special types to be handled + /// Microsoft.Management.Infrastructure.Options.PacketEncoding + /// Microsoft.Management.Infrastructure.Options.ImpersonationType + /// UInt32 + /// Authentication.None (default value)? + /// ProxyType.None + /// + /// + internal void CheckParameterSet() + { + if (this.parameterBinder != null) + { + try + { + this.parameterSetName = this.parameterBinder.GetParameterSet(); + } + finally + { + this.parameterBinder.reset(); + } + } + DebugHelper.WriteLog("current parameterset is: " + this.parameterSetName, 4); + } + + /// + /// Redirect to parameterBinder to set one parameter + /// + /// + internal void SetParameter(object value, string parameterName) + { + // Ignore the null value being set, + // Null value could be set by caller unintentionally, + // or by powershell to reset the parameter to default value + // before the next parameter binding, and ProcessRecord call + if (value == null) + { + return; + } + if (this.parameterBinder != null) + { + this.parameterBinder.SetParameter(parameterName, this.AtBeginProcess); + } + } + #endregion + + #region constructors + + /// + /// constructor + /// + internal CimBaseCommand() + { + this.disposed = false; + this.parameterBinder = null; + } + + /// + /// constructor + /// + internal CimBaseCommand(Dictionary> parameters, + Dictionary sets) + { + this.disposed = false; + this.parameterBinder = new ParameterBinder(parameters, sets); + } + + #endregion + + #region override functions of Cmdlet + + /// + /// StopProcessing method. + /// + protected override void StopProcessing() + { + Dispose(); + }//End StopProcessing() + + #endregion + + #region IDisposable interface + /// + /// IDisposable interface + /// + private bool disposed; + + /// + /// + /// Dispose() calls Dispose(true). + /// Implement IDisposable. Do not make this method virtual. + /// A derived class should not be able to override this method. + /// + /// + public void Dispose() + { + Dispose(true); + // This object will be cleaned up by the Dispose method. + // Therefore, you should call GC.SupressFinalize to + // take this object off the finalization queue + // and prevent finalization code for this object + // from executing a second time. + GC.SuppressFinalize(this); + } + + /// + /// + /// Dispose(bool disposing) executes in two distinct scenarios. + /// If disposing equals true, the method has been called directly + /// or indirectly by a user's code. Managed and unmanaged resources + /// can be disposed. + /// If disposing equals false, the method has been called by the + /// runtime from inside the finalizer and you should not reference + /// other objects. Only unmanaged resources can be disposed. + /// + /// + /// Whether it is directly called + protected void Dispose(bool disposing) + { + // Check to see if Dispose has already been called. + if (!this.disposed) + { + // If disposing equals true, dispose all managed + // and unmanaged resources. + if (disposing) + { + DisposeInternal(); + } + + // Call the appropriate methods to clean up + // unmanaged resources here. + // If disposing is false, + // only the following code is executed. + + // Note disposing has been done. + disposed = true; + } + } + + /// + /// Clean up resources + /// + protected virtual void DisposeInternal() + { + // Dispose managed resources. + if (this.operation != null) + { + this.operation.Dispose(); + } + } + #endregion + + #region private members + + /// + /// Parameter binder used to resolve parameter set name + /// + private ParameterBinder parameterBinder; + + /// + /// + /// Async operation handler + /// + /// + private CimAsyncOperation operation; + + /// + /// lock object + /// + private readonly object myLock = new object(); + + /// + /// + /// parameter set name + /// + /// + private string parameterSetName; + + /// + /// This flag is introduced to resolve the parameter set name + /// during process record + /// Whether at begin process time, false means in processrecord + /// + private bool atBeginProcess = true; + internal bool AtBeginProcess + { + get + { + return this.atBeginProcess; + } + set + { + this.atBeginProcess = value; + } + } + #endregion + + #region internal properties + + /// + /// + /// Set object, to which + /// current cmdlet will delegate all operations. + /// + /// + internal CimAsyncOperation AsyncOperation + { + set + { + lock (this.myLock) + { + Debug.Assert(this.operation == null, "Caller should verify that operation is null"); + this.operation = value; + } + } + get + { + return this.operation; + } + } + + /// + /// + /// Get current ParameterSetName of the cmdlet + /// + /// + internal string ParameterSetName + { + get + { + return this.parameterSetName; + } + } + + /// + /// Gets/Sets cmdlet operation wrapper object + /// + internal virtual CmdletOperationBase CmdletOperation + { + get; + set; + } + + /// + /// + /// Throw terminating error + /// + /// + internal void ThrowTerminatingError(Exception exception, string operation) + { + ErrorRecord errorRecord = new ErrorRecord(exception, operation, ErrorCategory.InvalidOperation, this); + this.CmdletOperation.ThrowTerminatingError(errorRecord); + } + + #endregion + + #region internal const strings + + /// + /// alias CN - computer name + /// + internal const string AliasCN = "CN"; + + /// + /// alias ServerName - computer name + /// + internal const string AliasServerName = "ServerName"; + + /// + /// alias OT - operation timeout + /// + internal const string AliasOT = "OT"; + + /// + /// session set name + /// + internal const string SessionSetName = "SessionSet"; + + /// + /// computer set name + /// + internal const string ComputerSetName = "ComputerSet"; + + /// + /// class name computer set name + /// + internal const string ClassNameComputerSet = "ClassNameComputerSet"; + + /// + /// resource Uri computer set name + /// + internal const string ResourceUriComputerSet = "ResourceUriComputerSet"; + + /// + /// computer set name + /// + internal const string CimInstanceComputerSet = "CimInstanceComputerSet"; + + /// + /// query computer set name + /// + internal const string QueryComputerSet = "QueryComputerSet"; + + /// + /// class name session set name + /// + internal const string ClassNameSessionSet = "ClassNameSessionSet"; + + + /// + /// resource Uri session set name + /// + internal const string ResourceUriSessionSet = "ResourceUriSessionSet"; + + /// + /// session set name + /// + internal const string CimInstanceSessionSet = "CimInstanceSessionSet"; + + /// + /// query session set name + /// + internal const string QuerySessionSet = "QuerySessionSet"; + + /// + /// computer set name + /// + internal const string CimClassComputerSet = "CimClassComputerSet"; + + /// + /// session set name + /// + internal const string CimClassSessionSet = "CimClassSessionSet"; + + #region Session related parameter set name + + internal const string ComputerNameSet = "ComputerNameSet"; + internal const string SessionIdSet = "SessionIdSet"; + internal const string InstanceIdSet = "InstanceIdSet"; + internal const string NameSet = "NameSet"; + internal const string CimSessionSet = "CimSessionSet"; + internal const string WSManParameterSet = "WSManParameterSet"; + internal const string DcomParameterSet = "DcomParameterSet"; + internal const string ProtocolNameParameterSet = "ProtocolTypeSet"; + #endregion + + #region register cimindication parameter set name + internal const string QueryExpressionSessionSet = "QueryExpressionSessionSet"; + internal const string QueryExpressionComputerSet = "QueryExpressionComputerSet"; + #endregion + + /// + /// credential parameter set + /// + internal const string CredentialParameterSet = "CredentialParameterSet"; + + /// + /// certificate parameter set + /// + internal const string CertificatePrameterSet = "CertificatePrameterSet"; + + /// + /// CimInstance parameter alias + /// + internal const string AliasCimInstance = "CimInstance"; + + #endregion + + #region internal helper function + + /// + /// + /// Throw invalid AuthenticationType + /// + /// + /// + /// + /// + internal void ThrowInvalidAuthenticationTypeError( + string operationName, + string parameterName, + PasswordAuthenticationMechanism authentication) + { + string message = String.Format(CultureInfo.CurrentUICulture, Strings.InvalidAuthenticationTypeWithNullCredential, + authentication, + ImpersonatedAuthenticationMechanism.None, + ImpersonatedAuthenticationMechanism.Negotiate, + ImpersonatedAuthenticationMechanism.Kerberos, + ImpersonatedAuthenticationMechanism.NtlmDomain); + PSArgumentOutOfRangeException exception = new PSArgumentOutOfRangeException( + parameterName, authentication, message); + ThrowTerminatingError(exception, operationName); + } + + /// + /// Throw conflict parameter error + /// + /// + /// + /// + internal void ThrowConflictParameterWasSet( + string operationName, + string parameterName, + string conflictParameterName) + { + string message = String.Format(CultureInfo.CurrentUICulture, + Strings.ConflictParameterWasSet, + parameterName, conflictParameterName); + PSArgumentException exception = new PSArgumentException(message, parameterName); + ThrowTerminatingError(exception, operationName); + } + + /// + /// + /// Throw not found property error + /// + /// + internal void ThrowInvalidProperty( + IEnumerable propertiesList, + string className, + string parameterName, + string operationName, + IDictionary actualValue) + { + StringBuilder propList = new StringBuilder(); + foreach (string property in propertiesList) + { + if (propList.Length > 0) + { + propList.Append(","); + } + propList.Append(property); + } + string message = String.Format(CultureInfo.CurrentUICulture, Strings.CouldNotFindPropertyFromGivenClass, + className, propList); + PSArgumentOutOfRangeException exception = new PSArgumentOutOfRangeException( + parameterName, actualValue, message); + ThrowTerminatingError(exception, operationName); + } + + /// + /// Create credentials based on given authentication type and PSCredential + /// + /// + /// + /// + internal CimCredential CreateCimCredentials(PSCredential psCredentials, + PasswordAuthenticationMechanism passwordAuthentication, + string operationName, + string parameterName) + { + DebugHelper.WriteLogEx("PSCredential:{0}; PasswordAuthenticationMechanism:{1}; operationName:{2}; parameterName:{3}.", 0, psCredentials, passwordAuthentication, operationName, parameterName); + + CimCredential credentials = null; + if (psCredentials != null) + { + NetworkCredential networkCredential = psCredentials.GetNetworkCredential(); + DebugHelper.WriteLog("Domain:{0}; UserName:{1}; Password:{2}.", 1, networkCredential.Domain, networkCredential.UserName, psCredentials.Password); + credentials = new CimCredential(passwordAuthentication, networkCredential.Domain, networkCredential.UserName, psCredentials.Password); + + } + else + { + ImpersonatedAuthenticationMechanism impersonatedAuthentication; + switch (passwordAuthentication) + { + case PasswordAuthenticationMechanism.Default: + impersonatedAuthentication = ImpersonatedAuthenticationMechanism.None; + break; + case PasswordAuthenticationMechanism.Negotiate: + impersonatedAuthentication = ImpersonatedAuthenticationMechanism.Negotiate; + break; + case PasswordAuthenticationMechanism.Kerberos: + impersonatedAuthentication = ImpersonatedAuthenticationMechanism.Kerberos; + break; + case PasswordAuthenticationMechanism.NtlmDomain: + impersonatedAuthentication = ImpersonatedAuthenticationMechanism.NtlmDomain; + break; + default: + ThrowInvalidAuthenticationTypeError(operationName, parameterName, passwordAuthentication); + return null; + } + credentials = new CimCredential(impersonatedAuthentication); + } + DebugHelper.WriteLogEx("return credential {0}", 1, credentials); + return credentials; + } + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetAssociatedInstance.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetAssociatedInstance.cs new file mode 100644 index 000000000..4f83c7dee --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetAssociatedInstance.cs @@ -0,0 +1,139 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System.Collections; +using System; +using System.Collections.Generic; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// + /// Implements operations of get-AssociatedInstance cmdlet. + /// + /// + internal sealed class CimGetAssociatedInstance : CimAsyncOperation + { + /// + /// + /// Constructor + /// + /// + public CimGetAssociatedInstance() + : base() + { + } + + /// + /// + /// Base on parametersetName to retrieve associated ciminstances + /// + /// + /// object + public void GetCimAssociatedInstance(GetCimAssociatedInstanceCommand cmdlet) + { + IEnumerable computerNames = ConstValue.GetComputerNames(cmdlet.ComputerName); + // use the namespace from parameter + string nameSpace = cmdlet.Namespace; + if ((nameSpace == null) && (cmdlet.ResourceUri == null)) + { + // try to use namespace of ciminstance, then fall back to default namespace + nameSpace = ConstValue.GetNamespace(cmdlet.CimInstance.CimSystemProperties.Namespace); + } + List proxys = new List(); + switch (cmdlet.ParameterSetName) + { + case CimBaseCommand.ComputerSetName: + foreach (string computerName in computerNames) + { + CimSessionProxy proxy = CreateSessionProxy(computerName, cmdlet.CimInstance, cmdlet); + proxys.Add(proxy); + } + break; + case CimBaseCommand.SessionSetName: + foreach (CimSession session in cmdlet.CimSession) + { + CimSessionProxy proxy = CreateSessionProxy(session, cmdlet); + proxys.Add(proxy); + } + break; + default: + return; + } + foreach (CimSessionProxy proxy in proxys) + { + proxy.EnumerateAssociatedInstancesAsync( + nameSpace, + cmdlet.CimInstance, + cmdlet.Association, + cmdlet.ResultClassName, + null, + null); + } + } + + #region private methods + + /// + /// + /// Set properties + /// + /// + /// + /// + private void SetSessionProxyProperties( + ref CimSessionProxy proxy, + GetCimAssociatedInstanceCommand cmdlet) + { + proxy.OperationTimeout = cmdlet.OperationTimeoutSec; + proxy.KeyOnly = cmdlet.KeyOnly; + if (cmdlet.ResourceUri != null) + { + proxy.ResourceUri = cmdlet.ResourceUri; + } + } + + /// + /// + /// Create and set properties + /// + /// + /// + /// + /// + /// + private CimSessionProxy CreateSessionProxy( + string computerName, + CimInstance cimInstance, + GetCimAssociatedInstanceCommand cmdlet) + { + CimSessionProxy proxy = CreateCimSessionProxy(computerName, cimInstance); + SetSessionProxyProperties(ref proxy, cmdlet); + return proxy; + } + + /// + /// Create and set properties + /// + /// + /// + /// + private CimSessionProxy CreateSessionProxy( + CimSession session, + GetCimAssociatedInstanceCommand cmdlet) + { + CimSessionProxy proxy = CreateCimSessionProxy(session); + SetSessionProxyProperties(ref proxy, cmdlet); + return proxy; + } + + #endregion + + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetCimClass.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetCimClass.cs new file mode 100644 index 000000000..4c7b2dc5b --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetCimClass.cs @@ -0,0 +1,231 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System.Collections; +using System; +using System.Collections.Generic; +using System.Management.Automation; +using System.Globalization; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// Containing all information originated from + /// the parameters of + /// + internal class CimGetCimClassContext : XOperationContextBase + { + /// + /// + /// Constructor + /// + /// + /// + /// + /// + internal CimGetCimClassContext( + string theClassName, + string theMethodName, + string thePropertyName, + string theQualifierName) + { + this.className = theClassName; + this.methodName = theMethodName; + this.propertyName = thePropertyName; + this.qualifierName = theQualifierName; + } + + /// + /// + /// The following is the definition of the input parameter "ClassName". + /// + /// + /// Wildcard expansion should be allowed. + /// + /// + public String ClassName + { + get { return className; } + set { className = value; } + } + private String className; + + /// + /// + /// The following is the definition of the input parameter "MethodName", + /// Which may contains wildchar. + /// Then Filter the by given methodname + /// + /// + internal String MethodName + { + get { return methodName; } + } + private String methodName; + + /// + /// + /// The following is the definition of the input parameter "PropertyName", + /// Which may contains wildchar. + /// Filter the by given property name. + /// + /// + internal String PropertyName + { + get { return propertyName; } + } + private String propertyName; + + /// + /// + /// The following is the definition of the input parameter "QualifierName", + /// Which may contains wildchar. + /// Filter the by given methodname + /// + /// + internal String QualifierName + { + get { return qualifierName; } + } + private String qualifierName; + } + + /// + /// + /// Implements operations of get-cimclass cmdlet. + /// + /// + internal sealed class CimGetCimClass : CimAsyncOperation + { + /// + /// + /// Constructor + /// + /// + public CimGetCimClass() + : base() + { + } + + /// + /// + /// Base on parametersetName to retrieve + /// + /// + /// object + public void GetCimClass(GetCimClassCommand cmdlet) + { + List proxys = new List(); + string nameSpace = ConstValue.GetNamespace(cmdlet.Namespace); + string className = (cmdlet.ClassName == null) ? @"*" : cmdlet.ClassName; + CimGetCimClassContext context = new CimGetCimClassContext( + cmdlet.ClassName, + cmdlet.MethodName, + cmdlet.PropertyName, + cmdlet.QualifierName); + switch (cmdlet.ParameterSetName) + { + case CimBaseCommand.ComputerSetName: + { + IEnumerable computerNames = ConstValue.GetComputerNames( + cmdlet.ComputerName); + foreach (string computerName in computerNames) + { + CimSessionProxy proxy = CreateSessionProxy(computerName, cmdlet); + proxy.ContextObject = context; + proxys.Add(proxy); + } + } + break; + case CimBaseCommand.SessionSetName: + { + foreach (CimSession session in cmdlet.CimSession) + { + CimSessionProxy proxy = CreateSessionProxy(session, cmdlet); + proxy.ContextObject = context; + proxys.Add(proxy); + } + } + break; + default: + return; + } + + if (WildcardPattern.ContainsWildcardCharacters(className)) + { + // retrieve all classes and then filter based on + // classname, propertyname, methodname, and qualifiername + foreach (CimSessionProxy proxy in proxys) + { + proxy.EnumerateClassesAsync(nameSpace); + } + } + else + { + foreach (CimSessionProxy proxy in proxys) + { + proxy.GetClassAsync(nameSpace, className); + } + } + } + + #region private methods + + /// + /// + /// Set properties + /// + /// + /// + /// + private void SetSessionProxyProperties( + ref CimSessionProxy proxy, + GetCimClassCommand cmdlet) + { + proxy.OperationTimeout = cmdlet.OperationTimeoutSec; + } + + /// + /// + /// Create and set properties + /// + /// + /// + /// + /// + private CimSessionProxy CreateSessionProxy( + string computerName, + GetCimClassCommand cmdlet) + { + CimSessionProxy proxy = new CimSessionProxyGetCimClass(computerName); + this.SubscribeEventAndAddProxytoCache(proxy); + SetSessionProxyProperties(ref proxy, cmdlet); + return proxy; + } + + /// + /// Create and set properties + /// + /// + /// + /// + private CimSessionProxy CreateSessionProxy( + CimSession session, + GetCimClassCommand cmdlet) + { + CimSessionProxy proxy = new CimSessionProxyGetCimClass(session); + this.SubscribeEventAndAddProxytoCache(proxy); + SetSessionProxyProperties(ref proxy, cmdlet); + return proxy; + } + + #endregion + + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetInstance.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetInstance.cs new file mode 100644 index 000000000..829959897 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimGetInstance.cs @@ -0,0 +1,517 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Management.Automation; +using System.Text; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// a class used to add pstypename to partial ciminstance + /// for , if -KeyOnly + /// or -SelectProperties is been specified, then add a pstypename: + /// "Microsoft.Management.Infrastructure.CimInstance#__PartialCIMInstance" + /// + internal class FormatPartialCimInstance : IObjectPreProcess + { + /// + /// Partial ciminstance pstypename + /// + internal const string PartialPSTypeName = @"Microsoft.Management.Infrastructure.CimInstance#__PartialCIMInstance"; + + /// + /// Add pstypename to the resultobject if necessary + /// + /// + /// + public object Process(object resultObject) + { + if (resultObject is CimInstance) + { + PSObject obj = PSObject.AsPSObject(resultObject); + obj.TypeNames.Insert(0, PartialPSTypeName); + return obj; + } + return resultObject; + } + } + + /// + /// + /// Implements operations of get-ciminstance cmdlet. + /// + /// + internal class CimGetInstance : CimAsyncOperation + { + /// + /// + /// Constructor + /// + /// + public CimGetInstance() : base() + { + } + + /// + /// + /// Base on parametersetName to retrieve ciminstances + /// + /// + /// object + public void GetCimInstance(GetCimInstanceCommand cmdlet) + { + GetCimInstanceInternal(cmdlet); + } + + /// + /// + /// Refactory to be reused by Get-CimInstance;Remove-CimInstance;Set-CimInstance + /// + /// + /// + protected void GetCimInstanceInternal(CimBaseCommand cmdlet) + { + IEnumerable computerNames = ConstValue.GetComputerNames( + GetComputerName(cmdlet)); + string nameSpace; + List proxys = new List(); + bool isGetCimInstanceCommand = (cmdlet is GetCimInstanceCommand); + CimInstance targetCimInstance = null; + switch (cmdlet.ParameterSetName) + { + case CimBaseCommand.CimInstanceComputerSet: + foreach (string computerName in computerNames) + { + targetCimInstance = GetCimInstanceParameter(cmdlet); + CimSessionProxy proxy = CreateSessionProxy(computerName, targetCimInstance, cmdlet); + if (isGetCimInstanceCommand) + { + this.SetPreProcess(proxy, cmdlet as GetCimInstanceCommand); + } + proxys.Add(proxy); + } + break; + case CimBaseCommand.ClassNameComputerSet: + case CimBaseCommand.QueryComputerSet: + case CimBaseCommand.ResourceUriComputerSet: + foreach (string computerName in computerNames) + { + CimSessionProxy proxy = CreateSessionProxy(computerName, cmdlet); + if (isGetCimInstanceCommand) + { + this.SetPreProcess(proxy, cmdlet as GetCimInstanceCommand); + } + proxys.Add(proxy); + } + break; + case CimBaseCommand.ClassNameSessionSet: + case CimBaseCommand.CimInstanceSessionSet: + case CimBaseCommand.QuerySessionSet: + case CimBaseCommand.ResourceUriSessionSet: + foreach (CimSession session in GetCimSession(cmdlet)) + { + CimSessionProxy proxy = CreateSessionProxy(session, cmdlet); + if (isGetCimInstanceCommand) + { + this.SetPreProcess(proxy, cmdlet as GetCimInstanceCommand); + } + proxys.Add(proxy); + } + break; + default: + break; + } + switch (cmdlet.ParameterSetName) + { + case CimBaseCommand.ClassNameComputerSet: + case CimBaseCommand.ClassNameSessionSet: + nameSpace = ConstValue.GetNamespace(GetNamespace(cmdlet)); + if (IsClassNameQuerySet(cmdlet)) + { + string query = CreateQuery(cmdlet); + DebugHelper.WriteLogEx(@"Query = {0}", 1, query); + foreach (CimSessionProxy proxy in proxys) + { + proxy.QueryInstancesAsync(nameSpace, + ConstValue.GetQueryDialectWithDefault(GetQueryDialect(cmdlet)), + query); + } + } + else + { + foreach (CimSessionProxy proxy in proxys) + { + proxy.EnumerateInstancesAsync(nameSpace, GetClassName(cmdlet)); + } + } + break; + case CimBaseCommand.CimInstanceComputerSet: + case CimBaseCommand.CimInstanceSessionSet: + { + CimInstance instance = GetCimInstanceParameter(cmdlet); + nameSpace = ConstValue.GetNamespace(instance.CimSystemProperties.Namespace); + foreach (CimSessionProxy proxy in proxys) + { + proxy.GetInstanceAsync(nameSpace, instance); + } + } + break; + case CimBaseCommand.QueryComputerSet: + case CimBaseCommand.QuerySessionSet: + nameSpace = ConstValue.GetNamespace(GetNamespace(cmdlet)); + foreach (CimSessionProxy proxy in proxys) + { + proxy.QueryInstancesAsync(nameSpace, + ConstValue.GetQueryDialectWithDefault(GetQueryDialect(cmdlet)), + GetQuery(cmdlet)); + } + break; + case CimBaseCommand.ResourceUriSessionSet: + case CimBaseCommand.ResourceUriComputerSet: + foreach (CimSessionProxy proxy in proxys) + { + proxy.EnumerateInstancesAsync(GetNamespace(cmdlet), GetClassName(cmdlet)); + } + break; + default: + break; + } + } + + #region bridge methods to read properties from cmdlet + + protected static String[] GetComputerName(CimBaseCommand cmdlet) + { + if (cmdlet is GetCimInstanceCommand) + { + return (cmdlet as GetCimInstanceCommand).ComputerName; + } + else if (cmdlet is RemoveCimInstanceCommand) + { + return (cmdlet as RemoveCimInstanceCommand).ComputerName; + } + else if (cmdlet is SetCimInstanceCommand) + { + return (cmdlet as SetCimInstanceCommand).ComputerName; + } + return null; + } + + protected static String GetNamespace(CimBaseCommand cmdlet) + { + if (cmdlet is GetCimInstanceCommand) + { + return (cmdlet as GetCimInstanceCommand).Namespace; + } + else if (cmdlet is RemoveCimInstanceCommand) + { + return (cmdlet as RemoveCimInstanceCommand).Namespace; + } + else if (cmdlet is SetCimInstanceCommand) + { + return (cmdlet as SetCimInstanceCommand).Namespace; + } + return null; + } + + protected static CimSession[] GetCimSession(CimBaseCommand cmdlet) + { + if (cmdlet is GetCimInstanceCommand) + { + return (cmdlet as GetCimInstanceCommand).CimSession; + } + else if (cmdlet is RemoveCimInstanceCommand) + { + return (cmdlet as RemoveCimInstanceCommand).CimSession; + } + else if (cmdlet is SetCimInstanceCommand) + { + return (cmdlet as SetCimInstanceCommand).CimSession; + } + return null; + } + + protected static String GetClassName(CimBaseCommand cmdlet) + { + if (cmdlet is GetCimInstanceCommand) + { + return (cmdlet as GetCimInstanceCommand).ClassName; + } + return null; + } + + protected static String GetQuery(CimBaseCommand cmdlet) + { + if (cmdlet is GetCimInstanceCommand) + { + return (cmdlet as GetCimInstanceCommand).Query; + } + else if (cmdlet is RemoveCimInstanceCommand) + { + return (cmdlet as RemoveCimInstanceCommand).Query; + } + else if (cmdlet is SetCimInstanceCommand) + { + return (cmdlet as SetCimInstanceCommand).Query; + } + return null; + } + + internal static bool IsClassNameQuerySet(CimBaseCommand cmdlet) + { + DebugHelper.WriteLogEx(); + GetCimInstanceCommand cmd = cmdlet as GetCimInstanceCommand; + if (cmd != null) + { + if (cmd.QueryDialect != null || cmd.SelectProperties != null || cmd.Filter != null) + { + return true; + } + } + return false; + } + + protected static String CreateQuery(CimBaseCommand cmdlet) + { + DebugHelper.WriteLogEx(); + GetCimInstanceCommand cmd = cmdlet as GetCimInstanceCommand; + if (cmd != null) + { + StringBuilder propertyList = new StringBuilder(); + if (cmd.SelectProperties == null) + { + propertyList.Append("*"); + } + else + { + foreach (string property in cmd.SelectProperties) + { + if (propertyList.Length > 0) + { + propertyList.Append(","); + } + propertyList.Append(property); + } + } + return (cmd.Filter == null) ? + String.Format(CultureInfo.CurrentUICulture, queryWithoutWhere, propertyList, cmd.ClassName) : + String.Format(CultureInfo.CurrentUICulture, queryWithWhere, propertyList, cmd.ClassName, cmd.Filter); + } + return null; + } + + protected static String GetQueryDialect(CimBaseCommand cmdlet) + { + if (cmdlet is GetCimInstanceCommand) + { + return (cmdlet as GetCimInstanceCommand).QueryDialect; + } + else if (cmdlet is RemoveCimInstanceCommand) + { + return (cmdlet as RemoveCimInstanceCommand).QueryDialect; + } + else if (cmdlet is SetCimInstanceCommand) + { + return (cmdlet as SetCimInstanceCommand).QueryDialect; + } + return null; + } + + protected static CimInstance GetCimInstanceParameter(CimBaseCommand cmdlet) + { + if (cmdlet is GetCimInstanceCommand) + { + return (cmdlet as GetCimInstanceCommand).CimInstance; + } + else if (cmdlet is RemoveCimInstanceCommand) + { + return (cmdlet as RemoveCimInstanceCommand).CimInstance; + } + else if (cmdlet is SetCimInstanceCommand) + { + return (cmdlet as SetCimInstanceCommand).CimInstance; + } + return null; + } + #endregion + + #region help methods + + /// + /// + /// Set properties + /// + /// + /// + /// + private void SetSessionProxyProperties( + ref CimSessionProxy proxy, + CimBaseCommand cmdlet) + { + if (cmdlet is GetCimInstanceCommand) + { + GetCimInstanceCommand getCimInstance = cmdlet as GetCimInstanceCommand; + proxy.KeyOnly = getCimInstance.KeyOnly; + proxy.Shallow = getCimInstance.Shallow; + proxy.OperationTimeout = getCimInstance.OperationTimeoutSec; + if(getCimInstance.ResourceUri != null ) + { + proxy.ResourceUri = getCimInstance.ResourceUri; + } + } + else if (cmdlet is RemoveCimInstanceCommand) + { + RemoveCimInstanceCommand removeCimInstance = cmdlet as RemoveCimInstanceCommand; + proxy.OperationTimeout = removeCimInstance.OperationTimeoutSec; + if(removeCimInstance.ResourceUri != null ) + { + proxy.ResourceUri = removeCimInstance.ResourceUri; + } + CimRemoveCimInstanceContext context = new CimRemoveCimInstanceContext( + ConstValue.GetNamespace(removeCimInstance.Namespace), + proxy); + proxy.ContextObject = context; + } + else if (cmdlet is SetCimInstanceCommand) + { + SetCimInstanceCommand setCimInstance = cmdlet as SetCimInstanceCommand; + proxy.OperationTimeout = setCimInstance.OperationTimeoutSec; + if(setCimInstance.ResourceUri != null ) + { + proxy.ResourceUri = setCimInstance.ResourceUri; + } + CimSetCimInstanceContext context = new CimSetCimInstanceContext( + ConstValue.GetNamespace(setCimInstance.Namespace), + setCimInstance.Property, + proxy, + cmdlet.ParameterSetName, + setCimInstance.PassThru); + proxy.ContextObject = context; + } + } + + /// + /// + /// Create and set properties. + /// + /// + /// + /// + /// + protected CimSessionProxy CreateSessionProxy( + string computerName, + CimBaseCommand cmdlet) + { + CimSessionProxy proxy = CreateCimSessionProxy(computerName); + SetSessionProxyProperties(ref proxy, cmdlet); + return proxy; + } + + /// + /// + /// Create and set properties. + /// + /// + /// + /// + /// + /// + protected CimSessionProxy CreateSessionProxy( + string computerName, + CimInstance cimInstance, + CimBaseCommand cmdlet, + bool passThru) + { + CimSessionProxy proxy = CreateCimSessionProxy(computerName, cimInstance, passThru); + SetSessionProxyProperties(ref proxy, cmdlet); + return proxy; + } + + /// + /// Create and set properties + /// + /// + /// + /// + protected CimSessionProxy CreateSessionProxy( + CimSession session, + CimBaseCommand cmdlet) + { + CimSessionProxy proxy = CreateCimSessionProxy(session); + SetSessionProxyProperties(ref proxy, cmdlet); + return proxy; + } + + /// + /// + /// Create and set properties + /// + /// + /// + /// + /// + /// + protected CimSessionProxy CreateSessionProxy( + string computerName, + CimInstance cimInstance, + CimBaseCommand cmdlet) + { + CimSessionProxy proxy = CreateCimSessionProxy(computerName, cimInstance); + SetSessionProxyProperties(ref proxy, cmdlet); + return proxy; + } + + /// + /// Create and set properties + /// + /// + /// + /// + protected CimSessionProxy CreateSessionProxy( + CimSession session, + CimBaseCommand cmdlet, + bool passThru) + { + CimSessionProxy proxy = CreateCimSessionProxy(session, passThru); + SetSessionProxyProperties(ref proxy, cmdlet); + return proxy; + } + + /// + /// Set object to proxy to pre-process + /// the result object if necessary + /// + /// + /// + private void SetPreProcess(CimSessionProxy proxy, GetCimInstanceCommand cmdlet) + { + if (cmdlet.KeyOnly || (cmdlet.SelectProperties != null)) + { + proxy.ObjectPreProcess = new FormatPartialCimInstance(); + } + } + #endregion + + #region const strings + /// + /// wql query format with where clause + /// + private const string queryWithWhere = @"SELECT {0} FROM {1} WHERE {2}"; + + /// + /// wql query format without where clause + /// + private const string queryWithoutWhere = @"SELECT {0} FROM {1}"; + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimIndicationWatcher.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimIndicationWatcher.cs new file mode 100644 index 000000000..74f618b08 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimIndicationWatcher.cs @@ -0,0 +1,399 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using System.ComponentModel; +using System.Management.Automation; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// + /// Abstract Cimindication event args, which containing all elements related to + /// an Cimindication. + /// + /// + public abstract class CimIndicationEventArgs : EventArgs + { + /// + /// + /// Returns an Object value for an operation context + /// + /// + public Object Context + { + get + { + return context; + } + } + internal Object context; + } + + /// + /// Cimindication exception event args, which containing occurred exception + /// + public class CimIndicationEventExceptionEventArgs : CimIndicationEventArgs + { + /// + /// + /// Returns an exception + /// + /// + public Exception Exception + { + get + { + return exception; + } + } + private Exception exception; + + /// + /// + /// Constructor + /// + /// + /// + public CimIndicationEventExceptionEventArgs(Exception theException) + { + context = null; + this.exception = theException; + } + } + + /// + /// Cimindication event args, which containing all elements related to + /// an Cimindication. + /// + public class CimIndicationEventInstanceEventArgs : CimIndicationEventArgs + { + /// + /// Get ciminstance of the indication object + /// + public CimInstance NewEvent + { + get + { + return (result == null) ? null : result.Instance; + } + } + + /// + /// Get MachineId of the indication object + /// + public string MachineId + { + get + { + return (result == null) ? null : result.MachineId; + } + } + + /// + /// Get BookMark of the indication object + /// + public string Bookmark + { + get + { + return (result == null) ? null : result.Bookmark; + } + } + + /// + /// + /// Constructor + /// + /// + /// + public CimIndicationEventInstanceEventArgs(CimSubscriptionResult result) + { + context = null; + this.result = result; + } + + /// + /// + /// subscription result + /// + /// + private CimSubscriptionResult result; + } + + /// + /// + /// A public class used to start/stop the subscription to specific indication source, + /// and listen to the incoming indications, event + /// will be raised for each cimindication. + /// + /// + public class CimIndicationWatcher + { + /// + /// status of object. + /// + internal enum Status + { + Default, + Started, + Stopped + } + + /// + /// + /// CimIndication arrived event + /// + /// + public event EventHandler CimIndicationArrived; + + /// + /// + /// Constructor with given computerName, namespace, queryExpression and timeout + /// + /// + /// + /// + /// + /// + public CimIndicationWatcher( + string computerName, + string theNamespace, + string queryDialect, + string queryExpression, + UInt32 operationTimeout) + { + ValidationHelper.ValidateNoNullorWhiteSpaceArgument(queryExpression, queryExpressionParameterName); + computerName = ConstValue.GetComputerName(computerName); + theNamespace = ConstValue.GetNamespace(theNamespace); + Initialize(computerName, null, theNamespace, queryDialect, queryExpression, operationTimeout); + } + + /// + /// + /// Constructor with given cimsession, namespace, queryExpression and timeout + /// + /// + /// + /// + /// + /// + public CimIndicationWatcher( + CimSession cimSession, + string theNamespace, + string queryDialect, + string queryExpression, + UInt32 operationTimeout) + { + ValidationHelper.ValidateNoNullorWhiteSpaceArgument(queryExpression, queryExpressionParameterName); + ValidationHelper.ValidateNoNullArgument(cimSession, cimSessionParameterName); + theNamespace = ConstValue.GetNamespace(theNamespace); + Initialize(null, cimSession, theNamespace, queryDialect, queryExpression, operationTimeout); + } + + /// + /// + /// Initialize + /// + /// + private void Initialize( + string theComputerName, + CimSession theCimSession, + string theNameSpace, + string theQueryDialect, + string theQueryExpression, + UInt32 theOpreationTimeout) + { + enableRaisingEvents = false; + status = Status.Default; + myLock = new object(); + cimRegisterCimIndication = new CimRegisterCimIndication(); + cimRegisterCimIndication.OnNewSubscriptionResult += NewSubscriptionResultHandler; + + this.cimSession = theCimSession; + this.nameSpace = theNameSpace; + this.queryDialect = ConstValue.GetQueryDialectWithDefault(theQueryDialect); + this.queryExpression = theQueryExpression; + this.opreationTimeout = theOpreationTimeout; + this.computerName = theComputerName; + } + + /// + /// + /// Hanlder of new subscription result + /// + /// + /// + /// + private void NewSubscriptionResultHandler(object src, CimSubscriptionEventArgs args) + { + EventHandler temp = this.CimIndicationArrived; + if (temp != null) + { + // raise the event + CimSubscriptionResultEventArgs resultArgs = args as CimSubscriptionResultEventArgs; + if (resultArgs != null) + temp(this, new CimIndicationEventInstanceEventArgs(resultArgs.Result)); + else + { + CimSubscriptionExceptionEventArgs exceptionArgs = args as CimSubscriptionExceptionEventArgs; + if (exceptionArgs != null) + temp(this, new CimIndicationEventExceptionEventArgs(exceptionArgs.Exception)); + } + } + } + + /// + /// + /// Will be called by admin\monad\src\eengine\EventManager.cs: + /// PSEventManager::ProcessNewSubscriber to start to listen to the Cim Indication. + /// + /// + /// If set EnableRaisingEvents to false, which will be ignored + /// + /// +#if !CORECLR + [BrowsableAttribute(false)] +#endif + public bool EnableRaisingEvents + { + get + { + return enableRaisingEvents; + } + set + { + DebugHelper.WriteLogEx(); + if (value && !enableRaisingEvents) + { + enableRaisingEvents = value; + Start(); + } + } + } + private bool enableRaisingEvents; + + /// + /// + /// Start the subscription + /// + /// + public void Start() + { + DebugHelper.WriteLogEx(); + + lock(myLock) + { + if (status == Status.Default) + { + if (this.cimSession == null) + { + cimRegisterCimIndication.RegisterCimIndication( + this.computerName, + this.nameSpace, + this.queryDialect, + this.queryExpression, + this.opreationTimeout); + } + else + { + cimRegisterCimIndication.RegisterCimIndication( + this.cimSession, + this.nameSpace, + this.queryDialect, + this.queryExpression, + this.opreationTimeout); + } + status = Status.Started; + } + } + } + + /// + /// + /// Unsubscribe the subscription + /// + /// + public void Stop() + { + DebugHelper.WriteLogEx("Status = {0}", 0, this.status); + + lock (this.myLock) + { + if (status == Status.Started) + { + if (this.cimRegisterCimIndication != null) + { + DebugHelper.WriteLog("Dispose CimRegisterCimIndication object", 4); + this.cimRegisterCimIndication.Dispose(); + } + status = Status.Stopped; + } + } + } + + #region internal method + /// + /// Set the cmdlet object to throw ThrowTerminatingError + /// in case there is a subscription failure + /// + /// + internal void SetCmdlet(Cmdlet cmdlet) + { + if (this.cimRegisterCimIndication != null) + { + this.cimRegisterCimIndication.Cmdlet = cmdlet; + } + } + #endregion + + #region private members + /// + /// + /// CimRegisterCimIndication object + /// + /// + private CimRegisterCimIndication cimRegisterCimIndication; + + /// + /// the status of object + /// + private Status status; + + /// + /// lock started field + /// + private object myLock; + + /// + /// CimSession parameter name + /// + private const string cimSessionParameterName = "cimSession"; + + /// + /// QueryExpression parameter name + /// + private const string queryExpressionParameterName = "queryExpression"; + + #region parameters + /// + /// + /// parameters used to start the subscription + /// + /// + private string computerName; + private CimSession cimSession; + private string nameSpace; + private string queryDialect; + private string queryExpression; + private UInt32 opreationTimeout; + #endregion + #endregion + } +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimInvokeCimMethod.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimInvokeCimMethod.cs new file mode 100644 index 000000000..667f7e163 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimInvokeCimMethod.cs @@ -0,0 +1,458 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Management.Automation; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// + /// Implements operations of invoke-cimmethod cmdlet. + /// + /// + internal sealed class CimInvokeCimMethod : CimAsyncOperation + { + /// + /// Containing all necessary information originated from + /// the parameters of + /// + internal class CimInvokeCimMethodContext : XOperationContextBase + { + /// + /// + /// Constructor + /// + /// + /// + /// + /// + internal CimInvokeCimMethodContext(string theNamespace, + string theMethodName, + CimMethodParametersCollection theCollection, + CimSessionProxy theProxy) + { + this.proxy = theProxy; + this.methodName = theMethodName; + this.collection = theCollection; + this.nameSpace = theNamespace; + } + + /// + /// namespce + /// + internal string MethodName + { + get + { + return this.methodName; + } + } + private string methodName; + + /// + /// parameters collection + /// + internal CimMethodParametersCollection ParametersCollection + { + get + { + return this.collection; + } + } + private CimMethodParametersCollection collection; + } + + /// + /// + /// Constructor + /// + /// + public CimInvokeCimMethod() + : base() + { + } + + /// + /// + /// Base on parametersetName to retrieve ciminstances + /// + /// + /// object + public void InvokeCimMethod(InvokeCimMethodCommand cmdlet) + { + IEnumerable computerNames = ConstValue.GetComputerNames(cmdlet.ComputerName); + string nameSpace; + List proxys = new List(); + string action = string.Format(CultureInfo.CurrentUICulture, actionTemplate, cmdlet.MethodName); + + switch (cmdlet.ParameterSetName) + { + case CimBaseCommand.CimInstanceComputerSet: + foreach (string computerName in computerNames) + { + proxys.Add(CreateSessionProxy(computerName, cmdlet.CimInstance, cmdlet)); + } + break; + case CimBaseCommand.ClassNameComputerSet: + case CimBaseCommand.CimClassComputerSet: + case CimBaseCommand.ResourceUriComputerSet: + case CimBaseCommand.QueryComputerSet: + foreach (string computerName in computerNames) + { + proxys.Add(CreateSessionProxy(computerName, cmdlet)); + } + break; + case CimBaseCommand.ClassNameSessionSet: + case CimBaseCommand.CimClassSessionSet: + case CimBaseCommand.QuerySessionSet: + case CimBaseCommand.CimInstanceSessionSet: + case CimBaseCommand.ResourceUriSessionSet: + foreach (CimSession session in cmdlet.CimSession) + { + CimSessionProxy proxy = CreateSessionProxy(session, cmdlet); + proxys.Add(proxy); + } + break; + default: + break; + } + CimMethodParametersCollection paramsCollection = + CreateParametersCollection(cmdlet.Arguments, cmdlet.CimClass, cmdlet.CimInstance, cmdlet.MethodName); + + // Invoke methods + switch (cmdlet.ParameterSetName) + { + case CimBaseCommand.ClassNameComputerSet: + case CimBaseCommand.ClassNameSessionSet: + case CimBaseCommand.ResourceUriSessionSet: + case CimBaseCommand.ResourceUriComputerSet: + { + string target = string.Format(CultureInfo.CurrentUICulture, targetClass, cmdlet.ClassName); + if(cmdlet.ResourceUri != null ) + { + nameSpace = cmdlet.Namespace; + } + else + { + nameSpace = ConstValue.GetNamespace(cmdlet.Namespace); + } + foreach (CimSessionProxy proxy in proxys) + { + if (!cmdlet.ShouldProcess(target, action)) + { + return; + } + proxy.InvokeMethodAsync( + nameSpace, + cmdlet.ClassName, + cmdlet.MethodName, + paramsCollection); + } + } + break; + case CimBaseCommand.CimClassComputerSet: + case CimBaseCommand.CimClassSessionSet: + { + string target = string.Format(CultureInfo.CurrentUICulture, targetClass, cmdlet.CimClass.CimSystemProperties.ClassName); + nameSpace = ConstValue.GetNamespace(cmdlet.CimClass.CimSystemProperties.Namespace); + foreach (CimSessionProxy proxy in proxys) + { + if (!cmdlet.ShouldProcess(target, action)) + { + return; + } + proxy.InvokeMethodAsync( + nameSpace, + cmdlet.CimClass.CimSystemProperties.ClassName, + cmdlet.MethodName, + paramsCollection); + } + } + break; + case CimBaseCommand.QueryComputerSet: + case CimBaseCommand.QuerySessionSet: + nameSpace = ConstValue.GetNamespace(cmdlet.Namespace); + foreach (CimSessionProxy proxy in proxys) + { + // create context object + CimInvokeCimMethodContext context = new CimInvokeCimMethodContext( + nameSpace, + cmdlet.MethodName, + paramsCollection, + proxy); + proxy.ContextObject = context; + // firstly query instance and then invoke method upon returned instances + proxy.QueryInstancesAsync(nameSpace, ConstValue.GetQueryDialectWithDefault(cmdlet.QueryDialect), cmdlet.Query); + } + break; + case CimBaseCommand.CimInstanceComputerSet: + case CimBaseCommand.CimInstanceSessionSet: + { + string target = cmdlet.CimInstance.ToString(); + if(cmdlet.ResourceUri != null ) + { + nameSpace = cmdlet.Namespace; + } + else + { + nameSpace = ConstValue.GetNamespace(cmdlet.CimInstance.CimSystemProperties.Namespace); + } + foreach (CimSessionProxy proxy in proxys) + { + if (!cmdlet.ShouldProcess(target, action)) + { + return; + } + proxy.InvokeMethodAsync( + nameSpace, + cmdlet.CimInstance, + cmdlet.MethodName, + paramsCollection); + } + } + break; + default: + break; + } + } + + /// + /// + /// Invoke cimmethod on given + /// + /// + /// + public void InvokeCimMethodOnCimInstance(CimInstance cimInstance, XOperationContextBase context, CmdletOperationBase operation) + { + DebugHelper.WriteLogEx(); + CimInvokeCimMethodContext cimInvokeCimMethodContext = context as CimInvokeCimMethodContext; + Debug.Assert(cimInvokeCimMethodContext != null, "CimInvokeCimMethod::InvokeCimMethodOnCimInstance should has CimInvokeCimMethodContext != NULL."); + + string action = string.Format(CultureInfo.CurrentUICulture, actionTemplate, cimInvokeCimMethodContext.MethodName); + if (!operation.ShouldProcess(cimInstance.ToString(), action)) + { + return; + } + + CimSessionProxy proxy = CreateCimSessionProxy(cimInvokeCimMethodContext.Proxy); + proxy.InvokeMethodAsync( + cimInvokeCimMethodContext.Namespace, + cimInstance, + cimInvokeCimMethodContext.MethodName, + cimInvokeCimMethodContext.ParametersCollection); + } + + #region private methods + + /// + /// + /// Set properties + /// + /// + /// + /// + private void SetSessionProxyProperties( + ref CimSessionProxy proxy, + InvokeCimMethodCommand cmdlet) + { + proxy.OperationTimeout = cmdlet.OperationTimeoutSec; + if(cmdlet.ResourceUri != null ) + { + proxy.ResourceUri = cmdlet.ResourceUri; + } + } + + /// + /// + /// Create and set properties + /// + /// + /// + /// + /// + private CimSessionProxy CreateSessionProxy( + string computerName, + InvokeCimMethodCommand cmdlet) + { + CimSessionProxy proxy = CreateCimSessionProxy(computerName); + SetSessionProxyProperties(ref proxy, cmdlet); + return proxy; + } + + /// + /// + /// Create and set properties + /// + /// + /// + /// + /// + /// + private CimSessionProxy CreateSessionProxy( + string computerName, + CimInstance cimInstance, + InvokeCimMethodCommand cmdlet) + { + CimSessionProxy proxy = CreateCimSessionProxy(computerName, cimInstance); + SetSessionProxyProperties(ref proxy, cmdlet); + return proxy; + } + + /// + /// Create and set properties + /// + /// + /// + /// + private CimSessionProxy CreateSessionProxy( + CimSession session, + InvokeCimMethodCommand cmdlet) + { + CimSessionProxy proxy = CreateCimSessionProxy(session); + SetSessionProxyProperties(ref proxy, cmdlet); + return proxy; + } + + /// + /// + /// Create with given key properties. + /// And/or object. + /// + /// + /// + /// + /// + /// + /// + /// See CimProperty.Create + /// CimProperty.Create + private CimMethodParametersCollection CreateParametersCollection( + IDictionary parameters, + CimClass cimClass, + CimInstance cimInstance, + string methodName) + { + DebugHelper.WriteLogEx(); + + CimMethodParametersCollection collection = null; + if (parameters == null) + { + return collection; + } + else if (parameters.Count == 0) + { + return collection; + } + + collection = new CimMethodParametersCollection(); + IDictionaryEnumerator enumerator = parameters.GetEnumerator(); + while (enumerator.MoveNext()) + { + string parameterName = enumerator.Key.ToString(); + + CimFlags parameterFlags = CimFlags.In; + object parameterValue = GetBaseObject(enumerator.Value); + + DebugHelper.WriteLog(@"Create parameter name= {0}, value= {1}, flags= {2}.", 4, + parameterName, + parameterValue, + parameterFlags); + + CimMethodParameter parameter = null; + CimMethodDeclaration declaration = null; + string className = null; + if (cimClass != null) + { + className = cimClass.CimSystemProperties.ClassName; + declaration = cimClass.CimClassMethods[methodName]; + if (declaration == null) + { + throw new ArgumentException(String.Format( + CultureInfo.CurrentUICulture, Strings.InvalidMethod, methodName, className)); + } + } + else if (cimInstance != null) + { + className = cimInstance.CimClass.CimSystemProperties.ClassName; + declaration = cimInstance.CimClass.CimClassMethods[methodName]; + } + + if (declaration != null) + { + CimMethodParameterDeclaration paramDeclaration = declaration.Parameters[parameterName]; + if (paramDeclaration == null) + { + throw new ArgumentException(String.Format( + CultureInfo.CurrentUICulture, Strings.InvalidMethodParameter, parameterName, methodName, className)); + } + parameter = CimMethodParameter.Create( + parameterName, + parameterValue, + paramDeclaration.CimType, + parameterFlags); + // FIXME: check in/out qualifier + // parameterFlags = paramDeclaration.Qualifiers; + } + else + { + if (parameterValue == null) + { + // try the best to get the type while value is null + parameter = CimMethodParameter.Create( + parameterName, + parameterValue, + CimType.String, + parameterFlags); + } + else + { + CimType referenceType = CimType.Unknown; + object referenceObject = GetReferenceOrReferenceArrayObject(parameterValue, ref referenceType); + if (referenceObject != null) + { + parameter = CimMethodParameter.Create( + parameterName, + referenceObject, + referenceType, + parameterFlags); + } + else + { + parameter = CimMethodParameter.Create( + parameterName, + parameterValue, + parameterFlags); + } + } + } + if (parameter != null) + collection.Add(parameter); + } + return collection; + } + #endregion + + #region const strings + /// + /// operation target + /// + private const string targetClass = @"{0}"; + + /// + /// action + /// + private const string actionTemplate = @"Invoke-CimMethod: {0}"; + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimNewCimInstance.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimNewCimInstance.cs new file mode 100644 index 000000000..bc462dd7c --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimNewCimInstance.cs @@ -0,0 +1,362 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Management.Automation; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// Containing all information originated from + /// the parameters of + /// + internal class CimNewCimInstanceContext : XOperationContextBase + { + /// + /// + /// Constructor + /// + /// + /// + /// + /// + internal CimNewCimInstanceContext( + CimSessionProxy theProxy, + string theNamespace) + { + this.proxy = theProxy; + this.nameSpace = theNamespace; + } + } + + /// + /// + /// Implements operations of new-ciminstance cmdlet. + /// + /// + internal sealed class CimNewCimInstance : CimAsyncOperation + { + /// + /// + /// Constructor + /// + /// + public CimNewCimInstance() + : base() + { + } + + /// + /// + /// Base on parametersetName to create ciminstances, + /// either remotely or locally + /// + /// + /// object + public void NewCimInstance(NewCimInstanceCommand cmdlet) + { + DebugHelper.WriteLogEx(); + + string nameSpace; + CimInstance cimInstance = null; + try + { + switch (cmdlet.ParameterSetName) + { + case CimBaseCommand.ClassNameComputerSet: + case CimBaseCommand.ClassNameSessionSet: + { + nameSpace = ConstValue.GetNamespace(cmdlet.Namespace); + cimInstance = CreateCimInstance(cmdlet.ClassName, + nameSpace, + cmdlet.Key, + cmdlet.Property, + cmdlet); + + } + break; + case CimBaseCommand.ResourceUriSessionSet: + case CimBaseCommand.ResourceUriComputerSet: + { + nameSpace = cmdlet.Namespace; //passing null is ok for resourceUri set + cimInstance = CreateCimInstance("DummyClass", + nameSpace, + cmdlet.Key, + cmdlet.Property, + cmdlet); + + } + break; + case CimBaseCommand.CimClassComputerSet: + case CimBaseCommand.CimClassSessionSet: + { + nameSpace = ConstValue.GetNamespace(cmdlet.CimClass.CimSystemProperties.Namespace); + cimInstance = CreateCimInstance(cmdlet.CimClass, + cmdlet.Property, + cmdlet); + + } + break; + default: + return; + } + } + catch (ArgumentNullException e) + { + cmdlet.ThrowTerminatingError(e, action); + return; + } + catch (ArgumentException e) + { + cmdlet.ThrowTerminatingError(e, action); + return; + } + + // return if create client only ciminstance + if (cmdlet.ClientOnly) + { + cmdlet.CmdletOperation.WriteObject(cimInstance, null); + return; + } + + string target = cimInstance.ToString(); + if (!cmdlet.ShouldProcess(target, action)) + { + return; + } + + // create ciminstance on server + List proxys = new List(); + + switch (cmdlet.ParameterSetName) + { + case CimBaseCommand.ClassNameComputerSet: + case CimBaseCommand.CimClassComputerSet: + case CimBaseCommand.ResourceUriComputerSet: + { + IEnumerable computerNames = ConstValue.GetComputerNames( + cmdlet.ComputerName); + foreach (string computerName in computerNames) + { + proxys.Add(CreateSessionProxy(computerName, cmdlet)); + } + } + break; + case CimBaseCommand.CimClassSessionSet: + case CimBaseCommand.ClassNameSessionSet: + case CimBaseCommand.ResourceUriSessionSet: + foreach (CimSession session in cmdlet.CimSession) + { + proxys.Add(CreateSessionProxy(session, cmdlet)); + } + break; + } + + foreach (CimSessionProxy proxy in proxys) + { + proxy.ContextObject = new CimNewCimInstanceContext(proxy, nameSpace); + proxy.CreateInstanceAsync(nameSpace, cimInstance); + } + } + + #region Get CimInstance after creation (on server) + + /// + /// + /// Get full from server based on the key + /// + /// + /// + internal void GetCimInstance(CimInstance cimInstance, XOperationContextBase context) + { + DebugHelper.WriteLogEx(); + + CimNewCimInstanceContext newCimInstanceContext = context as CimNewCimInstanceContext; + if (newCimInstanceContext == null) + { + DebugHelper.WriteLog("Invalid (null) CimNewCimInstanceContext", 1); + return; + } + + CimSessionProxy proxy = CreateCimSessionProxy(newCimInstanceContext.Proxy); + string nameSpace = (cimInstance.CimSystemProperties.Namespace == null) ? newCimInstanceContext.Namespace : cimInstance.CimSystemProperties.Namespace; + proxy.GetInstanceAsync(nameSpace, cimInstance); + } + + #endregion + + #region private methods + + /// + /// + /// Set properties + /// + /// + /// + /// + private void SetSessionProxyProperties( + ref CimSessionProxy proxy, + NewCimInstanceCommand cmdlet) + { + proxy.OperationTimeout = cmdlet.OperationTimeoutSec; + if(cmdlet.ResourceUri != null) + { + proxy.ResourceUri = cmdlet.ResourceUri; + } + } + + /// + /// + /// Create and set properties + /// + /// + /// + /// + /// + private CimSessionProxy CreateSessionProxy( + string computerName, + NewCimInstanceCommand cmdlet) + { + CimSessionProxy proxy = new CimSessionProxyNewCimInstance(computerName, this); + this.SubscribeEventAndAddProxytoCache(proxy); + SetSessionProxyProperties(ref proxy, cmdlet); + return proxy; + } + + /// + /// Create and set properties + /// + /// + /// + /// + private CimSessionProxy CreateSessionProxy( + CimSession session, + NewCimInstanceCommand cmdlet) + { + CimSessionProxy proxy = new CimSessionProxyNewCimInstance(session, this); + this.SubscribeEventAndAddProxytoCache(proxy); + SetSessionProxyProperties(ref proxy, cmdlet); + return proxy; + } + + /// + /// + /// Create with given properties. + /// + /// + /// + /// + /// + /// + /// + /// See CimProperty.Create + /// CimProperty.Create + private CimInstance CreateCimInstance( + string className, + string cimNamespace, + IEnumerable key, + IDictionary properties, + NewCimInstanceCommand cmdlet) + { + CimInstance cimInstance = new CimInstance(className,cimNamespace); + if (properties == null) + { + return cimInstance; + } + + List keys = new List(); + if (key != null) + { + foreach (string keyName in key) + { + keys.Add(keyName); + } + } + + IDictionaryEnumerator enumerator = properties.GetEnumerator(); + while (enumerator.MoveNext()) + { + CimFlags flag = CimFlags.None; + string propertyName = enumerator.Key.ToString().Trim(); + if (keys.Contains(propertyName, StringComparer.OrdinalIgnoreCase)) + { + flag = CimFlags.Key; + } + object propertyValue = GetBaseObject(enumerator.Value); + + DebugHelper.WriteLog("Create and add new property to ciminstance: name = {0}; value = {1}; flags = {2}", 5, propertyName, propertyValue, flag); + + PSReference cimReference = propertyValue as PSReference; + if( cimReference != null ) + { + CimProperty newProperty = CimProperty.Create(propertyName, GetBaseObject(cimReference.Value), CimType.Reference, flag); + cimInstance.CimInstanceProperties.Add(newProperty); + } + else + { + CimProperty newProperty = CimProperty.Create( + propertyName, + propertyValue, + flag); + cimInstance.CimInstanceProperties.Add(newProperty); + } + + } + return cimInstance; + } + + /// + /// + /// Create with given properties. + /// + /// + /// + /// + /// + /// + /// See CimProperty.Create + /// CimProperty.Create + private CimInstance CreateCimInstance( + CimClass cimClass, + IDictionary properties, + NewCimInstanceCommand cmdlet) + { + CimInstance cimInstance = new CimInstance(cimClass); + if (properties == null) + { + return cimInstance; + } + List notfoundProperties = new List(); + foreach (string property in properties.Keys) + { + if (cimInstance.CimInstanceProperties[property] == null) + { + notfoundProperties.Add(property); + cmdlet.ThrowInvalidProperty(notfoundProperties, cmdlet.CimClass.CimSystemProperties.ClassName, @"Property", action, properties); + return null; + } + object propertyValue = GetBaseObject(properties[property]); + cimInstance.CimInstanceProperties[property].Value = propertyValue; + } + return cimInstance; + } + + #endregion + + #region const strings + /// + /// action + /// + private const string action = @"New-CimInstance"; + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimPromptUser.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimPromptUser.cs new file mode 100644 index 000000000..0c9ee96db --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimPromptUser.cs @@ -0,0 +1,139 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives +using Microsoft.Management.Infrastructure.Options; +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// + /// Prompt user the message coming from provider. + /// + /// + /// At the same time class will prepare the + /// message for -whatif parameter, while the message represents + /// what will happen if execute the operation, but not do the operation. + /// For example, Remove-CimInstance, the whatif message will like, + /// "CIM Instance: Win32_Process@{Key=1} will be deleted." + /// + /// + internal sealed class CimPromptUser : CimSyncAction + { + /// + /// Constructor + /// + public CimPromptUser(string message, + CimPromptType prompt) + { + this.message = message; + this.prompt = prompt; + } + + /// + /// + /// Prompt user with the given message and prepared whatif message. + /// + /// + /// + /// cmdlet wrapper object, to which write result. + /// for details. + /// + public override void Execute(CmdletOperationBase cmdlet) + { + ValidationHelper.ValidateNoNullArgument(cmdlet, "cmdlet"); + + bool yestoall = false; + bool notoall = false; + bool result = false; + + switch (this.prompt) + { + case CimPromptType.Critical: + // NOTES: prepare the whatif message and caption + try + { + result = cmdlet.ShouldContinue(message, "caption", ref yestoall, ref notoall); + if (yestoall) + { + this.responseType = CimResponseType.YesToAll; + } + else if (notoall) + { + this.responseType = CimResponseType.NoToAll; + } + else if (result) + { + this.responseType = CimResponseType.Yes; + } + else if (!result) + { + this.responseType = CimResponseType.No; + } + } + catch + { + this.responseType = CimResponseType.NoToAll; + throw; + } + finally + { + // unblocking the waiting thread + this.OnComplete(); + } + break; + case CimPromptType.Normal: + try + { + result = cmdlet.ShouldProcess(message); + if (result) + { + this.responseType = CimResponseType.Yes; + } + else if (!result) + { + this.responseType = CimResponseType.No; + } + } + catch + { + this.responseType = CimResponseType.NoToAll; + throw; + } + finally + { + // unblocking the waiting thread + this.OnComplete(); + } + break; + default: + break; + } + this.OnComplete(); + } + + #region members + + /// + /// prompt message + /// + public string Message + { + get + { + return message; + } + } + private string message; + + /// + /// prompt type -Normal or Critical + /// + private CimPromptType prompt; + + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimRegisterCimIndication.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimRegisterCimIndication.cs new file mode 100644 index 000000000..f4c2589fb --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimRegisterCimIndication.cs @@ -0,0 +1,374 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using System.Globalization; +using System.Management.Automation; +using System.Threading; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + + /// + /// + /// Subscription result event args + /// + /// + internal abstract class CimSubscriptionEventArgs : EventArgs + { + /// + /// + /// Returns an Object value for an operation context + /// + /// + public Object Context + { + get + { + return context; + } + } + protected Object context; + } + + /// + /// + /// Subscription result event args + /// + /// + internal class CimSubscriptionResultEventArgs : CimSubscriptionEventArgs + { + /// + /// + /// subscription result + /// + /// + public CimSubscriptionResult Result + { + get + { + return result; + } + } + private CimSubscriptionResult result; + + /// + /// Constructor + /// + /// + public CimSubscriptionResultEventArgs( + CimSubscriptionResult theResult) + { + this.context = null; + this.result = theResult; + } + } + + /// + /// + /// Subscription result event args + /// + /// + internal class CimSubscriptionExceptionEventArgs : CimSubscriptionEventArgs + { + /// + /// + /// subscription result + /// + /// + public Exception Exception + { + get + { + return exception; + } + } + private Exception exception; + + /// + /// Constructor + /// + /// + public CimSubscriptionExceptionEventArgs( + Exception theException) + { + this.context = null; + this.exception = theException; + } + } + + /// + /// + /// Implements operations of register-cimindication cmdlet. + /// + /// + internal sealed class CimRegisterCimIndication : CimAsyncOperation + { + /// + /// + /// New subscritpion result event + /// + /// + public event EventHandler OnNewSubscriptionResult; + + /// + /// + /// Constructor + /// + /// + public CimRegisterCimIndication() + : base() + { + this.ackedEvent = new ManualResetEventSlim(false); + } + + /// + /// Start an indication subsctiption target to the given computer. + /// + /// null stands for localhost + /// + /// + /// + /// + public void RegisterCimIndication( + string computerName, + string nameSpace, + string queryDialect, + string queryExpression, + UInt32 opreationTimeout) + { + DebugHelper.WriteLogEx("queryDialect = '{0}'; queryExpression = '{1}'", 0, queryDialect, queryExpression); + this.TargetComputerName = computerName; + CimSessionProxy proxy = CreateSessionProxy(computerName, opreationTimeout); + proxy.SubscribeAsync(nameSpace, queryDialect, queryExpression); + WaitForAckMessage(); + } + + /// + /// Start an indication subsctiption through a given . + /// + /// Cannot be null + /// + /// + /// + /// + /// throw if cimSession is null + public void RegisterCimIndication( + CimSession cimSession, + string nameSpace, + string queryDialect, + string queryExpression, + UInt32 opreationTimeout) + { + DebugHelper.WriteLogEx("queryDialect = '{0}'; queryExpression = '{1}'", 0, queryDialect, queryExpression); + if (cimSession == null) + { + throw new ArgumentNullException(String.Format(CultureInfo.CurrentUICulture, Strings.NullArgument, @"cimSession")); + } + this.TargetComputerName = cimSession.ComputerName; + CimSessionProxy proxy = CreateSessionProxy(cimSession, opreationTimeout); + proxy.SubscribeAsync(nameSpace, queryDialect, queryExpression); + WaitForAckMessage(); + } + + #region override methods + + /// + /// + /// Subscribe to the events issued by . + /// + /// + /// + protected override void SubscribeToCimSessionProxyEvent(CimSessionProxy proxy) + { + DebugHelper.WriteLog("SubscribeToCimSessionProxyEvent", 4); + // Raise event instead of write object to ps + proxy.OnNewCmdletAction += this.CimIndicationHandler; + proxy.OnOperationCreated += this.OperationCreatedHandler; + proxy.OnOperationDeleted += this.OperationDeletedHandler; + proxy.EnableMethodResultStreaming = false; + } + + /// + /// + /// Handler used to handle new action event from + /// object. + /// + /// + /// + /// object raised the event + /// + /// event argument + private void CimIndicationHandler(object cimSession, CmdletActionEventArgs actionArgs) + { + DebugHelper.WriteLogEx("action is {0}. Disposed {1}", 0, actionArgs.Action, this.Disposed); + + if (this.Disposed) + { + return; + } + + // NOTES: should move after this.Disposed, but need to log the exception + CimWriteError cimWriteError = actionArgs.Action as CimWriteError; + if (cimWriteError != null) + { + this.exception = cimWriteError.Exception; + if (!this.ackedEvent.IsSet) + { + // an exception happened + DebugHelper.WriteLogEx("an exception happened", 0); + this.ackedEvent.Set(); + return; + } + EventHandler temp = this.OnNewSubscriptionResult; + if (temp != null) + { + DebugHelper.WriteLog("Raise an exception event", 2); + + temp(this, new CimSubscriptionExceptionEventArgs(this.exception)); + } + DebugHelper.WriteLog("Got an exception: {0}", 2, exception); + } + + CimWriteResultObject cimWriteResultObject = actionArgs.Action as CimWriteResultObject; + if (cimWriteResultObject != null) + { + CimSubscriptionResult result = cimWriteResultObject.Result as CimSubscriptionResult; + if (result != null) + { + EventHandler temp = this.OnNewSubscriptionResult; + if (temp != null) + { + DebugHelper.WriteLog("Raise an result event", 2); + temp(this, new CimSubscriptionResultEventArgs(result)); + } + } + else + { + if (!this.ackedEvent.IsSet) + { + // an ACK message returned + DebugHelper.WriteLogEx("an ack message happened", 0); + this.ackedEvent.Set(); + return; + } + else + { + DebugHelper.WriteLogEx("an ack message should not happen here", 0); + } + } + } + } + + /// + /// block the ps thread until ACK message or Error happened. + /// + private void WaitForAckMessage() + { + DebugHelper.WriteLogEx(); + this.ackedEvent.Wait(); + if (this.exception != null) + { + DebugHelper.WriteLogEx("error happened", 0); + if (this.Cmdlet != null) + { + DebugHelper.WriteLogEx("Throw Terminating error", 1); + + // throw terminating error + ErrorRecord errorRecord = ErrorToErrorRecord.ErrorRecordFromAnyException( + new InvocationContext(this.TargetComputerName, null), this.exception, null); + this.Cmdlet.ThrowTerminatingError(errorRecord); + } + else + { + DebugHelper.WriteLogEx("Throw exception", 1); + // throw exception out + throw this.exception; + } + } + DebugHelper.WriteLogEx("ACK happened", 0); + } + #endregion + + #region internal property + /// + /// The cmdlet object who issue this subscription, + /// to throw ThrowTerminatingError + /// in case there is a subscription failure + /// + /// + internal Cmdlet Cmdlet + { + set; + get; + } + + /// + /// target computername + /// + internal String TargetComputerName + { + set; + get; + } + + #endregion + + #region private methods + /// + /// + /// Create and set properties + /// + /// + /// + /// + /// + private CimSessionProxy CreateSessionProxy( + string computerName, + UInt32 timeout) + { + CimSessionProxy proxy = CreateCimSessionProxy(computerName); + proxy.OperationTimeout = timeout; + return proxy; + } + + /// + /// Create and set properties + /// + /// + /// + /// + private CimSessionProxy CreateSessionProxy( + CimSession session, + UInt32 timeout) + { + CimSessionProxy proxy = CreateCimSessionProxy(session); + proxy.OperationTimeout = timeout; + return proxy; + } + #endregion + + #region private members + + /// + /// Exception occurred while start the subscription + /// + internal Exception Exception + { + get + { + return exception; + } + } + private Exception exception; + + #endregion + + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimRemoveCimInstance.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimRemoveCimInstance.cs new file mode 100644 index 000000000..20837d5b7 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimRemoveCimInstance.cs @@ -0,0 +1,147 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System.Collections; +using System; +using System.Collections.Generic; +using System.Diagnostics; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// Containing all necessary information originated from + /// the parameters of + /// + internal class CimRemoveCimInstanceContext : XOperationContextBase + { + /// + /// + /// Constructor + /// + /// + /// + /// + internal CimRemoveCimInstanceContext(string theNamespace, + CimSessionProxy theProxy) + { + this.proxy = theProxy; + this.nameSpace = theNamespace; + } + } + + /// + /// + /// Implements operations of remove-ciminstance cmdlet. + /// + /// + internal sealed class CimRemoveCimInstance : CimGetInstance + { + /// + /// + /// Constructor + /// + /// + public CimRemoveCimInstance() + : base() + { + } + + /// + /// + /// Base on parametersetName to retrieve ciminstances + /// + /// + /// object + public void RemoveCimInstance(RemoveCimInstanceCommand cmdlet) + { + DebugHelper.WriteLogEx(); + + IEnumerable computerNames = ConstValue.GetComputerNames( + GetComputerName(cmdlet)); + List proxys = new List(); + switch (cmdlet.ParameterSetName) + { + case CimBaseCommand.CimInstanceComputerSet: + foreach (string computerName in computerNames) + { + proxys.Add(CreateSessionProxy(computerName, cmdlet.CimInstance, cmdlet)); + } + break; + case CimBaseCommand.CimInstanceSessionSet: + foreach (CimSession session in GetCimSession(cmdlet)) + { + proxys.Add(CreateSessionProxy(session, cmdlet)); + } + break; + default: + break; + } + switch (cmdlet.ParameterSetName) + { + case CimBaseCommand.CimInstanceComputerSet: + case CimBaseCommand.CimInstanceSessionSet: + string nameSpace = null; + if(cmdlet.ResourceUri != null ) + { + nameSpace = GetCimInstanceParameter(cmdlet).CimSystemProperties.Namespace; + } + else + { + nameSpace = ConstValue.GetNamespace(GetCimInstanceParameter(cmdlet).CimSystemProperties.Namespace); + } + string target = cmdlet.CimInstance.ToString(); + foreach (CimSessionProxy proxy in proxys) + { + if (!cmdlet.ShouldProcess(target, action)) + { + return; + } + proxy.DeleteInstanceAsync(nameSpace, cmdlet.CimInstance); + } + break; + case CimBaseCommand.QueryComputerSet: + case CimBaseCommand.QuerySessionSet: + GetCimInstanceInternal(cmdlet); + break; + default: + break; + } + } + + /// + /// + /// Remove from namespace specified in cmdlet + /// + /// + /// + internal void RemoveCimInstance(CimInstance cimInstance, XOperationContextBase context, CmdletOperationBase cmdlet) + { + DebugHelper.WriteLogEx(); + + string target = cimInstance.ToString(); + if (!cmdlet.ShouldProcess(target, action)) + { + return; + } + + CimRemoveCimInstanceContext removeContext = context as CimRemoveCimInstanceContext; + Debug.Assert(removeContext != null, "CimRemoveCimInstance::RemoveCimInstance should has CimRemoveCimInstanceContext != NULL."); + + CimSessionProxy proxy = CreateCimSessionProxy(removeContext.Proxy); + proxy.DeleteInstanceAsync(removeContext.Namespace, cimInstance); + } + + #region const strings + /// + /// action + /// + private const string action = @"Remove-CimInstance"; + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimResultObserver.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimResultObserver.cs new file mode 100644 index 000000000..07ae3ba02 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimResultObserver.cs @@ -0,0 +1,524 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using System.Management.Automation; +using System.Globalization; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + #region AsyncResultType + /// + /// + /// Async result type + /// + /// + public enum AsyncResultType + { + Result, + Exception, + Completion + } + #endregion + + #region CimResultContext + /// + /// Cim Result Context + /// + internal class CimResultContext + { + /// + /// constructor + /// + /// + internal CimResultContext(object ErrorSource) + { + this.errorSource = ErrorSource; + } + + /// + /// ErrorSource property + /// + internal object ErrorSource + { + get + { + return this.errorSource; + } + } + private object errorSource; + } + #endregion + + #region AsyncResultEventArgsBase + /// + /// + /// Base class of asyn result event argument + /// + /// + internal abstract class AsyncResultEventArgsBase : EventArgs + { + /// + /// Constructor + /// + /// + /// + /// + public AsyncResultEventArgsBase( + CimSession session, + IObservable observable, + AsyncResultType resultType) + { + this.session = session; + this.observable = observable; + this.resultType = resultType; + } + + /// + /// Constructor + /// + /// + /// + /// + /// + public AsyncResultEventArgsBase( + CimSession session, + IObservable observable, + AsyncResultType resultType, + CimResultContext cimResultContext) + { + this.session = session; + this.observable = observable; + this.resultType = resultType; + this.context = cimResultContext; + } + + public readonly CimSession session; + public readonly IObservable observable; + public readonly AsyncResultType resultType; + + // property ErrorSource + public readonly CimResultContext context; + } + + #endregion + + #region AsyncResult*Args + /// + /// + /// operation successfully completed event argument + /// + /// + internal class AsyncResultCompleteEventArgs : AsyncResultEventArgsBase + { + /// + /// + /// Constructor + /// + /// + /// object + /// + public AsyncResultCompleteEventArgs( + CimSession session, + IObservable observable) : + base(session, observable, AsyncResultType.Completion) + { + } + } + + /// + /// + /// async result argument with object + /// + /// + internal class AsyncResultObjectEventArgs : AsyncResultEventArgsBase + { + /// + /// Constructor + /// + /// + /// + /// + public AsyncResultObjectEventArgs( + CimSession session, + IObservable observable, + object resultObject) : + base(session, observable, AsyncResultType.Result) + { + this.resultObject = resultObject; + } + + public readonly object resultObject; + } + + /// + /// + /// operation completed with exception event argument + /// + /// + internal class AsyncResultErrorEventArgs : AsyncResultEventArgsBase + { + /// + /// Constructor + /// + /// + /// + /// + public AsyncResultErrorEventArgs( + CimSession session, + IObservable observable, + Exception error) : + base(session, observable, AsyncResultType.Exception) + { + this.error = error; + } + + /// + /// Constructor + /// + /// + /// + /// + /// + public AsyncResultErrorEventArgs( + CimSession session, + IObservable observable, + Exception error, + CimResultContext cimResultContext) : + base(session, observable, AsyncResultType.Exception, cimResultContext) + { + this.error = error; + } + + public readonly Exception error; + } + #endregion + + #region CimResultObserver + /// + /// + /// Observer to consume results from asynchronous operations, such as, + /// EnumerateInstancesAsync operation of object. + /// + /// + /// (See http://channel9.msdn.com/posts/J.Van.Gogh/Reactive-Extensions-API-in-depth-Contract/) + /// for the IObserver/IObservable contact + /// - the only possible sequence is OnNext* (OnCompleted|OnError)? + /// - callbacks are serialized + /// - Subscribe never throws + /// + /// + /// object type + internal class CimResultObserver : IObserver + { + /// + /// Define delegate that handles new cmdlet action come from + /// the operations related to the current CimSession object. + /// + /// cimSession object, which raised the event + /// Event args + public delegate void ResultEventHandler( + object observer, + AsyncResultEventArgsBase resultArgs); + + /// + /// Define an Event based on the NewActionHandler + /// + public event ResultEventHandler OnNewResult; + + /// + /// Constructor + /// + /// object that issued the operation + /// Operation that can be observed + public CimResultObserver(CimSession session, IObservable observable) + { + this.session = session; + this.observable = observable; + } + + /// + /// Constructor + /// + /// object that issued the operation + /// Operation that can be observed + public CimResultObserver(CimSession session, + IObservable observable, + CimResultContext cimResultContext) + { + this.session = session; + this.observable = observable; + this.context = cimResultContext; + } + + /// + /// + /// Operation completed successfully + /// + /// + public virtual void OnCompleted() + { + // callbacks should never throw any exception to + // protocol layer, otherwise the client process will be + // terminated because of unhandled exception, same with + // OnNext, OnError + try + { + AsyncResultCompleteEventArgs completeArgs = new AsyncResultCompleteEventArgs( + this.session, this.observable); + this.OnNewResult(this, completeArgs); + } + catch (Exception ex) + { + this.OnError(ex); + DebugHelper.WriteLogEx("{0}", 0, ex); + } + } + + /// + /// + /// Operation completed with an error + /// + /// + /// error object + public virtual void OnError(Exception error) + { + try + { + AsyncResultErrorEventArgs errorArgs = new AsyncResultErrorEventArgs( + this.session, this.observable, error, this.context); + this.OnNewResult(this, errorArgs); + } + catch (Exception ex) + { + // !!ignore the exception + DebugHelper.WriteLogEx("{0}", 0, ex); + } + } + + /// + /// Deliver the result value + /// + /// + protected void OnNextCore(object value) + { + DebugHelper.WriteLogEx("value = {0}.", 1, value); + try + { + AsyncResultObjectEventArgs resultArgs = new AsyncResultObjectEventArgs( + this.session, this.observable, value); + this.OnNewResult(this, resultArgs); + } + catch (Exception ex) + { + this.OnError(ex); + DebugHelper.WriteLogEx("{0}", 0, ex); + } + } + + /// + /// + /// Operation got a new result object + /// + /// + /// result object + public virtual void OnNext(T value) + { + DebugHelper.WriteLogEx("value = {0}.", 1, value); + // do not allow null value + if (value == null) + { + return; + } + this.OnNextCore(value); + } + + #region members + + /// + /// Session object of the operation + /// + protected CimSession CurrentSession + { + get + { + return session; + } + } + private CimSession session; + + /// + /// async operation that can be observed + /// + private IObservable observable; + + /// + /// object used during delivering result. + /// + private CimResultContext context; + #endregion + } + + /// + /// CimSubscriptionResultObserver class definition + /// + internal class CimSubscriptionResultObserver : CimResultObserver + { + /// + /// constructor + /// + /// + /// + public CimSubscriptionResultObserver(CimSession session, IObservable observable) + : base(session, observable) + { + } + + /// + /// constructor + /// + /// + /// + public CimSubscriptionResultObserver( + CimSession session, + IObservable observable, + CimResultContext context) + : base(session, observable, context) + { + } + + /// + /// Override the OnNext method + /// + /// + public override void OnNext(CimSubscriptionResult value) + { + DebugHelper.WriteLogEx(); + base.OnNextCore(value); + } + } + + /// + /// CimMethodResultObserver class definition + /// + internal class CimMethodResultObserver : CimResultObserver + { + /// + /// constructor + /// + /// + /// + public CimMethodResultObserver(CimSession session, IObservable observable) + : base(session, observable) + { + } + + /// + /// constructor + /// + /// + /// + /// + public CimMethodResultObserver( + CimSession session, + IObservable observable, + CimResultContext context) + : base(session, observable, context) + { + } + + /// + /// Override the OnNext method + /// + /// + public override void OnNext(CimMethodResultBase value) + { + DebugHelper.WriteLogEx(); + const string PSTypeCimMethodResult = @"Microsoft.Management.Infrastructure.CimMethodResult"; + const string PSTypeCimMethodStreamedResult = @"Microsoft.Management.Infrastructure.CimMethodStreamedResult"; + const string PSTypeCimMethodResultTemplate = @"{0}#{1}#{2}"; + + string resultObjectPSType = null; + PSObject resultObject = null; + CimMethodResult methodResult = value as CimMethodResult; + if (methodResult != null) + { + resultObjectPSType = PSTypeCimMethodResult; + resultObject = new PSObject(); + foreach (CimMethodParameter param in methodResult.OutParameters) + { + resultObject.Properties.Add(new PSNoteProperty(param.Name, param.Value)); + } + } + else + { + CimMethodStreamedResult methodStreamedResult = value as CimMethodStreamedResult; + if (methodStreamedResult != null) + { + resultObjectPSType = PSTypeCimMethodStreamedResult; + resultObject = new PSObject(); + resultObject.Properties.Add(new PSNoteProperty(@"ParameterName", methodStreamedResult.ParameterName)); + resultObject.Properties.Add(new PSNoteProperty(@"ItemType", methodStreamedResult.ItemType)); + resultObject.Properties.Add(new PSNoteProperty(@"ItemValue", methodStreamedResult.ItemValue)); + } + } + if (resultObject != null) + { + resultObject.Properties.Add(new PSNoteProperty(@"PSComputerName", this.CurrentSession.ComputerName)); + resultObject.TypeNames.Insert(0, resultObjectPSType); + resultObject.TypeNames.Insert(0, String.Format(CultureInfo.InvariantCulture, PSTypeCimMethodResultTemplate, resultObjectPSType, ClassName, MethodName)); + base.OnNextCore(resultObject); + } + } + + /// + /// methodname + /// + internal String MethodName + { + get; + set; + } + + /// + /// classname + /// + internal String ClassName + { + get; + set; + } + } + + /// + /// IgnoreResultObserver class definition + /// + internal class IgnoreResultObserver : CimResultObserver + { + /// + /// constructor + /// + /// + /// + public IgnoreResultObserver(CimSession session, IObservable observable) + : base(session, observable) + { + } + + /// + /// Override the OnNext method + /// + /// + public override void OnNext(CimInstance value) + { + DebugHelper.WriteLogEx(); + } + } + #endregion +} diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionOperations.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionOperations.cs new file mode 100644 index 000000000..0e25c5da5 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionOperations.cs @@ -0,0 +1,1271 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Management.Automation; +using System.Management.Automation.Runspaces; +using System.Globalization; +using Microsoft.Management.Infrastructure.Options; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + #region CimSessionWrapper + + internal class CimSessionWrapper + { + #region members + + /// + /// id of the cimsession + /// + public uint SessionId + { + get + { + return this.sessionId; + } + } + private uint sessionId; + + /// + /// instanceId of the cimsession + /// + public Guid InstanceId + { + get + { + return this.instanceId; + } + } + private Guid instanceId; + + /// + /// name of the cimsession + /// + public string Name + { + get + { + return this.name; + } + } + private string name; + + /// + /// computer name of the cimsession + /// + public string ComputerName + { + get + { + return this.computerName; + } + } + private string computerName; + + /// + /// wrapped cimsession object + /// + public CimSession CimSession + { + get + { + return this.cimSession; + } + } + private CimSession cimSession; + + /// + /// computer name of the cimsession + /// + public string Protocol + { + get + { + switch (protocol) + { + case ProtocolType.Dcom: + return "DCOM"; + case ProtocolType.Default: + case ProtocolType.Wsman: + default: + return "WSMAN"; + } + } + } + internal ProtocolType GetProtocolType() + { + return protocol; + } + private ProtocolType protocol; + + /// + /// PSObject that wrapped the cimSession + /// + private PSObject psObject; + + #endregion + + internal CimSessionWrapper( + uint theSessionId, + Guid theInstanceId, + string theName, + string theComputerName, + CimSession theCimSession, + ProtocolType theProtocol) + { + this.sessionId = theSessionId; + this.instanceId = theInstanceId; + this.name = theName; + this.computerName = theComputerName; + this.cimSession = theCimSession; + this.psObject = null; + this.protocol = theProtocol; + } + + internal PSObject GetPSObject() + { + if (psObject == null) + { + psObject = new PSObject(this.cimSession); + psObject.Properties.Add(new PSNoteProperty(CimSessionState.idPropName, this.sessionId)); + psObject.Properties.Add(new PSNoteProperty(CimSessionState.namePropName, this.name)); + psObject.Properties.Add(new PSNoteProperty(CimSessionState.instanceidPropName, this.instanceId)); + psObject.Properties.Add(new PSNoteProperty(CimSessionState.computernamePropName, this.ComputerName)); + psObject.Properties.Add(new PSNoteProperty(CimSessionState.protocolPropName, this.Protocol)); + } + else + { + psObject.Properties[CimSessionState.idPropName].Value = this.SessionId; + psObject.Properties[CimSessionState.namePropName].Value = this.name; + psObject.Properties[CimSessionState.instanceidPropName].Value = this.instanceId; + psObject.Properties[CimSessionState.computernamePropName].Value = this.ComputerName; + psObject.Properties[CimSessionState.protocolPropName].Value = this.Protocol; + } + return psObject; + } + } + + #endregion + + #region CimSessionState + + /// + /// + /// Class used to hold all cimsession related status data related to a runspace. + /// Including the CimSession cache, session counters for generating session name. + /// + /// + internal class CimSessionState : IDisposable + { + #region private members + + /// + /// Default session name. + /// If a name is not passed, then the session is given the name CimSession, + /// where is the next available session number. + /// For example, CimSession1, CimSession2, etc... + /// + internal static string CimSessionClassName = "CimSession"; + + /// + /// CimSession object name + /// + internal static string CimSessionObject = "{CimSession Object}"; + + /// + /// + /// CimSession object path, which is identifying a cimsession object + /// + /// + internal static string SessionObjectPath = @"CimSession id = {0}, name = {2}, ComputerName = {3}, instance id = {1}"; + + /// + /// Id property name of cimsession wrapper object + /// + internal static string idPropName = "Id"; + + /// + /// Instanceid property name of cimsession wrapper object + /// + internal static string instanceidPropName = "InstanceId"; + + /// + /// Name property name of cimsession wrapper object + /// + internal static string namePropName = "Name"; + + /// + /// Computer name property name of cimsession object + /// + internal static string computernamePropName = "ComputerName"; + + /// + /// Protocol name property name of cimsession object + /// + internal static string protocolPropName = "Protocol"; + + /// + /// + /// session counter bound to current runspace. + /// + /// + private UInt32 sessionNameCounter; + + /// + /// + /// Dictionary used to holds all CimSessions in current runspace by session name. + /// + /// + private Dictionary> curCimSessionsByName; + + /// + /// + /// Dictionary used to holds all CimSessions in current runspace by computer name. + /// + /// + private Dictionary> curCimSessionsByComputerName; + + /// + /// + /// Dictionary used to holds all CimSessions in current runspace by instance ID. + /// + /// + private Dictionary curCimSessionsByInstanceId; + + /// + /// + /// Dictionary used to holds all CimSessions in current runspace by session id. + /// + /// + private Dictionary curCimSessionsById; + + /// + /// + /// Dictionary used to link CimSession object with PSObject. + /// + /// + private Dictionary curCimSessionWrapper; + + #endregion + + /// + /// + /// constructor + /// + /// + internal CimSessionState() + { + sessionNameCounter = 1; + curCimSessionsByName = new Dictionary>( + StringComparer.OrdinalIgnoreCase); + curCimSessionsByComputerName = new Dictionary>( + StringComparer.OrdinalIgnoreCase); + curCimSessionsByInstanceId = new Dictionary(); + curCimSessionsById = new Dictionary(); + curCimSessionWrapper = new Dictionary(); + } + + /// + /// + /// Get sessions count. + /// + /// + /// The count of session objects in current runspace. + internal int GetSessionsCount() + { + return this.curCimSessionsById.Count; + } + + /// + /// + /// Generates an unique session id. + /// + /// + /// Unique session id under current runspace + internal UInt32 GenerateSessionId() + { + return this.sessionNameCounter++; + } + #region IDisposable + + /// + /// + /// Indicates whether this object was disposed or not + /// + /// + private bool _disposed; + + /// + /// + /// Dispose() calls Dispose(true). + /// Implement IDisposable. Do not make this method virtual. + /// A derived class should not be able to override this method. + /// + /// + public void Dispose() + { + Dispose(true); + // This object will be cleaned up by the Dispose method. + // Therefore, you should call GC.SupressFinalize to + // take this object off the finalization queue + // and prevent finalization code for this object + // from executing a second time. + GC.SuppressFinalize(this); + } + + /// + /// + /// Dispose(bool disposing) executes in two distinct scenarios. + /// If disposing equals true, the method has been called directly + /// or indirectly by a user's code. Managed and unmanaged resources + /// can be disposed. + /// If disposing equals false, the method has been called by the + /// runtime from inside the finalizer and you should not reference + /// other objects. Only unmanaged resources can be disposed. + /// + /// + /// Whether it is directly called + protected virtual void Dispose(bool disposing) + { + if (!this._disposed) + { + if (disposing) + { + // free managed resources + Cleanup(); + this._disposed = true; + } + // free native resources if there are any + } + } + + /// + /// + /// Performs application-defined tasks associated with freeing, releasing, or + /// resetting unmanaged resources. + /// + /// + public void Cleanup() + { + foreach (CimSession session in curCimSessionWrapper.Keys) + { + session.Dispose(); + } + curCimSessionWrapper.Clear(); + curCimSessionsByName.Clear(); + curCimSessionsByComputerName.Clear(); + curCimSessionsByInstanceId.Clear(); + curCimSessionsById.Clear(); + sessionNameCounter = 1; + } + + #endregion + + #region Add CimSession to/remove CimSession from cache + + /// + /// + /// Add new CimSession object to cache + /// + /// + /// + /// + /// + /// + /// + internal PSObject AddObjectToCache( + CimSession session, + UInt32 sessionId, + Guid instanceId, + String name, + String computerName, + ProtocolType protocol) + { + CimSessionWrapper wrapper = new CimSessionWrapper( + sessionId, instanceId, name, computerName, session, protocol); + + HashSet objects; + if (!this.curCimSessionsByComputerName.TryGetValue(computerName, out objects)) + { + objects = new HashSet(); + this.curCimSessionsByComputerName.Add(computerName, objects); + } + objects.Add(wrapper); + + if (!this.curCimSessionsByName.TryGetValue(name, out objects)) + { + objects = new HashSet(); + this.curCimSessionsByName.Add(name, objects); + } + objects.Add(wrapper); + + this.curCimSessionsByInstanceId.Add(instanceId, wrapper); + this.curCimSessionsById.Add(sessionId, wrapper); + this.curCimSessionWrapper.Add(session, wrapper); + return wrapper.GetPSObject(); + } + + /// + /// + /// Generates remove session message by given wrapper object. + /// + /// + /// + internal string GetRemoveSessionObjectTarget(PSObject psObject) + { + String message = String.Empty; + if (psObject.BaseObject is CimSession) + { + UInt32 id = 0x0; + Guid instanceId = Guid.Empty; + String name = String.Empty; + String computerName = string.Empty; + if (psObject.Properties[idPropName].Value is UInt32) + { + id = Convert.ToUInt32(psObject.Properties[idPropName].Value, null); + } + if (psObject.Properties[instanceidPropName].Value is Guid) + { + instanceId = (Guid)psObject.Properties[instanceidPropName].Value; + } + if (psObject.Properties[namePropName].Value is String) + { + name = (String)psObject.Properties[namePropName].Value; + } + if (psObject.Properties[computernamePropName].Value is String) + { + computerName = (String)psObject.Properties[computernamePropName].Value; + } + message = String.Format(CultureInfo.CurrentUICulture, SessionObjectPath, id, instanceId, name, computerName); + } + return message; + } + + /// + /// + /// Remove given object from cache + /// + /// + /// + internal void RemoveOneSessionObjectFromCache(PSObject psObject) + { + DebugHelper.WriteLogEx(); + + if (psObject.BaseObject is CimSession) + { + RemoveOneSessionObjectFromCache(psObject.BaseObject as CimSession); + } + } + + /// + /// + /// Remove given object from cache + /// + /// + /// + internal void RemoveOneSessionObjectFromCache(CimSession session) + { + DebugHelper.WriteLogEx(); + + if (!this.curCimSessionWrapper.ContainsKey(session)) + { + return; + } + CimSessionWrapper wrapper = this.curCimSessionWrapper[session]; + String name = wrapper.Name; + String computerName = wrapper.ComputerName; + + DebugHelper.WriteLog("name {0}, computername {1}, id {2}, instanceId {3}", 1, name, computerName, wrapper.SessionId, wrapper.InstanceId); + + HashSet objects; + if (this.curCimSessionsByComputerName.TryGetValue(computerName, out objects)) + { + objects.Remove(wrapper); + } + if (this.curCimSessionsByName.TryGetValue(name, out objects)) + { + objects.Remove(wrapper); + } + RemoveSessionInternal(session, wrapper); + } + + /// + /// + /// Remove given object from partial of the cache only. + /// + /// + /// + /// + private void RemoveSessionInternal(CimSession session, CimSessionWrapper wrapper) + { + DebugHelper.WriteLogEx(); + + this.curCimSessionsByInstanceId.Remove(wrapper.InstanceId); + this.curCimSessionsById.Remove(wrapper.SessionId); + this.curCimSessionWrapper.Remove(session); + session.Dispose(); + } + + #endregion + + #region Query CimSession from cache + + /// + /// + /// Add ErrorRecord to list. + /// + /// + /// + /// + /// + private void AddErrorRecord( + ref List errRecords, + string propertyName, + object propertyValue) + { + errRecords.Add( + new ErrorRecord( + new CimException(String.Format(CultureInfo.CurrentUICulture, Strings.CouldNotFindCimsessionObject, propertyName, propertyValue)), + string.Empty, + ErrorCategory.ObjectNotFound, + null)); + } + + /// + /// Query session list by given id array + /// + /// + /// List of session wrapper objects + internal IEnumerable QuerySession(IEnumerable ids, + out IEnumerable errorRecords) + { + HashSet sessions = new HashSet(); + HashSet sessionIds = new HashSet(); + List errRecords = new List(); + errorRecords = errRecords; + // NOTES: use template function to implement this will save duplicate code + foreach (UInt32 id in ids) + { + if (this.curCimSessionsById.ContainsKey(id)) + { + if (!sessionIds.Contains(id)) + { + sessionIds.Add(id); + sessions.Add(this.curCimSessionsById[id].GetPSObject()); + } + } + else + { + AddErrorRecord(ref errRecords, idPropName, id); + } + } + return sessions; + } + + /// + /// Query session list by given instance id array + /// + /// + /// List of session wrapper objects + internal IEnumerable QuerySession(IEnumerable instanceIds, + out IEnumerable errorRecords) + { + HashSet sessions = new HashSet(); + HashSet sessionIds = new HashSet(); + List errRecords = new List(); + errorRecords = errRecords; + foreach (Guid instanceid in instanceIds) + { + if (this.curCimSessionsByInstanceId.ContainsKey(instanceid)) + { + CimSessionWrapper wrapper = this.curCimSessionsByInstanceId[instanceid]; + if (!sessionIds.Contains(wrapper.SessionId)) + { + sessionIds.Add(wrapper.SessionId); + sessions.Add(wrapper.GetPSObject()); + } + } + else + { + AddErrorRecord(ref errRecords, instanceidPropName, instanceid); + } + } + return sessions; + } + + /// + /// Query session list by given name array + /// + /// + /// List of session wrapper objects + internal IEnumerable QuerySession(IEnumerable nameArray, + out IEnumerable errorRecords) + { + HashSet sessions = new HashSet(); + HashSet sessionIds = new HashSet(); + List errRecords = new List(); + errorRecords = errRecords; + foreach (string name in nameArray) + { + bool foundSession = false; + WildcardPattern pattern = new WildcardPattern(name, WildcardOptions.IgnoreCase); + foreach (KeyValuePair> kvp in this.curCimSessionsByName) + { + if (pattern.IsMatch(kvp.Key)) + { + HashSet wrappers = kvp.Value; + foundSession = (wrappers.Count > 0); + foreach (CimSessionWrapper wrapper in wrappers) + { + if (!sessionIds.Contains(wrapper.SessionId)) + { + sessionIds.Add(wrapper.SessionId); + sessions.Add(wrapper.GetPSObject()); + } + } + } + } + if (!foundSession && !WildcardPattern.ContainsWildcardCharacters(name)) + { + AddErrorRecord(ref errRecords, namePropName, name); + } + } + return sessions; + } + + /// + /// Query session list by given computer name array + /// + /// + /// List of session wrapper objects + internal IEnumerable QuerySessionByComputerName( + IEnumerable computernameArray, + out IEnumerable errorRecords) + { + HashSet sessions = new HashSet(); + HashSet sessionIds = new HashSet(); + List errRecords = new List(); + errorRecords = errRecords; + foreach (string computername in computernameArray) + { + bool foundSession = false; + if (this.curCimSessionsByComputerName.ContainsKey(computername)) + { + HashSet wrappers = this.curCimSessionsByComputerName[computername]; + foundSession = (wrappers.Count > 0); + foreach (CimSessionWrapper wrapper in wrappers) + { + if (!sessionIds.Contains(wrapper.SessionId)) + { + sessionIds.Add(wrapper.SessionId); + sessions.Add(wrapper.GetPSObject()); + } + } + } + if (!foundSession) + { + AddErrorRecord(ref errRecords, computernamePropName, computername); + } + } + return sessions; + } + + /// + /// Query session list by given session objects array + /// + /// + /// List of session wrapper objects + internal IEnumerable QuerySession(IEnumerable cimsessions, + out IEnumerable errorRecords) + { + HashSet sessions = new HashSet(); + HashSet sessionIds = new HashSet(); + List errRecords = new List(); + errorRecords = errRecords; + foreach (CimSession cimsession in cimsessions) + { + if (this.curCimSessionWrapper.ContainsKey(cimsession)) + { + CimSessionWrapper wrapper = this.curCimSessionWrapper[cimsession]; + if (!sessionIds.Contains(wrapper.SessionId)) + { + sessionIds.Add(wrapper.SessionId); + sessions.Add(wrapper.GetPSObject()); + } + } + else + { + AddErrorRecord(ref errRecords, CimSessionClassName, CimSessionObject); + } + } + return sessions; + } + + /// + /// Query session wrapper object + /// + /// + /// session wrapper + internal CimSessionWrapper QuerySession(CimSession cimsession) + { + CimSessionWrapper wrapper; + this.curCimSessionWrapper.TryGetValue(cimsession, out wrapper); + return wrapper; + } + + /// + /// Query session object with given CimSessionInstanceID + /// + /// + /// CimSession object + internal CimSession QuerySession(Guid cimSessionInstanceId) + { + if (this.curCimSessionsByInstanceId.ContainsKey(cimSessionInstanceId)) + { + CimSessionWrapper wrapper = this.curCimSessionsByInstanceId[cimSessionInstanceId]; + return wrapper.CimSession; + } + return null; + } + #endregion + } + + #endregion + + #region CimSessionBase + + /// + /// + /// Base class of all session operation classes. + /// All sessions created will be held in a ConcurrentDictionary:cimSessions. + /// It manages the lifecyclye of the sessions being created for each + /// runspace according to the state of the runspace. + /// + /// + internal class CimSessionBase + { + #region constructor + + /// + /// Constructor + /// + public CimSessionBase() + { + this.sessionState = cimSessions.GetOrAdd( + CurrentRunspaceId, + delegate(Guid instanceId) + { + if (Runspace.DefaultRunspace != null) + { + Runspace.DefaultRunspace.StateChanged += DefaultRunspace_StateChanged; + } + return new CimSessionState(); + }); + } + + #endregion + + #region members + + /// + /// + /// Thread safe static dictionary to store session objects associated + /// with each runspace, which is identified by a GUID. NOTE: cmdlet + /// can running parallelly under more than one runspace(s). + /// + /// + static internal ConcurrentDictionary cimSessions + = new ConcurrentDictionary(); + + /// + /// + /// Default runspace id + /// + /// + static internal Guid defaultRunspaceId = Guid.Empty; + + /// + /// + /// Object used to hold all CimSessions and status data bound + /// to current runspace. + /// + /// + internal CimSessionState sessionState; + + /// + /// Get current runspace id + /// + private static Guid CurrentRunspaceId + { + get + { + if (Runspace.DefaultRunspace != null) + { + return Runspace.DefaultRunspace.InstanceId; + } + else + { + return CimSessionBase.defaultRunspaceId; + } + } + } + #endregion + + public static CimSessionState GetCimSessionState() + { + CimSessionState state = null; + cimSessions.TryGetValue(CurrentRunspaceId, out state); + return state; + } + + /// + /// + /// clean up the dictionaries if the runspace is closed or broken. + /// + /// + /// Runspace + /// Event args + private static void DefaultRunspace_StateChanged(object sender, RunspaceStateEventArgs e) + { + Runspace runspace = (Runspace)sender; + switch (e.RunspaceStateInfo.State) + { + case RunspaceState.Broken: + case RunspaceState.Closed: + CimSessionState state; + if (cimSessions.TryRemove(runspace.InstanceId, out state)) + { + DebugHelper.WriteLog(String.Format(CultureInfo.CurrentUICulture, DebugHelper.runspaceStateChanged, runspace.InstanceId, e.RunspaceStateInfo.State)); + state.Dispose(); + } + runspace.StateChanged -= DefaultRunspace_StateChanged; + break; + default: + break; + } + } + } + + #endregion + + #region CimTestConnection + + #endregion + + #region CimNewSession + + /// + /// + /// CimNewSession is the class to create cimSession + /// based on given NewCimSessionCommand. + /// + /// + internal class CimNewSession : CimSessionBase, IDisposable + { + /// + /// CimTestCimSessionContext + /// + internal class CimTestCimSessionContext : XOperationContextBase + { + /// + /// + /// Constructor + /// + /// + /// + /// + internal CimTestCimSessionContext( + CimSessionProxy theProxy, + CimSessionWrapper wrapper) + { + this.proxy = theProxy; + this.cimSessionWrapper = wrapper; + this.nameSpace = null; + } + + /// + /// namespce + /// + internal CimSessionWrapper CimSessionWrapper + { + get + { + return this.cimSessionWrapper; + } + } + private CimSessionWrapper cimSessionWrapper; + } + + /// + /// + /// constructor + /// + /// + internal CimNewSession() : base() + { + this.cimTestSession = new CimTestSession(); + this._disposed = false; + } + + /// + /// Create a new base on given cmdlet + /// and its parameter + /// + /// + /// + /// + internal void NewCimSession(NewCimSessionCommand cmdlet, + CimSessionOptions sessionOptions, + CimCredential credential) + { + DebugHelper.WriteLogEx(); + + IEnumerable computerNames = ConstValue.GetComputerNames(cmdlet.ComputerName); + foreach (string computerName in computerNames) + { + CimSessionProxy proxy; + if (sessionOptions == null) + { + DebugHelper.WriteLog("Create CimSessionOption due to NewCimSessionCommand has null sessionoption", 1); + sessionOptions = CimSessionProxy.CreateCimSessionOption(computerName, + cmdlet.OperationTimeoutSec, credential); + } + proxy = new CimSessionProxyTestConnection(computerName, sessionOptions); + string computerNameValue = (computerName == ConstValue.NullComputerName) ? ConstValue.LocalhostComputerName : computerName; + CimSessionWrapper wrapper = new CimSessionWrapper(0, Guid.Empty, cmdlet.Name, computerNameValue, proxy.CimSession, proxy.Protocol); + CimTestCimSessionContext context = new CimTestCimSessionContext(proxy, wrapper); + proxy.ContextObject = context; + // Skip test the connection if user intend to + if(cmdlet.SkipTestConnection.IsPresent) + { + AddSessionToCache(proxy.CimSession, context, new CmdletOperationBase(cmdlet)); + } + else + { + //CimSession will be retunred as part of TestConnection + this.cimTestSession.TestCimSession(computerName, proxy); + } + } + } + + /// + /// + /// Add session to global cache + /// + /// + /// + /// + /// + internal void AddSessionToCache(CimSession cimSession, XOperationContextBase context, CmdletOperationBase cmdlet) + { + DebugHelper.WriteLogEx(); + + CimTestCimSessionContext testCimSessionContext = context as CimTestCimSessionContext; + UInt32 sessionId = this.sessionState.GenerateSessionId(); + string orginalSessioName = testCimSessionContext.CimSessionWrapper.Name; + string sessionName = (orginalSessioName != null) ? orginalSessioName : String.Format(CultureInfo.CurrentUICulture, @"{0}{1}", CimSessionState.CimSessionClassName, sessionId); + + // detach CimSession from the proxy object + CimSession createdCimSession = testCimSessionContext.Proxy.Detach(); + PSObject psObject = this.sessionState.AddObjectToCache( + createdCimSession, + sessionId, + createdCimSession.InstanceId, + sessionName, + testCimSessionContext.CimSessionWrapper.ComputerName, + testCimSessionContext.Proxy.Protocol); + cmdlet.WriteObject(psObject, null); + } + + /// + /// + /// process all actions in the action queue + /// + /// + /// + /// wrapper of cmdlet, for details + /// + public void ProcessActions(CmdletOperationBase cmdletOperation) + { + this.cimTestSession.ProcessActions(cmdletOperation); + } + + /// + /// + /// process remaining actions until all operations are completed or + /// current cmdlet is terminated by user + /// + /// + /// + /// wrapper of cmdlet, for details + /// + public void ProcessRemainActions(CmdletOperationBase cmdletOperation) + { + this.cimTestSession.ProcessRemainActions(cmdletOperation); + } + + #region private members + /// + /// + /// object. + /// + /// + private CimTestSession cimTestSession; + #endregion //private members + + #region IDisposable + + /// + /// + /// Indicates whether this object was disposed or not + /// + /// + protected bool Disposed + { + get + { + return _disposed; + } + } + private bool _disposed; + + /// + /// + /// Dispose() calls Dispose(true). + /// Implement IDisposable. Do not make this method virtual. + /// A derived class should not be able to override this method. + /// + /// + public void Dispose() + { + Dispose(true); + // This object will be cleaned up by the Dispose method. + // Therefore, you should call GC.SupressFinalize to + // take this object off the finalization queue + // and prevent finalization code for this object + // from executing a second time. + GC.SuppressFinalize(this); + } + + /// + /// + /// Dispose(bool disposing) executes in two distinct scenarios. + /// If disposing equals true, the method has been called directly + /// or indirectly by a user's code. Managed and unmanaged resources + /// can be disposed. + /// If disposing equals false, the method has been called by the + /// runtime from inside the finalizer and you should not reference + /// other objects. Only unmanaged resources can be disposed. + /// + /// + /// Whether it is directly called + protected virtual void Dispose(bool disposing) + { + if (!this._disposed) + { + if (disposing) + { + // free managed resources + this.cimTestSession.Dispose(); + this._disposed = true; + } + // free native resources if there are any + } + } + #endregion + }//End Class + + #endregion + + #region CimGetSession + + /// + /// + /// Get CimSession based on given id/instanceid/computername/name + /// + /// + internal class CimGetSession : CimSessionBase + { + /// + /// constructor + /// + public CimGetSession() : base() + { + } + + /// + /// Get objects based on the given cmdlet + /// and its parameter + /// + /// + public void GetCimSession(GetCimSessionCommand cmdlet) + { + DebugHelper.WriteLogEx(); + + IEnumerable sessionToGet = null; + IEnumerable errorRecords = null; + switch (cmdlet.ParameterSetName) + { + case CimBaseCommand.ComputerNameSet: + if (cmdlet.ComputerName == null) + { + sessionToGet = this.sessionState.QuerySession(ConstValue.DefaultSessionName, out errorRecords); + } + else + { + sessionToGet = this.sessionState.QuerySessionByComputerName(cmdlet.ComputerName, out errorRecords); + } + break; + case CimBaseCommand.SessionIdSet: + sessionToGet = this.sessionState.QuerySession(cmdlet.Id, out errorRecords); + break; + case CimBaseCommand.InstanceIdSet: + sessionToGet = this.sessionState.QuerySession(cmdlet.InstanceId, out errorRecords); + break; + case CimBaseCommand.NameSet: + sessionToGet = this.sessionState.QuerySession(cmdlet.Name, out errorRecords); + break; + default: + break; + } + if (sessionToGet != null) + { + foreach(PSObject psobject in sessionToGet) + { + cmdlet.WriteObject(psobject); + } + } + if (errorRecords != null) + { + foreach (ErrorRecord errRecord in errorRecords) + { + cmdlet.WriteError(errRecord); + } + } + } + + #region helper methods + + #endregion + }//End Class + + #endregion + + #region CimRemoveSession + + /// + /// + /// Get CimSession based on given id/instanceid/computername/name + /// + /// + internal class CimRemoveSession : CimSessionBase + { + /// + /// Remove session action string + /// + internal static string RemoveCimSessionActionName = "Remove CimSession"; + + /// + /// constructor + /// + public CimRemoveSession() : base() + { + } + + /// + /// Remove the objects based on given cmdlet + /// and its parameter + /// + /// + public void RemoveCimSession(RemoveCimSessionCommand cmdlet) + { + DebugHelper.WriteLogEx(); + + IEnumerable sessionToRemove = null; + IEnumerable errorRecords = null; + switch (cmdlet.ParameterSetName) + { + case CimBaseCommand.CimSessionSet: + sessionToRemove = this.sessionState.QuerySession(cmdlet.CimSession, out errorRecords); + break; + case CimBaseCommand.ComputerNameSet: + sessionToRemove = this.sessionState.QuerySessionByComputerName(cmdlet.ComputerName, out errorRecords); + break; + case CimBaseCommand.SessionIdSet: + sessionToRemove = this.sessionState.QuerySession(cmdlet.Id, out errorRecords); + break; + case CimBaseCommand.InstanceIdSet: + sessionToRemove = this.sessionState.QuerySession(cmdlet.InstanceId, out errorRecords); + break; + case CimBaseCommand.NameSet: + sessionToRemove = this.sessionState.QuerySession(cmdlet.Name, out errorRecords); + break; + default: + break; + } + if (sessionToRemove != null) + { + foreach (PSObject psobject in sessionToRemove) + { + if (cmdlet.ShouldProcess(this.sessionState.GetRemoveSessionObjectTarget(psobject), RemoveCimSessionActionName)) + { + this.sessionState.RemoveOneSessionObjectFromCache(psobject); + } + } + } + if (errorRecords != null) + { + foreach (ErrorRecord errRecord in errorRecords) + { + cmdlet.WriteError(errRecord); + } + } + } + }//End Class + + #endregion + + #region CimTestSession + + /// + /// Class , which is used to + /// test cimsession and execute async operations. + /// + internal class CimTestSession : CimAsyncOperation + { + /// + /// Constructor + /// + internal CimTestSession() + : base() + { + } + + /// + /// Test the session connection with + /// given object. + /// + /// + /// + internal void TestCimSession( + string computerName, + CimSessionProxy proxy) + { + DebugHelper.WriteLogEx(); + this.SubscribeEventAndAddProxytoCache(proxy); + proxy.TestConnectionAsync(); + } + } + + #endregion + +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionProxy.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionProxy.cs new file mode 100644 index 000000000..512ccb2d6 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSessionProxy.cs @@ -0,0 +1,2316 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Management.Automation; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using Microsoft.Management.Infrastructure.Generic; +using Microsoft.Management.Infrastructure.Options; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + #region Context base class + + /// + /// context base class for cross operations + /// for example, some cmdlets need to query instance first and then + /// remove instance, those scenarios need context object transferred + /// from one operation to antoher. + /// + internal abstract class XOperationContextBase + { + /// + /// namespce + /// + internal string Namespace + { + get + { + return this.nameSpace; + } + } + protected string nameSpace; + + /// + /// + /// Session proxy + /// + /// + internal CimSessionProxy Proxy + { + get + { + return this.proxy; + } + } + protected CimSessionProxy proxy; + } + + /// + /// class provides all information regarding the + /// current invocation to .net api + /// + internal class InvocationContext + { + /// + /// Constructor + /// + /// + internal InvocationContext(CimSessionProxy proxy) + { + if (proxy != null) + { + this.ComputerName = proxy.CimSession.ComputerName; + this.TargetCimInstance = proxy.TargetCimInstance; + } + } + + /// + /// Constructor + /// + /// + internal InvocationContext(string computerName, CimInstance targetCimInstance) + { + this.ComputerName = computerName; + this.TargetCimInstance = targetCimInstance; + } + + /// + /// + /// ComputerName of the session + /// + /// + /// return value could be null + /// + /// + internal virtual string ComputerName + { + get; + private set; + } + + /// + /// + /// CimInstance on which the current operation against. + /// + /// + /// return value could be null + /// + /// + internal virtual CimInstance TargetCimInstance + { + get; + private set; + } + } + #endregion + + #region Preprossessing of result object interface + /// + /// Defines a method to preprocessing an result object before sending to + /// output pipeline. + /// + [ComVisible(false)] + internal interface IObjectPreProcess + { + /// + /// Performs pre processing of given result object. + /// + /// + /// Pre-processed object + object Process(object resultObject); + } + #endregion + + #region Eventargs class + /// + /// + /// CmdletActionEventArgs holds a CimBaseAction object + /// + /// + internal sealed class CmdletActionEventArgs : EventArgs + { + /// + /// Constructor + /// + /// CimBaseAction object bound to the event + public CmdletActionEventArgs(CimBaseAction action) + { + this.Action = action; + } + public readonly CimBaseAction Action; + } + + /// + /// OperationEventArgs holds a cancellation object, and an operation. + /// + internal sealed class OperationEventArgs : EventArgs + { + /// + /// constructor + /// + /// Object used to cancel the operation + /// Async observable operation + public OperationEventArgs(IDisposable operationCancellation, + IObservable operation, + bool theSuccess) + { + this.operationCancellation = operationCancellation; + this.operation = operation; + this.success = theSuccess; + } + public readonly IDisposable operationCancellation; + public readonly IObservable operation; + public readonly bool success; + } + + #endregion + + /// + /// + /// Wrapper of object. + /// A CimSessionProxy object can only execute one operation at specific moment. + /// + /// + internal class CimSessionProxy : IDisposable + { + #region static members + + /// + /// + /// global operation counter + /// + /// + private static long gOperationCounter = 0; + + /// + /// temporary CimSession cache lock + /// + private static readonly object temporarySessionCacheLock = new object(); + + /// + /// temporary CimSession cache + /// Temporary CimSession means the session is created by cimcmdlets, + /// which is not created by cmdlet. + /// Due to some cmdlet, such as + /// might need to split the operation into multiple stages, i.e., query + /// CimInstance firstly, then remove the CimInstance resulted from query, + /// such that the temporary CimSession need to be shared between + /// multiple objects, introducing a + /// temporary session cache is necessary to control the lifetime of the + /// temporary CimSession objects. + /// + /// Once the reference count of the CimSession is decreased to 0, + /// then call Dispose on it. + /// + /// + private static Dictionary temporarySessionCache = new Dictionary(); + + /// + /// + /// Add to temporary cache. + /// If CimSession already present in cache, then increase the refcount by 1, + /// otherwise insert it into the cache. + /// + /// + /// CimSession to be added + internal static void AddCimSessionToTemporaryCache(CimSession session) + { + if (null != session) + { + lock (temporarySessionCacheLock) + { + if (temporarySessionCache.ContainsKey(session)) + { + temporarySessionCache[session]++; + DebugHelper.WriteLogEx(@"Increase cimsession ref count {0}", 1, temporarySessionCache[session]); + } + else + { + temporarySessionCache.Add(session, 1); + DebugHelper.WriteLogEx(@"Add cimsession to cache. Ref count {0}", 1, temporarySessionCache[session]); + } + } + } + } + + /// + /// Wrapper function to remove CimSession from cache + /// + /// + /// Whether need to dispose the object + private static void RemoveCimSessionFromTemporaryCache(CimSession session, + bool dispose) + { + if (null != session) + { + bool removed = false; + lock (temporarySessionCacheLock) + { + if (temporarySessionCache.ContainsKey(session)) + { + temporarySessionCache[session]--; + DebugHelper.WriteLogEx(@"Decrease cimsession ref count {0}", 1, temporarySessionCache[session]); + if (temporarySessionCache[session] == 0) + { + removed = true; + temporarySessionCache.Remove(session); + } + } + } + // there is a race condition that if + // one thread is waiting to add CimSession to cache, + // while current thread is removing the CimSession, + // then invalid CimSession may be added to cache. + // Ignored this scenario in CimCmdlet implementation, + // since the code inside cimcmdlet will not hit this + // scenario anyway. + if (removed && dispose) + { + DebugHelper.WriteLogEx(@"Dispose cimsession ", 1); + session.Dispose(); + } + } + } + + /// + /// + /// Remove from temporary cache. + /// If CimSession already present in cache, then decrease the refcount by 1, + /// otherwise ignore. + /// If refcount became 0, call dispose on the object. + /// + /// + /// CimSession to be added + internal static void RemoveCimSessionFromTemporaryCache(CimSession session) + { + RemoveCimSessionFromTemporaryCache(session, true); + } + #endregion + + #region Event definitions + + /// + /// Define delegate that handles new cmdlet action come from + /// the operations related to the current CimSession object. + /// + /// cimSession object, which raised the event + /// Event args + public delegate void NewCmdletActionHandler( + object cimSession, + CmdletActionEventArgs actionArgs); + + /// + /// Define an Event based on the NewActionHandler + /// + public event NewCmdletActionHandler OnNewCmdletAction; + + /// + /// Define delegate that handles operation creation and complete + /// issued by the current CimSession object. + /// + /// cimSession object, which raised the event + /// Event args + public delegate void OperationEventHandler( + object cimSession, + OperationEventArgs actionArgs); + + /// + /// Event triggered when a new operation is started + /// + public event OperationEventHandler OnOperationCreated; + + /// + /// Event triggered when a new operation is completed, + /// either success or failed. + /// + public event OperationEventHandler OnOperationDeleted; + + #endregion + + #region constructors + + /// + /// Then create wrapper object by given CimSessionProxy object. + /// + /// + public CimSessionProxy(CimSessionProxy proxy) + { + DebugHelper.WriteLogEx("protocol = {0}", 1, proxy.Protocol); + + CreateSetSession(null, proxy.CimSession, null, proxy.OperationOptions, proxy.IsTemporaryCimSession); + this.protocol = proxy.Protocol; + this.OperationTimeout = proxy.OperationTimeout; + this.isDefaultSession = proxy.isDefaultSession; + } + + /// + /// Create by given computer name. + /// Then create wrapper object. + /// + /// + public CimSessionProxy(string computerName) + { + CreateSetSession(computerName, null, null, null, false); + this.isDefaultSession = (computerName == ConstValue.NullComputerName); + } + + /// + /// Create by given computer name + /// and session options. + /// Then create wrapper object. + /// + /// + /// + public CimSessionProxy(string computerName, CimSessionOptions sessionOptions) + { + CreateSetSession(computerName, null, sessionOptions, null, false); + this.isDefaultSession = (computerName == ConstValue.NullComputerName); + } + + /// + /// Create by given computer name + /// and cimInstance. Then create wrapper object. + /// + /// + /// + public CimSessionProxy(string computerName, CimInstance cimInstance) + { + DebugHelper.WriteLogEx("ComptuerName {0}; cimInstance.CimSessionInstanceID = {1}; cimInstance.CimSessionComputerName = {2}.", + 0, + computerName, + cimInstance.GetCimSessionInstanceId(), + cimInstance.GetCimSessionComputerName()); + + if (computerName != ConstValue.NullComputerName) + { + CreateSetSession(computerName, null, null, null, false); + return; + } + + Debug.Assert(cimInstance != null, "Caller should verify cimInstance != null"); + + // computerName is null, fallback to create session from cimInstance + CimSessionState state = CimSessionBase.GetCimSessionState(); + if (state != null) + { + CimSession session = state.QuerySession(cimInstance.GetCimSessionInstanceId()); + if (session != null) + { + DebugHelper.WriteLogEx("Found the session from cache with InstanceID={0}.", 0, cimInstance.GetCimSessionInstanceId()); + CreateSetSession(null, session, null, null, false); + return; + } + } + String cimsessionComputerName = cimInstance.GetCimSessionComputerName(); + CreateSetSession(cimsessionComputerName, null, null, null, false); + this.isDefaultSession = (cimsessionComputerName == ConstValue.NullComputerName); + + DebugHelper.WriteLogEx("Create a temp session with computerName = {0}.", 0, cimsessionComputerName); + } + + /// + /// Create by given computer name, + /// session options + /// + /// + /// + /// Used when create async operation + public CimSessionProxy(string computerName, CimSessionOptions sessionOptions, CimOperationOptions operOptions) + { + CreateSetSession(computerName, null, sessionOptions, operOptions, false); + this.isDefaultSession = (computerName == ConstValue.NullComputerName); + } + + /// + /// Create by given computer name. + /// Then create wrapper object. + /// + /// + /// Used when create async operation + public CimSessionProxy(string computerName, CimOperationOptions operOptions) + { + CreateSetSession(computerName, null, null, operOptions, false); + this.isDefaultSession = (computerName == ConstValue.NullComputerName); + } + + /// + /// Create wrapper object by given session object + /// + /// + public CimSessionProxy(CimSession session) + { + CreateSetSession(null, session, null, null, false); + } + + /// + /// Create wrapper object by given session object + /// + /// + /// Used when create async operation + public CimSessionProxy(CimSession session, CimOperationOptions operOptions) + { + CreateSetSession(null, session, null, operOptions, false); + } + + /// + /// Initialize CimSessionProxy object + /// + /// + /// + /// + /// + private void CreateSetSession( + string computerName, + CimSession cimSession, + CimSessionOptions sessionOptions, + CimOperationOptions operOptions, + bool temporaryCimSession) + { + DebugHelper.WriteLogEx("computername {0}; cimsession {1}; sessionOptions {2}; operationOptions {3}.", 0, computerName, cimSession, sessionOptions, operOptions); + + lock (this.stateLock) + { + this.CancelOperation = null; + this.operation = null; + } + InitOption(operOptions); + this.protocol = ProtocolType.Wsman; + this.isTemporaryCimSession = temporaryCimSession; + + if (cimSession != null) + { + this.session = cimSession; + CimSessionState state = CimSessionBase.GetCimSessionState(); + if (state != null) + { + CimSessionWrapper wrapper = state.QuerySession(cimSession); + if (wrapper != null) + { + this.protocol = wrapper.GetProtocolType(); + } + } + } + else + { + if (sessionOptions != null) + { + if (sessionOptions is DComSessionOptions) + { + string defaultComputerName = ConstValue.IsDefaultComputerName(computerName) ? ConstValue.NullComputerName : computerName; + this.session = CimSession.Create(defaultComputerName, sessionOptions); + this.protocol = ProtocolType.Dcom; + } + else + { + this.session = CimSession.Create(computerName, sessionOptions); + } + } + else + { + this.session = CreateCimSessionByComputerName(computerName); + } + this.isTemporaryCimSession = true; + } + + if (this.isTemporaryCimSession) + { + AddCimSessionToTemporaryCache(this.session); + } + this.invocationContextObject = new InvocationContext(this); + DebugHelper.WriteLog("Protocol {0}, Is temporary session ? {1}", 1, this.protocol, this.isTemporaryCimSession); + } + + #endregion + + #region set operation options + + /// + /// Set timeout value (seconds) of the operation + /// + public UInt32 OperationTimeout + { + set + { + DebugHelper.WriteLogEx("OperationTimeout {0},", 0, value); + + this.options.Timeout = TimeSpan.FromSeconds((double)value); + } + get + { + return (UInt32)this.options.Timeout.TotalSeconds; + } + } + + /// + /// Set resource URI of the operation + /// + public Uri ResourceUri + { + set + { + DebugHelper.WriteLogEx("ResourceUri {0},", 0, value); + + this.options.ResourceUri= value; + } + get + { + return this.options.ResourceUri; + } + } + + /// + /// Enable/Disable the methos result streming, + /// it is enabled by default. + /// + public bool EnableMethodResultStreaming + { + get + { + return this.options.EnableMethodResultStreaming; + } + set + { + DebugHelper.WriteLogEx("EnableMethodResultStreaming {0}", 0, value); + this.options.EnableMethodResultStreaming = value; + } + } + + /// + /// Enable/Disable prompt user streming, + /// it is enabled by default. + /// + public bool EnablePromptUser + { + set + { + DebugHelper.WriteLogEx("EnablePromptUser {0}", 0, value); + if(value) + { + this.options.PromptUser = this.PromptUser; + } + } + } + + /// + /// Enable the pssemantics + /// + private void EnablePSSemantics() + { + DebugHelper.WriteLogEx(); + + // this.options.PromptUserForceFlag... + // this.options.WriteErrorMode + this.options.WriteErrorMode = CimCallbackMode.Inquire; + + // !!!NOTES: Does not subscribe to PromptUser for CimCmdlets now + // since cmdlet does not provider an approach + // to let user select how to handle prompt message + // this can be enabled later if needed. + this.options.WriteError = this.WriteError; + this.options.WriteMessage = this.WriteMessage; + this.options.WriteProgress = this.WriteProgress; + } + + /// + /// Set keyonly property. + /// + public SwitchParameter KeyOnly + { + set { this.options.KeysOnly = value.IsPresent; } + } + + /// + /// Set Shallow flag. + /// + public SwitchParameter Shallow + { + set + { + if (value.IsPresent) + { + this.options.Flags = CimOperationFlags.PolymorphismShallow; + } + else + { + this.options.Flags = CimOperationFlags.None; + } + } + } + + /// + /// Initialize the operation option + /// + private void InitOption(CimOperationOptions operOptions) + { + DebugHelper.WriteLogEx(); + + if (operOptions != null) + { + this.options = new CimOperationOptions(operOptions); + } + else if (this.options == null) + { + this.options = new CimOperationOptions(); + } + this.EnableMethodResultStreaming = true; + this.EnablePSSemantics(); + } + + #endregion + + #region misc operations + + /// + /// Caller call Detach to retrieve the session + /// object and control the lifecycle of the CimSession object. + /// + /// + public CimSession Detach() + { + DebugHelper.WriteLogEx(); + + // Remove the CimSession from cache but don't dispose it + RemoveCimSessionFromTemporaryCache(this.session, false); + CimSession sessionToReturn = this.session; + this.session = null; + this.isTemporaryCimSession = false; + return sessionToReturn; + } + + /// + /// Add a new opertion to cache. + /// + /// + /// + private void AddOperation(IObservable operation) + { + DebugHelper.WriteLogEx(); + + lock (this.stateLock) + { + Debug.Assert(this.Completed, "Caller should verify that there is no operation in progress"); + this.operation = operation; + } + } + + /// + /// Remove object from cache + /// + /// + private void RemoveOperation(IObservable operation) + { + DebugHelper.WriteLogEx(); + + lock (this.stateLock) + { + Debug.Assert(this.operation == operation, "Caller should verify that the operation to reomove is the operation in progress"); + + this.DisposeCancelOperation(); + + if (this.operation != null) + { + this.operation = null; + } + if (this.session != null && this.ContextObject == null) + { + DebugHelper.WriteLog("Dispose this proxy object @ RemoveOperation"); + this.Dispose(); + } + } + } + + /// + /// + /// Trigger an event that new action available + /// + /// + /// + protected void FireNewActionEvent(CimBaseAction action) + { + DebugHelper.WriteLogEx(); + + CmdletActionEventArgs actionArgs = new CmdletActionEventArgs(action); + if (!PreNewActionEvent(actionArgs)) + { + return; + } + + NewCmdletActionHandler temp = this.OnNewCmdletAction; + if (temp != null) + { + temp(this.session, actionArgs); + } + else + { + DebugHelper.WriteLog("Ignore action since OnNewCmdletAction is null.", 5); + } + this.PostNewActionEvent(actionArgs); + } + + /// + /// + /// Trigger an event that new operation is created + /// + /// + /// + /// + private void FireOperationCreatedEvent( + IDisposable cancelOperation, + IObservable operation) + { + DebugHelper.WriteLogEx(); + + OperationEventArgs args = new OperationEventArgs( + cancelOperation, operation, false); + OperationEventHandler temp = this.OnOperationCreated; + if (temp != null) + { + temp(this.session, args); + } + this.PostOperationCreateEvent(args); + } + + /// + /// + /// Trigger an event that an operation is deleted + /// + /// + /// + private void FireOperationDeletedEvent( + IObservable operation, + bool success) + { + DebugHelper.WriteLogEx(); + this.WriteOperationCompleteMessage(this.operationName); + OperationEventArgs args = new OperationEventArgs( + null, operation, success); + PreOperationDeleteEvent(args); + OperationEventHandler temp = this.OnOperationDeleted; + if (temp != null) + { + temp(this.session, args); + } + this.PostOperationDeleteEvent(args); + this.RemoveOperation(operation); + this.operationName = null; + } + + #endregion + + #region PSExtension callback functions + + /// + /// + /// WriteMessage callback + /// + /// + /// + /// + internal void WriteMessage(UInt32 channel, string message) + { + DebugHelper.WriteLogEx("Channel = {0} message = {1}", 0, channel, message); + try + { + CimWriteMessage action = new CimWriteMessage(channel, message); + this.FireNewActionEvent(action); + } + catch (Exception ex) + { + DebugHelper.WriteLogEx("{0}", 0, ex); + } + } + + /// + /// + /// Write opertion start verbose message + /// + /// + /// + /// + internal void WriteOperationStartMessage(string operation, Hashtable parameterList) + { + DebugHelper.WriteLogEx(); + StringBuilder parameters = new StringBuilder(); + if (parameterList != null) + { + foreach (string key in parameterList.Keys) + { + if (parameters.Length > 0) + { + parameters.Append(","); + } + parameters.Append(string.Format(CultureInfo.CurrentUICulture, @"'{0}' = {1}", key, parameterList[key])); + } + } + string operationStartMessage = string.Format(CultureInfo.CurrentUICulture, + Strings.CimOperationStart, + operation, + (parameters.Length == 0) ? "null" : parameters.ToString()); + WriteMessage((UInt32)CimWriteMessageChannel.Verbose, operationStartMessage); + } + + /// + /// + /// Write operation complete verbose message + /// + /// + /// + internal void WriteOperationCompleteMessage(string operation) + { + DebugHelper.WriteLogEx(); + string operationCompleteMessage = string.Format(CultureInfo.CurrentUICulture, + Strings.CimOperationCompleted, + operation); + WriteMessage((UInt32)CimWriteMessageChannel.Verbose, operationCompleteMessage); + } + + /// + /// + /// WriteProgress callback + /// + /// + /// + /// + /// + /// + /// + public void WriteProgress(string activity, + string currentOperation, + string statusDescription, + UInt32 percentageCompleted, + UInt32 secondsRemaining) + { + DebugHelper.WriteLogEx("activity:{0}; currentOperation:{1}; percentageCompleted:{2}; secondsRemaining:{3}", + 0, activity, currentOperation, percentageCompleted, secondsRemaining); + + try + { + CimWriteProgress action = new CimWriteProgress( + activity, + (int)this.operationID, + currentOperation, + statusDescription, + percentageCompleted, + secondsRemaining); + this.FireNewActionEvent(action); + } + catch (Exception ex) + { + DebugHelper.WriteLogEx("{0}", 0, ex); + } + } + + /// + /// + /// WriteError callback + /// + /// + /// + /// + public CimResponseType WriteError(CimInstance instance) + { + DebugHelper.WriteLogEx("Error:{0}", 0, instance); + try + { + CimWriteError action = new CimWriteError(instance, this.invocationContextObject); + this.FireNewActionEvent(action); + return action.GetResponse(); + } + catch (Exception ex) + { + DebugHelper.WriteLogEx("{0}", 0, ex); + return CimResponseType.NoToAll; + } + } + + /// + /// PromptUser callback + /// + /// + /// + /// + public CimResponseType PromptUser(string message, CimPromptType prompt) + { + DebugHelper.WriteLogEx("message:{0} prompt:{1}", 0, message, prompt); + try + { + CimPromptUser action = new CimPromptUser(message, prompt); + this.FireNewActionEvent(action); + return action.GetResponse(); + } + catch (Exception ex) + { + DebugHelper.WriteLogEx("{0}", 0, ex); + return CimResponseType.NoToAll; + } + } + #endregion + + #region Async result handler + + /// + /// + /// Handle async event triggered by + /// + /// + /// object triggered the event + /// async result event argument + internal void ResultEventHandler( + object observer, + AsyncResultEventArgsBase resultArgs) + { + DebugHelper.WriteLogEx(); + switch (resultArgs.resultType) + { + case AsyncResultType.Completion: + { + DebugHelper.WriteLog("ResultEventHandler::Completion", 4); + + AsyncResultCompleteEventArgs args = resultArgs as AsyncResultCompleteEventArgs; + this.FireOperationDeletedEvent(args.observable, true); + } + break; + case AsyncResultType.Exception: + { + AsyncResultErrorEventArgs args = resultArgs as AsyncResultErrorEventArgs; + DebugHelper.WriteLog("ResultEventHandler::Exception {0}", 4, args.error); + + using (CimWriteError action = new CimWriteError(args.error, this.invocationContextObject, args.context)) + { + this.FireNewActionEvent(action); + } + this.FireOperationDeletedEvent(args.observable, false); + } + break; + case AsyncResultType.Result: + { + AsyncResultObjectEventArgs args = resultArgs as AsyncResultObjectEventArgs; + DebugHelper.WriteLog("ResultEventHandler::Result {0}", 4, args.resultObject); + object resultObject = args.resultObject; + if (!this.isDefaultSession) + { + AddShowComputerNameMarker(resultObject); + } + if (this.ObjectPreProcess != null) + { + resultObject = this.ObjectPreProcess.Process(resultObject); + } +#if DEBUG + resultObject = PostProcessCimInstance(resultObject); +#endif + CimWriteResultObject action = new CimWriteResultObject(resultObject, this.ContextObject); + this.FireNewActionEvent(action); + } + break; + default: + break; + } + } + + /// + /// This method adds a note property to , + /// which will cause the default PowerShell formatting and output + /// to include PSComputerName column/property in the display. + /// + /// + private static void AddShowComputerNameMarker(object o) + { + if (o == null) + { + return; + } + + PSObject pso = PSObject.AsPSObject(o); + if (!(pso.BaseObject is CimInstance)) + { + return; + } + + PSNoteProperty psShowComputerNameProperty = new PSNoteProperty(ConstValue.ShowComputerNameNoteProperty, true); + pso.Members.Add(psShowComputerNameProperty); + } + +#if DEBUG + private static bool isCliXmlTestabilityHookActive = GetIsCliXmlTestabilityHookActive(); + private static bool GetIsCliXmlTestabilityHookActive() + { + return !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("CDXML_CLIXML_TEST")); + } + private object PostProcessCimInstance(object resultObject) + { + DebugHelper.WriteLogEx(); + if (isCliXmlTestabilityHookActive && (resultObject is CimInstance)) + { + string serializedForm = PSSerializer.Serialize(resultObject as CimInstance, depth: 1); + object deserializedObject = PSSerializer.Deserialize(serializedForm); + object returnObject = (deserializedObject is PSObject) ? (deserializedObject as PSObject).BaseObject : deserializedObject; + DebugHelper.WriteLogEx("Deserialized Object is {0}, type {1}", 1, returnObject, returnObject.GetType()); + return returnObject; + } + return resultObject; + } +#endif + #endregion + + #region Async operations + + /// + /// + /// create a cim instance asynchronously + /// + /// + /// + /// + public void CreateInstanceAsync(string namespaceName, CimInstance instance) + { + Debug.Assert(instance != null, "Caller should verify that instance != NULL."); + DebugHelper.WriteLogEx("EnableMethodResultStreaming = {0}", 0, this.options.EnableMethodResultStreaming); + this.CheckAvailability(); + this.targetCimInstance = instance; + this.operationName = Strings.CimOperationNameCreateInstance; + this.operationParameters.Clear(); + this.operationParameters.Add(@"namespaceName", namespaceName); + this.operationParameters.Add(@"instance", instance); + this.WriteOperationStartMessage(this.operationName, this.operationParameters); + CimAsyncResult asyncResult = this.session.CreateInstanceAsync(namespaceName, instance, this.options); + ConsumeCimInstanceAsync(asyncResult, new CimResultContext(instance)); + } + + /// + /// delete a cim instance asynchronously + /// + /// + /// + public void DeleteInstanceAsync(string namespaceName, CimInstance instance) + { + Debug.Assert(instance != null, "Caller should verify that instance != NULL."); + DebugHelper.WriteLogEx("namespace = {0}; classname = {1};", 0, namespaceName, instance.CimSystemProperties.ClassName); + this.CheckAvailability(); + this.targetCimInstance = instance; + this.operationName = Strings.CimOperationNameDeleteInstance; + this.operationParameters.Clear(); + this.operationParameters.Add(@"namespaceName", namespaceName); + this.operationParameters.Add(@"instance", instance); + this.WriteOperationStartMessage(this.operationName, this.operationParameters); + CimAsyncStatus asyncResult = this.session.DeleteInstanceAsync(namespaceName, instance, this.options); + ConsumeObjectAsync(asyncResult, new CimResultContext(instance)); + } + + /// + /// Get cim instance asynchronously + /// + /// + /// + public void GetInstanceAsync(string namespaceName, CimInstance instance) + { + Debug.Assert(instance != null, "Caller should verify that instance != NULL."); + DebugHelper.WriteLogEx("namespace = {0}; classname = {1}; keyonly = {2}", 0, namespaceName, instance.CimSystemProperties.ClassName, this.options.KeysOnly); + this.CheckAvailability(); + this.targetCimInstance = instance; + this.operationName = Strings.CimOperationNameGetInstance; + this.operationParameters.Clear(); + this.operationParameters.Add(@"namespaceName", namespaceName); + this.operationParameters.Add(@"instance", instance); + this.WriteOperationStartMessage(this.operationName, this.operationParameters); + CimAsyncResult asyncResult = this.session.GetInstanceAsync(namespaceName, instance, this.options); + ConsumeCimInstanceAsync(asyncResult, new CimResultContext(instance)); + } + + /// + /// Modify cim instance asynchronously + /// + /// + /// + public void ModifyInstanceAsync(string namespaceName, CimInstance instance) + { + Debug.Assert(instance != null, "Caller should verify that instance != NULL."); + DebugHelper.WriteLogEx("namespace = {0}; classname = {1}", 0, namespaceName, instance.CimSystemProperties.ClassName); + this.CheckAvailability(); + this.targetCimInstance = instance; + this.operationName = Strings.CimOperationNameModifyInstance; + this.operationParameters.Clear(); + this.operationParameters.Add(@"namespaceName", namespaceName); + this.operationParameters.Add(@"instance", instance); + this.WriteOperationStartMessage(this.operationName, this.operationParameters); + CimAsyncResult asyncResult = this.session.ModifyInstanceAsync(namespaceName, instance, this.options); + ConsumeObjectAsync(asyncResult, new CimResultContext(instance)); + } + + /// + /// Enumerate cim instance associated with the + /// given instance asynchronously + /// + /// + /// + /// + /// + /// + /// + public void EnumerateAssociatedInstancesAsync( + string namespaceName, + CimInstance sourceInstance, + string associationClassName, + string resultClassName, + string sourceRole, + string resultRole) + { + Debug.Assert(sourceInstance != null, "Caller should verify that sourceInstance != NULL."); + DebugHelper.WriteLogEx("Instance class {0}, association class {1}", 0, sourceInstance.CimSystemProperties.ClassName, associationClassName); + this.CheckAvailability(); + this.targetCimInstance = sourceInstance; + this.operationName = Strings.CimOperationNameEnumerateAssociatedInstances; + this.operationParameters.Clear(); + this.operationParameters.Add(@"namespaceName", namespaceName); + this.operationParameters.Add(@"sourceInstance", sourceInstance); + this.operationParameters.Add(@"associationClassName", associationClassName); + this.operationParameters.Add(@"resultClassName", resultClassName); + this.operationParameters.Add(@"sourceRole", sourceRole); + this.operationParameters.Add(@"resultRole", resultRole); + this.WriteOperationStartMessage(this.operationName, this.operationParameters); + CimAsyncMultipleResults asyncResult = this.session.EnumerateAssociatedInstancesAsync(namespaceName, sourceInstance, associationClassName, resultClassName, sourceRole, resultRole, this.options); + ConsumeCimInstanceAsync(asyncResult, new CimResultContext(sourceInstance)); + } + + /// + /// Enumerate cim instance asynchronously + /// + /// + /// + public void EnumerateInstancesAsync(string namespaceName, string className) + { + DebugHelper.WriteLogEx("KeyOnly {0}", 0, this.options.KeysOnly); + this.CheckAvailability(); + this.targetCimInstance = null; + this.operationName = Strings.CimOperationNameEnumerateInstances; + this.operationParameters.Clear(); + this.operationParameters.Add(@"namespaceName", namespaceName); + this.operationParameters.Add(@"className", className); + this.WriteOperationStartMessage(this.operationName, this.operationParameters); + CimAsyncMultipleResults asyncResult = this.session.EnumerateInstancesAsync(namespaceName, className, this.options); + string errorSource = String.Format(CultureInfo.CurrentUICulture, "{0}:{1}", namespaceName, className); + ConsumeCimInstanceAsync(asyncResult, new CimResultContext(errorSource)); + } + + /// + /// + /// Enumerate referencing instance associated with + /// the given instance asynchronously + /// + /// + /// + /// + /// + /// + public void EnumerateReferencingInstancesAsync( + string namespaceName, + CimInstance sourceInstance, + string associationClassName, + string sourceRole) + { + this.CheckAvailability(); + } + + /// + /// + /// Query cim instance asynchronously + /// + /// + /// + /// + /// + public void QueryInstancesAsync( + string namespaceName, + string queryDialect, + string queryExpression) + { + DebugHelper.WriteLogEx("KeyOnly = {0}", 0, this.options.KeysOnly); + this.CheckAvailability(); + this.targetCimInstance = null; + this.operationName = Strings.CimOperationNameQueryInstances; + this.operationParameters.Clear(); + this.operationParameters.Add(@"namespaceName", namespaceName); + this.operationParameters.Add(@"queryDialect", queryDialect); + this.operationParameters.Add(@"queryExpression", queryExpression); + this.WriteOperationStartMessage(this.operationName, this.operationParameters); + CimAsyncMultipleResults asyncResult = this.session.QueryInstancesAsync(namespaceName, queryDialect, queryExpression, this.options); + ConsumeCimInstanceAsync(asyncResult, null); + } + + /// + /// Enumerate cim class asynchronously + /// + /// + /// + public void EnumerateClassesAsync(string namespaceName) + { + DebugHelper.WriteLogEx("namespace {0}", 0, namespaceName); + this.CheckAvailability(); + this.targetCimInstance = null; + this.operationName = Strings.CimOperationNameEnumerateClasses; + this.operationParameters.Clear(); + this.operationParameters.Add(@"namespaceName", namespaceName); + this.WriteOperationStartMessage(this.operationName, this.operationParameters); + CimAsyncMultipleResults asyncResult = this.session.EnumerateClassesAsync(namespaceName, null, this.options); + ConsumeCimClassAsync(asyncResult, null); + } + + /// + /// Enumerate cim class asynchronously + /// + /// + /// + public void EnumerateClassesAsync(string namespaceName, string className) + { + this.CheckAvailability(); + this.targetCimInstance = null; + this.operationName = Strings.CimOperationNameEnumerateClasses; + this.operationParameters.Clear(); + this.operationParameters.Add(@"namespaceName", namespaceName); + this.operationParameters.Add(@"className", className); + this.WriteOperationStartMessage(this.operationName, this.operationParameters); + CimAsyncMultipleResults asyncResult = this.session.EnumerateClassesAsync(namespaceName, className, this.options); + string errorSource = String.Format(CultureInfo.CurrentUICulture, "{0}:{1}", namespaceName, className); + ConsumeCimClassAsync(asyncResult, new CimResultContext(errorSource)); + } + + /// + /// Get cim class asynchronously + /// + /// + /// + public void GetClassAsync(string namespaceName, string className) + { + DebugHelper.WriteLogEx("namespace = {0}, className = {1}", 0, namespaceName, className); + this.CheckAvailability(); + this.targetCimInstance = null; + this.operationName = Strings.CimOperationNameGetClass; + this.operationParameters.Clear(); + this.operationParameters.Add(@"namespaceName", namespaceName); + this.operationParameters.Add(@"className", className); + this.WriteOperationStartMessage(this.operationName, this.operationParameters); + CimAsyncResult asyncResult = this.session.GetClassAsync(namespaceName, className, this.options); + string errorSource = String.Format(CultureInfo.CurrentUICulture, "{0}:{1}", namespaceName, className); + ConsumeCimClassAsync(asyncResult, new CimResultContext(errorSource)); + } + + /// + /// Invoke method of a given cim instance asynchronously + /// + /// + /// + /// + /// + public void InvokeMethodAsync( + string namespaceName, + CimInstance instance, + string methodName, + CimMethodParametersCollection methodParameters) + { + Debug.Assert(instance != null, "Caller should verify that instance != NULL."); + DebugHelper.WriteLogEx("EnableMethodResultStreaming = {0}", 0, this.options.EnableMethodResultStreaming); + this.CheckAvailability(); + this.targetCimInstance = instance; + this.operationName = Strings.CimOperationNameInvokeMethod; + this.operationParameters.Clear(); + this.operationParameters.Add(@"namespaceName", namespaceName); + this.operationParameters.Add(@"instance", instance); + this.operationParameters.Add(@"methodName", methodName); + this.WriteOperationStartMessage(this.operationName, this.operationParameters); + CimAsyncMultipleResults asyncResult = this.session.InvokeMethodAsync(namespaceName, instance, methodName, methodParameters, this.options); + ConsumeCimInvokeMethodResultAsync(asyncResult, instance.CimSystemProperties.ClassName, methodName, new CimResultContext(instance)); + } + + /// + /// Invoke static method of a given class asynchronously + /// + /// + /// + /// + /// + public void InvokeMethodAsync( + string namespaceName, + string className, + string methodName, + CimMethodParametersCollection methodParameters) + { + DebugHelper.WriteLogEx("EnableMethodResultStreaming = {0}", 0, this.options.EnableMethodResultStreaming); + this.CheckAvailability(); + this.targetCimInstance = null; + this.operationName = Strings.CimOperationNameInvokeMethod; + this.operationParameters.Clear(); + this.operationParameters.Add(@"namespaceName", namespaceName); + this.operationParameters.Add(@"className", className); + this.operationParameters.Add(@"methodName", methodName); + this.WriteOperationStartMessage(this.operationName, this.operationParameters); + CimAsyncMultipleResults asyncResult = this.session.InvokeMethodAsync(namespaceName, className, methodName, methodParameters, this.options); + string errorSource = String.Format(CultureInfo.CurrentUICulture, "{0}:{1}", namespaceName, className); + ConsumeCimInvokeMethodResultAsync(asyncResult, className, methodName, new CimResultContext(errorSource)); + } + + /// + /// + /// Subscribe to cim indication asynchronously + /// + /// + /// + /// + /// + public void SubscribeAsync( + string namespaceName, + string queryDialect, + string queryExpression) + { + DebugHelper.WriteLogEx("QueryDialect = '{0}'; queryExpression = '{1}'", 0, queryDialect, queryExpression); + this.CheckAvailability(); + this.targetCimInstance = null; + this.operationName = Strings.CimOperationNameSubscribeIndication; + this.operationParameters.Clear(); + this.operationParameters.Add(@"namespaceName", namespaceName); + this.operationParameters.Add(@"queryDialect", queryDialect); + this.operationParameters.Add(@"queryExpression", queryExpression); + this.WriteOperationStartMessage(this.operationName, this.operationParameters); + + this.options.Flags |= CimOperationFlags.ReportOperationStarted; + CimAsyncMultipleResults asyncResult = this.session.SubscribeAsync(namespaceName, queryDialect, queryExpression, this.options); + ConsumeCimSubscriptionResultAsync(asyncResult, null); + } + + /// + /// + /// Test connection asynchronously + /// + /// + public void TestConnectionAsync() + { + DebugHelper.WriteLogEx("Start test connection", 0); + this.CheckAvailability(); + this.targetCimInstance = null; + CimAsyncResult asyncResult = this.session.TestConnectionAsync(); + // ignore the test connection result objects + ConsumeCimInstanceAsync(asyncResult, true, null); + } + + #endregion + + #region pre action APIs + /// + /// Called before new action event + /// + /// + protected virtual bool PreNewActionEvent(CmdletActionEventArgs args) + { + return true; + } + /// + /// Called before operation delete event + /// + /// + protected virtual void PreOperationDeleteEvent(OperationEventArgs args) + { + } + #endregion + + #region post action APIs + + /// + /// Called after new action event + /// + /// + protected virtual void PostNewActionEvent(CmdletActionEventArgs args) + { + } + /// + /// Called after operation create event + /// + /// + protected virtual void PostOperationCreateEvent(OperationEventArgs args) + { + } + /// + /// Called after operation delete event + /// + /// + protected virtual void PostOperationDeleteEvent(OperationEventArgs args) + { + } + #endregion + + #region members + + /// + /// + /// Unique operation ID + /// + /// + private long operationID; + + /// + /// The CimSession object managed by this proxy object, + /// which is either created by constructor OR passed in by caller. + /// The session will be closed while disposing this proxy object + /// if it is created by constuctor. + /// + internal CimSession CimSession + { + get + { + return this.session; + } + } + private CimSession session; + + /// + /// The current CimInstance object, against which issued + /// current operation, it could be null + /// + internal CimInstance TargetCimInstance + { + get + { + return this.targetCimInstance; + } + } + private CimInstance targetCimInstance = null; + + /// + /// Flag controls whether session object should be closed or not. + /// + private bool isTemporaryCimSession; + internal bool IsTemporaryCimSession + { + get + { + return isTemporaryCimSession; + } + } + + /// + /// The CimOperationOptions object, which specifies the options + /// of the operation against the session object. + /// Caller can control the timeout, method streaming support, and + /// extended ps semantics support, etc. + /// The setting MUST be set before start new operation on the + /// this proxy object. + /// + internal CimOperationOptions OperationOptions + { + get + { + return this.options; + } + } + private CimOperationOptions options; + + /// + /// All operations completed. + /// + private bool Completed + { + get { return this.operation == null; } + } + + /// + /// lock object used to lock + /// operation & cancelOperation members + /// + private readonly object stateLock = new object(); + + /// + /// the operation issued by cimSession + /// + private IObservable operation; + + /// + /// the current opration name + /// + private string operationName; + + /// + /// the current operation parameters + /// + private Hashtable operationParameters = new Hashtable(); + + /// + /// hanlder used to cancel operation + /// + private IDisposable _cancelOperation; + + /// + /// cancelOperation disposed flag + /// + private int _cancelOperationDisposed = 0; + + /// + /// Dispose the cancel opreation + /// + private void DisposeCancelOperation() + { + DebugHelper.WriteLogEx("CancelOperation Disposed = {0}", 0, this._cancelOperationDisposed); + if (Interlocked.CompareExchange(ref this._cancelOperationDisposed, 1, 0) == 0) + { + if (this._cancelOperation != null) + { + DebugHelper.WriteLog("CimSessionProxy::Dispose async operation.", 4); + this._cancelOperation.Dispose(); + this._cancelOperation = null; + } + } + } + + /// + /// Set the cancel opreation + /// + private IDisposable CancelOperation + { + set + { + DebugHelper.WriteLogEx(); + this._cancelOperation = value; + Interlocked.Exchange(ref this._cancelOperationDisposed, 0); + } + get + { + return this._cancelOperation; + } + } + + /// + /// current protocol name + /// DCOM or WSMAN + /// + internal ProtocolType Protocol + { + get + { + return protocol; + } + } + private ProtocolType protocol; + + /// + /// cross operation context object + /// + internal XOperationContextBase ContextObject + { + set + { + this.contextObject = value; + } + get + { + return this.contextObject; + } + } + private XOperationContextBase contextObject; + + /// + /// invocation context object + /// + private InvocationContext invocationContextObject; + + /// + /// a preprocess object to pre-processing the result object, + /// for example, adding PSTypeName, etc. + /// + internal IObjectPreProcess ObjectPreProcess + { + set + { + this.objectPreprocess = value; + } + get + { + return this.objectPreprocess; + } + } + private IObjectPreProcess objectPreprocess; + + /// + /// is true if this was + /// created to handle the "default" session, in cases where cmdlets are invoked without + /// ComputerName and/or CimSession parameters. + /// + private bool isDefaultSession; + + #endregion + + #region IDisposable + + /// + /// IDisposable interface + /// + private int _disposed; + + // Implement IDisposable. + // Do not make this method virtual. + // A derived class should not be able to override this method. + public void Dispose() + { + Dispose(true); + // This object will be cleaned up by the Dispose method. + // Therefore, you should call GC.SupressFinalize to + // take this object off the finalization queue + // and prevent finalization code for this object + // from executing a second time. + GC.SuppressFinalize(this); + } + + // Dispose(bool disposing) executes in two distinct scenarios. + // If disposing equals true, the method has been called directly + // or indirectly by a user's code. Managed and unmanaged resources + // can be disposed. + // If disposing equals false, the method has been called by the + // runtime from inside the finalizer and you should not reference + // other objects. Only unmanaged resources can be disposed. + protected virtual void Dispose(bool disposing) + { + DebugHelper.WriteLogEx("Disposed = {0}", 0, this.IsDisposed); + + if (Interlocked.CompareExchange(ref this._disposed, 1, 0) == 0) + { + if (disposing) + { + // Dispose managed resources. + this.DisposeCancelOperation(); + + if (this.options != null) + { + this.options.Dispose(); + this.options = null; + } + DisposeTemporaryCimSession(); + } + } + } + + public bool IsDisposed + { + get + { + return this._disposed == 1; + } + } + + /// + /// + /// Dispose temporary . + /// + /// + private void DisposeTemporaryCimSession() + { + if (this.isTemporaryCimSession && this.session != null) + { + // remove the cimsession from temporary cache + RemoveCimSessionFromTemporaryCache(this.session); + this.isTemporaryCimSession = false; + this.session = null; + } + } + #endregion + + #region helper methods + + /// + /// + /// Consume the results of async operations + /// + /// + /// + /// + protected void ConsumeCimInstanceAsync(IObservable asyncResult, + CimResultContext cimResultContext) + { + ConsumeCimInstanceAsync(asyncResult, false, cimResultContext); + } + + /// + /// + /// Consume the CimInstance results of async operations. + /// + /// + /// + /// + /// + protected void ConsumeCimInstanceAsync( + IObservable asyncResult, + bool ignoreResultObjects, + CimResultContext cimResultContext) + { + CimResultObserver observer; + if (ignoreResultObjects) + { + observer = new IgnoreResultObserver(this.session, asyncResult); + } + else + { + observer = new CimResultObserver(this.session, asyncResult, cimResultContext); + } + + observer.OnNewResult += this.ResultEventHandler; + this.operationID = Interlocked.Increment(ref gOperationCounter); + this.AddOperation(asyncResult); + this.CancelOperation = asyncResult.Subscribe(observer); + this.FireOperationCreatedEvent(this.CancelOperation, asyncResult); + } + + /// + /// + /// Consume the results of async operations + /// + /// + /// + /// + protected void ConsumeObjectAsync(IObservable asyncResult, + CimResultContext cimResultContext) + { + CimResultObserver observer = new CimResultObserver( + this.session, asyncResult, cimResultContext); + + observer.OnNewResult += this.ResultEventHandler; + this.operationID = Interlocked.Increment(ref gOperationCounter); + this.AddOperation(asyncResult); + this.CancelOperation = asyncResult.Subscribe(observer); + DebugHelper.WriteLog("FireOperationCreatedEvent"); + this.FireOperationCreatedEvent(this.CancelOperation, asyncResult); + } + + /// + /// + /// Consume the of async operations + /// + /// + /// + /// + protected void ConsumeCimClassAsync(IObservable asyncResult, + CimResultContext cimResultContext) + { + CimResultObserver observer = new CimResultObserver( + this.session, asyncResult, cimResultContext); + + observer.OnNewResult += this.ResultEventHandler; + this.operationID = Interlocked.Increment(ref gOperationCounter); + this.AddOperation(asyncResult); + this.CancelOperation = asyncResult.Subscribe(observer); + this.FireOperationCreatedEvent(this.CancelOperation, asyncResult); + } + + /// + /// + /// Consume the of async operations + /// + /// + /// + /// + protected void ConsumeCimSubscriptionResultAsync( + IObservable asyncResult, + CimResultContext cimResultContext) + { + CimSubscriptionResultObserver observer = new CimSubscriptionResultObserver( + this.session, asyncResult, cimResultContext); + observer.OnNewResult += this.ResultEventHandler; + this.operationID = Interlocked.Increment(ref gOperationCounter); + this.AddOperation(asyncResult); + this.CancelOperation = asyncResult.Subscribe(observer); + this.FireOperationCreatedEvent(this.CancelOperation, asyncResult); + } + + /// + /// + /// Consume the of async operations + /// + /// + /// + /// + /// + /// + protected void ConsumeCimInvokeMethodResultAsync( + IObservable asyncResult, + String className, + String methodName, + CimResultContext cimResultContext) + { + CimMethodResultObserver observer = new CimMethodResultObserver(this.session, asyncResult, cimResultContext) + { + ClassName = className, + MethodName = methodName + }; + + observer.OnNewResult += this.ResultEventHandler; + this.operationID = Interlocked.Increment(ref gOperationCounter); + this.AddOperation(asyncResult); + this.CancelOperation = asyncResult.Subscribe(observer); + this.FireOperationCreatedEvent(this.CancelOperation, asyncResult); + } + + /// + /// + /// Check whether current proxy object is available + /// + /// + private void CheckAvailability() + { + DebugHelper.WriteLogEx(); + + AssertSession(); + lock (this.stateLock) + { + if (!this.Completed) + { + throw new InvalidOperationException(Strings.OperationInProgress); + } + } + DebugHelper.WriteLog("KeyOnly {0},", 1, this.options.KeysOnly); + } + + /// + /// + /// Check the wrapped object + /// + /// + private void AssertSession() + { + if (this.IsDisposed || (this.session == null)) + { + DebugHelper.WriteLogEx("Invalid CimSessionProxy object, disposed? {0}; session object {1}", 1, this.IsDisposed, this.session); + throw new ObjectDisposedException(this.ToString()); + } + } + + /// + /// + /// Create based on the given computerName + /// + /// + /// + private CimSession CreateCimSessionByComputerName(string computerName) + { + DebugHelper.WriteLogEx("ComputerName {0}", 0, computerName); + + CimSessionOptions option = CreateCimSessionOption(computerName, 0, null); + if (option is DComSessionOptions) + { + DebugHelper.WriteLog("Create dcom cimSession"); + this.protocol = ProtocolType.Dcom; + return CimSession.Create(ConstValue.NullComputerName, option); + } + else + { + DebugHelper.WriteLog("Create wsman cimSession"); + return CimSession.Create(computerName, option); + } + } + + /// + /// + /// Create based on the given computerName, + /// timeout and credential + /// + /// + /// + /// + /// + /// + internal static CimSessionOptions CreateCimSessionOption(string computerName, + UInt32 timeout, CimCredential credential) + { + DebugHelper.WriteLogEx(); + + CimSessionOptions option; + if (ConstValue.IsDefaultComputerName(computerName)) + { + DebugHelper.WriteLog("<<<<<<<<<< Use protocol DCOM {0}", 1, computerName); + option = new DComSessionOptions(); + } + else + { + DebugHelper.WriteLog("<<<<<<<<<< Use protocol WSMAN {0}", 1, computerName); + option = new WSManSessionOptions(); + } + if (timeout != 0) + { + option.Timeout = TimeSpan.FromSeconds((double)timeout); + } + if (credential != null) + { + option.AddDestinationCredentials(credential); + } + DebugHelper.WriteLogEx("returned option :{0}.", 1, option); + return option; + } + + #endregion + + }//End Class + + #region class CimSessionProxyTestConnection + /// + /// + /// Write session to pipeline after test connection success + /// + /// + internal class CimSessionProxyTestConnection : CimSessionProxy + { + #region constructors + + /// + /// Create by given computer name + /// and session options. + /// Then create wrapper object. + /// + /// + /// + public CimSessionProxyTestConnection(string computerName, CimSessionOptions sessionOptions) + : base(computerName, sessionOptions) + { + } + + #endregion + + #region pre action APIs + + /// + /// Called after operation delete event + /// + /// + protected override void PreOperationDeleteEvent(OperationEventArgs args) + { + DebugHelper.WriteLogEx("test connection result {0}", 0, args.success); + + if (args.success) + { + // test connection success, write session object to pipeline + CimWriteResultObject result = new CimWriteResultObject(this.CimSession, this.ContextObject); + this.FireNewActionEvent(result); + } + } + + #endregion + } + + #endregion + + #region class CimSessionProxyGetCimClass + + /// + /// + /// Write CimClass to pipeline if the CimClass satisfied + /// the given conditions + /// + /// + internal class CimSessionProxyGetCimClass : CimSessionProxy + { + #region constructors + + /// + /// Create by given computer name. + /// Then create wrapper object. + /// + /// + public CimSessionProxyGetCimClass(string computerName) + : base(computerName) + { + } + + /// + /// Create by given computer name + /// and session options. + /// Then create wrapper object. + /// + /// + /// + public CimSessionProxyGetCimClass(CimSession session) + : base(session) + { + } + + #endregion + + #region pre action APIs + /// + /// Called before new action event + /// + /// + protected override bool PreNewActionEvent(CmdletActionEventArgs args) + { + DebugHelper.WriteLogEx(); + + if (!(args.Action is CimWriteResultObject)) + { + // allow all other actions + return true; + } + + CimWriteResultObject writeResultObject = args.Action as CimWriteResultObject; + CimClass cimClass = writeResultObject.Result as CimClass; + if (cimClass == null) + { + return true; + } + + DebugHelper.WriteLog("class name = {0}", 1, cimClass.CimSystemProperties.ClassName); + + CimGetCimClassContext context = this.ContextObject as CimGetCimClassContext; + Debug.Assert(context != null, "Caller should verify that CimGetCimClassContext != NULL."); + + WildcardPattern pattern; + if (WildcardPattern.ContainsWildcardCharacters(context.ClassName)) + { + pattern = new WildcardPattern(context.ClassName, WildcardOptions.IgnoreCase); + if (!pattern.IsMatch(cimClass.CimSystemProperties.ClassName)) + { + return false; + } + } + if (context.PropertyName != null) + { + pattern = new WildcardPattern(context.PropertyName, WildcardOptions.IgnoreCase); + bool match = false; + if (cimClass.CimClassProperties != null) + { + foreach (CimPropertyDeclaration decl in cimClass.CimClassProperties) + { + DebugHelper.WriteLog("--- property name : {0}", 1, decl.Name); + if (pattern.IsMatch(decl.Name)) + { + match = true; + break; + } + } + } + + if (!match) + { + DebugHelper.WriteLog("Property name does not match: {0}", 1, context.PropertyName); + return match; + } + } + if (context.MethodName != null) + { + pattern = new WildcardPattern(context.MethodName, WildcardOptions.IgnoreCase); + bool match = false; + if (cimClass.CimClassMethods != null) + { + foreach (CimMethodDeclaration decl in cimClass.CimClassMethods) + { + DebugHelper.WriteLog("--- method name : {0}", 1, decl.Name); + if (pattern.IsMatch(decl.Name)) + { + match = true; + break; + } + } + } + + if (!match) + { + DebugHelper.WriteLog("Method name does not match: {0}", 1, context.MethodName); + return match; + } + } + if (context.QualifierName != null) + { + pattern = new WildcardPattern(context.QualifierName, WildcardOptions.IgnoreCase); + bool match = false; + if (cimClass.CimClassQualifiers != null) + { + foreach (CimQualifier qualifier in cimClass.CimClassQualifiers) + { + DebugHelper.WriteLog("--- qualifier name : {0}", 1, qualifier.Name); + if (pattern.IsMatch(qualifier.Name)) + { + match = true; + break; + } + } + } + + if (!match) + { + DebugHelper.WriteLog("Qualifer name does not match: {0}", 1, context.QualifierName); + return match; + } + } + DebugHelper.WriteLog("CimClass '{0}' is qulified.", 1, cimClass.CimSystemProperties.ClassName); + return true; + } + #endregion + } + + #endregion + + #region class CimSessionProxyNewCimInstance + + /// + /// + /// Get full if create successfully. + /// + /// + internal class CimSessionProxyNewCimInstance : CimSessionProxy + { + #region constructors + + /// + /// Create by given computer name. + /// Then create wrapper object. + /// + /// + public CimSessionProxyNewCimInstance(string computerName, CimNewCimInstance operation) + : base(computerName) + { + this.newCimInstance = operation; + } + + /// + /// Create by given computer name + /// and session options. + /// Then create wrapper object. + /// + /// + /// + public CimSessionProxyNewCimInstance(CimSession session, CimNewCimInstance operation) + : base(session) + { + this.newCimInstance = operation; + } + + #endregion + + #region pre action APIs + /// + /// Called before new action event + /// + /// + protected override bool PreNewActionEvent(CmdletActionEventArgs args) + { + DebugHelper.WriteLogEx(); + + if (!(args.Action is CimWriteResultObject)) + { + // allow all other actions + return true; + } + + CimWriteResultObject writeResultObject = args.Action as CimWriteResultObject; + CimInstance cimInstance = writeResultObject.Result as CimInstance; + if (cimInstance == null) + { + return true; + } + + DebugHelper.WriteLog("Going to read CimInstance classname = {0}; namespace = {1}", 1, cimInstance.CimSystemProperties.ClassName, cimInstance.CimSystemProperties.Namespace); + this.NewCimInstanceOperation.GetCimInstance(cimInstance, this.ContextObject); + return false; + } + #endregion + + #region private members + + private CimNewCimInstance newCimInstance = null; + internal CimNewCimInstance NewCimInstanceOperation + { + get + { + return this.newCimInstance; + } + } + + #endregion + } + + #endregion + + #region class CimSessionProxyNewCimInstance + + /// + /// + /// Support PassThru for set-ciminstance. + /// + /// + internal class CimSessionProxySetCimInstance : CimSessionProxy + { + #region constructors + /// + /// Create by given object. + /// Then create wrapper object. + /// + /// object to clone. + /// PassThru, true means output the modified instance; otherwise does not output + public CimSessionProxySetCimInstance(CimSessionProxy originalProxy, bool passThru) + : base(originalProxy) + { + this.passThru = passThru; + } + + /// + /// Create by given computer name. + /// Then create wrapper object. + /// + /// + /// + /// + public CimSessionProxySetCimInstance(string computerName, + CimInstance cimInstance, + bool passThru) + : base(computerName, cimInstance) + { + this.passThru = passThru; + } + + /// + /// Create by given computer name + /// and session options. + /// Then create wrapper object. + /// + /// + /// + public CimSessionProxySetCimInstance(CimSession session, bool passThru) + : base(session) + { + this.passThru = passThru; + } + #endregion + + #region pre action APIs + /// + /// Called before new action event + /// + /// + protected override bool PreNewActionEvent(CmdletActionEventArgs args) + { + DebugHelper.WriteLogEx(); + + if ((!this.passThru) && (args.Action is CimWriteResultObject)) + { + // filter out any output object + return false; + } + + return true; + } + #endregion + + #region private members + + /// + /// Ture indicates need to output the modified result + /// + private bool passThru = false; + + #endregion + } + + #endregion +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSetCimInstance.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSetCimInstance.cs new file mode 100644 index 000000000..7ed4d1b19 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimSetCimInstance.cs @@ -0,0 +1,309 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System.Collections; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Management.Automation; + + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// Containing all necessary information originated from + /// the parameters of + /// + internal class CimSetCimInstanceContext : XOperationContextBase + { + /// + /// + /// Constructor + /// + /// + /// + /// + /// + internal CimSetCimInstanceContext(string theNamespace, + IDictionary theProperty, + CimSessionProxy theProxy, + string theParameterSetName, + bool passThru) + { + this.proxy = theProxy; + this.property = theProperty; + this.nameSpace = theNamespace; + this.parameterSetName = theParameterSetName; + this.passThru = passThru; + } + + /// + /// property value + /// + internal IDictionary Property + { + get + { + return this.property; + } + } + private IDictionary property; + + /// + /// prameter set name + /// + internal string ParameterSetName + { + get + { + return this.parameterSetName; + } + } + private string parameterSetName; + + /// + /// PassThru value + /// + internal bool PassThru + { + get + { + return this.passThru; + } + } + private bool passThru; + } + + /// + /// + /// Implements operations of set-ciminstance cmdlet. + /// + /// + internal sealed class CimSetCimInstance : CimGetInstance + { + /// + /// + /// Constructor + /// + /// + public CimSetCimInstance() + : base() + { + } + + /// + /// + /// Base on parametersetName to set ciminstances + /// + /// + /// object + public void SetCimInstance(SetCimInstanceCommand cmdlet) + { + IEnumerable computerNames = ConstValue.GetComputerNames( + GetComputerName(cmdlet)); + List proxys = new List(); + switch (cmdlet.ParameterSetName) + { + case CimBaseCommand.CimInstanceComputerSet: + foreach (string computerName in computerNames) + { + // create CimSessionProxySetCimInstance object internally + proxys.Add(CreateSessionProxy(computerName, cmdlet.CimInstance, cmdlet, cmdlet.PassThru)); + } + break; + case CimBaseCommand.CimInstanceSessionSet: + foreach (CimSession session in GetCimSession(cmdlet)) + { + // create CimSessionProxySetCimInstance object internally + proxys.Add(CreateSessionProxy(session, cmdlet, cmdlet.PassThru)); + } + break; + default: + break; + } + switch (cmdlet.ParameterSetName) + { + case CimBaseCommand.CimInstanceComputerSet: + case CimBaseCommand.CimInstanceSessionSet: + string nameSpace = ConstValue.GetNamespace(GetCimInstanceParameter(cmdlet).CimSystemProperties.Namespace); + string target = cmdlet.CimInstance.ToString(); + foreach (CimSessionProxy proxy in proxys) + { + if (!cmdlet.ShouldProcess(target, action)) + { + return; + } + + Exception exception = null; + CimInstance intance = cmdlet.CimInstance; + // For CimInstance parameter sets, Property is an optional parameter + if (cmdlet.Property != null) + { + if (!SetProperty(cmdlet.Property, ref intance, ref exception)) + { + cmdlet.ThrowTerminatingError(exception, action); + return; + } + } + proxy.ModifyInstanceAsync(nameSpace, intance); + } + break; + case CimBaseCommand.QueryComputerSet: + case CimBaseCommand.QuerySessionSet: + GetCimInstanceInternal(cmdlet); + break; + default: + break; + } + } + + /// + /// + /// Set with properties specified in cmdlet + /// + /// + /// + public void SetCimInstance(CimInstance cimInstance, CimSetCimInstanceContext context, CmdletOperationBase cmdlet) + { + DebugHelper.WriteLog("CimSetCimInstance::SetCimInstance", 4); + + if (!cmdlet.ShouldProcess(cimInstance.ToString(), action)) + { + return; + } + + Exception exception = null; + if (!SetProperty(context.Property, ref cimInstance, ref exception)) + { + cmdlet.ThrowTerminatingError(exception, action); + return; + } + CimSessionProxy proxy = CreateCimSessionProxy(context.Proxy, context.PassThru); + proxy.ModifyInstanceAsync(cimInstance.CimSystemProperties.Namespace, cimInstance); + } + + #region private members + + /// + /// + /// Set the properties value to be modified to the given + /// + /// + /// + /// + /// + /// + /// + private bool SetProperty(IDictionary properties, ref CimInstance cimInstance, ref Exception exception) + { + DebugHelper.WriteLogEx(); + if (properties.Count == 0) + { + // simply ignore if empty properties was provided + return true; + } + IDictionaryEnumerator enumerator = properties.GetEnumerator(); + while (enumerator.MoveNext()) + { + object value = GetBaseObject(enumerator.Value); + string key = enumerator.Key.ToString(); + DebugHelper.WriteLog("Input property name '{0}' with value '{1}'", 1, key, value); + + try + { + CimProperty property = cimInstance.CimInstanceProperties[key]; + // modify existing property value if found + if (property != null) + { + if ((property.Flags & CimFlags.ReadOnly) == CimFlags.ReadOnly) + { + // can not modify ReadOnly property + exception = new CimException(String.Format(CultureInfo.CurrentUICulture, + Strings.CouldNotModifyReadonlyProperty, key, cimInstance)); + return false; + } + // allow modify the key property value as long as it is not readonly, + // then the modified ciminstance is stand for a different CimInstance + DebugHelper.WriteLog("Set property name '{0}' has old value '{1}'", 4, key, property.Value); + property.Value = value; + } + else // For dynamic instance, it is valid to add a new property + { + CimProperty newProperty; + if( value == null ) + { + newProperty = CimProperty.Create( + key, + value, + CimType.String, + CimFlags.Property); + } + else + { + CimType referenceType = CimType.Unknown; + object referenceObject = GetReferenceOrReferenceArrayObject(value, ref referenceType); + if (referenceObject != null) + { + newProperty = CimProperty.Create( + key, + referenceObject, + referenceType, + CimFlags.Property); + } + else + { + newProperty = CimProperty.Create( + key, + value, + CimFlags.Property); + } + } + try + { + cimInstance.CimInstanceProperties.Add(newProperty); + } + catch (CimException e) + { + if (e.NativeErrorCode == NativeErrorCode.Failed) + { + string errorMessage = String.Format(CultureInfo.CurrentUICulture, + Strings.UnableToAddPropertyToInstance, + newProperty.Name, + cimInstance); + exception = new CimException(errorMessage, e); + } + else + { + exception = e; + } + return false; + } + DebugHelper.WriteLog("Add non-key property name '{0}' with value '{1}'.", 3, key, value); + } + } + catch (Exception e) + { + DebugHelper.WriteLog("Exception {0}", 4, e); + exception = e; + return false; + } + } + return true; + } + + #endregion + + #region const strings + /// + /// action + /// + private const string action = @"Set-CimInstance"; + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteError.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteError.cs new file mode 100644 index 000000000..780eae525 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteError.cs @@ -0,0 +1,435 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using System.Diagnostics; +using System.Globalization; +using System.Management.Automation; +using Microsoft.Management.Infrastructure.Options; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + #region class ErrorToErrorRecord + + /// + /// + /// Convert error or exception to + /// + /// + internal sealed class ErrorToErrorRecord + { + /// + /// + /// Convert ErrorRecord from exception object, + /// can be either or general . + /// + /// + /// + /// the context starting the operation, which generated the error + /// the CimResultContext used to provide ErrorSource, etc. info. + /// + internal static ErrorRecord ErrorRecordFromAnyException( + InvocationContext context, + Exception inner, + CimResultContext cimResultContext) + { + Debug.Assert(inner != null, "Caller should verify inner != null"); + + CimException cimException = inner as CimException; + if (cimException != null) + { + return CreateFromCimException(context, cimException, cimResultContext); + } + + var containsErrorRecord = inner as IContainsErrorRecord; + if (containsErrorRecord != null) + { + return InitializeErrorRecord(context, + exception : inner, + errorId: "CimCmdlet_" + containsErrorRecord.ErrorRecord.FullyQualifiedErrorId, + errorCategory: containsErrorRecord.ErrorRecord.CategoryInfo.Category, + cimResultContext: cimResultContext); + } + else + { + return InitializeErrorRecord(context, + exception :inner, + errorId: "CimCmdlet_" + inner.GetType().Name, + errorCategory: ErrorCategory.NotSpecified, + cimResultContext: cimResultContext); + } + } + + #region Helper functions + /// + /// Create from object. + /// + /// + /// + /// the CimResultContext used to provide ErrorSource, etc. info. + /// + internal static ErrorRecord CreateFromCimException( + InvocationContext context, + CimException cimException, + CimResultContext cimResultContext) + { + Debug.Assert(cimException != null, "Caller should verify cimException != null"); + + return InitializeErrorRecord(context, cimException, cimResultContext); + } + + /// + /// Create from object. + /// + /// + /// + /// + /// + /// the CimResultContext used to provide ErrorSource, etc. info. + /// + internal static ErrorRecord InitializeErrorRecord( + InvocationContext context, + Exception exception, + string errorId, + ErrorCategory errorCategory, + CimResultContext cimResultContext) + { + return InitializeErrorRecordCore( + context, + exception: exception, + errorId: errorId, + errorCategory: errorCategory, + cimResultContext: cimResultContext); + } + + /// + /// Create from object. + /// + /// + /// + /// the CimResultContext used to provide ErrorSource, etc. info. + /// + internal static ErrorRecord InitializeErrorRecord( + InvocationContext context, + CimException cimException, + CimResultContext cimResultContext) + { + ErrorRecord errorRecord = InitializeErrorRecordCore( + context, + exception: cimException, + errorId: cimException.MessageId ?? "MiClientApiError_" + cimException.NativeErrorCode, + errorCategory: ConvertCimExceptionToErrorCategory(cimException), + cimResultContext: cimResultContext); + + if (cimException.ErrorData != null) + { + errorRecord.CategoryInfo.TargetName = cimException.ErrorSource; + } + return errorRecord; + } + + /// + /// Create from object. + /// + /// + /// + /// + /// + /// the CimResultContext used to provide ErrorSource, etc. info. + /// + internal static ErrorRecord InitializeErrorRecordCore( + InvocationContext context, + Exception exception, + string errorId, + ErrorCategory errorCategory, + CimResultContext cimResultContext) + { + object theTargetObject = null; + if (cimResultContext != null) + { + theTargetObject = cimResultContext.ErrorSource; + } + if (theTargetObject == null) + { + if (context != null) + { + if (context.TargetCimInstance != null) + { + theTargetObject = context.TargetCimInstance; + } + } + } + ErrorRecord coreErrorRecord = new ErrorRecord( + exception: exception, + errorId: errorId, + errorCategory: errorCategory, + targetObject: theTargetObject); + + if (context == null) + { + return coreErrorRecord; + } + + System.Management.Automation.Remoting.OriginInfo originInfo = new System.Management.Automation.Remoting.OriginInfo( + context.ComputerName, + Guid.Empty); + + ErrorRecord errorRecord = new System.Management.Automation.Runspaces.RemotingErrorRecord( + coreErrorRecord, + originInfo); + + DebugHelper.WriteLogEx("Created RemotingErrorRecord.", 0); + // errorRecord.SetInvocationInfo(jobContext.CmdletInvocationInfo); + // errorRecord.PreserveInvocationInfoOnce = true; + return errorRecord; + } + + /// + /// Convert to . + /// + /// + /// + internal static ErrorCategory ConvertCimExceptionToErrorCategory(CimException cimException) + { + ErrorCategory result = ErrorCategory.NotSpecified; + + if (cimException.ErrorData != null) + { + result = ConvertCimErrorToErrorCategory(cimException.ErrorData); + } + + if (result == ErrorCategory.NotSpecified) + { + result = ConvertCimNativeErrorCodeToErrorCategory(cimException.NativeErrorCode); + } + + return result; + } + + /// + /// Convert to . + /// + /// + /// + internal static ErrorCategory ConvertCimNativeErrorCodeToErrorCategory(NativeErrorCode nativeErrorCode) + { + switch (nativeErrorCode) + { + case NativeErrorCode.Failed: + return ErrorCategory.NotSpecified; + case NativeErrorCode.AccessDenied: + return ErrorCategory.PermissionDenied; + case NativeErrorCode.InvalidNamespace: + return ErrorCategory.MetadataError; + case NativeErrorCode.InvalidParameter: + return ErrorCategory.InvalidArgument; + case NativeErrorCode.InvalidClass: + return ErrorCategory.MetadataError; + case NativeErrorCode.NotFound: + return ErrorCategory.ObjectNotFound; + case NativeErrorCode.NotSupported: + return ErrorCategory.NotImplemented; + case NativeErrorCode.ClassHasChildren: + return ErrorCategory.MetadataError; + case NativeErrorCode.ClassHasInstances: + return ErrorCategory.MetadataError; + case NativeErrorCode.InvalidSuperClass: + return ErrorCategory.MetadataError; + case NativeErrorCode.AlreadyExists: + return ErrorCategory.ResourceExists; + case NativeErrorCode.NoSuchProperty: + return ErrorCategory.MetadataError; + case NativeErrorCode.TypeMismatch: + return ErrorCategory.InvalidType; + case NativeErrorCode.QueryLanguageNotSupported: + return ErrorCategory.NotImplemented; + case NativeErrorCode.InvalidQuery: + return ErrorCategory.InvalidArgument; + case NativeErrorCode.MethodNotAvailable: + return ErrorCategory.MetadataError; + case NativeErrorCode.MethodNotFound: + return ErrorCategory.MetadataError; + case NativeErrorCode.NamespaceNotEmpty: + return ErrorCategory.MetadataError; + case NativeErrorCode.InvalidEnumerationContext: + return ErrorCategory.MetadataError; + case NativeErrorCode.InvalidOperationTimeout: + return ErrorCategory.InvalidArgument; + case NativeErrorCode.PullHasBeenAbandoned: + return ErrorCategory.OperationStopped; + case NativeErrorCode.PullCannotBeAbandoned: + return ErrorCategory.CloseError; + case NativeErrorCode.FilteredEnumerationNotSupported: + return ErrorCategory.NotImplemented; + case NativeErrorCode.ContinuationOnErrorNotSupported: + return ErrorCategory.NotImplemented; + case NativeErrorCode.ServerLimitsExceeded: + return ErrorCategory.ResourceBusy; + case NativeErrorCode.ServerIsShuttingDown: + return ErrorCategory.ResourceUnavailable; + default: + return ErrorCategory.NotSpecified; + } + } + + /// + /// Convert to . + /// + /// + /// + internal static ErrorCategory ConvertCimErrorToErrorCategory(CimInstance cimError) + { + if (cimError == null) + { + return ErrorCategory.NotSpecified; + } + + CimProperty errorCategoryProperty = cimError.CimInstanceProperties[@"Error_Category"]; + if (errorCategoryProperty == null) + { + return ErrorCategory.NotSpecified; + } + + ErrorCategory errorCategoryValue; + if (!LanguagePrimitives.TryConvertTo(errorCategoryProperty.Value, CultureInfo.InvariantCulture, out errorCategoryValue)) + { + return ErrorCategory.NotSpecified; + } + + return errorCategoryValue; + } + + #endregion + } + + #endregion + + /// + /// + /// Write error to pipeline + /// + /// + internal sealed class CimWriteError : CimSyncAction + { + /// + /// Constructor with an error + /// + /// + public CimWriteError(CimInstance error, InvocationContext context) + { + this.error = error; + this.invocationContext = context; + } + + /// + /// Construct with an exception object + /// + /// + public CimWriteError(Exception exception, InvocationContext context, CimResultContext cimResultContext) + { + this.exception = exception; + this.invocationContext = context; + this.cimResultContext = cimResultContext; + } + + /// + /// + /// Write error to pipeline + /// + /// + /// + public override void Execute(CmdletOperationBase cmdlet) + { + Debug.Assert(cmdlet != null, "Caller should verify that cmdlet != null"); + try + { + Exception errorException = (error != null) ? new CimException(error) : this.Exception; + + // PS engine takes care of handling error action + cmdlet.WriteError(ErrorToErrorRecord.ErrorRecordFromAnyException(this.invocationContext, errorException, this.cimResultContext)); + + // if user wants to continue, we will get here + this.responseType = CimResponseType.Yes; + } + catch + { + this.responseType = CimResponseType.NoToAll; + throw; + } + finally + { + // unblocking the waiting thread + this.OnComplete(); + } + } + + #region members + + /// + /// + /// Error instance + /// + /// + private CimInstance error; + + internal CimInstance Error + { + get + { + return error; + } + } + + /// + /// + /// Exception object + /// + /// + internal Exception Exception + { + get + { + return exception; + } + } + private Exception exception; + + /// + /// + /// object that contains + /// the information while issuing the current operation + /// + /// + private InvocationContext invocationContext; + + internal InvocationContext CimInvocationContext + { + get + { + return invocationContext; + } + } + + + /// + /// + /// + private CimResultContext cimResultContext; + + internal CimResultContext ResultContext + { + get + { + return cimResultContext; + } + } + + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteMessage.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteMessage.cs new file mode 100644 index 000000000..914d499bb --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteMessage.cs @@ -0,0 +1,85 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using Microsoft.Management.Infrastructure.Options; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// + /// Write message to message channel + /// + /// + internal sealed class CimWriteMessage : CimBaseAction + { + #region members + + /// + /// channel id + /// + private UInt32 channel; + + /// + /// message to write to the channel + /// + private string message; + #endregion + + #region Properties + + internal UInt32 Channel + { + get { return channel; } + } + + internal string Message + { + get { return message; } + } + + #endregion + + /// + /// Constructor method. + /// + public CimWriteMessage(UInt32 channel, + string message) + { + this.channel = channel; + this.message = message; + } + + /// + /// + /// Write message to the target channel + /// + /// + /// + public override void Execute(CmdletOperationBase cmdlet) + { + ValidationHelper.ValidateNoNullArgument(cmdlet, "cmdlet"); + + switch ((CimWriteMessageChannel)channel) + { + case CimWriteMessageChannel.Verbose: + cmdlet.WriteVerbose(message); + break; + case CimWriteMessageChannel.Warning: + cmdlet.WriteWarning(message); + break; + case CimWriteMessageChannel.Debug: + cmdlet.WriteDebug(message); + break; + default: + break; + } + } + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteProgress.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteProgress.cs new file mode 100644 index 000000000..ce28ce144 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteProgress.cs @@ -0,0 +1,155 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using System.Management.Automation; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// + /// Write progress record of given activity + /// + /// + internal sealed class CimWriteProgress : CimBaseAction + { + /// + /// Constructor + /// + /// + /// Activity identifier of the given activity + /// + /// + /// current operation description of the given activity + /// + /// + /// current status description of the given activity + /// + /// + /// percentage completed of the given activity + /// + /// + /// how many seconds remained for the given activity + /// + public CimWriteProgress( + string theActivity, + int theActivityID, + string theCurrentOperation, + string theStatusDescription, + UInt32 thePercentageCompleted, + UInt32 theSecondsRemaining) + { + this.activity = theActivity; + this.activityID = theActivityID; + this.currentOperation = theCurrentOperation; + if (String.IsNullOrEmpty(theStatusDescription)) + { + this.statusDescription = Strings.DefaultStatusDescription; + } + else + { + this.statusDescription = theStatusDescription; + } + this.percentageCompleted = thePercentageCompleted; + this.secondsRemaining = theSecondsRemaining; + } + + /// + /// + /// Write progress record to powershell + /// + /// + /// + public override void Execute(CmdletOperationBase cmdlet) + { + DebugHelper.WriteLog( + "...Activity {0}: id={1}, remain seconds ={2}, percentage completed = {3}", + 4, + this.activity, + this.activityID, + this.secondsRemaining, + this.percentageCompleted); + + ValidationHelper.ValidateNoNullArgument(cmdlet, "cmdlet"); + ProgressRecord record = new ProgressRecord( + this.activityID, + this.activity, + this.statusDescription); + record.Activity = this.activity; + record.ParentActivityId = 0; + record.SecondsRemaining = (int)this.secondsRemaining; + record.PercentComplete = (int)this.percentageCompleted; + cmdlet.WriteProgress(record); + } + + #region members + + /// + /// Activity of the given activity + /// + private string activity; + + /// + /// Activity identifier of the given activity + /// + private int activityID; + + /// + /// current operation text of the given activity + /// + private string currentOperation; + + /// + /// status description of the given activity + /// + private string statusDescription; + + /// + /// percentage completed of the given activity + /// + private UInt32 percentageCompleted; + + /// + /// how many seconds remained for the given activity + /// + private UInt32 secondsRemaining; + + internal string Activity + { + get { return activity; } + } + + internal int ActivityID + { + get { return activityID; } + } + + internal string CurrentOperation + { + get { return currentOperation; } + } + + internal string StatusDescription + { + get { return statusDescription; } + } + + internal UInt32 PercentageCompleted + { + get { return percentageCompleted; } + } + + internal UInt32 SecondsRemaining + { + get { return secondsRemaining; } + } + + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteResultObject.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteResultObject.cs new file mode 100644 index 000000000..c95bb7284 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CimWriteResultObject.cs @@ -0,0 +1,55 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// + /// Write result object to ps pipeline + /// + /// + internal sealed class CimWriteResultObject : CimBaseAction + { + /// + /// Constructor + /// + public CimWriteResultObject(object result, XOperationContextBase theContext) + { + this.result = result; + this.Context = theContext; + } + + /// + /// + /// Write result object to ps pipeline + /// + /// + /// + public override void Execute(CmdletOperationBase cmdlet) + { + ValidationHelper.ValidateNoNullArgument(cmdlet, "cmdlet"); + cmdlet.WriteObject(result, this.Context); + } + + #region members + /// + /// result object + /// + internal object Result + { + get + { + return result; + } + } + private object result; + #endregion + }//End Class + +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/CmdletOperation.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/CmdletOperation.cs new file mode 100644 index 000000000..b3aac9c1c --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/CmdletOperation.cs @@ -0,0 +1,390 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives +using System.Management.Automation; +using System; +using System.Globalization; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// + /// Wrapper of Cmdlet, forward the operation to Cmdlet directly. + /// This is for unit test purpose, unit test can derive from this class, + /// to hook up all of the cmdlet related operation and verify the correctness. + /// + /// + internal class CmdletOperationBase + { + /// + /// + /// Wrap the Cmdlet object. + /// + /// + private readonly Cmdlet cmdlet; + + /// + /// + /// Wrap the Cmdlet methods, for testing purpose. + /// Test binary can define a child class of CmdletOperationBase. + /// While Execute method of accept the + /// object of CmdletOperationBase as parameter. + /// + /// + #region CMDLET methods + + public virtual bool ShouldContinue(string query, string caption) + { + return cmdlet.ShouldContinue(query, caption); + } + public virtual bool ShouldContinue(string query, string caption, ref bool yesToAll, ref bool noToAll) + { + return cmdlet.ShouldContinue(query, caption, ref yesToAll, ref noToAll); + } + public virtual bool ShouldProcess(string target) + { + return cmdlet.ShouldProcess(target); + } + public virtual bool ShouldProcess(string target, string action) + { + return cmdlet.ShouldProcess(target, action); + } + public virtual bool ShouldProcess(string verboseDescription, string verboseWarning, string caption) + { + return cmdlet.ShouldProcess(verboseDescription, verboseWarning, caption); + } + public virtual bool ShouldProcess(string verboseDescription, string verboseWarning, string caption, out ShouldProcessReason shouldProcessReason) + { + return cmdlet.ShouldProcess(verboseDescription, verboseWarning, caption, out shouldProcessReason); + } + public virtual void ThrowTerminatingError(ErrorRecord errorRecord) + { + cmdlet.ThrowTerminatingError(errorRecord); + } + public virtual void WriteCommandDetail(string text) + { + cmdlet.WriteCommandDetail(text); + } + public virtual void WriteDebug(string text) + { + cmdlet.WriteDebug(text); + } + public virtual void WriteError(ErrorRecord errorRecord) + { + cmdlet.WriteError(errorRecord); + } + public virtual void WriteObject(object sendToPipeline, XOperationContextBase context) + { + cmdlet.WriteObject(sendToPipeline); + } + public virtual void WriteObject(object sendToPipeline, bool enumerateCollection, XOperationContextBase context) + { + cmdlet.WriteObject(sendToPipeline, enumerateCollection); + } + public virtual void WriteProgress(ProgressRecord progressRecord) + { + cmdlet.WriteProgress(progressRecord); + } + public virtual void WriteVerbose(string text) + { + cmdlet.WriteVerbose(text); + } + public virtual void WriteWarning(string text) + { + cmdlet.WriteWarning(text); + } + + /// + /// + /// Throw terminating error + /// + /// + internal void ThrowTerminatingError(Exception exception, string operation) + { + ErrorRecord errorRecord = new ErrorRecord(exception, operation, ErrorCategory.InvalidOperation, this); + cmdlet.ThrowTerminatingError(errorRecord); + } + #endregion + + /// + /// Constructor method. + /// + public CmdletOperationBase(Cmdlet cmdlet) + { + ValidationHelper.ValidateNoNullArgument(cmdlet, "cmdlet"); + this.cmdlet = cmdlet; + } + }//End Class + + #region Class CmdletOperationRemoveCimInstance + + /// + /// + /// Wrapper of Cmdlet, override WriteObject function call since + /// we need to remove . + /// + /// + internal class CmdletOperationRemoveCimInstance : CmdletOperationBase + { + /// + /// Constructor method + /// + /// + public CmdletOperationRemoveCimInstance(Cmdlet cmdlet, + CimRemoveCimInstance cimRemoveCimInstance) + : base(cmdlet) + { + ValidationHelper.ValidateNoNullArgument(cimRemoveCimInstance, cimRemoveCimInstanceParameterName); + this.removeCimInstance = cimRemoveCimInstance; + } + + /// + /// + /// Object here need to be removed if it is CimInstance + /// + /// + /// + public override void WriteObject(object sendToPipeline, XOperationContextBase context) + { + if (sendToPipeline is CimInstance) + { + DebugHelper.WriteLog(">>>>CmdletOperationRemoveCimInstance::WriteObject", 4); + this.removeCimInstance.RemoveCimInstance(sendToPipeline as CimInstance, context, this); + } + else + { + base.WriteObject(sendToPipeline, context); + } + } + + public override void WriteObject(object sendToPipeline, bool enumerateCollection, XOperationContextBase context) + { + if (sendToPipeline is CimInstance) + { + this.WriteObject(sendToPipeline, context); + } + else + { + base.WriteObject(sendToPipeline, enumerateCollection, context); + } + } + + #region private methods + + private CimRemoveCimInstance removeCimInstance; + + private const string cimRemoveCimInstanceParameterName = @"cimRemoveCimInstance"; + + #endregion + }//End Class + + #endregion + + #region Class CmdletOperationSetCimInstance + + /// + /// + /// Wrapper of Cmdlet, override WriteObject function call since + /// we need to set . + /// + /// + internal class CmdletOperationSetCimInstance : CmdletOperationBase + { + /// + /// Constructor method + /// + /// + public CmdletOperationSetCimInstance(Cmdlet cmdlet, + CimSetCimInstance theCimSetCimInstance) + : base(cmdlet) + { + ValidationHelper.ValidateNoNullArgument(theCimSetCimInstance, theCimSetCimInstanceParameterName); + this.setCimInstance = theCimSetCimInstance; + } + + /// + /// + /// Object here need to be removed if it is CimInstance + /// + /// + /// + public override void WriteObject(object sendToPipeline, XOperationContextBase context) + { + DebugHelper.WriteLogEx(); + + if (sendToPipeline is CimInstance) + { + CimSetCimInstanceContext setContext = context as CimSetCimInstanceContext; + if (setContext != null) + { + if ((String.Compare(setContext.ParameterSetName, CimBaseCommand.QueryComputerSet, StringComparison.OrdinalIgnoreCase) == 0) || + (String.Compare(setContext.ParameterSetName, CimBaseCommand.QuerySessionSet, StringComparison.OrdinalIgnoreCase) == 0)) + { + this.setCimInstance.SetCimInstance(sendToPipeline as CimInstance, setContext, this); + return; + } + else + { + DebugHelper.WriteLog("Write the cimInstance to pipeline since this CimInstance is returned by SetCimInstance.", 4); + } + } + else + { + DebugHelper.WriteLog("Assert. CimSetCimInstance::SetCimInstance has NULL CimSetCimInstanceContext", 4); + } + } + base.WriteObject(sendToPipeline, context); + } + + public override void WriteObject(object sendToPipeline, bool enumerateCollection, XOperationContextBase context) + { + if (sendToPipeline is CimInstance) + { + this.WriteObject(sendToPipeline, context); + } + else + { + base.WriteObject(sendToPipeline, enumerateCollection, context); + } + } + + #region private methods + + private CimSetCimInstance setCimInstance; + + private const string theCimSetCimInstanceParameterName = @"theCimSetCimInstance"; + + #endregion + }//End Class + #endregion + + #region Class CmdletOperationInvokeCimMethod + /// + /// + /// Wrapper of Cmdlet, override WriteObject function call since + /// we need to invoke cim method. + /// + /// + internal class CmdletOperationInvokeCimMethod : CmdletOperationBase + { + /// + /// Constructor method + /// + /// + public CmdletOperationInvokeCimMethod(Cmdlet cmdlet, + CimInvokeCimMethod theCimInvokeCimMethod) + : base(cmdlet) + { + ValidationHelper.ValidateNoNullArgument(theCimInvokeCimMethod, theCimInvokeCimMethodParameterName); + this.cimInvokeCimMethod = theCimInvokeCimMethod; + } + + /// + /// + /// Object here need to be removed if it is CimInstance + /// + /// + /// + public override void WriteObject(object sendToPipeline, XOperationContextBase context) + { + DebugHelper.WriteLogEx(); + + if (sendToPipeline is CimInstance) + { + this.cimInvokeCimMethod.InvokeCimMethodOnCimInstance(sendToPipeline as CimInstance, context, this); + } + else + { + base.WriteObject(sendToPipeline, context); + } + } + + public override void WriteObject(object sendToPipeline, bool enumerateCollection, XOperationContextBase context) + { + if (sendToPipeline is CimInstance) + { + this.WriteObject(sendToPipeline, context); + } + else + { + base.WriteObject(sendToPipeline, enumerateCollection, context); + } + } + + #region private methods + + private CimInvokeCimMethod cimInvokeCimMethod; + + private const string theCimInvokeCimMethodParameterName = @"theCimInvokeCimMethod"; + + #endregion + }//End Class + + #endregion + + #region Class CmdletOperationTestCimSession + + /// + /// + /// Wrapper of Cmdlet, override WriteObject function call since + /// we need to add cim session to global cache. + /// + /// + internal class CmdletOperationTestCimSession : CmdletOperationBase + { + /// + /// Constructor method + /// + /// + public CmdletOperationTestCimSession(Cmdlet cmdlet, + CimNewSession theCimNewSession) + : base(cmdlet) + { + ValidationHelper.ValidateNoNullArgument(theCimNewSession, theCimNewSessionParameterName); + this.cimNewSession = theCimNewSession; + } + + /// + /// + /// Add session object to cache + /// + /// + /// + public override void WriteObject(object sendToPipeline, XOperationContextBase context) + { + DebugHelper.WriteLogEx(); + + if (sendToPipeline is CimSession) + { + DebugHelper.WriteLog("Call CimNewSession::AddSessionToCache", 1); + + this.cimNewSession.AddSessionToCache(sendToPipeline as CimSession, context, this); + } + else if (sendToPipeline is PSObject) + { + DebugHelper.WriteLog("Write PSObject to pipeline", 1); + base.WriteObject(sendToPipeline, context); + } + else + { + // NOTES: May need to output for warning message/verbose message + DebugHelper.WriteLog("Ignore other type object {0}", 1, sendToPipeline); + } + } + + #region private methods + + private CimNewSession cimNewSession; + + private const string theCimNewSessionParameterName = @"theCimNewSession"; + + #endregion + }//End Class + + #endregion +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/ExportBinaryMiLogCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/ExportBinaryMiLogCommand.cs new file mode 100644 index 000000000..c76b98d18 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/ExportBinaryMiLogCommand.cs @@ -0,0 +1,116 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +using System; +using System.IO; +using System.Management.Automation; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +#if CORECLR +// Use stubs for SafeHandleZeroOrMinusOneIsInvalid and ReliabilityContractAttribute +using Microsoft.PowerShell.CoreClr.Stubs; +#else +using System.Runtime.ConstrainedExecution; +#endif + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + [Cmdlet(VerbsData.Export, BinaryMiLogBase.Noun, HelpUri = "http://go.microsoft.com/fwlink/?LinkId=301310")] + public sealed class ExportBinaryMiLogCommand : BinaryMiLogBase, IDisposable + { + [Parameter(ValueFromPipeline = true)] + [ValidateNotNull] + public CimInstance InputObject { get; set; } + + private static class NativeMethods + { + internal class WriterHandle : SafeHandleZeroOrMinusOneIsInvalid + { + private WriterHandle() + : base(true) + { + } + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + protected override bool ReleaseHandle() + { + Native.InstanceHandle errorHandle = null; + Native.MiResult result = SyncBmilWriter_Delete(this.handle, out errorHandle); + return true; + } + } + + [DllImport("mpunits.dll", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] + internal static extern Native.MiResult SyncBmilWriter_Create( + string filePath, + out WriterHandle writerHandle, + out Native.InstanceHandle errorHandle); + + [DllImport("mpunits.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + internal static extern Native.MiResult SyncBmilWriter_WriteInstance( + WriterHandle writerHandle, + Native.InstanceHandle instanceHandle, + out Native.InstanceHandle errorHandle); + + [DllImport("mpunits.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + private static extern Native.MiResult SyncBmilWriter_Delete( + IntPtr writerHandle, + out Native.InstanceHandle errorHandle); + } + + private sealed class Writer : IDisposable + { + private readonly NativeMethods.WriterHandle _writerHandle = null; + + internal Writer(string file) + { + Native.InstanceHandle errorHandle; + Native.MiResult miResult; + miResult = NativeMethods.SyncBmilWriter_Create(file, out _writerHandle, out errorHandle); + CimException.ThrowIfMiResultFailure(miResult, errorHandle); + } + + internal void WriteInstance(CimInstance cimInstance) + { + if (cimInstance == null) + { + throw new ArgumentNullException("cimInstance"); + } + + Native.InstanceHandle errorHandle; + Native.MiResult miResult; + miResult = NativeMethods.SyncBmilWriter_WriteInstance(_writerHandle, cimInstance.InstanceHandle, out errorHandle); + CimException.ThrowIfMiResultFailure(miResult, errorHandle); + } + + public void Dispose() + { + _writerHandle.Dispose(); + } + } + + private Writer _writer; + + protected override void BeginProcessing() + { + _writer = new Writer(this.GetVerifiedFilePath(FileAccess.Write)); + } + + protected override void ProcessRecord() + { + _writer.WriteInstance(InputObject); + } + + public void Dispose() + { + if (_writer != null) + { + _writer.Dispose(); + _writer = null; + } + } + } +} diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimAssociatedInstanceCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimAssociatedInstanceCommand.cs new file mode 100644 index 000000000..d83205907 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimAssociatedInstanceCommand.cs @@ -0,0 +1,370 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Management.Automation; +using System.Collections.Generic; + +#endregion + + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// + /// The Cmdlet retrieves instances connected to the given instance, which + /// is called the source instance, via a given association. In an + /// association each instance has a named role, and the same instance can + /// participate in an association in different roles. Hence, the Cmdlet + /// takes SourceRole and AssciatorRole parameters in addition to the + /// Association parameter. + /// + /// + [Cmdlet(VerbsCommon.Get, + GetCimAssociatedInstanceCommand.Noun, + DefaultParameterSetName = CimBaseCommand.ComputerSetName, + HelpUri = "http://go.microsoft.com/fwlink/?LinkId=227958")] + [OutputType(typeof(CimInstance))] + public class GetCimAssociatedInstanceCommand : CimBaseCommand + { + #region constructor + + /// + /// constructor + /// + public GetCimAssociatedInstanceCommand() + : base(parameters, parameterSets) + { + DebugHelper.WriteLogEx(); + } + + #endregion + + #region parameters + + /// + /// The following is the definition of the input parameter "Association". + /// Specifies the class name of the association to be traversed from the + /// SourceRole to AssociatorRole. + /// + [Parameter( + Position = 1, + ValueFromPipelineByPropertyName = true)] + public String Association + { + get { return association; } + set { association = value; } + } + private String association; + + /// + /// The following is the definition of the input parameter "ResultClassName". + /// Specifies the class name of the result class name, which associated with + /// the given instance. + /// + [Parameter] + public String ResultClassName + { + get { return resultClassName; } + set { resultClassName = value; } + } + private String resultClassName; + + /// + /// The following is the definition of the input parameter "AssociatorRole". + /// Specifies the name of the association role of the instances to be retrieved. + /// + //[Parameter(ValueFromPipelineByPropertyName = true)] + //public String AssociatorRole + //{ + // get { return associatorRole; } + // set { associatorRole = value; } + //} + //private String associatorRole; + + /// + /// The following is the definition of the input parameter "SourceRole". + /// Specifies the name of the association role of the source instance where the + /// association traversal should begin. + /// + //[Parameter(ValueFromPipelineByPropertyName = true)] + //public String SourceRole + //{ + // get { return sourcerole; } + // set { sourcerole = value; } + //} + //private String sourcerole; + + /// + /// + /// The following is the definition of the input parameter "InputObject". + /// Provides the instance from which the association traversal is to begin. + /// + /// + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipeline = true)] + [Alias(CimBaseCommand.AliasCimInstance)] + public CimInstance InputObject + { + get { return cimInstance; } + set + { + cimInstance = value; + base.SetParameter(value, nameCimInstance); + } + } + + /// + /// Property for internal usage purpose + /// + internal CimInstance CimInstance + { + get { return cimInstance; } + } + private CimInstance cimInstance; + + /// + /// The following is the definition of the input parameter "Namespace". + /// Identifies the Namespace in which the source class, indicated by ClassName, + /// is registered. + /// + [Parameter(ValueFromPipelineByPropertyName = true)] + public String Namespace + { + get { return nameSpace; } + set { nameSpace = value; } + } + private String nameSpace; + + /// + /// The following is the definition of the input parameter "OperationTimeoutSec". + /// Specifies the operation timeout after which the client operation should be + /// canceled. The default is the CimSession operation timeout. If this parameter + /// is specified, then this value takes precedence over the CimSession + /// OperationTimeout. + /// + [Alias(AliasOT)] + [Parameter(ValueFromPipelineByPropertyName = true)] + public UInt32 OperationTimeoutSec + { + get { return operationTimeout; } + set { operationTimeout = value; } + } + private UInt32 operationTimeout; + + /// + /// + /// The following is the definition of the input parameter "ResourceUri". + /// Define the Resource Uri for which the instances are retrieved. + /// + /// + [Parameter] + public Uri ResourceUri + { + get { return resourceUri; } + set + { + this.resourceUri = value; + base.SetParameter(value, nameResourceUri); + } + } + private Uri resourceUri; + + /// + /// + /// The following is the definition of the input parameter "ComputerName". + /// Specifies the name of the computer where the source instance is stored and + /// where the association traversal should begin. + /// + /// + /// This is an optional parameter and if it is not provided, the default value + /// will be "localhost". + /// + /// + [Alias(AliasCN, AliasServerName)] + [Parameter( + ParameterSetName = ComputerSetName)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public String[] ComputerName + { + get { return computerName; } + set + { + computerName = value; + base.SetParameter(value, nameComputerName); + } + } + private String[] computerName; + + /// + /// The following is the definition of the input parameter "CimSession". + /// Identifies the CimSession which is to be used to retrieve the instances. + /// + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = SessionSetName)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public Microsoft.Management.Infrastructure.CimSession[] CimSession + { + get { return cimSession; } + set + { + cimSession = value; + base.SetParameter(value, nameCimSession); + } + } + private Microsoft.Management.Infrastructure.CimSession[] cimSession; + + /// + /// + /// The following is the definition of the input parameter "KeyOnly". + /// Indicates that only key properties of the retrieved instances should be + /// returned to the client. + /// + /// + [Parameter] + public SwitchParameter KeyOnly + { + get { return keyOnly; } + set { keyOnly = value; } + } + private SwitchParameter keyOnly; + + #endregion + + #region cmdlet methods + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + this.CmdletOperation = new CmdletOperationBase(this); + this.AtBeginProcess = false; + }//End BeginProcessing() + + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + base.CheckParameterSet(); + CimGetAssociatedInstance operation = this.GetOperationAgent(); + if (operation == null) + { + operation = this.CreateOperationAgent(); + } + operation.GetCimAssociatedInstance(this); + operation.ProcessActions(this.CmdletOperation); + }//End ProcessRecord() + + /// + /// EndProcessing method. + /// + protected override void EndProcessing() + { + CimGetAssociatedInstance operation = this.GetOperationAgent(); + if (operation != null) + operation.ProcessRemainActions(this.CmdletOperation); + }//End EndProcessing() + + #endregion + + #region helper methods + + /// + /// + /// Get object, which is + /// used to delegate all Get-CimAssociatedInstance operations. + /// + /// + CimGetAssociatedInstance GetOperationAgent() + { + return this.AsyncOperation as CimGetAssociatedInstance; + } + + /// + /// + /// Create object, which is + /// used to delegate all Get-CimAssociatedInstance operations. + /// + /// + /// + CimGetAssociatedInstance CreateOperationAgent() + { + this.AsyncOperation = new CimGetAssociatedInstance(); + return GetOperationAgent(); + } + + #endregion + + #region internal const strings + + /// + /// Noun of current cmdlet + /// + internal const string Noun = @"CimAssociatedInstance"; + + #endregion + + #region private members + + #region const string of parameter names + // internal const string nameAssociation = "Association"; + internal const string nameCimInstance = "InputObject"; + // internal const string nameNamespace = "Namespace"; + // internal const string nameOperationTimeoutSec = "OperationTimeoutSec"; + internal const string nameComputerName = "ComputerName"; + internal const string nameCimSession = "CimSession"; + internal const string nameResourceUri = "ResourceUri"; + // internal const string nameKeyOnly = "KeyOnly"; + #endregion + + /// + /// static parameter definition entries + /// + static Dictionary> parameters = new Dictionary> + { + { + nameComputerName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ComputerSetName, false), + } + }, + { + nameCimSession, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.SessionSetName, true), + } + }, + { + nameCimInstance, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ComputerSetName, true), + new ParameterDefinitionEntry(CimBaseCommand.SessionSetName, true), + } + }, + { + nameResourceUri, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ComputerSetName, false), + new ParameterDefinitionEntry(CimBaseCommand.SessionSetName, false), + } + }, + }; + + /// + /// static parameter set entries + /// + static Dictionary parameterSets = new Dictionary + { + { CimBaseCommand.SessionSetName, new ParameterSetEntry(2, false) }, + { CimBaseCommand.ComputerSetName, new ParameterSetEntry(1, true) }, + }; + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimClassCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimClassCommand.cs new file mode 100644 index 000000000..ef8e1bd3b --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimClassCommand.cs @@ -0,0 +1,304 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Management.Automation; + +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// + /// Enables the user to enumerate the list of CIM Classes under a specific + /// Namespace. If no list of classes is given, the Cmdlet returns all + /// classes in the given namespce. + /// + /// + /// NOTES: The class instance contains the Namespace properties + /// Should the class remember what Session it came from? No. + /// + /// + [Cmdlet(VerbsCommon.Get, GetCimClassCommand.Noun, DefaultParameterSetName = ComputerSetName, HelpUri = "http://go.microsoft.com/fwlink/?LinkId=227959")] + [OutputType(typeof(CimClass))] + public class GetCimClassCommand : CimBaseCommand + { + #region constructor + + /// + /// constructor + /// + public GetCimClassCommand() + : base(parameters, parameterSets) + { + DebugHelper.WriteLogEx(); + } + + #endregion + + #region parameters + + /// + /// + /// The following is the definition of the input parameter "ClassName". + /// + /// + /// Wildcard expansion should be allowed. + /// + /// + [Parameter( + Position = 0, + ValueFromPipelineByPropertyName = true)] + public String ClassName + { + get { return className; } + set { className = value; } + } + private String className; + + /// + /// + /// The following is the definition of the input parameter "Namespace". + /// Specifies the Namespace under which to look for the specified class name. + /// If no class name is specified, the cmdlet should return all classes under + /// the specified Namespace. + /// + /// + /// Default namespace is root\cimv2 + /// + /// + [Parameter( + Position = 1, + ValueFromPipelineByPropertyName = true)] + public String Namespace + { + get { return nameSpace; } + set { nameSpace = value; } + } + private String nameSpace; + + /// + /// The following is the definition of the input parameter "OperationTimeoutSec". + /// Enables the user to specify the operation timeout in Seconds. This value + /// overwrites the value specified by the CimSession Operation timeout. + /// + [Alias(AliasOT)] + [Parameter(ValueFromPipelineByPropertyName = true)] + public UInt32 OperationTimeoutSec + { + get { return operationTimeout;} + set { operationTimeout = value; } + } + private UInt32 operationTimeout; + + /// + /// The following is the definition of the input parameter "Session". + /// Uses a CimSession context. + /// + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = SessionSetName)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public CimSession[] CimSession + { + get { return cimSession;} + set + { + cimSession = value; + base.SetParameter(value, nameCimSession); + } + } + private CimSession[] cimSession; + + /// + /// The following is the definition of the input parameter "ComputerName". + /// Provides the name of the computer from which to retrieve the + /// + /// + /// If no ComputerName is specified the default value is "localhost" + /// + /// + [Alias(AliasCN, AliasServerName)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = ComputerSetName)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public String[] ComputerName + { + get { return computerName; } + set + { + computerName = value; + base.SetParameter(value, nameComputerName); + } + } + private String[] computerName; + + /// + /// + /// The following is the definition of the input parameter "MethodName", + /// Which may contains wildchar. + /// Then Filter the by given methodname + /// + /// + [Parameter(ValueFromPipelineByPropertyName = true)] + public String MethodName + { + get { return methodName; } + set { methodName = value; } + } + private String methodName; + + /// + /// + /// The following is the definition of the input parameter "PropertyName", + /// Which may contains wildchar. + /// Filter the by given property name. + /// + /// + [Parameter(ValueFromPipelineByPropertyName = true)] + public String PropertyName + { + get { return propertyName; } + set { propertyName = value; } + } + private String propertyName; + + /// + /// + /// The following is the definition of the input parameter "QualifierName", + /// Which may contains wildchar. + /// Filter the by given methodname + /// + /// + [Parameter(ValueFromPipelineByPropertyName = true)] + public String QualifierName + { + get { return qualifierName; } + set { qualifierName = value; } + } + private String qualifierName; + + #endregion + + #region cmdlet methods + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + this.CmdletOperation = new CmdletOperationBase(this); + this.AtBeginProcess = false; + }//End BeginProcessing() + + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + base.CheckParameterSet(); + CimGetCimClass cimGetCimClass = this.GetOperationAgent(); + if (cimGetCimClass == null) + { + cimGetCimClass = CreateOperationAgent(); + } + cimGetCimClass.GetCimClass(this); + cimGetCimClass.ProcessActions(this.CmdletOperation); + }//End ProcessRecord() + + /// + /// EndProcessing method. + /// + protected override void EndProcessing() + { + CimGetCimClass cimGetCimClass = this.GetOperationAgent(); + if (cimGetCimClass != null) + { + cimGetCimClass.ProcessRemainActions(this.CmdletOperation); + } + }//End EndProcessing() + + #endregion + + #region helper methods + + /// + /// + /// Get object, which is + /// used to delegate all New-CimInstance operations. + /// + /// + CimGetCimClass GetOperationAgent() + { + return (this.AsyncOperation as CimGetCimClass); + } + + /// + /// + /// Create object, which is + /// used to delegate all Get-CimClass operations. + /// + /// + /// + CimGetCimClass CreateOperationAgent() + { + CimGetCimClass cimGetCimClass = new CimGetCimClass(); + this.AsyncOperation = cimGetCimClass; + return cimGetCimClass; + } + + #endregion + + #region internal const strings + + /// + /// Noun of current cmdlet + /// + internal const string Noun = @"CimClass"; + + #endregion + + #region private members + + #region const string of parameter names + internal const string nameCimSession = "CimSession"; + internal const string nameComputerName = "ComputerName"; + #endregion + + /// + /// static parameter definition entries + /// + static Dictionary> parameters = new Dictionary> + { + { + nameCimSession, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.SessionSetName, true), + } + }, + + { + nameComputerName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ComputerSetName, false), + } + }, + }; + + /// + /// static parameter set entries + /// + static Dictionary parameterSets = new Dictionary + { + { CimBaseCommand.SessionSetName, new ParameterSetEntry(1) }, + { CimBaseCommand.ComputerSetName, new ParameterSetEntry(0, true) }, + }; + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimInstanceCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimInstanceCommand.cs new file mode 100644 index 000000000..e7347b4c2 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimInstanceCommand.cs @@ -0,0 +1,648 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using System.Collections.Generic; +using System.Management.Automation; +using System.Collections; +using System.Diagnostics.CodeAnalysis; + +#endregion + + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// Returns zero, one or more CIM (dynamic) instances with the properties + /// specified in the Property parameter, KeysOnly parameter or the Select clause + /// of the Query parameter. + /// + [Cmdlet(VerbsCommon.Get, "CimInstance", DefaultParameterSetName = CimBaseCommand.ClassNameComputerSet, HelpUri = "http://go.microsoft.com/fwlink/?LinkId=227961")] + [OutputType(typeof(CimInstance))] + public class GetCimInstanceCommand : CimBaseCommand + { + #region constructor + + /// + /// constructor + /// + public GetCimInstanceCommand() + : base(parameters, parameterSets) + { + DebugHelper.WriteLogEx(); + } + + #endregion + + #region parameters + + /// + /// + /// The following is the definition of the input parameter "CimSession". + /// Identifies the CimSession which is to be used to retrieve the instances. + /// + /// + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.CimInstanceSessionSet)] + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public CimSession[] CimSession + { + get { return cimSession; } + set + { + cimSession = value; + base.SetParameter(value, nameCimSession); + } + } + private CimSession[] cimSession; + + /// + /// + /// The following is the definition of the input parameter "ClassName". + /// Define the class name for which the instances are retrieved. + /// + /// + [Parameter(Mandatory = true, + Position = 0, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Parameter(Mandatory = true, + Position = 0, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + public String ClassName + { + get { return className; } + set + { + this.className = value; + base.SetParameter(value, nameClassName); + } + } + private String className; + + /// + /// + /// The following is the definition of the input parameter "ResourceUri". + /// Define the Resource Uri for which the instances are retrieved. + /// + /// + [Parameter(Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] + [Parameter(Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] + [Parameter( + ParameterSetName = CimBaseCommand.CimInstanceComputerSet)] + [Parameter( + ParameterSetName = CimBaseCommand.CimInstanceSessionSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + public Uri ResourceUri + { + get { return resourceUri; } + set + { + this.resourceUri = value; + base.SetParameter(value, nameResourceUri); + } + } + private Uri resourceUri; + + /// + /// The following is the definition of the input parameter "ComputerName". + /// Provides the name of the computer from which to retrieve the instances. The + /// ComputerName is used to create a temporary CimSession with default parameter + /// values, which is then used to retrieve the instances. + /// + /// + /// If no ComputerName is specified the default value is "localhost" + /// + /// + [Alias(AliasCN, AliasServerName)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + [Parameter( + ParameterSetName = CimBaseCommand.CimInstanceComputerSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public String[] ComputerName + { + get { return computerName; } + set + { + computerName = value; + base.SetParameter(value, nameComputerName); + } + } + private String[] computerName; + + /// + /// + /// The following is the definition of the input parameter "KeyOnly". + /// Indicates that only key properties of the retrieved instances should be + /// returned to the client. + /// + /// + [Parameter(ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + [Parameter(ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Parameter(ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] + [Parameter(ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] + public SwitchParameter KeyOnly + { + get { return keyOnly; } + set + { + keyOnly = value; + base.SetParameter(value, nameKeyOnly); + } + } + private SwitchParameter keyOnly; + + /// + /// + /// The following is the definition of the input parameter "Namespace". + /// Identifies the Namespace in which the class, indicated by ClassName, is + /// registered. + /// + /// + /// Default namespace is 'root\cimv2' if this property is not specified. + /// + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + public String Namespace + { + get { return nameSpace; } + set + { + nameSpace = value; + base.SetParameter(value, nameNamespace); + } + } + private String nameSpace; + + /// + /// + /// The following is the definition of the input parameter "OperationTimeoutSec". + /// Specifies the operation timeout after which the client operation should be + /// canceled. The default is the CimSession operation timeout. If this parameter + /// is specified, then this value takes precedence over the CimSession + /// OperationTimeout. + /// + /// + [Alias(AliasOT)] + [Parameter] + public UInt32 OperationTimeoutSec + { + get { return operationTimeout; } + set { operationTimeout = value; } + } + private UInt32 operationTimeout; + + /// + /// The following is the definition of the input parameter "InputObject". + /// Provides the that containing the [Key] properties, + /// based on the key properties to retrieve the . + /// + /// + /// User can call New-CimInstance to create the CimInstance with key only + /// properties, for example: + /// New-CimInstance -ClassName C -Namespace root\cimv2 + /// -Property @{CreationClassName="CIM_VirtualComputerSystem";Name="VM3358"} + /// -Keys {"CreationClassName", "Name"} -Local + /// + /// + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.CimInstanceComputerSet)] + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.CimInstanceSessionSet)] + [Alias(CimBaseCommand.AliasCimInstance)] + public CimInstance InputObject + { + get { return cimInstance; } + set + { + cimInstance = value; + base.SetParameter(value, nameCimInstance); + } + } + + /// + /// Property for internal usage purpose + /// + internal CimInstance CimInstance + { + get { return cimInstance; } + } + private CimInstance cimInstance; + + /// + /// The following is the definition of the input parameter "Query". + /// Specifies the query string for what instances, and what properties of those + /// instances, should be retrieve. + /// + [Parameter(Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + [Parameter(Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + public String Query + { + get { return query; } + set + { + query = value; + base.SetParameter(value, nameQuery); + } + } + private String query; + + /// + /// + /// The following is the definition of the input parameter "QueryDialect". + /// Specifies the dialect used by the query Engine that interprets the Query + /// string. + /// + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + + public String QueryDialect + { + get { return queryDialect; } + set + { + queryDialect = value; + base.SetParameter(value, nameQueryDialect); + } + } + private String queryDialect; + + /// + /// + /// The following is the definition of the input parameter "Shallow". + /// If the switch is set to True, only instance of the class identified by + /// Namespace + ClassName will be returned. If the switch is not set, instances + /// of the above class and of all of its descendents will be returned (the + /// enumeration will cascade the class inheritance hierarchy). + /// + /// + [Parameter(ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + [Parameter(ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Parameter(ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] + [Parameter(ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] + [Parameter(ParameterSetName = CimBaseCommand.QueryComputerSet)] + [Parameter(ParameterSetName = CimBaseCommand.QuerySessionSet)] + public SwitchParameter Shallow + { + get { return shallow; } + set + { + shallow = value; + base.SetParameter(value, nameShallow); + } + } + private SwitchParameter shallow; + + /// + /// + /// The following is the definition of the input parameter "Filter". + /// Specifies the where clause of the query. + /// + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] + public String Filter + { + get { return filter; } + set + { + filter = value; + base.SetParameter(value, nameFilter); + } + } + private String filter; + + /// + /// + /// The following is the definition of the input parameter "Property". + /// Specifies the selected properties of result instances. + /// + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + [Alias("SelectProperties")] + public String[] Property + { + get { return property; } + set + { + property = value; + base.SetParameter(value, nameSelectProperties); + } + } + /// + /// Property for internal usage + /// + internal String[] SelectProperties + { + get { return property; } + } + private String[] property; + + #endregion + + #region cmdlet methods + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + this.CmdletOperation = new CmdletOperationBase(this); + this.AtBeginProcess = false; + }//End BeginProcessing() + + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + base.CheckParameterSet(); + this.CheckArgument(); + CimGetInstance cimGetInstance = this.GetOperationAgent(); + if (cimGetInstance == null) + { + cimGetInstance = CreateOperationAgent(); + } + cimGetInstance.GetCimInstance(this); + cimGetInstance.ProcessActions(this.CmdletOperation); + }//End ProcessRecord() + + /// + /// EndProcessing method. + /// + protected override void EndProcessing() + { + CimGetInstance cimGetInstance = this.GetOperationAgent(); + if (cimGetInstance != null) + { + cimGetInstance.ProcessRemainActions(this.CmdletOperation); + } + }//End EndProcessing() + + #endregion + + #region helper methods + + /// + /// + /// Get object, which is + /// used to delegate all Get-CimInstance operations, such + /// as enumerate instances, get instance, query instance. + /// + /// + CimGetInstance GetOperationAgent() + { + return (this.AsyncOperation as CimGetInstance); + } + + /// + /// + /// Create object, which is + /// used to delegate all Get-CimInstance operations, such + /// as enumerate instances, get instance, query instance. + /// + /// + /// + CimGetInstance CreateOperationAgent() + { + CimGetInstance cimGetInstance = new CimGetInstance(); + this.AsyncOperation = cimGetInstance; + return cimGetInstance; + } + + /// + /// check argument value + /// + private void CheckArgument() + { + switch (this.ParameterSetName) + { + case CimBaseCommand.ClassNameComputerSet: + case CimBaseCommand.ClassNameSessionSet: + // validate the classname & property + this.className = ValidationHelper.ValidateArgumentIsValidName(nameClassName, this.className); + this.property = ValidationHelper.ValidateArgumentIsValidName(nameSelectProperties, this.property); + break; + default: + break; + } + } + #endregion + + #region private members + + #region const string of parameter names + internal const string nameCimInstance = "InputObject"; + internal const string nameCimSession = "CimSession"; + internal const string nameClassName = "ClassName"; + internal const string nameResourceUri = "ResourceUri"; + internal const string nameComputerName = "ComputerName"; + internal const string nameFilter = "Filter"; + internal const string nameKeyOnly = "KeyOnly"; + internal const string nameNamespace = "Namespace"; + internal const string nameOperationTimeoutSec = "OperationTimeoutSec"; + internal const string nameQuery = "Query"; + internal const string nameQueryDialect = "QueryDialect"; + internal const string nameSelectProperties = "Property"; + internal const string nameShallow = "Shallow"; + #endregion + + /// + /// static parameter definition entries + /// + static Dictionary> parameters = new Dictionary> + { + { + nameCimSession, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriSessionSet, true), + } + }, + { + nameResourceUri, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriComputerSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, false), + } + }, + { + nameClassName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, true), + } + }, + { + nameComputerName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriComputerSet, false), + } + }, + { + nameKeyOnly, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriComputerSet, false), + } + }, + { + nameNamespace, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, false), + } + }, + { + nameCimInstance, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceComputerSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceSessionSet, true), + } + }, + { + nameQuery, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, true), + } + }, + { + nameQueryDialect, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, false), + + } + }, + { + nameShallow, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, false), + } + }, + { + nameFilter, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriComputerSet, false), + } + }, + { + nameSelectProperties, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriComputerSet, false), + } + }, + }; + + /// + /// static parameter set entries + /// + static Dictionary parameterSets = new Dictionary + { + { CimBaseCommand.CimInstanceComputerSet, new ParameterSetEntry(1) }, + { CimBaseCommand.CimInstanceSessionSet, new ParameterSetEntry(2) }, + { CimBaseCommand.ClassNameComputerSet, new ParameterSetEntry(1, true) }, + { CimBaseCommand.ClassNameSessionSet, new ParameterSetEntry(2) }, + { CimBaseCommand.QueryComputerSet, new ParameterSetEntry(1) }, + { CimBaseCommand.ResourceUriSessionSet, new ParameterSetEntry(2) }, + { CimBaseCommand.ResourceUriComputerSet, new ParameterSetEntry(1) }, + { CimBaseCommand.QuerySessionSet, new ParameterSetEntry(2) } + }; + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimSessionCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimSessionCommand.cs new file mode 100644 index 000000000..4aa52de8d --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimSessionCommand.cs @@ -0,0 +1,207 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Management.Automation; +#endregion + + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// The command returns zero, one or more CimSession objects that represent + /// connections with remote computers established from the current PS Session. + /// + + [Cmdlet(VerbsCommon.Get, "CimSession", DefaultParameterSetName = ComputerNameSet, HelpUri = "http://go.microsoft.com/fwlink/?LinkId=227966")] + [OutputType(typeof(CimSession))] + public sealed class GetCimSessionCommand : CimBaseCommand + { + #region constructor + + /// + /// constructor + /// + public GetCimSessionCommand() + : base(parameters, parameterSets) + { + DebugHelper.WriteLogEx(); + } + + #endregion + + #region parameters + + /// + /// + /// The following is the definition of the input parameter "ComputerName". + /// Specifies one or more connections by providing their ComputerName(s). The + /// Cmdlet then gets CimSession(s) opened with those connections. This parameter + /// is an alternative to using CimSession(s) that also identifies the remote + /// computer(s). + /// + /// + /// This is the only optional parameter of the Cmdlet. If not provided, the + /// Cmdlet returns all CimSession(s) live/active in the runspace. + /// + /// + /// If an instance of CimSession is pipelined to Get-CimSession, the + /// ComputerName property of the instance is bound by name with this parameter. + /// + /// + [Alias(AliasCN, AliasServerName)] + [Parameter(Position = 0, + ValueFromPipelineByPropertyName = true, + ParameterSetName = ComputerNameSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public String[] ComputerName + { + get { return computername;} + set + { + computername = value; + base.SetParameter(value, nameComputerName); + } + } + private String[] computername; + + /// + /// The following is the definition of the input parameter "Id". + /// Specifies one or more numeric Id(s) for which to get CimSession(s). + /// + [Parameter(Mandatory = true, + Position = 0, + ValueFromPipelineByPropertyName = true, + ParameterSetName = SessionIdSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public UInt32[] Id + { + get { return id;} + set + { + id = value; + base.SetParameter(value, nameId); + } + } + private UInt32[] id; + + /// + /// The following is the definition of the input parameter "InstanceID". + /// Specifies one or Session Instance IDs + /// + [Parameter(Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = InstanceIdSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public Guid[] InstanceId + { + get { return instanceid;} + set + { + instanceid = value; + base.SetParameter(value, nameInstanceId); + } + } + private Guid[] instanceid; + + /// + /// The following is the definition of the input parameter "Name". + /// Specifies one or more session Name(s) for which to get CimSession(s). The + /// argument may contain wildcard characters. + /// + [Parameter(Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = NameSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public String[] Name + { + get { return name;} + set + { + name = value; + base.SetParameter(value, nameName); + } + } + private String[] name; + + #endregion + + #region cmdlet processing methods + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + cimGetSession = new CimGetSession(); + this.AtBeginProcess = false; + }//End BeginProcessing() + + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + base.CheckParameterSet(); + cimGetSession.GetCimSession(this); + }//End ProcessRecord() + + #endregion + + #region private members + /// + /// object used to search CimSession from cache + /// + private CimGetSession cimGetSession; + + #region const string of parameter names + internal const string nameComputerName = "ComputerName"; + internal const string nameId = "Id"; + internal const string nameInstanceId = "InstanceId"; + internal const string nameName = "Name"; + #endregion + + /// + /// static parameter definition entries + /// + static Dictionary> parameters = new Dictionary> + { + { + nameComputerName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ComputerNameSet, false), + } + }, + { + nameId, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.SessionIdSet, true), + } + }, + { + nameInstanceId, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.InstanceIdSet, true), + } + }, + { + nameName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.NameSet, true), + } + }, + }; + + /// + /// static parameter set entries + /// + static Dictionary parameterSets = new Dictionary + { + { CimBaseCommand.ComputerNameSet, new ParameterSetEntry(0, true) }, + { CimBaseCommand.SessionIdSet, new ParameterSetEntry(1) }, + { CimBaseCommand.InstanceIdSet, new ParameterSetEntry(1) }, + { CimBaseCommand.NameSet, new ParameterSetEntry(1) }, + }; + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/ImportBinaryMiLogCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/ImportBinaryMiLogCommand.cs new file mode 100644 index 000000000..934e9d90a --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/ImportBinaryMiLogCommand.cs @@ -0,0 +1,113 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +using System; +using System.IO; +using System.Management.Automation; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +#if CORECLR +// Use stubs for SafeHandleZeroOrMinusOneIsInvalid and ReliabilityContractAttribute +using Microsoft.PowerShell.CoreClr.Stubs; +#else +using System.Runtime.ConstrainedExecution; +#endif + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + [Cmdlet(VerbsData.Import, BinaryMiLogBase.Noun, HelpUri = "http://go.microsoft.com/fwlink/?LinkId=301309")] + public sealed class ImportBinaryMiLogCommand : BinaryMiLogBase + { + private static class NativeMethods + { + internal class ReaderHandle : SafeHandleZeroOrMinusOneIsInvalid + { + private ReaderHandle() + : base(true) + { + } + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + protected override bool ReleaseHandle() + { + Native.InstanceHandle errorHandle = null; + Native.MiResult result = SyncBmilReader_Delete(this.handle, out errorHandle); + return true; + } + } + + [DllImport("mpunits.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + internal static extern Native.MiResult SyncBmilReader_Create( + string filePath, + out ReaderHandle readerHandle, + out Native.InstanceHandle errorHandle); + + [DllImport("mpunits.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + internal static extern Native.MiResult SyncBmilReader_ReadInstance( + ReaderHandle readerHandle, + out Native.InstanceHandle instanceHandle, + out Native.InstanceHandle errorHandle); + + [DllImport("mpunits.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + private static extern Native.MiResult SyncBmilReader_Delete( + IntPtr readerHandle, + out Native.InstanceHandle errorHandle); + } + + private sealed class Reader : IDisposable + { + private readonly NativeMethods.ReaderHandle _readerHandle; + + internal Reader(string file) + { + Native.InstanceHandle errorHandle; + Native.MiResult miResult; + miResult = NativeMethods.SyncBmilReader_Create(file, out _readerHandle, out errorHandle); + CimException.ThrowIfMiResultFailure(miResult, errorHandle); + } + + internal CimInstance ReadInstance() + { + Native.InstanceHandle errorHandle; + Native.InstanceHandle instanceHandle; + Native.MiResult miResult; + miResult = NativeMethods.SyncBmilReader_ReadInstance(_readerHandle, out instanceHandle, out errorHandle); + CimException.ThrowIfMiResultFailure(miResult, errorHandle); + + if (instanceHandle.IsInvalid) + { + return null; + } + var cimInstance = new CimInstance(instanceHandle, null); + return cimInstance; + } + + public void Dispose() + { + _readerHandle.Dispose(); + } + } + + protected override void BeginProcessing() + { + base.BeginProcessing(); + + this.GetVerifiedFilePath(FileAccess.Read); + using (var reader = new Reader(this.GetVerifiedFilePath(FileAccess.Read))) + { + CimInstance cimInstance; + do + { + cimInstance = reader.ReadInstance(); + if (cimInstance != null) + { + this.WriteObject(cimInstance); + } + } while (cimInstance != null); + } + } + } +} diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/InvokeCimMethodCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/InvokeCimMethodCommand.cs new file mode 100644 index 000000000..4d9d56f62 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/InvokeCimMethodCommand.cs @@ -0,0 +1,556 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Management.Automation; +#endregion + + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// This cmdlet enables the user to invoke a static method on a CIM class using + /// the arguments passed as a list of name value pair dictionary. + /// + + [Cmdlet( + "Invoke", + "CimMethod", + SupportsShouldProcess = true, + DefaultParameterSetName = CimBaseCommand.ClassNameComputerSet, + HelpUri = "http://go.microsoft.com/fwlink/?LinkId=227965")] + public class InvokeCimMethodCommand : CimBaseCommand + { + #region constructor + + /// + /// constructor + /// + public InvokeCimMethodCommand() + : base(parameters, parameterSets) + { + DebugHelper.WriteLogEx(); + } + + #endregion + + #region parameters + + /// + /// The following is the definition of the input parameter "ClassName". + /// Specifies the Class Name, on which to invoke static method. + /// + [Parameter(Mandatory = true, + Position = 0, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + [Parameter(Mandatory = true, + Position = 0, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Alias("Class")] + public String ClassName + { + get { return className; } + set + { + className = value; + base.SetParameter(value, nameClassName); + } + } + private String className; + + /// + /// + /// The following is the definition of the input parameter "ResourceUri". + /// Define the Resource Uri for which the instances are retrieved. + /// + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.CimInstanceComputerSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.CimInstanceSessionSet)] + [Parameter(Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] + [Parameter(Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] + public Uri ResourceUri + { + get { return resourceUri; } + set + { + this.resourceUri = value; + base.SetParameter(value, nameResourceUri); + } + } + private Uri resourceUri; + + /// + /// The following is the definition of the input parameter "CimClass". + /// Specifies the object, on which to invoke static method. + /// + [Parameter(Mandatory = true, + Position = 0, + ValueFromPipeline = true, + ParameterSetName = CimClassComputerSet)] + [Parameter(Mandatory = true, + Position = 0, + ValueFromPipeline = true, + ParameterSetName = CimClassSessionSet)] + public CimClass CimClass + { + get { return cimClass; } + set + { + cimClass = value; + base.SetParameter(value, nameCimClass); + } + } + private CimClass cimClass; + + /// + /// The following is the definition of the input parameter "Query". + /// Specifies the object, on which to invoke static method. + /// + [Parameter(Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + [Parameter(Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + public string Query + { + get { return query; } + set + { + query = value; + base.SetParameter(value, nameQuery); + } + } + private string query; + + /// + /// + /// The following is the definition of the input parameter "QueryDialect". + /// Specifies the dialect used by the query Engine that interprets the Query + /// string. + /// + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + public String QueryDialect + { + get { return queryDialect; } + set + { + queryDialect = value; + base.SetParameter(value, nameQueryDialect); + } + } + private String queryDialect; + + /// + /// The following is the definition of the input parameter "InputObject". + /// Takes a CimInstance object retrieved by a Get-CimInstance call. + /// Invoke the method against the given instance + /// + [Parameter(Mandatory = true, + Position = 0, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.CimInstanceComputerSet)] + [Parameter(Mandatory = true, + Position = 0, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.CimInstanceSessionSet)] + [Alias(CimBaseCommand.AliasCimInstance)] + public CimInstance InputObject + { + get { return cimInstance; } + set + { + cimInstance = value; + base.SetParameter(value, nameCimInstance); + } + } + + /// + /// Property for internal usage purpose + /// + internal CimInstance CimInstance + { + get { return cimInstance; } + } + private CimInstance cimInstance; + + /// + /// The following is the definition of the input parameter "ComputerName". + /// Provides the name of the computer from which to invoke the method. The + /// ComputerName is used to create a temporary CimSession with default parameter + /// values, which is then used to retrieve the instances. + /// + /// + /// If no ComputerName is specified the default value is "localhost" + /// + /// + [Alias(AliasCN, AliasServerName)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + [Parameter( + ParameterSetName = CimBaseCommand.CimInstanceComputerSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.CimClassComputerSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public String[] ComputerName + { + get { return computerName; } + set + { + DebugHelper.WriteLogEx(); + computerName = value; + base.SetParameter(value, nameComputerName); + } + } + private String[] computerName; + + /// + /// + /// The following is the definition of the input parameter "CimSession". + /// Identifies the CimSession which is to be used to retrieve the instances. + /// + /// + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.CimInstanceSessionSet)] + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = CimClassSessionSet)] + [Parameter(Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public CimSession[] CimSession + { + get { return cimSession; } + set + { + cimSession = value; + base.SetParameter(value, nameCimSession); + } + } + private CimSession[] cimSession; + + /// + /// The following is the definition of the input parameter "Arguments". + /// Specifies the parameter arguments for the static method using a name value + /// pair. + /// + [Parameter(Position = 1, ValueFromPipelineByPropertyName = true)] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public IDictionary Arguments + { + get { return arguments; } + set { arguments = value; } + } + private IDictionary arguments; + + /// + /// The following is the definition of the input parameter "MethodName". + /// Name of the Static Method to use. + /// + [Parameter(Mandatory = true, + Position = 2, + ValueFromPipelineByPropertyName = true)] + [Alias("Name")] + public String MethodName + { + get { return methodName; } + set + { + methodName = value; + base.SetParameter(value, nameMethodName); + } + } + private String methodName; + + /// + /// The following is the definition of the input parameter "Namespace". + /// Specifies the NameSpace in which the class or instance lives under. + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] + public String Namespace + { + get { return nameSpace; } + set + { + nameSpace = value; + base.SetParameter(value, nameNamespace); + } + } + private String nameSpace; + + /// + /// The following is the definition of the input parameter "OperationTimeoutSec". + /// Enables the user to specify the operation timeout in Seconds. This value + /// overwrites the value specified by the CimSession Operation timeout. + /// + [Alias(AliasOT)] + [Parameter] + public UInt32 OperationTimeoutSec + { + get { return operationTimeout; } + set { operationTimeout = value; } + } + private UInt32 operationTimeout; + + #endregion + + #region cmdlet methods + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + CimInvokeCimMethod cimInvokeMethod = this.GetOperationAgent(); + if (cimInvokeMethod == null) + { + cimInvokeMethod = CreateOperationAgent(); + } + this.CmdletOperation = new CmdletOperationInvokeCimMethod(this, cimInvokeMethod); + this.AtBeginProcess = false; + }//End BeginProcessing() + + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + base.CheckParameterSet(); + this.CheckArgument(); + CimInvokeCimMethod cimInvokeMethod = this.GetOperationAgent(); + cimInvokeMethod.InvokeCimMethod(this); + cimInvokeMethod.ProcessActions(this.CmdletOperation); + }//End ProcessRecord() + + /// + /// EndProcessing method. + /// + protected override void EndProcessing() + { + CimInvokeCimMethod cimInvokeMethod = this.GetOperationAgent(); + if (cimInvokeMethod != null) + { + cimInvokeMethod.ProcessRemainActions(this.CmdletOperation); + } + }//End EndProcessing() + + #endregion + + #region helper methods + + /// + /// + /// Get object, which is + /// used to delegate all Inovke-CimMethod operations. + /// + /// + CimInvokeCimMethod GetOperationAgent() + { + return this.AsyncOperation as CimInvokeCimMethod; + } + + /// + /// + /// Create object, which is + /// used to delegate all Invoke-CimMethod operations. + /// + /// + /// + CimInvokeCimMethod CreateOperationAgent() + { + CimInvokeCimMethod cimInvokeMethod = new CimInvokeCimMethod(); + this.AsyncOperation = cimInvokeMethod; + return cimInvokeMethod; + } + + /// + /// check argument value + /// + private void CheckArgument() + { + switch (this.ParameterSetName) + { + case CimBaseCommand.ClassNameComputerSet: + case CimBaseCommand.ClassNameSessionSet: + // validate the classname + this.className = ValidationHelper.ValidateArgumentIsValidName(nameClassName, this.className); + break; + default: + break; + } + } + #endregion + + #region private members + + #region const string of parameter names + internal const string nameClassName = "ClassName"; + internal const string nameCimClass = "CimClass"; + internal const string nameQuery = "Query"; + internal const string nameResourceUri = "ResourceUri"; + internal const string nameQueryDialect = "QueryDialect"; + internal const string nameCimInstance = "InputObject"; + internal const string nameComputerName = "ComputerName"; + internal const string nameCimSession = "CimSession"; + internal const string nameArguments = "Arguments"; + internal const string nameMethodName = "MethodName"; + internal const string nameNamespace = "Namespace"; + #endregion + + /// + /// static parameter definition entries + /// + static Dictionary> parameters = new Dictionary> + { + { + nameClassName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, true), + } + }, + { + nameCimClass, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.CimClassComputerSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimClassSessionSet, true), + } + }, + { + nameQuery, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, true), + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, true), + } + }, + { + nameQueryDialect, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, false), + } + }, + { + nameCimInstance, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceComputerSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceSessionSet, true), + } + }, + { + nameComputerName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.CimClassComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriComputerSet, false), + } + }, + { + nameCimSession, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimClassSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriSessionSet, true), + } + }, + { + nameMethodName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, true), + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceComputerSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimClassComputerSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimClassSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriComputerSet, true), + } + }, + { + nameNamespace, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriComputerSet, false), + } + }, + { + nameResourceUri, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriComputerSet, true), + } + }, + }; + + /// + /// static parameter set entries + /// + static Dictionary parameterSets = new Dictionary + { + { CimBaseCommand.ClassNameComputerSet, new ParameterSetEntry(2, true) }, + { CimBaseCommand.ResourceUriSessionSet, new ParameterSetEntry(3) }, + { CimBaseCommand.ResourceUriComputerSet, new ParameterSetEntry(2) }, + { CimBaseCommand.ClassNameSessionSet, new ParameterSetEntry(3) }, + { CimBaseCommand.QueryComputerSet, new ParameterSetEntry(2) }, + { CimBaseCommand.QuerySessionSet, new ParameterSetEntry(3) }, + { CimBaseCommand.CimInstanceComputerSet, new ParameterSetEntry(2) }, + { CimBaseCommand.CimInstanceSessionSet, new ParameterSetEntry(3) }, + { CimBaseCommand.CimClassComputerSet, new ParameterSetEntry(2) }, + { CimBaseCommand.CimClassSessionSet, new ParameterSetEntry(3) }, + }; + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimInstanceCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimInstanceCommand.cs new file mode 100644 index 000000000..2c843deb4 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimInstanceCommand.cs @@ -0,0 +1,497 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Management.Automation; +#endregion + + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// + /// This Cmdlet creates an instance of a CIM class based on the class + /// definition, which is an instance factory + /// + /// + /// If -ClientOnly is not specified, New-CimInstance will create a new instance + /// on the server, otherwise just create client in-memory instance + /// + /// + [Cmdlet(VerbsCommon.New, "CimInstance", DefaultParameterSetName = CimBaseCommand.ClassNameComputerSet, SupportsShouldProcess = true, HelpUri = "http://go.microsoft.com/fwlink/?LinkId=227963")] + [OutputType(typeof(CimInstance))] + public class NewCimInstanceCommand : CimBaseCommand + { + #region constructor + + /// + /// constructor + /// + public NewCimInstanceCommand() + : base(parameters, parameterSets) + { + DebugHelper.WriteLogEx(); + } + + #endregion + + #region parameters + + /// + /// The following is the definition of the input parameter "ClassName". + /// Name of the Class to use to create Instance. + /// + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + public String ClassName + { + get { return className; } + set + { + className = value; + base.SetParameter(value, nameClassName); + } + } + private String className; + + /// + /// + /// The following is the definition of the input parameter "ResourceUri". + /// Define the Resource Uri for which the instances are retrieved. + /// + /// + [Parameter(Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] + [Parameter(Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] + public Uri ResourceUri + { + get { return resourceUri; } + set + { + this.resourceUri = value; + base.SetParameter(value, nameResourceUri); + } + } + private Uri resourceUri; + + /// + /// + /// The following is the definition of the input parameter "Key". + /// Enables the user to specify list of key property name. + /// + /// + /// Example: -Key {"K1", "K2"} + /// + /// + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public String[] Key + { + get { return key; } + set + { + key = value; + base.SetParameter(value, nameKey); + } + } + private String[] key; + + /// + /// The following is the definition of the input parameter "CimClass". + /// The CimClass is used to create Instance. + /// + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipeline = true, + ParameterSetName = CimClassSessionSet)] + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipeline = true, + ParameterSetName = CimClassComputerSet)] + public CimClass CimClass + { + get { return cimClass; } + set + { + cimClass = value; + base.SetParameter(value, nameCimClass); + } + } + private CimClass cimClass; + + /// + /// + /// The following is the definition of the input parameter "Property". + /// Enables the user to specify instances with specific property values. + /// + /// + /// Example: -Property @{P1="Value1";P2="Value2"} + /// + /// + [Parameter( + Position = 1, + ValueFromPipelineByPropertyName = true)] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + [Alias("Arguments")] + public IDictionary Property + { + get { return property; } + set { property = value; } + } + private IDictionary property; + + /// + /// The following is the definition of the input parameter "Namespace". + /// Namespace used to look for the classes under to store the instances. + /// Default namespace is 'root\cimv2' + /// + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] + public String Namespace + { + get { return nameSpace; } + set + { + nameSpace = value; + base.SetParameter(value, nameNamespace); + } + } + private String nameSpace; + + /// + /// The following is the definition of the input parameter "OperationTimeoutSec". + /// Operation Timeout of the cmdlet in seconds. Overrides the value in the Cim + /// Session. + /// + [Alias(AliasOT)] + [Parameter] + public UInt32 OperationTimeoutSec + { + get { return operationTimeout; } + set { operationTimeout = value; } + } + private UInt32 operationTimeout; + + /// + /// + /// The following is the definition of the input parameter "CimSession". + /// Identifies the CimSession which is to be used to create the instances. + /// + /// + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.ResourceUriSessionSet)] + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = CimClassSessionSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public CimSession[] CimSession + { + get { return cimSession; } + set + { + cimSession = value; + base.SetParameter(value, nameCimSession); + } + } + private CimSession[] cimSession; + + /// + /// The following is the definition of the input parameter "ComputerName". + /// Provides the name of the computer from which to create the instances. + /// + /// + /// If no ComputerName is specified the default value is "localhost" + /// + /// + [Alias(AliasCN, AliasServerName)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.ResourceUriComputerSet)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimClassComputerSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public String[] ComputerName + { + get { return computerName; } + set + { + computerName = value; + base.SetParameter(value, nameComputerName); + } + } + private String[] computerName; + + /// + /// + /// The following is the definition of the input parameter "ClientOnly". + /// Indicates to create a client only ciminstance object, NOT on the server. + /// + /// + [Alias("Local")] + [Parameter( + ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Parameter( + ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + [Parameter( + ParameterSetName = CimBaseCommand.CimClassComputerSet)] + [Parameter( + ParameterSetName = CimBaseCommand.CimClassSessionSet)] + public SwitchParameter ClientOnly + { + get { return clientOnly; } + set { + clientOnly = value; + base.SetParameter(value, nameClientOnly); + } + } + private SwitchParameter clientOnly; + + #endregion + + #region cmdlet methods + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + this.CmdletOperation = new CmdletOperationBase(this); + this.AtBeginProcess = false; + }//End BeginProcessing() + + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + base.CheckParameterSet(); + this.CheckArgument(); + if (this.ClientOnly) + { + string conflictParameterName = null; + if (null != this.ComputerName) + { + conflictParameterName = @"ComputerName"; + } + else if (null != this.CimSession) + { + conflictParameterName = @"CimSession"; + } + if (null != conflictParameterName) + { + ThrowConflictParameterWasSet(@"New-CimInstance", conflictParameterName, @"ClientOnly"); + return; + } + } + + CimNewCimInstance cimNewCimInstance = this.GetOperationAgent(); + if (cimNewCimInstance == null) + { + cimNewCimInstance = CreateOperationAgent(); + } + cimNewCimInstance.NewCimInstance(this); + cimNewCimInstance.ProcessActions(this.CmdletOperation); + }//End ProcessRecord() + + /// + /// EndProcessing method. + /// + protected override void EndProcessing() + { + CimNewCimInstance cimNewCimInstance = this.GetOperationAgent(); + if (cimNewCimInstance != null) + { + cimNewCimInstance.ProcessRemainActions(this.CmdletOperation); + } + }//End EndProcessing() + + #endregion + + #region helper methods + + /// + /// + /// Get object, which is + /// used to delegate all New-CimInstance operations. + /// + /// + CimNewCimInstance GetOperationAgent() + { + return (this.AsyncOperation as CimNewCimInstance); + } + + /// + /// + /// Create object, which is + /// used to delegate all New-CimInstance operations. + /// + /// + /// + CimNewCimInstance CreateOperationAgent() + { + CimNewCimInstance cimNewCimInstance = new CimNewCimInstance(); + this.AsyncOperation = cimNewCimInstance; + return cimNewCimInstance; + } + + /// + /// check argument value + /// + private void CheckArgument() + { + switch (this.ParameterSetName) + { + case CimBaseCommand.ClassNameComputerSet: + case CimBaseCommand.ClassNameSessionSet: + // validate the classname + this.className = ValidationHelper.ValidateArgumentIsValidName(nameClassName, this.className); + break; + default: + break; + } + } + #endregion + + #region private members + + #region const string of parameter names + internal const string nameClassName = "ClassName"; + internal const string nameResourceUri = "ResourceUri"; + internal const string nameKey = "Key"; + internal const string nameCimClass = "CimClass"; + internal const string nameProperty = "Property"; + internal const string nameNamespace = "Namespace"; + internal const string nameCimSession = "CimSession"; + internal const string nameComputerName = "ComputerName"; + internal const string nameClientOnly = "ClientOnly"; + #endregion + + /// + /// static parameter definition entries + /// + static Dictionary> parameters = new Dictionary> + { + { + nameClassName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, true), + } + }, + { + nameResourceUri, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriComputerSet, true), + } + }, + { + nameKey, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriSessionSet, false), + } + }, + { + nameCimClass, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.CimClassSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimClassComputerSet, true), + } + }, + { + nameNamespace, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriSessionSet, false), + } + }, + { + nameCimSession, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimClassSessionSet, true), + } + }, + { + nameComputerName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ResourceUriComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.CimClassComputerSet, false), + } + }, + { + nameClientOnly, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimClassSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimClassComputerSet, true), + } + }, + }; + + /// + /// static parameter set entries + /// + static Dictionary parameterSets = new Dictionary + { + { CimBaseCommand.ClassNameSessionSet, new ParameterSetEntry(2) }, + { CimBaseCommand.ClassNameComputerSet, new ParameterSetEntry(1, true) }, + { CimBaseCommand.CimClassSessionSet, new ParameterSetEntry(2) }, + { CimBaseCommand.CimClassComputerSet, new ParameterSetEntry(1) }, + { CimBaseCommand.ResourceUriSessionSet, new ParameterSetEntry(2) }, + { CimBaseCommand.ResourceUriComputerSet, new ParameterSetEntry(1) }, + }; + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionCommand.cs new file mode 100644 index 000000000..8c1109ab7 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionCommand.cs @@ -0,0 +1,352 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives +using System; +using System.Management.Automation; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Management.Infrastructure.Options; + +#endregion + + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// This Cmdlet enables the IT Pro to create a CIM Session. CIM Session object + /// is a client-side representation of the connection between the client and the + /// server. + /// The CimSession object returned by the Cmdlet is used by all other CIM + /// cmdlets. + /// + [Cmdlet(VerbsCommon.New, "CimSession", DefaultParameterSetName = CredentialParameterSet, HelpUri = "http://go.microsoft.com/fwlink/?LinkId=227967")] + [OutputType(typeof(CimSession))] + public sealed class NewCimSessionCommand : CimBaseCommand + { + #region cmdlet parameters + + /// + /// The following is the definition of the input parameter "Authentication". + /// The following is the validation set for allowed authentication types. + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CredentialParameterSet)] + public PasswordAuthenticationMechanism Authentication + { + get { return authentication;} + set + { + authentication = value; + authenticationSet = true; + } + } + private PasswordAuthenticationMechanism authentication; + private bool authenticationSet = false; + + /// + /// The following is the definition of the input parameter "Credential". + /// Specifies a user account that has permission to perform this action. + /// The default is the current user. + /// + [Parameter(Position = 1, ParameterSetName = CredentialParameterSet)] + [Credential()] + public PSCredential Credential + { + get { return credential; } + set { credential = value; } + } + private PSCredential credential; + + /// + /// The following is the definition of the input parameter "CertificateThumbprint". + /// This is specificly for wsman protocol. + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CertificatePrameterSet)] + public String CertificateThumbprint + { + get { return certificatethumbprint; } + set { certificatethumbprint = value; } + } + private String certificatethumbprint; + + /// + /// The following is the definition of the input parameter "ComputerName". + /// Specifies the computer on which the commands associated with this session + /// will run. The default value is LocalHost. + /// + [Alias(AliasCN, AliasServerName)] + [Parameter( + Position = 0, + ValueFromPipelineByPropertyName = true)] + [ValidateNotNullOrEmpty] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public String[] ComputerName + { + get { return computername;} + set { computername = value; } + } + private String[] computername; + + /// + /// + /// The following is the definition of the input parameter "Name". + /// Specifies a friendly name for the CIM Session connection. + /// + /// + /// If a name is not passed, then the session is given the name CimSession, + /// where is the next available session number. Example, CimSession1, + /// CimSession2, etc... + /// + /// + [Parameter(ValueFromPipelineByPropertyName = true)] + public String Name + { + get { return name;} + set { name = value; } + } + private String name; + + /// + /// + /// The following is the definition of the input parameter "OperationTimeoutSec". + /// Specifies the operation timeout for all operations in session. Individual + /// operations can override this timeout. + /// + /// + /// The unit is Second. + /// + /// + [Alias(AliasOT)] + [Parameter(ValueFromPipelineByPropertyName = true)] + public UInt32 OperationTimeoutSec + { + get { return operationTimeout; } + set + { + operationTimeout = value; + operationTimeoutSet = true; + } + } + private UInt32 operationTimeout; + internal bool operationTimeoutSet = false; + + /// + /// + /// The following is the definition of the input parameter "SkipTestConnection". + /// Specifies where test connection should be skipped + /// + /// + [Parameter(ValueFromPipelineByPropertyName = true)] + public SwitchParameter SkipTestConnection + { + get { return skipTestConnection; } + set + { + skipTestConnection = value; + } + } + private SwitchParameter skipTestConnection; + + /// + /// The following is the definition of the input parameter "Port". + /// Specifies the port number to use, if different than the default port number. + /// This is specificly for wsman protocol. + /// + [Parameter(ValueFromPipelineByPropertyName = true)] + public UInt32 Port + { + get { return port; } + set + { + port = value; + portSet = true; + } + } + private UInt32 port; + private bool portSet = false; + + /// + /// + /// The following is the definition of the input parameter "SessionOption". + /// Specifies the SessionOption object that is passed to the Cmdlet as argument. + /// + /// + /// If the argument is not given, a default SessionOption will be created for + /// the session in .NET API layer. + /// + /// If a object is passed, then + /// connection is made using DCOM. If a + /// object is passed, then connection is made using WsMan. + /// + [Parameter(ValueFromPipelineByPropertyName = true)] + public Microsoft.Management.Infrastructure.Options.CimSessionOptions SessionOption + { + get { return sessionOption; } + set { sessionOption = value; } + } + private Microsoft.Management.Infrastructure.Options.CimSessionOptions sessionOption; + + #endregion + + #region cmdlet processing methods + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + cimNewSession = new CimNewSession(); + this.CmdletOperation = new CmdletOperationTestCimSession(this, this.cimNewSession); + this.AtBeginProcess = false; + }//End BeginProcessing() + + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + CimSessionOptions outputOptions; + CimCredential outputCredential; + BuildSessionOptions(out outputOptions, out outputCredential); + cimNewSession.NewCimSession(this, outputOptions, outputCredential); + cimNewSession.ProcessActions(this.CmdletOperation); + }//End ProcessRecord() + + /// + /// EndProcessing method. + /// + protected override void EndProcessing() + { + cimNewSession.ProcessRemainActions(this.CmdletOperation); + }//End EndProcessing() + #endregion + + #region helper methods + + /// + /// Build a CimSessionOptions, used to create CimSession + /// + /// Null means no prefer CimSessionOptions + internal void BuildSessionOptions(out CimSessionOptions outputOptions, out CimCredential outputCredential) + { + DebugHelper.WriteLogEx(); + + CimSessionOptions options = null; + if (this.SessionOption != null) + { + // clone the sessionOption object + if (this.SessionOption is WSManSessionOptions) + { + options = new WSManSessionOptions(this.sessionOption as WSManSessionOptions); + } + else + { + options = new DComSessionOptions(this.sessionOption as DComSessionOptions); + } + } + outputOptions = null; + outputCredential = null; + if (options != null) + { + DComSessionOptions dcomOptions = (options as DComSessionOptions); + if (dcomOptions != null) + { + bool conflict = false; + string parameterName = string.Empty; + if (this.CertificateThumbprint != null) + { + conflict = true; + parameterName = @"CertificateThumbprint"; + } + if (portSet) + { + conflict = true; + parameterName = @"Port"; + } + if (conflict) + { + ThrowConflictParameterWasSet(@"New-CimSession", parameterName, @"DComSessionOptions"); + return; + } + } + } + if (portSet || (this.CertificateThumbprint != null)) + { + WSManSessionOptions wsmanOptions = (options == null) ? new WSManSessionOptions() : options as WSManSessionOptions; + if (portSet) + { + wsmanOptions.DestinationPort = this.Port; + portSet = false; + } + if (this.CertificateThumbprint != null) + { + CimCredential credentials = new CimCredential(CertificateAuthenticationMechanism.Default, this.CertificateThumbprint); + wsmanOptions.AddDestinationCredentials(credentials); + } + options = wsmanOptions; + } + if (this.operationTimeoutSet) + { + if (options != null) + { + options.Timeout = TimeSpan.FromSeconds((double)this.OperationTimeoutSec); + } + } + if (this.authenticationSet || (this.credential != null)) + { + PasswordAuthenticationMechanism authentication = this.authenticationSet ? this.Authentication : PasswordAuthenticationMechanism.Default; + if (this.authenticationSet) + { + this.authenticationSet = false; + } + CimCredential credentials = CreateCimCredentials(this.Credential, authentication, @"New-CimSession", @"Authentication"); + if (credentials == null) + { + return; + } + + DebugHelper.WriteLog("Credentials: {0}", 1, credentials); + outputCredential = credentials; + if (options != null) + { + DebugHelper.WriteLog("Add credentials to option: {0}", 1, options); + options.AddDestinationCredentials(credentials); + } + } + DebugHelper.WriteLogEx("Set outputOptions: {0}", 1, outputOptions); + outputOptions = options; + } + + #endregion + + #region private members + + /// + /// + /// CimNewSession object + /// + /// + private CimNewSession cimNewSession; + + #endregion + + #region IDisposable + /// + /// Clean up resources + /// + protected override void DisposeInternal() + { + base.DisposeInternal(); + + // Dispose managed resources. + if (this.cimNewSession != null) + { + this.cimNewSession.Dispose(); + } + } + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionOptionCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionOptionCommand.cs new file mode 100644 index 000000000..ae265cb13 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/NewCimSessionOptionCommand.cs @@ -0,0 +1,765 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Management.Automation; +using Microsoft.Management.Infrastructure.Options; +#endregion + + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// Define Protocol type. + /// + public enum ProtocolType + { + Default, + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")] + Dcom, + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")] + Wsman + }; + + /// + /// The Cmdlet allows the IT Pro to create a CimSessionOptions object that she/he + /// can subsequently use to crate one or more CimSession connections. The + /// options object holds the CIM Session information that is less commonly set + /// and used by the IT Pro, and most commonly defaulted. + /// + /// The Cmdlet has two parameter sets, one for WMMan options and one for DCOM + /// options. Depending on the arguments the Cmdlet will return an instance of + /// DComSessionOptions or WSManSessionOptions, which derive from + /// CimSessionOptions. + /// + [Cmdlet(VerbsCommon.New, "CimSessionOption", DefaultParameterSetName = ProtocolNameParameterSet, HelpUri = "http://go.microsoft.com/fwlink/?LinkId=227969")] + [OutputType(typeof(CimSessionOptions))] + public sealed class NewCimSessionOptionCommand : CimBaseCommand + { + #region constructor + + /// + /// constructor + /// + public NewCimSessionOptionCommand() + : base(parameters, parameterSets) + { + DebugHelper.WriteLogEx(); + } + + #endregion + + #region cmdlet parameters + + /// + /// The following is the definition of the input parameter "NoEncruption". + /// Switch indicating if WSMan can use no encryption in the given CimSession (there are also global client and server WSMan settings - AllowUnencrypted). + /// + [Parameter(ParameterSetName = WSManParameterSet)] + public SwitchParameter NoEncryption + { + get { return noEncryption; } + set + { + noEncryption = value; + noEncryptionSet = true; + base.SetParameter(value, nameNoEncryption); + } + } + private SwitchParameter noEncryption; + private bool noEncryptionSet = false; + + /// + /// The following is the definition of the input parameter "CertificateCACheck". + /// Switch indicating if Certificate Authority should be validated + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = WSManParameterSet)] + public SwitchParameter SkipCACheck + { + get { return skipCACheck; } + set + { + skipCACheck = value; + skipCACheckSet = true; + base.SetParameter(value, nameSkipCACheck); + } + } + private SwitchParameter skipCACheck; + private bool skipCACheckSet = false; + + /// + /// The following is the definition of the input parameter "CertificateCNCheck". + /// Switch indicating if Certificate Name should be validated + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = WSManParameterSet)] + public SwitchParameter SkipCNCheck + { + get { return skipCNCheck; } + set + { + skipCNCheck = value; + skipCNCheckSet = true; + base.SetParameter(value, nameSkipCNCheck); + } + } + private SwitchParameter skipCNCheck; + private bool skipCNCheckSet = false; + + /// + /// The following is the definition of the input parameter "CertRevocationCheck". + /// Switch indicating if certificate should be revoked. + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = WSManParameterSet)] + public SwitchParameter SkipRevocationCheck + { + get { return skipRevocationCheck; } + set + { + skipRevocationCheck = value; + skipRevocationCheckSet = true; + base.SetParameter(value, nameSkipRevocationCheck); + } + } + private SwitchParameter skipRevocationCheck; + private bool skipRevocationCheckSet = false; + + /// + /// The following is the definition of the input parameter "EncodePortInServicePrincipalName". + /// Switch indicating if to encode Port In Service Principal Name + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = WSManParameterSet)] + public SwitchParameter EncodePortInServicePrincipalName + { + get { return encodeportinserviceprincipalname; } + set + { + encodeportinserviceprincipalname = value; + encodeportinserviceprincipalnameSet = true; + base.SetParameter(value, nameEncodePortInServicePrincipalName); + } + } + private SwitchParameter encodeportinserviceprincipalname; + private bool encodeportinserviceprincipalnameSet = false; + + /// + /// The following is the definition of the input parameter "Encoding". + /// Defined the message encoding. + /// The allowed encodings are { Defauolt | Utf8 | Utf16 }. The default value + /// should be Utf8. + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = WSManParameterSet)] + public PacketEncoding Encoding + { + get { return encoding; } + set + { + encoding = value; + encodingSet = true; + base.SetParameter(value, nameEncoding); + } + } + private PacketEncoding encoding; + private bool encodingSet = false; + + /// + /// The following is the definition of the input parameter "HttpPrefix". + /// This is the HTTP URL on the server on which the WSMan service is listening. + /// In most cases it is /wsman, which is the default. + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = WSManParameterSet)] + public Uri HttpPrefix + { + get { return httpprefix; } + set + { + httpprefix = value; + base.SetParameter(value, nameHttpPrefix); + } + } + private Uri httpprefix; + + /// + /// The following is the definition of the input parameter "MaxEnvelopeSizeKB". + /// Sets the limit to the maximum size of the WSMan message envelope. + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = WSManParameterSet)] + public UInt32 MaxEnvelopeSizeKB + { + get { return maxenvelopesizekb; } + set + { + maxenvelopesizekb = value; + maxenvelopesizekbSet = true; + base.SetParameter(value, nameMaxEnvelopeSizeKB); + } + } + private UInt32 maxenvelopesizekb; + private bool maxenvelopesizekbSet = false; + + /// + /// The following is the definition of the input parameter "ProxyAuthentication". + /// Which proxy authentication types to use: Allowed set is: + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = WSManParameterSet)] + public PasswordAuthenticationMechanism ProxyAuthentication + { + get { return proxyAuthentication; } + set + { + proxyAuthentication = value; + proxyauthenticationSet = true; + base.SetParameter(value, nameProxyAuthentication); + } + } + private PasswordAuthenticationMechanism proxyAuthentication; + private bool proxyauthenticationSet = false; + + /// + /// The following is the definition of the input parameter "ProxyCertificateThumbprint". + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = WSManParameterSet)] + public String ProxyCertificateThumbprint + { + get { return proxycertificatethumbprint; } + set + { + proxycertificatethumbprint = value; + base.SetParameter(value, nameProxyCertificateThumbprint); + } + } + private String proxycertificatethumbprint; + + /// + /// The following is the definition of the input parameter "ProxyCredential". + /// Ps Credential used by the proxy server when required by the server. + /// + [Parameter(ParameterSetName = WSManParameterSet)] + [Credential()] + public PSCredential ProxyCredential + { + get { return proxycredential; } + set + { + proxycredential = value; + base.SetParameter(value, nameProxyCredential); + } + } + private PSCredential proxycredential; + + /// + /// The following is the definition of the input parameter "ProxyType". + /// Which proxy type to use: Valid set is: + /// { InternetExplorer | WinHttp | Auto | None } + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = WSManParameterSet)] + public ProxyType ProxyType + { + get { return proxytype; } + set + { + proxytype = value; + proxytypeSet = true; + base.SetParameter(value, nameProxyType); + } + } + private ProxyType proxytype; + private bool proxytypeSet = false; + + /// + /// The following is the definition of the input parameter "UseSSL". + /// Switch indicating if Secure Sockets Layer connection should be used. + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = WSManParameterSet)] + public SwitchParameter UseSsl + { + get { return usessl; } + set + { + usessl = value; + usesslSet = true; + base.SetParameter(value, nameUseSsl); + } + } + private SwitchParameter usessl; + private bool usesslSet = false; + + /// + /// The following is the definition of the input parameter "Impersonation". + /// Used to select if, and if so what kind of, impersonation should be used. + /// Applies only to the DCOM channel. + /// + [Parameter(ParameterSetName = DcomParameterSet)] + public ImpersonationType Impersonation + { + get { return impersonation; } + set + { + impersonation = value; + impersonationSet = true; + base.SetParameter(value, nameImpersonation); + } + } + private ImpersonationType impersonation; + private bool impersonationSet = false; + + /// + /// The following is the definition of the input parameter "PacketIntegrity". + /// Switch indicating if the package integrity in DCOM connections should be + /// checked/enforced. + /// + [Parameter(ParameterSetName = DcomParameterSet)] + public SwitchParameter PacketIntegrity + { + get { return packetintegrity; } + set + { + packetintegrity = value; + packetintegritySet = true; + base.SetParameter(value, namePacketIntegrity); + } + } + private SwitchParameter packetintegrity; + private bool packetintegritySet = false; + + /// + /// The following is the definition of the input parameter "PacketPrivacy". + /// Switch indicating if packet privacy of the packets in DCOM communications + /// should be checked/enforced. + /// + [Parameter(ParameterSetName = DcomParameterSet)] + public SwitchParameter PacketPrivacy + { + get { return packetprivacy; } + set + { + packetprivacy = value; + packetprivacySet = true; + base.SetParameter(value, namePacketPrivacy); + } + } + private SwitchParameter packetprivacy; + private bool packetprivacySet = false; + + /// + /// The following is the definition of the input parameter "Protocol". + /// Switch indicating if to encode Port In Service Principal Name + /// + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipelineByPropertyName = true, + ParameterSetName = ProtocolNameParameterSet)] + public ProtocolType Protocol + { + get { return protocol; } + set + { + protocol = value; + base.SetParameter(value, nameProtocol); + } + } + private ProtocolType protocol; + + /// + /// The following is the definition of the input parameter "UICulture". + /// Specifies the UI Culture to use. i.e. en-us, ar-sa + /// + [Parameter(ValueFromPipelineByPropertyName = true)] + public CultureInfo UICulture + { + get { return uiculture; } + set { uiculture = value; } + } + private CultureInfo uiculture; + + /// + /// The following is the definition of the input parameter "Culture". + /// Specifies the culture to use. i.e. en-us, ar-sa + /// + [Parameter(ValueFromPipelineByPropertyName = true)] + public CultureInfo Culture + { + get { return culture; } + set { culture = value; } + } + private CultureInfo culture; + + #endregion + + #region cmdlet processing methods + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + this.CmdletOperation = new CmdletOperationBase(this); + this.AtBeginProcess = false; + }//End BeginProcessing() + + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + base.CheckParameterSet(); + CimSessionOptions options; + switch (this.ParameterSetName) + { + case WSManParameterSet: + { + options = CreateWSMANSessionOptions(); + } + break; + case DcomParameterSet: + { + options = CreateDComSessionOptions(); + } + break; + case ProtocolNameParameterSet: + switch (Protocol) + { + case ProtocolType.Dcom: + options = CreateDComSessionOptions(); + break; + case ProtocolType.Wsman: + default: + options = CreateWSMANSessionOptions(); + break; + } + break; + default: + return; + } + if (options != null) + { + if (this.Culture != null) + { + options.Culture = this.Culture; + } + if (this.UICulture != null) + { + options.UICulture = this.UICulture; + } + this.WriteObject(options); + } + }//End ProcessRecord() + + /// + /// EndProcessing method. + /// + protected override void EndProcessing() + { + }//End EndProcessing() + + #endregion + + #region helper functions + /// + /// Create DComSessionOptions + /// + /// + internal DComSessionOptions CreateDComSessionOptions() + { + DComSessionOptions dcomoptions = new DComSessionOptions(); + if (this.impersonationSet) + { + dcomoptions.Impersonation = this.Impersonation; + this.impersonationSet = false; + } + else + { + dcomoptions.Impersonation = ImpersonationType.Impersonate; + } + if (this.packetintegritySet) + { + dcomoptions.PacketIntegrity = this.packetintegrity; + this.packetintegritySet = false; + } + else + { + dcomoptions.PacketIntegrity = true; + } + if (this.packetprivacySet) + { + dcomoptions.PacketPrivacy = this.PacketPrivacy; + this.packetprivacySet = false; + } + else + { + dcomoptions.PacketPrivacy = true; + } + return dcomoptions; + } + + /// + /// Create WSMANSessionOptions + /// + /// + internal WSManSessionOptions CreateWSMANSessionOptions() + { + WSManSessionOptions wsmanoptions = new WSManSessionOptions(); + if (this.noEncryptionSet) + { + wsmanoptions.NoEncryption = true; + this.noEncryptionSet = false; + } + else + { + wsmanoptions.NoEncryption = false; + } + if (this.skipCACheckSet) + { + wsmanoptions.CertCACheck = false; + this.skipCACheckSet = false; + } + else + { + wsmanoptions.CertCACheck = true; + } + if (this.skipCNCheckSet) + { + wsmanoptions.CertCNCheck = false; + this.skipCNCheckSet = false; + } + else + { + wsmanoptions.CertCNCheck = true; + } + if (this.skipRevocationCheckSet) + { + wsmanoptions.CertRevocationCheck = false; + this.skipRevocationCheckSet = false; + } + else + { + wsmanoptions.CertRevocationCheck = true; + } + if (this.encodeportinserviceprincipalnameSet) + { + wsmanoptions.EncodePortInServicePrincipalName = this.EncodePortInServicePrincipalName; + this.encodeportinserviceprincipalnameSet = false; + } + else + { + wsmanoptions.EncodePortInServicePrincipalName = false; + } + if (this.encodingSet) + { + wsmanoptions.PacketEncoding = this.Encoding; + } + else + { + wsmanoptions.PacketEncoding = PacketEncoding.Utf8; + } + if (this.HttpPrefix != null) + { + wsmanoptions.HttpUrlPrefix = this.HttpPrefix; + } + if (this.maxenvelopesizekbSet) + { + wsmanoptions.MaxEnvelopeSize = this.MaxEnvelopeSizeKB; + } + else + { + wsmanoptions.MaxEnvelopeSize = 0; + } + if (!String.IsNullOrWhiteSpace(this.ProxyCertificateThumbprint)) + { + CimCredential credentials = new CimCredential(CertificateAuthenticationMechanism.Default, this.ProxyCertificateThumbprint); + wsmanoptions.AddProxyCredentials(credentials); + } + if (this.proxyauthenticationSet) + { + this.proxyauthenticationSet = false; + DebugHelper.WriteLogEx("create credential", 1); + CimCredential credentials = CreateCimCredentials(this.ProxyCredential, this.ProxyAuthentication, @"New-CimSessionOption", @"ProxyAuthentication"); + if (credentials != null) + { + try + { + DebugHelper.WriteLogEx("Add proxy credential", 1); + wsmanoptions.AddProxyCredentials(credentials); + } + catch (Exception ex) + { + DebugHelper.WriteLogEx(ex.ToString(), 1); + throw ex; + } + } + } + if (this.proxytypeSet) + { + wsmanoptions.ProxyType = this.ProxyType; + this.proxytypeSet = false; + } + else + { + wsmanoptions.ProxyType = Options.ProxyType.WinHttp; + } + if (this.usesslSet) + { + wsmanoptions.UseSsl = this.UseSsl; + this.usesslSet = false; + } + else + { + wsmanoptions.UseSsl = false; + } + wsmanoptions.DestinationPort = 0; + return wsmanoptions; + } + #endregion + + #region private members + + #region const string of parameter names + internal const string nameNoEncryption = "NoEncryption"; + internal const string nameSkipCACheck = "SkipCACheck"; + internal const string nameSkipCNCheck = "SkipCNCheck"; + internal const string nameSkipRevocationCheck = "SkipRevocationCheck"; + internal const string nameEncodePortInServicePrincipalName = "EncodePortInServicePrincipalName"; + internal const string nameEncoding = "Encoding"; + internal const string nameHttpPrefix = "HttpPrefix"; + internal const string nameMaxEnvelopeSizeKB = "MaxEnvelopeSizeKB"; + internal const string nameProxyAuthentication = "ProxyAuthentication"; + internal const string nameProxyCertificateThumbprint = "ProxyCertificateThumbprint"; + internal const string nameProxyCredential = "ProxyCredential"; + internal const string nameProxyType = "ProxyType"; + internal const string nameUseSsl = "UseSsl"; + internal const string nameImpersonation = "Impersonation"; + internal const string namePacketIntegrity = "PacketIntegrity"; + internal const string namePacketPrivacy = "PacketPrivacy"; + internal const string nameProtocol = "Protocol"; + #endregion + + /// + /// static parameter definition entries + /// + static Dictionary> parameters = new Dictionary> + { + { + nameNoEncryption, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.WSManParameterSet, false), + } + }, + + { + nameSkipCACheck, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.WSManParameterSet, false), + } + }, + + { + nameSkipCNCheck, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.WSManParameterSet, false), + } + }, + { + nameSkipRevocationCheck, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.WSManParameterSet, false), + } + }, + + { + nameEncodePortInServicePrincipalName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.WSManParameterSet, false), + } + }, + { + nameEncoding, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.WSManParameterSet, false), + } + }, + + { + nameHttpPrefix, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.WSManParameterSet, false), + } + }, + { + nameMaxEnvelopeSizeKB, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.WSManParameterSet, false), + } + }, + + { + nameProxyAuthentication, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.WSManParameterSet, false), + } + }, + { + nameProxyCertificateThumbprint, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.WSManParameterSet, false), + } + }, + + { + nameProxyCredential, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.WSManParameterSet, false), + } + }, + { + nameProxyType, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.WSManParameterSet, false), + } + }, + + { + nameUseSsl, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.WSManParameterSet, false), + } + }, + { + nameImpersonation, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.DcomParameterSet, false), + } + }, + + { + namePacketIntegrity, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.DcomParameterSet, false), + } + }, + { + namePacketPrivacy, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.DcomParameterSet, false), + } + }, + + { + nameProtocol, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ProtocolNameParameterSet, true), + } + }, + }; + + /// + /// static parameter set entries + /// + static Dictionary parameterSets = new Dictionary + { + { CimBaseCommand.ProtocolNameParameterSet, new ParameterSetEntry(1, true) }, + { CimBaseCommand.DcomParameterSet, new ParameterSetEntry(0) }, + { CimBaseCommand.WSManParameterSet, new ParameterSetEntry(0) }, + }; + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/RegisterCimIndicationCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/RegisterCimIndicationCommand.cs new file mode 100644 index 000000000..0dd5def31 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/RegisterCimIndicationCommand.cs @@ -0,0 +1,351 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Management.Automation; +using Microsoft.PowerShell.Commands; +#endregion + + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// Enables the user to subscribe to indications using Filter Expression or + /// Query Expression. + /// -SourceIdentifier is a name given to the subscription + /// The Cmdlet should return a PS EventSubscription object that can be used to + /// cancel the subscription + /// Should we have the second parameter set with a -Query? + /// + [Cmdlet(VerbsLifecycle.Register, "CimIndicationEvent", DefaultParameterSetName = CimBaseCommand.ClassNameComputerSet, HelpUri = "http://go.microsoft.com/fwlink/?LinkId=227960")] + public class RegisterCimIndicationCommand : ObjectEventRegistrationBase + { + #region parameters + + /// + /// + /// The following is the definition of the input parameter "Namespace". + /// Specifies the NameSpace under which to look for the specified class name. + /// + /// + /// Default value is root\cimv2 + /// + /// + [Parameter] + public String Namespace + { + get { return nameSpace; } + set { nameSpace = value; } + } + private String nameSpace; + + /// + /// The following is the definition of the input parameter "ClassName". + /// Specifies the Class Name to register the indication on. + /// + [Parameter( + Mandatory = true, + Position = 0, + ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + [Parameter(Mandatory = true, + Position = 0, + ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + public String ClassName + { + get { return className; } + set + { + className = value; + this.SetParameter(value, nameClassName); + } + } + private String className; + + /// + /// The following is the definition of the input parameter "Query". + /// The Query Expression to pass. + /// + [Parameter( + Mandatory = true, + Position = 0, + ParameterSetName = CimBaseCommand.QueryExpressionSessionSet)] + [Parameter( + Mandatory = true, + Position = 0, + ParameterSetName = CimBaseCommand.QueryExpressionComputerSet)] + public String Query + { + get { return query; } + set + { + query = value; + this.SetParameter(value, nameQuery); + } + } + private String query; + + /// + /// + /// The following is the definition of the input parameter "QueryDialect". + /// Specifies the dialect used by the query Engine that interprets the Query + /// string. + /// + /// + [Parameter(ParameterSetName = CimBaseCommand.QueryExpressionComputerSet)] + [Parameter(ParameterSetName = CimBaseCommand.QueryExpressionSessionSet)] + public String QueryDialect + { + get { return queryDialect; } + set + { + queryDialect = value; + this.SetParameter(value, nameQueryDialect); + } + } + private String queryDialect; + + /// + /// The following is the definition of the input parameter "OperationTimeoutSec". + /// Enables the user to specify the operation timeout in Seconds. This value + /// overwrites the value specified by the CimSession Operation timeout. + /// + [Alias(CimBaseCommand.AliasOT)] + [Parameter] + public UInt32 OperationTimeoutSec + { + get { return operationTimeout; } + set { operationTimeout = value; } + } + private UInt32 operationTimeout; + + /// + /// The following is the definition of the input parameter "Session". + /// Uses a CimSession context. + /// + [Parameter( + Mandatory = true, + ParameterSetName = CimBaseCommand.QueryExpressionSessionSet)] + [Parameter( + Mandatory = true, + ParameterSetName = CimBaseCommand.ClassNameSessionSet)] + public CimSession CimSession + { + get { return cimSession; } + set + { + cimSession = value; + this.SetParameter(value, nameCimSession); + } + } + private CimSession cimSession; + + /// + /// The following is the definition of the input parameter "ComputerName". + /// Specifies the computer on which the commands associated with this session + /// will run. The default value is LocalHost. + /// + [Alias(CimBaseCommand.AliasCN, CimBaseCommand.AliasServerName)] + [Parameter(ParameterSetName = CimBaseCommand.QueryExpressionComputerSet)] + [Parameter(ParameterSetName = CimBaseCommand.ClassNameComputerSet)] + public String ComputerName + { + get { return computername; } + set + { + computername = value; + this.SetParameter(value, nameComputerName); + } + } + private String computername; + + #endregion + + /// + /// Returns the object that generates events to be monitored + /// + protected override Object GetSourceObject() + { + CimIndicationWatcher watcher = null; + string parameterSetName = null; + try + { + parameterSetName = this.parameterBinder.GetParameterSet(); + } + finally + { + this.parameterBinder.reset(); + } + string tempQueryExpression = string.Empty; + switch (parameterSetName) + { + case CimBaseCommand.QueryExpressionSessionSet: + case CimBaseCommand.QueryExpressionComputerSet: + tempQueryExpression = this.Query; + break; + case CimBaseCommand.ClassNameSessionSet: + case CimBaseCommand.ClassNameComputerSet: + // validate the classname + this.CheckArgument(); + tempQueryExpression = String.Format(CultureInfo.CurrentCulture, "Select * from {0}", this.ClassName); + break; + } + switch (parameterSetName) + { + case CimBaseCommand.QueryExpressionSessionSet: + case CimBaseCommand.ClassNameSessionSet: + { + watcher = new CimIndicationWatcher(this.CimSession, this.Namespace, this.QueryDialect, tempQueryExpression, this.OperationTimeoutSec); + } + break; + case CimBaseCommand.QueryExpressionComputerSet: + case CimBaseCommand.ClassNameComputerSet: + { + watcher = new CimIndicationWatcher(this.ComputerName, this.Namespace, this.QueryDialect, tempQueryExpression, this.OperationTimeoutSec); + } + break; + } + if (watcher != null) + { + watcher.SetCmdlet(this); + } + return watcher; + } + + /// + /// Returns the event name to be monitored on the input object + /// + protected override String GetSourceObjectEventName() + { + return "CimIndicationArrived"; + } + + /// + /// EndProcessing method. + /// + protected override void EndProcessing() + { + DebugHelper.WriteLogEx(); + + base.EndProcessing(); + + // Register for the "Unsubscribed" event so that we can stop the + // Cimindication event watcher. + PSEventSubscriber newSubscriber = NewSubscriber; + if (newSubscriber != null) + { + DebugHelper.WriteLog("RegisterCimIndicationCommand::EndProcessing subscribe to Unsubscribed event", 4); + newSubscriber.Unsubscribed += new PSEventUnsubscribedEventHandler(newSubscriber_Unsubscribed); + } + }//End EndProcessing() + + /// + /// + /// Hanlder to handle unsubcribe event + /// + /// + /// + /// + private static void newSubscriber_Unsubscribed( + object sender, PSEventUnsubscribedEventArgs e) + { + DebugHelper.WriteLogEx(); + + CimIndicationWatcher watcher = sender as CimIndicationWatcher; + if (watcher != null) + { + watcher.Stop(); + } + } + + #region private members + /// + /// check argument value + /// + private void CheckArgument() + { + this.className = ValidationHelper.ValidateArgumentIsValidName(nameClassName, this.className); + } + + /// + /// Parameter binder used to resolve parameter set name + /// + private ParameterBinder parameterBinder = new ParameterBinder( + parameters, parameterSets); + + /// + /// Set the parameter + /// + /// + private void SetParameter(object value, string parameterName) + { + if (value == null) + { + return; + } + this.parameterBinder.SetParameter(parameterName, true); + } + + #region const string of parameter names + internal const string nameClassName = "ClassName"; + internal const string nameQuery = "Query"; + internal const string nameQueryDialect = "QueryDialect"; + internal const string nameCimSession = "CimSession"; + internal const string nameComputerName = "ComputerName"; + #endregion + + /// + /// static parameter definition entries + /// + static Dictionary> parameters = new Dictionary> + { + { + nameClassName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, true), + } + }, + { + nameQuery, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QueryExpressionSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.QueryExpressionComputerSet, true), + } + }, + { + nameQueryDialect, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QueryExpressionSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.QueryExpressionComputerSet, false), + } + }, + { + nameCimSession, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QueryExpressionSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameSessionSet, true), + } + }, + { + nameComputerName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QueryExpressionComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.ClassNameComputerSet, false), + } + }, + }; + + /// + /// static parameter set entries + /// + static Dictionary parameterSets = new Dictionary + { + { CimBaseCommand.QueryExpressionSessionSet, new ParameterSetEntry(2) }, + { CimBaseCommand.QueryExpressionComputerSet, new ParameterSetEntry(1) }, + { CimBaseCommand.ClassNameSessionSet, new ParameterSetEntry(2) }, + { CimBaseCommand.ClassNameComputerSet, new ParameterSetEntry(1, true) }, + }; + + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimInstanceCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimInstanceCommand.cs new file mode 100644 index 000000000..72e84c545 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimInstanceCommand.cs @@ -0,0 +1,370 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Management.Automation; + +#endregion + + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// Enables the user to remove a CimInstance. + /// + [Cmdlet( + VerbsCommon.Remove, + "CimInstance", + SupportsShouldProcess=true, + DefaultParameterSetName = CimBaseCommand.CimInstanceComputerSet, + HelpUri = "http://go.microsoft.com/fwlink/?LinkId=227964")] + public class RemoveCimInstanceCommand : CimBaseCommand + { + #region constructor + + /// + /// constructor + /// + public RemoveCimInstanceCommand() + : base(parameters, parameterSets) + { + DebugHelper.WriteLogEx(); + } + + #endregion + + #region parameters + /// + /// The following is the definition of the input parameter "Session". + /// CIM session used to remove the CIM Instance. + /// + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.CimInstanceSessionSet)] + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public CimSession[] CimSession + { + get { return cimSession; } + set + { + cimSession = value; + base.SetParameter(value, nameCimSession); + } + } + private CimSession[] cimSession; + + + /// + /// + /// The following is the definition of the input parameter "ResourceUri". + /// Define the Resource Uri for which the instances are retrieved. + /// + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.CimInstanceComputerSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.CimInstanceSessionSet)] + public Uri ResourceUri + { + get { return resourceUri; } + set + { + this.resourceUri = value; + base.SetParameter(value, nameResourceUri); + } + } + private Uri resourceUri; + + /// + /// The following is the definition of the input parameter "ComputerName". + /// + [Alias(AliasCN, AliasServerName)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + [Parameter( + ParameterSetName = CimBaseCommand.CimInstanceComputerSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public String[] ComputerName + { + get { return computername; } + set + { + computername = value; + base.SetParameter(value, nameComputerName); + } + } + private String[] computername; + + /// + /// The following is the definition of the input parameter "Namespace". + /// The Namespace used to look for the Class instances under. + /// + [Parameter( + Position = 1, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + [Parameter( + Position = 1, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + public String Namespace + { + get { return nameSpace; } + set + { + nameSpace = value; + base.SetParameter(value, nameNamespace); + } + } + private String nameSpace; + + /// + /// The following is the definition of the input parameter "OperationTimeoutSec". + /// Used to set the invocation operation time out. This value overrides the + /// CimSession operation timeout. + /// + [Alias(AliasOT)] + [Parameter] + public UInt32 OperationTimeoutSec + { + get { return operationTimeout;} + set { operationTimeout = value; } + } + private UInt32 operationTimeout; + + /// + /// The following is the definition of the input parameter "InputObject". + /// Used to get a CimInstance using Get-CimInstance | Remove-CimInstance. + /// + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.CimInstanceComputerSet)] + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.CimInstanceSessionSet)] + [Alias(CimBaseCommand.AliasCimInstance)] + public CimInstance InputObject + { + get { return cimInstance; } + set + { + cimInstance = value; + base.SetParameter(value, nameCimInstance); + } + } + + /// + /// Property for internal usage purpose + /// + internal CimInstance CimInstance + { + get { return cimInstance; } + } + private CimInstance cimInstance; + + /// + /// The following is the definition of the input parameter "Query". + /// + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + public String Query + { + get { return query;} + set + { + query = value; + base.SetParameter(value, nameQuery); + } + } + private String query; + + /// + /// The following is the definition of the input parameter "QueryDialect". + /// Specifies the dialect used by the query Engine that interprets the Query + /// string. + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + public String QueryDialect + { + get { return querydialect;} + set + { + querydialect = value; + base.SetParameter(value, nameQueryDialect); + } + } + private String querydialect; + + #endregion + + #region cmdlet methods + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + CimRemoveCimInstance cimRemoveInstance = this.GetOperationAgent(); + if (cimRemoveInstance == null) + { + cimRemoveInstance = CreateOperationAgent(); + } + this.CmdletOperation = new CmdletOperationRemoveCimInstance(this, cimRemoveInstance); + this.AtBeginProcess = false; + }//End BeginProcessing() + + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + base.CheckParameterSet(); + CimRemoveCimInstance cimRemoveInstance = this.GetOperationAgent(); + cimRemoveInstance.RemoveCimInstance(this); + cimRemoveInstance.ProcessActions(this.CmdletOperation); + }//End ProcessRecord() + + /// + /// EndProcessing method. + /// + protected override void EndProcessing() + { + CimRemoveCimInstance cimRemoveInstance = this.GetOperationAgent(); + if (cimRemoveInstance != null) + { + cimRemoveInstance.ProcessRemainActions(this.CmdletOperation); + } + }//End EndProcessing() + + #endregion + + #region helper methods + + /// + /// + /// Get object, which is + /// used to delegate all Remove-CimInstance operations. + /// + /// + CimRemoveCimInstance GetOperationAgent() + { + return (this.AsyncOperation as CimRemoveCimInstance); + } + + /// + /// + /// Create object, which is + /// used to delegate all Remove-CimInstance operations. + /// + /// + /// + CimRemoveCimInstance CreateOperationAgent() + { + CimRemoveCimInstance cimRemoveInstance = new CimRemoveCimInstance(); + this.AsyncOperation = cimRemoveInstance; + return cimRemoveInstance; + } + + #endregion + + #region private members + + #region const string of parameter names + internal const string nameCimSession = "CimSession"; + internal const string nameComputerName = "ComputerName"; + internal const string nameResourceUri = "ResourceUri"; + internal const string nameNamespace = "Namespace"; + internal const string nameCimInstance = "InputObject"; + internal const string nameQuery = "Query"; + internal const string nameQueryDialect = "QueryDialect"; + #endregion + + /// + /// static parameter definition entries + /// + static Dictionary> parameters = new Dictionary> + { + { + nameCimSession, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, true), + } + }, + { + nameComputerName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceComputerSet, false), + } + }, + { + nameNamespace, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, false), + } + }, + { + nameCimInstance, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceComputerSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceSessionSet, true), + } + }, + { + nameQuery, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, true), + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, true), + } + }, + { + nameQueryDialect, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, false), + } + }, + { + nameResourceUri, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceSessionSet, false), + } + }, + }; + + /// + /// static parameter set entries + /// + static Dictionary parameterSets = new Dictionary + { + { CimBaseCommand.CimInstanceComputerSet, new ParameterSetEntry(1, true) }, + { CimBaseCommand.CimInstanceSessionSet, new ParameterSetEntry(2) }, + { CimBaseCommand.QueryComputerSet, new ParameterSetEntry(1) }, + { CimBaseCommand.QuerySessionSet, new ParameterSetEntry(2) }, + }; + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimSessionCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimSessionCommand.cs new file mode 100644 index 000000000..ad586791b --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/RemoveCimSessionCommand.cs @@ -0,0 +1,234 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +#region Using directives + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Management.Automation; + +#endregion + +/****************************************************************************** + * warning 28750: Banned usage of lstrlen and its variants: lstrlenW is a + * banned API for improved error handling purposes. + *****************************************************************************/ +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// This Cmdlet allows the to remove, or terminate, one or more CimSession(s). + /// + + [Cmdlet(VerbsCommon.Remove, "CimSession", + SupportsShouldProcess = true, + DefaultParameterSetName = CimSessionSet, + HelpUri = "http://go.microsoft.com/fwlink/?LinkId=227968")] + public sealed class RemoveCimSessionCommand : CimBaseCommand + { + #region constructor + + /// + /// constructor + /// + public RemoveCimSessionCommand() + : base(parameters, parameterSets) + { + } + + #endregion + + #region parameters + + /// + /// The following is the definition of the input parameter "CimSession". + /// Specifies one or more CimSession object to be removed from the local PS + /// session/runspace. + /// + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimSessionSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public CimSession[] CimSession + { + get { return cimsession;} + set + { + cimsession = value; + base.SetParameter(value, nameCimSession); + } + } + private CimSession[] cimsession; + + /// + /// The following is the definition of the input parameter "ComputerName". + /// Specified one or more computer names for which all CimSession(s) + /// (connections) should be removed (terminated). + /// This is the only optional parameter. If no value for this parameter is + /// provided, all CimSession(s) are terminated. + /// + [Alias(AliasCN, AliasServerName)] + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipelineByPropertyName = true, + ParameterSetName = ComputerNameSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public String[] ComputerName + { + get { return computername; } + set + { + computername = value; + base.SetParameter(value, nameComputerName); + } + } + private String[] computername; + + /// + /// The following is the definition of the input parameter "Id". + /// Specifies the friendly Id(s) of the CimSession(s) that should be removed + /// (terminated). + /// + [Parameter(Mandatory = true, + Position = 0, + ValueFromPipelineByPropertyName = true, + ParameterSetName = SessionIdSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public UInt32[] Id + { + get { return id;} + set + { + id = value; + base.SetParameter(value, nameId); + } + } + private UInt32[] id; + + /// + /// The following is the definition of the input parameter "InstanceId". + /// Specifies one or more automatically generated InstanceId(s) (GUIDs) of the + /// CimSession(s) that should be removed (terminated). + /// + [Parameter( + Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = InstanceIdSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public Guid[] InstanceId + { + get { return instanceid;} + set + { + instanceid = value; + base.SetParameter(value, nameInstanceId); + } + } + private Guid[] instanceid; + + /// + /// The following is the definition of the input parameter "Name". + /// Specifies one or more of friendly Names of the CimSession(s) that should be + /// removed (terminated). + /// + [Parameter( + Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = NameSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public String[] Name + { + get { return name;} + set + { + name = value; + base.SetParameter(value, nameName); + } + } + private String[] name; + + #endregion + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + this.cimRemoveSession = new CimRemoveSession(); + this.AtBeginProcess = false; + }//End BeginProcessing() + + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + base.CheckParameterSet(); + this.cimRemoveSession.RemoveCimSession(this); + }//End ProcessRecord() + + #region private members + /// + /// object used to remove the session from + /// session cache + /// + private CimRemoveSession cimRemoveSession; + + #region const string of parameter names + internal const string nameCimSession = "CimSession"; + internal const string nameComputerName = "ComputerName"; + internal const string nameId = "Id"; + internal const string nameInstanceId = "InstanceId"; + internal const string nameName = "Name"; + #endregion + + /// + /// static parameter definition entries + /// + static Dictionary> parameters = new Dictionary> + { + { + nameCimSession, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.CimSessionSet, true), + } + }, + { + nameComputerName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.ComputerNameSet, true), + } + }, + { + nameId, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.SessionIdSet, true), + } + }, + { + nameInstanceId, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.InstanceIdSet, true), + } + }, + { + nameName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.NameSet, true), + } + }, + }; + + /// + /// static parameter set entries + /// + static Dictionary parameterSets = new Dictionary + { + { CimBaseCommand.CimSessionSet, new ParameterSetEntry(1, true) }, + { CimBaseCommand.ComputerNameSet, new ParameterSetEntry(1) }, + { CimBaseCommand.SessionIdSet, new ParameterSetEntry(1) }, + { CimBaseCommand.InstanceIdSet, new ParameterSetEntry(1) }, + { CimBaseCommand.NameSet, new ParameterSetEntry(1) }, + }; + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/SetCimInstanceCommand.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/SetCimInstanceCommand.cs new file mode 100644 index 000000000..3e4eb119c --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/SetCimInstanceCommand.cs @@ -0,0 +1,430 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +#region Using directives +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Management.Automation; +#endregion + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// + /// Enables the user to Set properties and keys on a specific + /// CimInstance must have values of all [KEY] properties. + /// + /// + [Cmdlet( + VerbsCommon.Set, + "CimInstance", + SupportsShouldProcess = true, + DefaultParameterSetName = CimBaseCommand.CimInstanceComputerSet, + HelpUri = "http://go.microsoft.com/fwlink/?LinkId=227962")] + public class SetCimInstanceCommand : CimBaseCommand + { + #region constructor + + /// + /// constructor + /// + public SetCimInstanceCommand() + : base(parameters, parameterSets) + { + } + + #endregion + + #region parameters + /// + /// The following is the definition of the input parameter "Session". + /// CIM session used to set the CIM Instance. + /// + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.CimInstanceSessionSet)] + [Parameter( + Mandatory = true, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public CimSession[] CimSession + { + get { return cimSession; } + set + { + cimSession = value; + base.SetParameter(value, nameCimSession); + } + } + private CimSession[] cimSession; + + /// + /// The following is the definition of the input parameter "ComputerName". + /// + [Alias(AliasCN, AliasServerName)] + [Parameter( + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + [Parameter( + ParameterSetName = CimBaseCommand.CimInstanceComputerSet)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public String[] ComputerName + { + get { return computername; } + set + { + computername = value; + base.SetParameter(value, nameComputerName); + } + } + private String[] computername; + + /// + /// + /// The following is the definition of the input parameter "ResourceUri". + /// Define the Resource Uri for which the instances are retrieved. + /// + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.CimInstanceComputerSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.CimInstanceSessionSet)] + public Uri ResourceUri + { + get { return resourceUri; } + set + { + this.resourceUri = value; + base.SetParameter(value, nameResourceUri); + } + } + private Uri resourceUri; + + /// + /// The following is the definition of the input parameter "Namespace". + /// The Namespace used to look for the Class instances under. + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + public String Namespace + { + get { return nameSpace; } + set + { + nameSpace = value; + base.SetParameter(value, nameNamespace); + } + } + private String nameSpace; + + /// + /// The following is the definition of the input parameter "OperationTimeoutSec". + /// Used to set the invocation operation time out. This value overrides the + /// CimSession operation timeout. + /// + [Alias(AliasOT)] + [Parameter] + public UInt32 OperationTimeoutSec + { + get { return operationTimeout; } + set { operationTimeout = value; } + } + private UInt32 operationTimeout; + + /// + /// The following is the definition of the input parameter "InputObject". + /// Used to get a CimInstance using Get-CimInstance | Set-CimInstance. + /// + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.CimInstanceComputerSet)] + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipeline = true, + ParameterSetName = CimBaseCommand.CimInstanceSessionSet)] + [Alias(CimBaseCommand.AliasCimInstance)] + public CimInstance InputObject + { + get { return cimInstance; } + set + { + cimInstance = value; + base.SetParameter(value, nameCimInstance); + } + } + + /// + /// Property for internal usage purpose + /// + internal CimInstance CimInstance + { + get { return cimInstance; } + } + private CimInstance cimInstance; + + /// + /// The following is the definition of the input parameter "Query". + /// + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + [Parameter( + Mandatory = true, + Position = 0, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + public String Query + { + get { return query; } + set + { + query = value; + base.SetParameter(value, nameQuery); + } + } + private String query; + + /// + /// The following is the definition of the input parameter "QueryDialect". + /// Specifies the dialect used by the query Engine that interprets the Query + /// string. + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + public String QueryDialect + { + get { return querydialect; } + set + { + querydialect = value; + base.SetParameter(value, nameQueryDialect); + } + } + private String querydialect; + + /// + /// + /// The following is the definition of the input parameter "Property", + /// defines the value to be changed. + /// + /// + /// The key properties will be ignored. Any invalid property will cause + /// termination of the cmdlet execution. + /// + /// + [Parameter(Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QuerySessionSet)] + [Parameter(Mandatory = true, + ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.QueryComputerSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.CimInstanceSessionSet)] + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = CimBaseCommand.CimInstanceComputerSet)] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + [Alias("Arguments")] + public IDictionary Property + { + get { return property; } + set + { + property = value; + base.SetParameter(value, nameProperty); + } + } + private IDictionary property; + + /// + /// The following is the definition of the input parameter "PassThru", + /// indicate whether Set-CimInstance should output modified result instance or not. + /// + /// True indicates output the result instance, otherwise output nothing as by default + /// behavior. + /// + /// + [Parameter] + [ValidateNotNull] + public SwitchParameter PassThru + { + set + { + this.passThru = value; + } + get + { + return this.passThru; + } + } + private SwitchParameter passThru; + + #endregion + + #region cmdlet methods + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + CimSetCimInstance cimSetCimInstance = this.GetOperationAgent(); + if (cimSetCimInstance == null) + { + cimSetCimInstance = CreateOperationAgent(); + } + this.CmdletOperation = new CmdletOperationSetCimInstance(this, cimSetCimInstance); + this.AtBeginProcess = false; + }//End BeginProcessing() + + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + base.CheckParameterSet(); + CimSetCimInstance cimSetCimInstance = this.GetOperationAgent(); + cimSetCimInstance.SetCimInstance(this); + cimSetCimInstance.ProcessActions(this.CmdletOperation); + }//End ProcessRecord() + + /// + /// EndProcessing method. + /// + protected override void EndProcessing() + { + CimSetCimInstance cimSetCimInstance = this.GetOperationAgent(); + if (cimSetCimInstance != null) + { + cimSetCimInstance.ProcessRemainActions(this.CmdletOperation); + } + }//End EndProcessing() + + #endregion + + #region helper methods + + /// + /// + /// Get object, which is + /// used to delegate all Set-CimInstance operations. + /// + /// + CimSetCimInstance GetOperationAgent() + { + return (this.AsyncOperation as CimSetCimInstance); + } + + /// + /// + /// Create object, which is + /// used to delegate all Set-CimInstance operations. + /// + /// + /// + CimSetCimInstance CreateOperationAgent() + { + CimSetCimInstance cimSetCimInstance = new CimSetCimInstance(); + this.AsyncOperation = cimSetCimInstance; + return cimSetCimInstance; + } + + #endregion + + #region private members + + #region const string of parameter names + internal const string nameCimSession = "CimSession"; + internal const string nameComputerName = "ComputerName"; + internal const string nameResourceUri = "ResourceUri"; + internal const string nameNamespace = "Namespace"; + internal const string nameCimInstance = "InputObject"; + internal const string nameQuery = "Query"; + internal const string nameQueryDialect = "QueryDialect"; + internal const string nameProperty = "Property"; + #endregion + + /// + /// static parameter definition entries + /// + static Dictionary> parameters = new Dictionary> + { + { + nameCimSession, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceSessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, true), + } + }, + { + nameComputerName, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceComputerSet, false), + } + }, + { + nameNamespace, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, false), + } + }, + { + nameCimInstance, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceComputerSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceSessionSet, true), + } + }, + { + nameQuery, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, true), + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, true), + } + }, + { + nameQueryDialect, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, false), + } + }, + { + nameProperty, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.QuerySessionSet, true), + new ParameterDefinitionEntry(CimBaseCommand.QueryComputerSet, true), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceSessionSet, false), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceComputerSet, false), + } + }, + { + nameResourceUri, new HashSet { + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceComputerSet, false), + new ParameterDefinitionEntry(CimBaseCommand.CimInstanceSessionSet, false), + } + }, + }; + + /// + /// static parameter set entries + /// + static Dictionary parameterSets = new Dictionary + { + { CimBaseCommand.QuerySessionSet, new ParameterSetEntry(3) }, + { CimBaseCommand.QueryComputerSet, new ParameterSetEntry(2) }, + { CimBaseCommand.CimInstanceSessionSet, new ParameterSetEntry(2) }, + { CimBaseCommand.CimInstanceComputerSet, new ParameterSetEntry(1, true) }, + }; + #endregion + }//End Class +}//End namespace diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/Utils.cs b/src/Microsoft.Management.Infrastructure.CimCmdlets/Utils.cs new file mode 100644 index 000000000..edf8f370d --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/Utils.cs @@ -0,0 +1,465 @@ +/*============================================================================ + * Copyright (C) Microsoft Corporation, All rights reserved. + *============================================================================ + */ + +// #define LOGENABLE // uncomment this line to enable the log, + // create c:\temp\cim.log before invoking cimcmdlets + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Management.Automation; +using System.Text.RegularExpressions; +using System.Threading; + +namespace Microsoft.Management.Infrastructure.CimCmdlets +{ + /// + /// + /// Global Non-localization strings + /// + /// + internal static class ConstValue + { + /// + /// + /// Default computername + /// + /// + internal static string[] DefaultSessionName = {@"*"}; + + /// + /// + /// Empty computername, which will create DCOM session + /// + /// + internal static string NullComputerName = null; + + /// + /// + /// Empty computername array, which will create DCOM session + /// + /// + internal static string[] NullComputerNames = { NullComputerName }; + + /// + /// + /// localhost computername, which will create WSMAN session + /// + /// + internal static string LocalhostComputerName = @"localhost"; + + /// + /// + /// Default namespace + /// + /// + internal static string DefaultNameSpace = @"root\cimv2"; + + /// + /// + /// Default namespace + /// + /// + internal static string DefaultQueryDialect = @"WQL"; + + /// + /// Name of the note property that controls if "PSComputerName" column is shown + /// + internal static string ShowComputerNameNoteProperty = "PSShowComputerName"; + + /// + /// + /// Whether given computername is either null or empty + /// + /// + /// + /// + internal static bool IsDefaultComputerName(string computerName) + { + return String.IsNullOrEmpty(computerName); + } + + /// + /// + /// Get computer names, if it is null then return DCOM one + /// + /// + /// + /// + internal static IEnumerable GetComputerNames(IEnumerable computerNames) + { + return (computerNames == null) ? NullComputerNames : computerNames; + } + + /// + /// Get computer name, if it is null then return default one + /// + /// + /// + internal static string GetComputerName(string computerName) + { + return string.IsNullOrEmpty(computerName) ? NullComputerName : computerName; + } + + /// + /// + /// Get namespace, if it is null then return default one + /// + /// + /// + /// + internal static string GetNamespace(string nameSpace) + { + return (nameSpace == null) ? DefaultNameSpace : nameSpace; + } + + /// + /// + /// Get queryDialect, if it is null then return default query Dialect + /// + /// + /// + /// + internal static string GetQueryDialectWithDefault(string queryDialect) + { + return (queryDialect == null) ? DefaultQueryDialect : queryDialect; + } + } + + /// + /// + /// Debug helper class used to dump debug message to log file + /// + /// + internal static class DebugHelper + { + #region private members + + /// + /// Flag used to control generating log message into file. + /// + private static bool generateLog = true; + internal static bool GenerateLog + { + get { return generateLog; } + set { generateLog = value; } + } + + /// + /// Whether the log been initialized + /// + private static bool logInitialized = false; + + /// + /// Flag used to control generating message into powershell + /// + private static bool genrateVerboseMessage = true; + internal static bool GenrateVerboseMessage + { + get { return genrateVerboseMessage; } + set { genrateVerboseMessage = value; } + } + + /// + /// Flag used to control generating message into powershell + /// + internal static string logFile = @"c:\temp\Cim.log"; + + /// + /// Indent space string + /// + internal static string space = @" "; + + /// + /// Indent space strings array + /// + internal static string[] spaces = { + string.Empty, + space, + space + space, + space + space + space, + space + space + space + space, + space + space + space + space + space, + }; + + /// + /// Lock the log file + /// + internal static object logLock = new object(); + + #endregion + + #region internal strings + internal static string runspaceStateChanged = "Runspace {0} state changed to {1}"; + internal static string classDumpInfo = @"Class type is {0}"; + internal static string propertyDumpInfo = @"Property name {0} of type {1}, its value is {2}"; + internal static string defaultPropertyType = @"It is a default property, default value is {0}"; + internal static string propertyValueSet = @"This property value is set by user {0}"; + internal static string addParameterSetName = @"Add parameter set {0} name to cache"; + internal static string removeParameterSetName = @"Remove parameter set {0} name from cache"; + internal static string currentParameterSetNameCount = @"Cache have {0} parameter set names"; + internal static string currentParameterSetNameInCache = @"Cache have parameter set {0} valid {1}"; + internal static string currentnonMadatoryParameterSetInCache = @"Cache have optional parameter set {0} valid {1}"; + internal static string optionalParameterSetNameCount = @"Cache have {0} optional parameter set names"; + internal static string finalParameterSetName = @"------Final parameter set name of the cmdlet is {0}"; + internal static string addToOptionalParameterSet = @"Add to optional ParameterSetNames {0}"; + internal static string startToResolveParameterSet = @"------Resolve ParameterSet Name"; + internal static string reservedString = @"------"; + #endregion + + #region runtime methods + internal static string GetSourceCodeInformation(bool withFileName, int depth) + { +#if CORECLR + //return a dummy string as StackFrame won't be available on CoreCLR + return string.Format(CultureInfo.CurrentUICulture, "{0}::{1} ", "Type", "Method"); +#else + StackTrace trace = new StackTrace(); + StackFrame frame = trace.GetFrame(depth); + //if (withFileName) + //{ + // return string.Format(CultureInfo.CurrentUICulture, "{0}#{1}:{2}:", frame.GetFileName()., frame.GetFileLineNumber(), frame.GetMethod().Name); + //} + //else + //{ + // return string.Format(CultureInfo.CurrentUICulture, "{0}:", frame.GetMethod()); + //} + return string.Format(CultureInfo.CurrentUICulture, "{0}::{1} ", + frame.GetMethod().DeclaringType.Name, + frame.GetMethod().Name); + +#endif + } + #endregion + + /// + /// Write message to log file named @logFile + /// + /// + internal static void WriteLog(string message) + { + WriteLog(message, 0); + } + + /// + /// Write blank line to log file named @logFile + /// + /// + internal static void WriteEmptyLine() + { + WriteLog(string.Empty, 0); + } + + /// + /// Write message to log file named @logFile with args + /// + /// + internal static void WriteLog(string message, int indent, params object[] args) + { + String outMessage = String.Empty; + FormatLogMessage(ref outMessage, message, args); + WriteLog(outMessage, indent); + } + + /// + /// Write message to log file w/o arguments + /// + /// + /// + internal static void WriteLog(string message, int indent) + { + WriteLogInternal(message, indent, -1); + } + + /// + /// Write message to log file named @logFile with args + /// + /// + internal static void WriteLogEx(string message, int indent, params object[] args) + { + String outMessage = String.Empty; + WriteLogInternal(string.Empty, 0, -1); + FormatLogMessage(ref outMessage, message, args); + WriteLogInternal(outMessage, indent, 3); + } + + /// + /// Write message to log file w/o arguments + /// + /// + /// + internal static void WriteLogEx(string message, int indent) + { + WriteLogInternal(string.Empty, 0, -1); + WriteLogInternal(message, indent, 3); + } + + /// + /// Write message to log file w/o arguments + /// + /// + /// + internal static void WriteLogEx() + { + WriteLogInternal(string.Empty, 0, -1); + WriteLogInternal(string.Empty, 0, 3); + } + + /// + /// Format the message + /// + /// + /// + /// + [Conditional("LOGENABLE")] + private static void FormatLogMessage(ref String outMessage, string message, params object[] args) + { + outMessage = String.Format(CultureInfo.CurrentCulture, message, args); + } + + /// + /// Write message to log file named @logFile + /// with indent space ahead of the message. + /// + /// + /// + [Conditional("LOGENABLE")] + private static void WriteLogInternal(string message, int indent, int depth) + { + if (!logInitialized) + { + lock (logLock) + { + if (!logInitialized) + { + DebugHelper.GenerateLog = File.Exists(logFile); + logInitialized = true; + } + } + } + + if (generateLog) + { + if (indent < 0) + { + indent = 0; + } + if (indent > 5) + { + indent = 5; + } + string sourceInformation = string.Empty; + if (depth != -1) + { + sourceInformation = string.Format( + CultureInfo.InvariantCulture, + "Thread {0}#{1}:{2}:{3} {4}", + Thread.CurrentThread.ManagedThreadId, + DateTime.Now.Hour, + DateTime.Now.Minute, + DateTime.Now.Second, + GetSourceCodeInformation(true, depth)); + } + lock (logLock) + { + using (FileStream fs = new FileStream(logFile,FileMode.OpenOrCreate)) + using (StreamWriter writer = new StreamWriter(fs)) + { + writer.WriteLineAsync(spaces[indent] + sourceInformation + @" " + message); + } + + } + } + } + } + + /// + /// + /// Helper class used to validate given parameter + /// + /// + internal static class ValidationHelper + { + /// + /// Validate the argument is not null + /// + /// + /// + public static void ValidateNoNullArgument(object obj, string argumentName) + { + if (obj == null) + { + throw new ArgumentNullException(argumentName); + } + } + + /// + /// Validate the argument is not null and not whitespace + /// + /// + /// + public static void ValidateNoNullorWhiteSpaceArgument(string obj, string argumentName) + { + if (String.IsNullOrWhiteSpace(obj)) + { + throw new ArgumentException(argumentName); + } + } + + /// + /// Validate that given classname/propertyname is a valid name compliance with DMTF standard. + /// Only for verifying ClassName and PropertyName argument + /// + /// + /// + /// + /// Throw if the given value is not a valid name (class name or property name) + public static string ValidateArgumentIsValidName(string parameterName, string value) + { + DebugHelper.WriteLogEx(); + if (value != null) + { + string trimed = value.Trim(); + // The first character should be contained in set: [A-Za-z_] + // Inner characters should be contained in set: [A-Za-z0-9_] + Regex regex = new Regex(@"^[a-zA-Z_][a-zA-Z0-9_]*\z"); + if (regex.IsMatch(trimed)) + { + DebugHelper.WriteLogEx("A valid name: {0}={1}", 0, parameterName, value); + return trimed; + } + } + DebugHelper.WriteLogEx("An invalid name: {0}={1}", 0, parameterName, value); + throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Strings.InvalidParameterValue, value, parameterName)); + } + + /// + /// Validate given arry argument contains all valid name (for -SelectProperties). + /// * is valid for this case. + /// + /// + /// + /// + /// Throw if the given value contains any invalid name (class name or property name) + public static String[] ValidateArgumentIsValidName(string parameterName, String[] value) + { + if (value != null) + { + foreach (string propertyName in value) + { + // * is wild char supported in select properties + if ((propertyName != null) && (String.Compare(propertyName.Trim(), "*", StringComparison.OrdinalIgnoreCase) == 0)) + { + continue; + } + ValidationHelper.ValidateArgumentIsValidName(parameterName, propertyName); + } + } + return value; + } + } +} diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/map.json b/src/Microsoft.Management.Infrastructure.CimCmdlets/map.json new file mode 100644 index 000000000..439b349e8 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/map.json @@ -0,0 +1,41 @@ +{ + "wmi/WMIv2/client/CIMCmdlets/CimAsyncOperation.cs" : "CimAsyncOperation.cs", + "wmi/WMIv2/client/CIMCmdlets/CimBaseAction.cs" : "CimBaseAction.cs", + "wmi/WMIv2/client/CIMCmdlets/CimCmdletModuleInitialize.cs" : "CimCmdletModuleInitialize.cs", + "wmi/WMIv2/client/CIMCmdlets/CimCommandBase.cs" : "CimCommandBase.cs", + "wmi/WMIv2/client/CIMCmdlets/CimGetAssociatedInstance.cs" : "CimGetAssociatedInstance.cs", + "wmi/WMIv2/client/CIMCmdlets/CimGetCimClass.cs" : "CimGetCimClass.cs", + "wmi/WMIv2/client/CIMCmdlets/CimGetInstance.cs" : "CimGetInstance.cs", + "wmi/WMIv2/client/CIMCmdlets/CimIndicationWatcher.cs" : "CimIndicationWatcher.cs", + "wmi/WMIv2/client/CIMCmdlets/CimInvokeCimMethod.cs" : "CimInvokeCimMethod.cs", + "wmi/WMIv2/client/CIMCmdlets/CimNewCimInstance.cs" : "CimNewCimInstance.cs", + "wmi/WMIv2/client/CIMCmdlets/CimPromptUser.cs" : "CimPromptUser.cs", + "wmi/WMIv2/client/CIMCmdlets/CimRegisterCimIndication.cs" : "CimRegisterCimIndication.cs", + "wmi/WMIv2/client/CIMCmdlets/CimRemoveCimInstance.cs" : "CimRemoveCimInstance.cs", + "wmi/WMIv2/client/CIMCmdlets/CimResultObserver.cs" : "CimResultObserver.cs", + "wmi/WMIv2/client/CIMCmdlets/CimSessionOperations.cs" : "CimSessionOperations.cs", + "wmi/WMIv2/client/CIMCmdlets/CimSessionProxy.cs" : "CimSessionProxy.cs", + "wmi/WMIv2/client/CIMCmdlets/CimSetCimInstance.cs" : "CimSetCimInstance.cs", + "wmi/WMIv2/client/CIMCmdlets/CimWriteError.cs" : "CimWriteError.cs", + "wmi/WMIv2/client/CIMCmdlets/CimWriteMessage.cs" : "CimWriteMessage.cs", + "wmi/WMIv2/client/CIMCmdlets/CimWriteProgress.cs" : "CimWriteProgress.cs", + "wmi/WMIv2/client/CIMCmdlets/CimWriteResultObject.cs" : "CimWriteResultObject.cs", + "wmi/WMIv2/client/CIMCmdlets/CmdletOperation.cs" : "CmdletOperation.cs", + "wmi/WMIv2/client/CIMCmdlets/GetCimAssociatedInstanceCommand.cs" : "GetCimAssociatedInstanceCommand.cs", + "wmi/WMIv2/client/CIMCmdlets/GetCimClassCommand.cs" : "GetCimClassCommand.cs", + "wmi/WMIv2/client/CIMCmdlets/GetCimInstanceCommand.cs" : "GetCimInstanceCommand.cs", + "wmi/WMIv2/client/CIMCmdlets/GetCimSessionCommand.cs" : "GetCimSessionCommand.cs", + "wmi/WMIv2/client/CIMCmdlets/InvokeCimMethodCommand.cs" : "InvokeCimMethodCommand.cs", + "wmi/WMIv2/client/CIMCmdlets/NewCimInstanceCommand.cs" : "NewCimInstanceCommand.cs", + "wmi/WMIv2/client/CIMCmdlets/NewCimSessionCommand.cs" : "NewCimSessionCommand.cs", + "wmi/WMIv2/client/CIMCmdlets/NewCimSessionOptionCommand.cs" : "NewCimSessionOptionCommand.cs", + "wmi/WMIv2/client/CIMCmdlets/RegisterCimIndicationCommand.cs" : "RegisterCimIndicationCommand.cs", + "wmi/WMIv2/client/CIMCmdlets/RemoveCimInstanceCommand.cs" : "RemoveCimInstanceCommand.cs", + "wmi/WMIv2/client/CIMCmdlets/RemoveCimSessionCommand.cs" : "RemoveCimSessionCommand.cs", + "wmi/WMIv2/client/CIMCmdlets/SetCimInstanceCommand.cs" : "SetCimInstanceCommand.cs", + "wmi/WMIv2/client/CIMCmdlets/Utils.cs" : "Utils.cs", + "wmi/WMIv2/client/CIMCmdlets/BinaryMiLogBase.cs" : "BinaryMiLogBase.cs", + "wmi/WMIv2/client/CIMCmdlets/ExportBinaryMiLogCommand.cs" : "ExportBinaryMiLogCommand.cs", + "wmi/WMIv2/client/CIMCmdlets/ImportBinaryMiLogCommand.cs" : "ImportBinaryMiLogCommand.cs", + "wmi/WMIv2/client/CIMCmdlets/Strings.resx" : "resources/Microsoft.Management.Infrastructure.CimCmdlets.Strings.resx" +} \ No newline at end of file diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/project.json b/src/Microsoft.Management.Infrastructure.CimCmdlets/project.json new file mode 100644 index 000000000..9e21e52ae --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/project.json @@ -0,0 +1,29 @@ +{ + "name" : "Microsoft.Management.Infrastructure.CimCmdlets", + "version" : "1.0.0-*", + + "buildOptions": { + "keyFile": "../signing/visualstudiopublic.snk", + "delaySign": true, + "publicSign": false, + "warningsAsErrors": true, + }, + + "dependencies": { + "System.Management.Automation": "1.0.0-*" + }, + + "frameworks": { + "netstandard1.6": { + "imports": [ "dnxcore50"], + "buildOptions": { + "define": [ "CORECLR" ] + }, + }, + "net451": { + "frameworkAssemblies": { + "System": "" + } + } + } +} diff --git a/src/Microsoft.Management.Infrastructure.CimCmdlets/resources/Microsoft.Management.Infrastructure.CimCmdlets.Strings.resx b/src/Microsoft.Management.Infrastructure.CimCmdlets/resources/Microsoft.Management.Infrastructure.CimCmdlets.Strings.resx new file mode 100644 index 000000000..90a60cd30 --- /dev/null +++ b/src/Microsoft.Management.Infrastructure.CimCmdlets/resources/Microsoft.Management.Infrastructure.CimCmdlets.Strings.resx @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Operation '{0}' complete. + {0} is a placeholder for operation name. (i.e, GetCimInstance) + + + Create CimInstance + + + Delete CimInstance + + + Enumerate Associated CimInstances + + + Enumerate CimClasses + + + Enumerate CimInstances + + + Get CimClass + + + Get CimInstance + + + Invoke CimMethod + + + Modify CimInstance + + + Query CimInstances + + + Subscribe CimIndication + + + Perform operation '{0}' with following parameters, '{1}'. + {0} is a placeholder for operation name; {1} is a placeholder for parameters value + + + Parameter '{0}' cannot be used with the parameter '{1}'. + {0} is a placeholder for parameter name; {1} is a placeholder for another parameter name; + + + Could not find CimSession with the given {0} = {1} + {0} is a placeholder for property name; {1} is a placeholder for property value. + + + Could not find the following properties from the given class {0}: {1}. + {0} is a placeholder for class name; {1} is a placeholder for list of property names. + + + Could not modify readonly property '{0}' of object '{1}'. + {0} is a placeholder for propertyname; {1} is a placeholder for object string. + + + Default status description. + N/A + + + Cannot perform operation because the wildcard path {0} did not resolve to a file. + {0} is a placeholder for a path + + + Authentication type '{0}' is invalid without credential. Only following authentication type are allowed without credential, '{1}', '{2}', '{3}', or '{4}'. + {0} is a placeholder for authentication type. {1}-{4} are placeholders for authentication types. + + + Can not find method '{0}' in class '{1}'. + {0} is a placeholder for method name. {1} is a placeholders for class name. + + + Can not find Parameter '{0}' in method '{1}' of class '{2}'. + {0} is a placeholder for parameter name; {1} is a placeholder for method name; {2} is a placeholder for class name. + + + Invalid operation. Current cmdlet already have operation created. + N/A + + + Argument '{0}' contains characters that are not allowed in parameter '{1}'. Supply an argument that is valid and then try the command again. + {0} stand for argument value, {1} stand for parameter name. + + + Cannot perform operation because the path resolved to more than one file. This command cannot operate on multiple files. + + + Argument '{0}' can not be null. + N/A + + + CimSession proxy object already have operation in progress. + N/A + + + Cannot open file because the current provider ({0}) cannot open a file. + {0} is a placeholder for PowerShell filesystem-like provider name (i.e. registry provider) + + + Unable to add property '{0}' to input object '{1}'. The class schema does not contain the property. + {0} stand for property name, {1} stand for cim instance path. + + + Unable to resolve the parameter set name. + N/A + + \ No newline at end of file diff --git a/src/Microsoft.PowerShell.Commands.Management/project.json b/src/Microsoft.PowerShell.Commands.Management/project.json index 02994cdae..8bab6d7b6 100644 --- a/src/Microsoft.PowerShell.Commands.Management/project.json +++ b/src/Microsoft.PowerShell.Commands.Management/project.json @@ -88,7 +88,7 @@ "System.Web.Services": "" }, "dependencies": { - "Microsoft.WSMan.Management": "1.0.1-*" + "Microsoft.WSMan.Management": "1.0.0-*" }, "buildOptions": { "compile": { diff --git a/src/Microsoft.WSMan.Management/AssemblyInfo.cs b/src/Microsoft.WSMan.Management/AssemblyInfo.cs new file mode 100644 index 000000000..e55ec824d --- /dev/null +++ b/src/Microsoft.WSMan.Management/AssemblyInfo.cs @@ -0,0 +1,4 @@ +using System.Reflection; + +[assembly:AssemblyFileVersionAttribute("3.0.0.0")] +[assembly:AssemblyVersion("3.0.0.0")] diff --git a/src/Microsoft.WSMan.Management/ConfigProvider.cs b/src/Microsoft.WSMan.Management/ConfigProvider.cs new file mode 100644 index 000000000..e5ff34a8d --- /dev/null +++ b/src/Microsoft.WSMan.Management/ConfigProvider.cs @@ -0,0 +1,6379 @@ +/********************************************************************++ +Copyright (c) Microsoft Corporation. All rights reserved. +--********************************************************************/ +using System; +using System.Collections.Generic; +using System.Collections; +using System.Text; +using System.Management.Automation; +using System.Management.Automation.Provider; +using System.Collections.ObjectModel; +using System.Xml; +using System.Xml.XPath; +using System.Text.RegularExpressions; +using System.IO; +using System.Runtime.InteropServices; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Security; +#if !CORECLR +using System.ServiceProcess; +#endif + +namespace Microsoft.WSMan.Management +{ + + /// + /// WsMan Provider. + /// + [CmdletProvider(WSManStringLiterals.ProviderName, ProviderCapabilities.Credentials)] + public sealed partial class WSManConfigProvider : NavigationCmdletProvider, ICmdletProviderSupportsHelp + { + //Plugin Name Storage + private PSObject objPluginNames = null; + + /// + /// Determinies if Set-Item user input type validateion is required or not. + /// It is True by default, Clear-Item will set it to false so that it can + /// pass Empty String as value for Set-Item. + /// + private bool clearItemIsCalled = false; + + WSManHelper helper = new WSManHelper(); + + /// + /// Object contains the cache of the enumarate results for the cmdlet to execute. + /// + Dictionary enumarateMapping = new Dictionary(); + + /// + /// Mapping of ResourceURI with the XML returned by the Get call. + /// + Dictionary getMapping = new Dictionary(); + + #region ICmdletProviderSupportsHelp Members + + /// + /// This implements Get-Help for config provider custom path. + /// When user calls "Get-Help new-item" in our config provider path, this function will get called. + /// + /// + /// + /// + string ICmdletProviderSupportsHelp.GetHelpMaml(string helpItemName, string path) + { + //Get the leaf node from the path for which help is requested. + int ChildIndex = path.LastIndexOf("\\", StringComparison.OrdinalIgnoreCase); + if (ChildIndex == -1) + { + //Means we are at host level, where no new-item is supported. Return empty string. + return String.Empty; + } + String child = path.Substring(ChildIndex + 1); + + //We only return help for the below set of 5 commands, not for any other case. + switch (helpItemName) + { + case "New-Item": + case "Get-Item": + case "Set-Item": + case "Clear-Item": + case "Remove-Item": + break; + default: + return String.Empty; + } + + // Load the help file from the current UI culture subfolder of the module's root folder + XmlDocument document = new XmlDocument(); + CultureInfo culture = Host.CurrentUICulture; + String providerBase = this.ProviderInfo.PSSnapIn != null ? this.ProviderInfo.PSSnapIn.ApplicationBase : this.ProviderInfo.Module.ModuleBase; // "\windows\system32\WindowsPowerShell\v1.0" + String helpFile = null; + + do + { + string muiDirectory = Path.Combine(providerBase, culture.Name); + if (Directory.Exists(muiDirectory)) + { + if (File.Exists(muiDirectory + "\\" + this.ProviderInfo.HelpFile)) + { + helpFile = muiDirectory + "\\" + this.ProviderInfo.HelpFile; + break; + } + } + culture = culture.Parent; + } while (culture != culture.Parent); + + if (helpFile == null) + { + //Can't find help file. Return empty string + return String.Empty; + } + + try + { + //XmlDocument in CoreCLR takes a stream instead of a string for loading xml + byte[] byteArray = Encoding.UTF8.GetBytes(helpFile); + MemoryStream stream = new MemoryStream(byteArray); + document.Load(stream); + } + catch(XmlException) + { + return String.Empty; + } + catch(PathTooLongException) + { + return String.Empty; + } + catch(IOException) + { + return String.Empty; + } + catch(UnauthorizedAccessException) + { + return String.Empty; + } + catch(NotSupportedException) + { + return String.Empty; + } + catch(SecurityException) + { + return String.Empty; + } + + // Add the "command" namespace from the MAML schema + XmlNamespaceManager nsMgr = new XmlNamespaceManager(document.NameTable); + nsMgr.AddNamespace("command", "http://schemas.microsoft.com/maml/dev/command/2004/10"); + + // Split the help item name into verb and noun + string verb = helpItemName.Split('-')[0]; + string noun = helpItemName.Substring(helpItemName.IndexOf('-')+1); + + //Compose XPath query to select the appropriate node based on the verb,noun and ID + string xpathQuery = "/helpItems/providerHelp/CmdletHelpPaths/CmdletHelpPath[@ID='" + child + "']/command:command/command:details[command:verb='" + verb + "' and command:noun='" + noun + "']"; + + // Execute the XPath query and if the command was found, return its MAML snippet + XmlNode result = null; + try + { + result = document.SelectSingleNode(xpathQuery, nsMgr); + } + catch(XPathException) + { + return String.Empty; + } + if (result != null) + { + return result.ParentNode.OuterXml; + } + return String.Empty; + } + + #endregion + + + #region DriveCmdletProvider + /// + /// + /// + /// + /// + protected override PSDriveInfo NewDrive(PSDriveInfo drive) + { + if (drive == null) + { + return null; + } + + if (String.IsNullOrEmpty(drive.Root) == false) + { + AssertError(helper.GetResourceMsgFromResourcetext("NewDriveRootDoesNotExist"), false); + return null; + } + + return drive; + } + + /// + /// Adds the requird drive + /// + /// + protected override Collection InitializeDefaultDrives() + { + Collection drives = new Collection(); + drives.Add(new PSDriveInfo(WSManStringLiterals.rootpath, ProviderInfo, String.Empty, + helper.GetResourceMsgFromResourcetext("ConfigStorage"), null)); + return drives; + } + + /// + /// Removes the requird drive + /// + /// + protected override PSDriveInfo RemoveDrive(PSDriveInfo drive) + { + WSManHelper.ReleaseSessions(); + return drive; + } + + + #endregion + + #region ItemCmdletProvider + + /// + /// Get a Child Name. This methos is called from MakePath method. + /// This Method helps in getting the correct case of particular element in the provider path. + /// XML is case senstive but Powershell is not. + /// + /// + /// + protected override string GetChildName(string path) + { + + string result = String.Empty; + int separatorIndex = path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator); + string hostname = String.Empty; + if (separatorIndex == -1) + { + result = path; + hostname = path; + } + else + { + result = path.Substring(separatorIndex + 1); + hostname = GetHostName(path); + } + + return GetCorrectCaseOfName(result, hostname, path); + + } + + /// + /// This method is provided by the Provider infrastructure. This method is called in all actions done + /// by the provider to get the resolved path. Internally Resolve-Path is called. + /// Since Root is empty for WsMan Provider the default path generated by Makepath is not correct. + /// So we have made the tweaks in this method to return the correct resolved path. + /// + /// + /// + /// + protected override string MakePath(string parent, string child) + { + if (child.EndsWith(WSManStringLiterals.DefaultPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase)) + { + child = child.Remove(child.LastIndexOf(WSManStringLiterals.DefaultPathSeparator)); + } + + //For Listeners only ... should remove Listener from listener\listener but not from listener_[Hashcode] + if (parent.Equals(WSManStringLiterals.containerListener, StringComparison.OrdinalIgnoreCase) && child.StartsWith(parent, StringComparison.OrdinalIgnoreCase)) + { + if (!child.StartsWith(parent + "_", StringComparison.OrdinalIgnoreCase)) + { + child = child.Remove(0, parent.Length); + } + } + string path = string.Empty; + string ChildName = string.Empty; + string CorrectCaseChildName = string.Empty; + if (parent.Length != 0) + { + path = parent + WSManStringLiterals.DefaultPathSeparator + child; + } + else + { + path = child; + } + if (path.Length != 0) + { + ChildName = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1); + CorrectCaseChildName = GetChildName(path); + } + if (ChildName.Equals(CorrectCaseChildName, StringComparison.OrdinalIgnoreCase)) + { + if (child.Contains(WSManStringLiterals.DefaultPathSeparator.ToString())) + { + child = child.Substring(0, child.LastIndexOf(WSManStringLiterals.DefaultPathSeparator)); + child = child + WSManStringLiterals.DefaultPathSeparator + CorrectCaseChildName; + } + else + { + child = CorrectCaseChildName; + } + } + String basepath = base.MakePath(parent, child); + return GetCorrectCaseOfPath(basepath); + } + + /// + /// Checks whether the path is Valid. + /// eg. winrm/config/client + /// + /// + /// + protected override bool IsValidPath(string path) + { + bool result = false; + result = CheckValidContainerOrPath(path); + return result; + + } + + /// + /// Check whether an Item Exist in the winrm configuration + /// + /// + /// + protected override bool ItemExists(string path) + { + bool result = false; + result = CheckValidContainerOrPath(path); + return result; + } + + /// + /// Checks whether the given path has got child items. + /// e.g: This is called by Provider infrastructure when we do a Remove-Item and prompts user + /// if child items are present. + /// + /// + /// + protected override bool HasChildItems(string path) + { + string childname = String.Empty; + string strPathCheck = String.Empty; + + if (path.Length == 0 && String.IsNullOrEmpty(childname)) + { + return true; + } + + //if endswith '\', removes it. + if (path.EndsWith(WSManStringLiterals.DefaultPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase)) + { + path = path.Remove(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator)); + } + + if (path.Contains(WSManStringLiterals.DefaultPathSeparator.ToString())) + { + //Get the ChildName + childname = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1); + } + Dictionary SessionObjCache = WSManHelper.GetSessionObjCache(); + if (SessionObjCache.ContainsKey(path)) + { + return true; + } + + //Get the wsman host name to find the session object + string host = GetHostName(path); + + //Chks the WinRM Service + if (IsPathLocalMachine(host)) + { + if (!IsWSManServiceRunning()) + { + WSManHelper.ThrowIfNotAdministrator(); + StartWSManService(Force); + } + } + string WsManURI = NormalizePath(path, host); + + lock(WSManHelper.AutoSession) + { + //Gets the session object from the cache. + object sessionobj; + SessionObjCache.TryGetValue(host, out sessionobj); + + + + /* + WsMan Config Can be divided in to Four Fixed Regions to Check Whether it has Child Items. + + * 1. Branch in to Listerners (winrm/config/listener) + * 2. Branch in to CertMapping (winrm/config/service/certmapping) + * 3. Branch in to Plugin (winrm/config/plugin) - Plugin is subdivided in Resources,Security & InitParams + * 4. Rest all the branches like Client, Shell(WinRS) ,Service + + */ + + // 1. Listener Checks + strPathCheck = host + WSManStringLiterals.DefaultPathSeparator; + if (WsManURI.Contains(WSManStringLiterals.containerListener)) + { + XmlDocument xmlListeners = EnumerateResourceValue(sessionobj, WsManURI); + if (xmlListeners != null) + { + Hashtable KeyCache, ListenerObjCache; + ProcessListernerObjects(xmlListeners, out ListenerObjCache, out KeyCache); + if (ListenerObjCache.Count > 0) + { + return true; + } + } + } + // 2. Client Certificate Checks + else if (WsManURI.Contains(WSManStringLiterals.containerCertMapping)) + { + XmlDocument xmlCertificates = EnumerateResourceValue(sessionobj, WsManURI); + Hashtable KeyCache, CertificatesObjCache; + if (xmlCertificates == null) + { + return true; + } + ProcessCertMappingObjects(xmlCertificates, out CertificatesObjCache, out KeyCache); + if (CertificatesObjCache.Count > 0) + { + return true; + } + } + // 3. Plugin and its internal structure Checks + else if (WsManURI.Contains(WSManStringLiterals.containerPlugin)) + { + + strPathCheck = strPathCheck + WSManStringLiterals.containerPlugin; + //Check for Plugin path + XmlDocument xmlPlugins = FindResourceValue(sessionobj, WsManURI, null); + string currentpluginname = string.Empty; + int PluginCount = GetPluginNames(xmlPlugins, out objPluginNames, out currentpluginname, path); + if (path.Equals(strPathCheck)) + { + if (PluginCount > 0) + { + return true; + } + else + { + return false; + } + + } + strPathCheck = strPathCheck + WSManStringLiterals.DefaultPathSeparator + currentpluginname; + if (path.EndsWith(strPathCheck, StringComparison.OrdinalIgnoreCase)) + { + if (objPluginNames != null) + { + if (objPluginNames.Properties.Match(currentpluginname).Count > 0) + { + return true; + } + else + { + return false; + } + } + } + string filter = WsManURI + "?Name=" + currentpluginname; + XmlDocument CurrentPluginXML = GetResourceValue(sessionobj, filter, null); + ArrayList arrSecurities = null; + ArrayList arrResources = ProcessPluginResourceLevel(CurrentPluginXML, out arrSecurities); + ArrayList arrInitParams = ProcessPluginInitParamLevel(CurrentPluginXML); + strPathCheck = strPathCheck + WSManStringLiterals.DefaultPathSeparator; + if (path.EndsWith(strPathCheck + WSManStringLiterals.containerResources, StringComparison.OrdinalIgnoreCase)) + { + if (null != arrResources && arrResources.Count > 0) + { + return true; + } + } + if (path.EndsWith(strPathCheck + WSManStringLiterals.containerInitParameters, StringComparison.OrdinalIgnoreCase)) + { + if (arrInitParams != null && arrInitParams.Count > 0) + { + return true; + } + } + if (path.EndsWith(strPathCheck + WSManStringLiterals.containerQuotasParameters, StringComparison.OrdinalIgnoreCase)) + { + XmlNodeList nodeListForQuotas = CurrentPluginXML.GetElementsByTagName(WSManStringLiterals.containerQuotasParameters); + if (nodeListForQuotas.Count > 0) + { + XmlNode pluginQuotas = nodeListForQuotas[0]; + return pluginQuotas.Attributes.Count > 0; + } + + return false; + } + if (arrResources != null) + { + foreach (PSObject objresource in arrResources) + { + string sResourceDirName = objresource.Properties["ResourceDir"].Value.ToString(); + if (path.Contains(sResourceDirName)) + { + strPathCheck = strPathCheck + WSManStringLiterals.containerResources + WSManStringLiterals.DefaultPathSeparator; + if (path.EndsWith(strPathCheck + sResourceDirName, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + strPathCheck = strPathCheck + sResourceDirName + WSManStringLiterals.DefaultPathSeparator; + if (path.Contains(strPathCheck + WSManStringLiterals.containerSecurity)) + { + if (path.EndsWith(strPathCheck + WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase)) + { + if (null != arrSecurities && arrSecurities.Count > 0) + { + return true; + } + } + strPathCheck = strPathCheck + WSManStringLiterals.containerSecurity + WSManStringLiterals.DefaultPathSeparator; + if (path.Contains(strPathCheck + WSManStringLiterals.containerSecurity + "_")) + { + if (null == arrSecurities) + { + return false; + } + foreach (PSObject security in arrSecurities) + { + string sSecurity = security.Properties["SecurityDIR"].Value.ToString(); + if (path.EndsWith(sSecurity, StringComparison.OrdinalIgnoreCase)) + return true; + + } + } + } + } + } + } + } + else + // 4. All Other Item Checks + { + string getXml = this.GetResourceValueInXml(sessionobj, WsManURI, null); + XmlDocument xmlResourceValues = new XmlDocument(); + xmlResourceValues.LoadXml(getXml.ToLowerInvariant()); + XmlNodeList nodes = SearchXml(xmlResourceValues, childname, WsManURI, path, host); + if (nodes != null) + { + return IsItemContainer(nodes); + } + } + return false; + } + } + + /// + /// This cmdlet is used to get a particular item. + /// cd wsman:\localhost\client> Get-Item .\Auth + /// + /// + [SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode")] + protected override void GetItem(string path) + { + + string childname = string.Empty; + + if (path.Length == 0 && String.IsNullOrEmpty(childname)) + { + WriteItemObject(GetItemPSObjectWithTypeName(WSManStringLiterals.rootpath, WSManStringLiterals.ContainerChildValue, null, null, null, WsManElementObjectTypes.WSManConfigElement), WSManStringLiterals.rootpath, true); + return; + } + + + if (path.Contains(WSManStringLiterals.DefaultPathSeparator.ToString())) + { + //Get the ChildName + childname = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1); + } + else + { + childname = path; + } + + Dictionary SessionObjCache = WSManHelper.GetSessionObjCache(); + if (childname.Equals(path, StringComparison.OrdinalIgnoreCase)) + { + if (SessionObjCache.ContainsKey(childname)) + { + WriteItemObject(GetItemPSObjectWithTypeName(childname, WSManStringLiterals.ContainerChildValue, null, null, "ComputerLevel", WsManElementObjectTypes.WSManConfigContainerElement), WSManStringLiterals.rootpath + WSManStringLiterals.DefaultPathSeparator + childname, true); + } + return; + } + + path = path.Substring(0, path.LastIndexOf(childname, StringComparison.OrdinalIgnoreCase)); + + //Get the wsman host name to find the session object + string host = GetHostName(path); + string uri = NormalizePath(path, host); + + lock(WSManHelper.AutoSession) + { + //Gets the session object from the cache. + object sessionobj; + SessionObjCache.TryGetValue(host, out sessionobj); + + XmlDocument xmlResource = FindResourceValue(sessionobj, uri, null); + if (xmlResource == null) { return; } + + //if endswith '\', removes it. + if (path.EndsWith(WSManStringLiterals.DefaultPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase)) + { + path = path.Remove(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator)); + } + + string strPathChk = host + WSManStringLiterals.DefaultPathSeparator; + + if (path.Contains(strPathChk + WSManStringLiterals.containerListener)) + { + GetItemListenerOrCertMapping(path, xmlResource, WSManStringLiterals.containerListener, childname, host); + } + else if (path.Contains(strPathChk + WSManStringLiterals.containerClientCertificate)) + { + GetItemListenerOrCertMapping(path, xmlResource, WSManStringLiterals.containerClientCertificate, childname, host); + } + else if (path.Contains(strPathChk + WSManStringLiterals.containerPlugin)) + { + string currentpluginname = string.Empty; + GetPluginNames(xmlResource, out objPluginNames, out currentpluginname, path); + + if (path.EndsWith(strPathChk + WSManStringLiterals.containerPlugin, StringComparison.OrdinalIgnoreCase)) + { + try + { + WriteItemObject(GetItemPSObjectWithTypeName(objPluginNames.Properties[childname].Name, objPluginNames.Properties[childname].Value.ToString(), null, new string[] { "Name=" + objPluginNames.Properties[childname].Name }, null, WsManElementObjectTypes.WSManConfigContainerElement), path + WSManStringLiterals.DefaultPathSeparator + childname, true); + } + catch (PSArgumentNullException) { return; } + catch (NullReferenceException) { return; } + } + else + { + strPathChk = strPathChk + WSManStringLiterals.containerPlugin + WSManStringLiterals.DefaultPathSeparator; + string filter = uri + "?Name=" + currentpluginname; + XmlDocument CurrentPluginXML = GetResourceValue(sessionobj, filter, null); + if (null == CurrentPluginXML) + { + return; + } + PSObject objPluginlevel = ProcessPluginConfigurationLevel(CurrentPluginXML, true); + ArrayList arrSecurity = null; + ArrayList arrResources = ProcessPluginResourceLevel(CurrentPluginXML, out arrSecurity); + ArrayList arrInitParams = ProcessPluginInitParamLevel(CurrentPluginXML); + try + { + if (path.Contains(strPathChk + currentpluginname)) + { + if (path.EndsWith(strPathChk + currentpluginname, StringComparison.OrdinalIgnoreCase)) + { + if (!objPluginlevel.Properties[childname].Value.ToString().Equals(WSManStringLiterals.ContainerChildValue)) + { + WriteItemObject(GetItemPSObjectWithTypeName(objPluginlevel.Properties[childname].Name, objPluginlevel.Properties[childname].TypeNameOfValue, objPluginlevel.Properties[childname].Value, null, null, WsManElementObjectTypes.WSManConfigLeafElement), path + WSManStringLiterals.DefaultPathSeparator + objPluginlevel.Properties[childname].Name, false); + } + else + { + WriteItemObject(GetItemPSObjectWithTypeName(objPluginlevel.Properties[childname].Name, objPluginlevel.Properties[childname].Value.ToString(), null, null, null, WsManElementObjectTypes.WSManConfigLeafElement), path + WSManStringLiterals.DefaultPathSeparator + objPluginlevel.Properties[childname].Name, true); + } + } + strPathChk = strPathChk + currentpluginname + WSManStringLiterals.DefaultPathSeparator; + if (path.Contains(strPathChk + WSManStringLiterals.containerResources)) + { + if (null == arrResources) + { + return; + } + if (path.EndsWith(strPathChk + WSManStringLiterals.containerResources, StringComparison.OrdinalIgnoreCase)) + { + foreach (PSObject p in arrResources) + { + if (p.Properties["ResourceDir"].Value.ToString().Equals(childname)) + { + WriteItemObject(GetItemPSObjectWithTypeName(childname, WSManStringLiterals.ContainerChildValue, null, new string[] { "ResourceURI=" + p.Properties["ResourceUri"].Value.ToString() }, null, WsManElementObjectTypes.WSManConfigContainerElement), path + WSManStringLiterals.DefaultPathSeparator + childname, true); + } + } + return; + } + strPathChk = strPathChk + WSManStringLiterals.containerResources + WSManStringLiterals.DefaultPathSeparator; + int Sepindex = path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathChk.Length); + string sResourceDirName = string.Empty; + if (Sepindex == -1) + { + sResourceDirName = path.Substring(strPathChk.Length); + } + else + { + sResourceDirName = path.Substring(strPathChk.Length, path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathChk.Length) - (strPathChk.Length)); + } + if (path.Contains(strPathChk + sResourceDirName)) + { + if (path.EndsWith(strPathChk + sResourceDirName, StringComparison.OrdinalIgnoreCase)) + { + foreach (PSObject p in arrResources) + { + if (sResourceDirName.Equals(p.Properties["ResourceDir"].Value.ToString(), StringComparison.OrdinalIgnoreCase)) + { + p.Properties.Remove("ResourceDir"); + if (p.Properties[childname].Value.ToString().Equals(WSManStringLiterals.ContainerChildValue)) + { + WriteItemObject(GetItemPSObjectWithTypeName(p.Properties[childname].Name, p.Properties[childname].Value.ToString(), null, null, null, WsManElementObjectTypes.WSManConfigLeafElement), path + WSManStringLiterals.DefaultPathSeparator + p.Properties[childname].Name, true); + } + else + { + WriteItemObject(GetItemPSObjectWithTypeName(p.Properties[childname].Name, p.Properties[childname].TypeNameOfValue, p.Properties[childname].Value, null, null, WsManElementObjectTypes.WSManConfigLeafElement), path + WSManStringLiterals.DefaultPathSeparator + p.Properties[childname].Name, false); + } + break; + } + } + return; + } + strPathChk = strPathChk + sResourceDirName + WSManStringLiterals.DefaultPathSeparator; + if (path.Contains(strPathChk + WSManStringLiterals.containerSecurity)) + { + if (null == arrSecurity) + { + return; + } + foreach (PSObject p in arrSecurity) + { + if (path.EndsWith(WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase)) + { + WriteItemObject(GetItemPSObjectWithTypeName(p.Properties["SecurityDIR"].Value.ToString(), WSManStringLiterals.ContainerChildValue, null, new string[] { "Uri=" + p.Properties["Uri"].Value.ToString() }, null, WsManElementObjectTypes.WSManConfigContainerElement), path + WSManStringLiterals.DefaultPathSeparator + p.Properties["SecurityDIR"].Value.ToString(), true); + } + else + { + string sSecurityDirName = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1, path.Length - (path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1)); + if (sSecurityDirName.Equals(p.Properties["SecurityDIR"].Value.ToString())) + { + p.Properties.Remove("SecurityDIR"); + WriteItemObject(GetItemPSObjectWithTypeName(p.Properties[childname].Name, p.Properties[childname].TypeNameOfValue, p.Properties[childname].Value, null, null, WsManElementObjectTypes.WSManConfigLeafElement), path + WSManStringLiterals.DefaultPathSeparator + p.Properties[childname].Name, false); + break; + } + } + } + return; + } + } + } + else if (path.EndsWith(host + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerPlugin + WSManStringLiterals.DefaultPathSeparator + currentpluginname + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerInitParameters, StringComparison.OrdinalIgnoreCase)) + { + if (null != arrInitParams) + { + foreach (PSObject p in arrInitParams) + { + if (p.Properties.Match(childname, PSMemberTypes.NoteProperty).Count > 0) + WriteItemObject(GetItemPSObjectWithTypeName(p.Properties[childname].Name, p.Properties[childname].TypeNameOfValue, p.Properties[childname].Value, null, "InitParams", WsManElementObjectTypes.WSManConfigLeafElement), path + WSManStringLiterals.DefaultPathSeparator + p.Properties[childname].Name, false); + } + } + } + else if (path.EndsWith(WSManStringLiterals.containerQuotasParameters, StringComparison.OrdinalIgnoreCase)) + { + // Get the Quotas element from the config XML. + XmlNodeList nodeListForQuotas = CurrentPluginXML.GetElementsByTagName(WSManStringLiterals.containerQuotasParameters); + if (nodeListForQuotas.Count > 0) + { + XmlNode pluginQuotas = nodeListForQuotas[0]; + foreach (XmlAttribute attrOfQuotas in pluginQuotas.Attributes) + { + if (childname.Equals(attrOfQuotas.Name, StringComparison.OrdinalIgnoreCase)) + { + PSObject objectToAdd = + GetItemPSObjectWithTypeName( + attrOfQuotas.Name, + attrOfQuotas.Value.GetType().ToString(), + attrOfQuotas.Value, + null, + null, + WsManElementObjectTypes.WSManConfigLeafElement); + + String pathToAdd = + String.Format( + CultureInfo.InvariantCulture, + "{0}{1}{2}", + path, + WSManStringLiterals.DefaultPathSeparator, + attrOfQuotas.Name); + + WriteItemObject(objectToAdd, pathToAdd, false); + break; + } + } + } + } + } + } + catch (PSArgumentNullException) { return; } + catch (NullReferenceException) { return; } + } + } + else + { + try + { + PSObject mshObject = null; + if (!uri.Equals(WinrmRootName[0].ToString(), StringComparison.OrdinalIgnoreCase)) + { + foreach (XmlNode innerResourceNodes in xmlResource.ChildNodes) + { + mshObject = ConvertToPSObject(innerResourceNodes); + } + } + else + { + mshObject = BuildHostLevelPSObjectArrayList(sessionobj, uri, false); + } + if (mshObject != null) + { + if (mshObject.Properties[childname].Value.ToString().Equals(WSManStringLiterals.ContainerChildValue)) + { + WriteItemObject(GetItemPSObjectWithTypeName(mshObject.Properties[childname].Name, mshObject.Properties[childname].Value.ToString(), null, null, null, WsManElementObjectTypes.WSManConfigLeafElement), path + WSManStringLiterals.DefaultPathSeparator + mshObject.Properties[childname].Name, true); + } + else + { + WriteItemObject( + GetItemPSObjectWithTypeName( + mshObject.Properties[childname].Name, + mshObject.Properties[childname].TypeNameOfValue, + mshObject.Properties[childname].Value, + null, null, + WsManElementObjectTypes.WSManConfigLeafElement, + mshObject), + path + WSManStringLiterals.DefaultPathSeparator + mshObject.Properties[childname].Name, + false); + } + } + } + catch (PSArgumentNullException) { return;/*Leaving this known exception for no value found. Not Throwing error.*/} + catch (NullReferenceException) { return; /*Leaving this known exception for no value found. Not Throwing error.*/} + } + } + } + + /// + /// This cmdlet is used to set the value of a particular item. + /// cd wsman:\localhost\client> Set-Item .\TrustedHosts -value "*" + /// This has one dynamic parameter. It is used with TrustedHost only. + /// The parameter is -Concatenate. + /// + /// + /// + [SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode")] + protected override void SetItem(string path, object value) + { + + if (null == value) + { + throw new ArgumentException(helper.GetResourceMsgFromResourcetext("value")); + } + + string ChildName = string.Empty; + + if (path.Length == 0 && String.IsNullOrEmpty(ChildName)) + { + AssertError(helper.GetResourceMsgFromResourcetext("SetItemNotSupported"), false); + return; + } + + + if (path.Contains(WSManStringLiterals.DefaultPathSeparator.ToString())) + { + //Get the ChildName + ChildName = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1); + } + else + { + ChildName = path; + } + + if (ChildName.Equals(path, StringComparison.OrdinalIgnoreCase)) + { + AssertError(helper.GetResourceMsgFromResourcetext("SetItemNotSupported"), false); + return; + } + + if (!this.clearItemIsCalled) + { + value = this.ValidateAndGetUserObject(ChildName, value); + + // The value will be Null only if the object provided by User is not of accepted type. + // As of now, this can only happen in case of RunAsUserName and RunAsPassword + if (value == null) + { + return; + } + } + else + { + // If validation is not required, that means Clear-Item cmdlet is called. + // Clear-Item is not allowed on RunAsPassword, Admin should call Clear-Item RunAsUser + // if he intends to disable RunAs on the Plugin. + if(String.Equals(ChildName, WSManStringLiterals.ConfigRunAsPasswordName, StringComparison.OrdinalIgnoreCase)) + { + AssertError(helper.GetResourceMsgFromResourcetext("ClearItemOnRunAsPassword"), false); + return; + } + } + + string whatIfMessage = String.Format(CultureInfo.CurrentUICulture, helper.GetResourceMsgFromResourcetext("SetItemWhatIfAndConfirmText"), path, value); + if (!ShouldProcess(whatIfMessage, "", "")) + { + return; + } + + path = path.Substring(0, path.LastIndexOf(ChildName, StringComparison.OrdinalIgnoreCase)); + + //Get the wsman host name to find the session object + string host = GetHostName(path); + string uri = NormalizePath(path, host); + + //Chk for Winrm Service + if (IsPathLocalMachine(host)) + { + if (!IsWSManServiceRunning()) + { + WSManHelper.ThrowIfNotAdministrator(); + StartWSManService(this.Force); + } + } + + bool settingPickedUpDynamically = false; + + lock(WSManHelper.AutoSession) + { + //Gets the session object from the cache. + object sessionobj; + Dictionary SessionObjCache = WSManHelper.GetSessionObjCache(); + SessionObjCache.TryGetValue(host, out sessionobj); + + List warningMessage = new List(); + + //if endswith '\', removes it. + if (path.EndsWith(WSManStringLiterals.DefaultPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase)) + { + path = path.Remove(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator)); + } + string strPathChk = host + WSManStringLiterals.DefaultPathSeparator; + if (path.Contains(strPathChk + WSManStringLiterals.containerListener)) + { + SetItemListenerOrClientCertificate(sessionobj, uri, PKeyListener, ChildName, value, path, WSManStringLiterals.containerListener, host); + } + else if (path.Contains(strPathChk + WSManStringLiterals.containerClientCertificate)) + { + SetItemListenerOrClientCertificate(sessionobj, uri, PKeyCertMapping, ChildName, value, path, WSManStringLiterals.containerClientCertificate, host); + } + else if (path.Contains(strPathChk + WSManStringLiterals.containerPlugin)) + { + if (path.EndsWith(strPathChk + WSManStringLiterals.containerPlugin, StringComparison.OrdinalIgnoreCase)) + { + AssertError(helper.GetResourceMsgFromResourcetext("SetItemNotSupported"), false); + } + try + { + XmlDocument xmlPlugins = FindResourceValue(sessionobj, uri, null); + string currentpluginname = string.Empty; + GetPluginNames(xmlPlugins, out objPluginNames, out currentpluginname, path); + if (String.IsNullOrEmpty(currentpluginname)) + { + if (!this.clearItemIsCalled) + { + // Don't need an error if ClearItem is called. + AssertError(helper.GetResourceMsgFromResourcetext("ItemDoesNotExist"), false); + } + return; + } + string filter = uri + "?Name=" + currentpluginname; + + CurrentConfigurations pluginConfiguration = new CurrentConfigurations((IWSManSession)sessionobj); + + string pluginXML = this.GetResourceValueInXml((IWSManSession)sessionobj, filter, null); + pluginConfiguration.RefreshCurrentConfiguration(pluginXML); + + XmlDocument CurrentPluginXML = pluginConfiguration.RootDocument; + + ArrayList arrSecurity = null; + ArrayList arrResources = ProcessPluginResourceLevel(CurrentPluginXML, out arrSecurity); + ArrayList arrInitParams = ProcessPluginInitParamLevel(CurrentPluginXML); + + try + { + // Remove XML:LANG attribute if present. + // If not present ignore the exception. + pluginConfiguration.RemoveOneConfiguration("./attribute::xml:lang"); + } + catch (ArgumentException) + { } + + strPathChk = strPathChk + WSManStringLiterals.containerPlugin + WSManStringLiterals.DefaultPathSeparator; + if (path.EndsWith(strPathChk + currentpluginname, StringComparison.OrdinalIgnoreCase)) + { + if (WSManStringLiterals.ConfigRunAsUserName.Equals(ChildName, StringComparison.OrdinalIgnoreCase)) + { + PSCredential runAsCredentials = value as PSCredential; + + if (runAsCredentials != null) + { + // UserName + value = runAsCredentials.UserName; + + pluginConfiguration.UpdateOneConfiguration( + ".", + WSManStringLiterals.ConfigRunAsPasswordName, + this.GetStringFromSecureString(runAsCredentials.Password)); + } + } + + if (WSManStringLiterals.ConfigRunAsPasswordName.Equals(ChildName, StringComparison.OrdinalIgnoreCase)) + { + if(String.IsNullOrEmpty( + pluginConfiguration.GetOneConfiguration( + String.Format( + CultureInfo.InvariantCulture, + "./attribute::{0}", + WSManStringLiterals.ConfigRunAsUserName)))) + { + // User Cannot set RunAsPassword if, RunAsUser is not present. + AssertError(helper.GetResourceMsgFromResourcetext("SetItemOnRunAsPasswordNoRunAsUser"), false); + } + + value = this.GetStringFromSecureString(value); + } + + pluginConfiguration.UpdateOneConfiguration(".", ChildName, value.ToString()); + } + strPathChk = strPathChk + currentpluginname + WSManStringLiterals.DefaultPathSeparator; + if (path.Contains(strPathChk + WSManStringLiterals.containerResources)) + { + if (path.EndsWith(strPathChk + WSManStringLiterals.containerResources, StringComparison.OrdinalIgnoreCase)) + { + AssertError(helper.GetResourceMsgFromResourcetext("SetItemNotSupported"), false); + return; + + } + strPathChk = strPathChk + WSManStringLiterals.containerResources + WSManStringLiterals.DefaultPathSeparator; + int Sepindex = path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathChk.Length); + string sResourceDirName = string.Empty; + if (Sepindex == -1) + { + sResourceDirName = path.Substring(strPathChk.Length); + } + else + { + sResourceDirName = path.Substring(strPathChk.Length, path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathChk.Length) - (strPathChk.Length)); + } + if (path.Contains(strPathChk + sResourceDirName)) + { + if (path.EndsWith(strPathChk + sResourceDirName, StringComparison.OrdinalIgnoreCase)) + { + if (null == arrResources) + { + return; + } + + if (ChildName.Equals(WSManStringLiterals.ConfigResourceUriName, StringComparison.OrdinalIgnoreCase)) + { + AssertError(helper.GetResourceMsgFromResourcetext("NoChangeValue"), false); + return; + } + + foreach (PSObject p in arrResources) + { + if (sResourceDirName.Equals(p.Properties["ResourceDir"].Value.ToString(), StringComparison.OrdinalIgnoreCase)) + { + string xpathToUse = String.Format( + CultureInfo.InvariantCulture, + "{0}:{1}/{0}:{2}[attribute::{3}='{4}']", + CurrentConfigurations.DefaultNameSpacePrefix, + WSManStringLiterals.containerResources, + WSManStringLiterals.containerSingleResource, + WSManStringLiterals.ConfigResourceUriName, + p.Properties[WSManStringLiterals.ConfigResourceUriName].Value.ToString()); + + if (!p.Properties[ChildName].Value.ToString().Equals(WSManStringLiterals.ContainerChildValue)) + { + // Allow Set-Item on non-container values only. + pluginConfiguration.UpdateOneConfiguration(xpathToUse, ChildName, value.ToString()); + } + else + { + AssertError(helper.GetResourceMsgFromResourcetext("NoChangeValue"), false); + } + } + } + } + strPathChk = strPathChk + sResourceDirName + WSManStringLiterals.DefaultPathSeparator; + if (path.Contains(strPathChk + WSManStringLiterals.containerSecurity)) + { + if (path.EndsWith(strPathChk + WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase)) + { + AssertError(helper.GetResourceMsgFromResourcetext("NoChangeValue"), false); + return; + } + + if (null == arrSecurity) + { + return; + } + + if (path.Contains(strPathChk + WSManStringLiterals.containerSecurity + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerSecurity + "_")) + { + // Any setting inside security for plugin is picked up by service dynamically + settingPickedUpDynamically = true; + + foreach (PSObject p in arrSecurity) + { + string sSecurityDirName = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1, path.Length - (path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1)); + if (sSecurityDirName.Equals(p.Properties["SecurityDIR"].Value.ToString(), StringComparison.OrdinalIgnoreCase)) + { + if (!Force) + { + string query = helper.GetResourceMsgFromResourcetext("ShouldContinueSecurityQuery"); + query = String.Format(CultureInfo.CurrentCulture, query, currentpluginname); + if (!ShouldContinue(query, helper.GetResourceMsgFromResourcetext("ShouldContinueSecurityCaption"))) + { + return; + } + } + + //NameSpace:Resources/NameSpace:Resource[@ResourceUri={''}]/NameSpace:Security[@Uri='{2}'] + string xpathToUse = String.Format( + CultureInfo.InvariantCulture, + "{0}:{1}/{0}:{2}[@{6}='{7}']/{0}:{3}[@{4}='{5}']", + CurrentConfigurations.DefaultNameSpacePrefix, + WSManStringLiterals.containerResources, + WSManStringLiterals.containerSingleResource, + WSManStringLiterals.containerSecurity, + WSManStringLiterals.ConfigSecurityUri, + p.Properties[WSManStringLiterals.ConfigSecurityUri].Value.ToString(), + WSManStringLiterals.ConfigResourceUriName, + p.Properties["ParentResourceUri"].Value.ToString()); + + pluginConfiguration.UpdateOneConfiguration(xpathToUse, ChildName, value.ToString()); + } + } + } + } + } + } + else if (path.EndsWith(strPathChk + WSManStringLiterals.containerInitParameters, StringComparison.OrdinalIgnoreCase)) + { + foreach (PSObject p in arrInitParams) + { + if (p.Properties[ChildName] != null) + { + string xpathToUse = String.Format( + CultureInfo.InvariantCulture, + "{0}:{1}/{0}:{2}[@{3}='{4}']", + CurrentConfigurations.DefaultNameSpacePrefix, + WSManStringLiterals.containerInitParameters, + WSManStringLiterals.ConfigInitializeParameterTag, + WSManStringLiterals.ConfigInitializeParameterName, + p.Properties[ChildName].Name); + + pluginConfiguration.UpdateOneConfiguration(xpathToUse, WSManStringLiterals.ConfigInitializeParameterValue, value.ToString()); + + break; + } + } + } + else if (path.EndsWith(strPathChk + WSManStringLiterals.containerQuotasParameters, StringComparison.OrdinalIgnoreCase)) + { + string xpathToUse = String.Format( + CultureInfo.InvariantCulture, + "{0}:{1}", + CurrentConfigurations.DefaultNameSpacePrefix, + WSManStringLiterals.containerQuotasParameters); + + pluginConfiguration.UpdateOneConfiguration(xpathToUse, ChildName, value.ToString()); + + if (ppqWarningConfigurations.Contains(ChildName.ToLowerInvariant())) + { + string adjustedChileName = ChildName; + + if (ChildName.Equals("IdleTimeoutms", StringComparison.OrdinalIgnoreCase)) + { + adjustedChileName = "IdleTimeout"; + } + + string pathForGlobalQuota = + String.Format( + CultureInfo.InvariantCulture, + @"{0}:\{1}\{2}\{3}", + WSManStringLiterals.rootpath, + host, + WSManStringLiterals.containerShell, + adjustedChileName); + + warningMessage.Add(String.Format(helper.GetResourceMsgFromResourcetext("SetItemWarnigForPPQ"), pathForGlobalQuota)); + } + } + + SessionObjCache.TryGetValue(host, out sessionobj); + string resourceUri = String.Format( + CultureInfo.InvariantCulture, + "{0}?Name={1}", + uri, + currentpluginname); + + try + { + pluginConfiguration.PutConfiguraitonOnServer(resourceUri); + + // Show Win RM service restart warning only when the changed setting is not picked up dynamically + if (settingPickedUpDynamically == false) + { + if (IsPathLocalMachine(host)) + { + warningMessage.Add(helper.GetResourceMsgFromResourcetext("SetItemServiceRestartWarning")); + } + else + { + warningMessage.Add(String.Format(helper.GetResourceMsgFromResourcetext("SetItemServiceRestartWarningRemote"), host)); + } + } + } + finally + { + if (!String.IsNullOrEmpty(pluginConfiguration.ServerSession.Error)) + { + AssertError(pluginConfiguration.ServerSession.Error, true); + } + } + } + catch (PSArgumentException) + { + AssertError(helper.GetResourceMsgFromResourcetext("ItemDoesNotExist"), false); + return; + } + catch (PSArgumentNullException) + { + AssertError(helper.GetResourceMsgFromResourcetext("ItemDoesNotExist"), false); + return; + } + catch (NullReferenceException) + { + AssertError(helper.GetResourceMsgFromResourcetext("ItemDoesNotExist"), false); + return; + } + } + else + { + try + { + Hashtable cmdlinevalue = new Hashtable(); + if (ChildName.Equals("TrustedHosts", StringComparison.OrdinalIgnoreCase) || ChildName.Equals("RootSDDL", StringComparison.OrdinalIgnoreCase)) + { + if (value.GetType().FullName.Equals("System.String")) + { + if (!Force) + { + string query=""; + string caption = helper.GetResourceMsgFromResourcetext("SetItemGeneralSecurityCaption"); + if (ChildName.Equals("TrustedHosts", StringComparison.OrdinalIgnoreCase)) + { + query = helper.GetResourceMsgFromResourcetext("SetItemTrustedHostsWarningQuery"); + } + else if (ChildName.Equals("RootSDDL", StringComparison.OrdinalIgnoreCase)) + { + query = helper.GetResourceMsgFromResourcetext("SetItemRootSDDLWarningQuery"); + } + if (!ShouldContinue(query, caption)) + { + return; + } + } + WSManProviderSetItemDynamicParameters dynParams = DynamicParameters as WSManProviderSetItemDynamicParameters; + if (dynParams != null) + { + if (dynParams.Concatenate) + { + if (!String.IsNullOrEmpty(value.ToString())) + { + // ',' is used as the delimiter in WSMan for TrustedHosts. + value = SplitAndUpdateStringUsingDelimiter(sessionobj, uri, ChildName, value.ToString(), ","); + } + } + } + cmdlinevalue.Add(ChildName, value); + } + else + { + AssertError(helper.GetResourceMsgFromResourcetext("TrustedHostValueTypeError"), false); + } + } + else + { + cmdlinevalue.Add(ChildName, value); + + if (globalWarningUris.Contains(uri) && globalWarningConfigurations.Contains(ChildName.ToLowerInvariant())) + { + warningMessage.Add(String.Format(helper.GetResourceMsgFromResourcetext("SetItemWarningForGlobalQuota"), value)); + } + } + PutResourceValue(sessionobj, uri, cmdlinevalue, host); + } + catch (COMException e) + { + AssertError(e.Message, false); + return; + } + } + + foreach(String warnings in warningMessage) + { + WriteWarning(warnings); + } + } + } + + /// + /// This commad is used to clear the value of a item. + /// + /// + protected override void ClearItem(string path) + { + this.clearItemIsCalled = true; + SetItem(path, string.Empty); + this.clearItemIsCalled = false; + } + + /// + /// This is method which create the dynamic or runtime parameter for set-item + /// + /// + /// + /// + protected override object SetItemDynamicParameters(string path, object value) + { + if (path.Length != 0) + { + string hostname = GetHostName(path); + if (path.EndsWith(hostname + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerClient, StringComparison.OrdinalIgnoreCase)) + { + //To have Tab completion. + return new WSManProviderSetItemDynamicParameters(); + } + else if (path.EndsWith(hostname + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerClient + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerTrustedHosts, StringComparison.OrdinalIgnoreCase)) + { + //To Support Concatenate parameter for trustedhosts. + return new WSManProviderSetItemDynamicParameters(); + } + } + return null; + } + + + #endregion + + #region ContainerCmdletProvider + /// + /// Gets the Child items. dir functionality + /// wsman:\localhost\client> dir + /// + /// + /// + protected override void GetChildItems(string path, bool recurse) + { + + GetChildItemsOrNames(path, ProviderMethods.GetChildItems, recurse); + } + + /// + /// This method gives the names of child items. this is used for Tab compeletion. + /// + /// + /// + protected override void GetChildNames(string path, ReturnContainers returnContainers) + { + + GetChildItemsOrNames(path, ProviderMethods.GetChildNames, false); + } + #endregion + + #region NavigationalCmdletProvider + + /// + /// Checks whether the specified path is a container path + /// + /// + /// + protected override bool IsItemContainer(string path) + { + + string childname = String.Empty; + string strPathCheck = String.Empty; + + if (path.Length == 0 && String.IsNullOrEmpty(childname)) + { + return true; + } + + //if endswith '\', removes it. + if (path.EndsWith(WSManStringLiterals.DefaultPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase)) + { + path = path.Remove(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator)); + } + + if (path.Contains(WSManStringLiterals.DefaultPathSeparator.ToString())) + { + //Get the ChildName + childname = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1); + } + Dictionary SessionObjCache = WSManHelper.GetSessionObjCache(); + if (SessionObjCache.ContainsKey(path)) + { + return true; + } + + //Get the wsman host name to find the session object + string host = GetHostName(path); + string WsManURI = NormalizePath(path, host); + + lock(WSManHelper.AutoSession) + { + //Gets the session object from the cache. + object sessionobj; + SessionObjCache.TryGetValue(host, out sessionobj); + + + + /* + WsMan Config Can be divided in to Four Fixed Regions to Check Whether Item is Container + + * 1. Branch in to Listerners (winrm/config/listener) + * 2. Branch in to CertMapping (winrm/config/service/certmapping) + * 3. Branch in to Plugin (winrm/config/plugin) - Plugin is subdivided in Resources,Security & InitParams + * 4. Rest all the branches like Client, Shell(WinRS) ,Service + + */ + + // 1. Listener Checks + strPathCheck = host + WSManStringLiterals.DefaultPathSeparator; + if (WsManURI.Contains(WSManStringLiterals.containerListener)) + { + strPathCheck = strPathCheck + WSManStringLiterals.containerListener; + if (path.EndsWith(strPathCheck, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + XmlDocument xmlListeners = EnumerateResourceValue(sessionobj, WsManURI); + + if (xmlListeners != null) + { + Hashtable KeyCache, ListenerObjCache; + ProcessListernerObjects(xmlListeners, out ListenerObjCache, out KeyCache); + if (KeyCache.Contains(childname)) + { + return true; + } + } + } + // 2. Client Certificate Checks + else if (WsManURI.Contains(WSManStringLiterals.containerCertMapping)) + { + strPathCheck = strPathCheck + WSManStringLiterals.containerClientCertificate; + if (path.EndsWith(strPathCheck, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + XmlDocument xmlCertificates = EnumerateResourceValue(sessionobj, WsManURI); + if (xmlCertificates != null) + { + Hashtable KeyCache, CertificatesObjCache; + ProcessCertMappingObjects(xmlCertificates, out CertificatesObjCache, out KeyCache); + if (KeyCache.Contains(childname)) + { + return true; + } + } + } + // 3. Plugin and its internal structure Checks + else if (WsManURI.Contains(WSManStringLiterals.containerPlugin)) + { + + strPathCheck = strPathCheck + WSManStringLiterals.containerPlugin; + //Check for Plugin path + if (path.EndsWith(strPathCheck, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + strPathCheck = strPathCheck + WSManStringLiterals.DefaultPathSeparator; + XmlDocument xmlPlugins = FindResourceValue(sessionobj, WsManURI, null); + + + string currentpluginname = string.Empty; + GetPluginNames(xmlPlugins, out objPluginNames, out currentpluginname, path); + strPathCheck = strPathCheck + currentpluginname; + if (path.EndsWith(currentpluginname, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + string filter = WsManURI + "?Name=" + currentpluginname; + XmlDocument CurrentPluginXML = GetResourceValue(sessionobj, filter, null); + ArrayList arrSecurities = null; + ArrayList arrResources = ProcessPluginResourceLevel(CurrentPluginXML, out arrSecurities); + if (path.EndsWith(strPathCheck, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + strPathCheck = strPathCheck + WSManStringLiterals.DefaultPathSeparator; + if (path.EndsWith(strPathCheck + WSManStringLiterals.containerResources, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + if (path.EndsWith(strPathCheck + WSManStringLiterals.containerInitParameters, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + if (path.EndsWith(strPathCheck + WSManStringLiterals.containerQuotasParameters, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + if (null == arrResources || arrResources.Count == 0) + { + return false; + } + foreach (PSObject objresource in arrResources) + { + string sResourceDirName = objresource.Properties["ResourceDir"].Value.ToString(); + if (path.Contains(sResourceDirName)) + { + strPathCheck = strPathCheck + WSManStringLiterals.containerResources + WSManStringLiterals.DefaultPathSeparator; + if (path.EndsWith(strPathCheck + sResourceDirName, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + strPathCheck = strPathCheck + sResourceDirName + WSManStringLiterals.DefaultPathSeparator; + if (path.Contains(strPathCheck + WSManStringLiterals.containerSecurity)) + { + if (path.EndsWith(strPathCheck + WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + strPathCheck = strPathCheck + WSManStringLiterals.containerSecurity + WSManStringLiterals.DefaultPathSeparator; + if (path.Contains(strPathCheck + WSManStringLiterals.containerSecurity + "_")) + { + if (null == arrSecurities) + { + return false; + } + foreach (PSObject security in arrSecurities) + { + string sSecurity = security.Properties["SecurityDIR"].Value.ToString(); + if (path.EndsWith(sSecurity, StringComparison.OrdinalIgnoreCase)) + return true; + + } + } + } + } + } + } + else + // 4. All Other Item Checks + { + string getXml = this.GetResourceValueInXml(sessionobj, WsManURI, null); + XmlDocument xmlResourceValues = new XmlDocument(); + xmlResourceValues.LoadXml(getXml.ToLowerInvariant()); + XmlNodeList nodes = SearchXml(xmlResourceValues, childname, WsManURI, path, host); + bool result = IsItemContainer(nodes); + return result; + } + return false; + } + } + + /// + /// Removes a particular item. + /// + /// + /// + protected override void RemoveItem(string path, bool recurse) + { + bool throwerror = true; + if (path.Length == 0) + { + AssertError(helper.GetResourceMsgFromResourcetext("RemoveItemNotSupported"), false); + return; + } + String ChildName = String.Empty; + + if (path.Contains(WSManStringLiterals.DefaultPathSeparator.ToString())) + { + //Get the ChildName + ChildName = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1); + } + else + { + ChildName = path; + } + + if (ChildName.Equals(path, StringComparison.OrdinalIgnoreCase)) + { + if (ChildName.Equals("localhost", StringComparison.OrdinalIgnoreCase)) + { + AssertError(helper.GetResourceMsgFromResourcetext("LocalHost"), false); + } + helper.RemoveFromDictionary(ChildName); + return; + } + + path = path.Substring(0, path.LastIndexOf(ChildName, StringComparison.OrdinalIgnoreCase)); + + //Get the wsman host name to find the session object + string host = GetHostName(path); + string uri = NormalizePath(path, host); + + + //Chk for Winrm Service + if (IsPathLocalMachine(host)) + { + if (!IsWSManServiceRunning()) + { + WSManHelper.ThrowIfNotAdministrator(); + StartWSManService(this.Force); + } + } + + lock(WSManHelper.AutoSession) + { + //Gets the session object from the cache. + object sessionobj; + Dictionary SessionObjCache = WSManHelper.GetSessionObjCache(); + SessionObjCache.TryGetValue(host, out sessionobj); + + //if endswith '\', removes it. + if (path.EndsWith(WSManStringLiterals.DefaultPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase)) + { + path = path.Remove(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator)); + } + + string inputStr = String.Empty; + string strPathCheck = String.Empty; + strPathCheck = host + WSManStringLiterals.DefaultPathSeparator; + + + if (path.Contains(strPathCheck + WSManStringLiterals.containerPlugin))//(path.Contains(@"\plugin")) + { + if (path.EndsWith(strPathCheck + WSManStringLiterals.containerPlugin, StringComparison.OrdinalIgnoreCase)) + { + //Deletes all the Plugin when user is in WsMan:\Localhost\Plugin. + string pluginUri = uri + "?Name=" + ChildName; + DeleteResourceValue(sessionobj, pluginUri, null, recurse); + return; + } + + strPathCheck = strPathCheck + WSManStringLiterals.containerPlugin; + int pos = 0; string pName = null; + + pos = path.LastIndexOf(strPathCheck + WSManStringLiterals.DefaultPathSeparator, StringComparison.OrdinalIgnoreCase) + strPathCheck.Length + 1; + int pindex = path.IndexOf(WSManStringLiterals.DefaultPathSeparator, pos); + if (pindex != -1) + { + pName = path.Substring(pos, path.IndexOf(WSManStringLiterals.DefaultPathSeparator, pos) - pos); + } + else + { + pName = path.Substring(pos); + } + string filter1 = uri + "?Name=" + pName; + XmlDocument pxml = GetResourceValue(sessionobj, filter1, null); + + PSObject ps = ProcessPluginConfigurationLevel(pxml); + ArrayList SecurityArray = null; + ArrayList ResourceArray = ProcessPluginResourceLevel(pxml, out SecurityArray); + ArrayList InitParamArray = ProcessPluginInitParamLevel(pxml); + + strPathCheck = strPathCheck + WSManStringLiterals.DefaultPathSeparator + pName + WSManStringLiterals.DefaultPathSeparator; + if (path.Contains(strPathCheck + WSManStringLiterals.containerResources)) + { + // Remove-Item is called for one of the resources. + if (path.EndsWith(strPathCheck + WSManStringLiterals.containerResources, StringComparison.OrdinalIgnoreCase)) + { + throwerror = false; + ResourceArray = RemoveItemfromResourceArray(ResourceArray, ChildName, "", "ResourceDir"); + } + if (throwerror) + { + strPathCheck = strPathCheck + WSManStringLiterals.containerResources + WSManStringLiterals.DefaultPathSeparator; + int Sepindex = path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathCheck.Length); + string sResourceDirName = string.Empty; + if (Sepindex == -1) + { + sResourceDirName = path.Substring(strPathCheck.Length); + } + else + { + sResourceDirName = path.Substring(strPathCheck.Length, path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathCheck.Length) - (strPathCheck.Length)); + } + strPathCheck = strPathCheck + sResourceDirName + WSManStringLiterals.DefaultPathSeparator; + if (path.EndsWith(strPathCheck + WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase)) + { + throwerror = false; + SecurityArray = RemoveItemfromResourceArray(SecurityArray, ChildName, "", "SecurityDIR"); + } + } + } + else if (path.EndsWith(strPathCheck + WSManStringLiterals.containerInitParameters, StringComparison.OrdinalIgnoreCase)) + { + // Remove-Item is called for one of the initialization Parameters. + throwerror = false; + InitParamArray = RemoveItemfromResourceArray(InitParamArray, ChildName, "InitParams", ""); + } + if (throwerror) + { + AssertError(helper.GetResourceMsgFromResourcetext("RemoveItemNotSupported"), false); + return; + } + inputStr = ConstructPluginXml(ps, uri, host, "Set", ResourceArray, SecurityArray, InitParamArray); + try + { + ((IWSManSession)sessionobj).Put(uri + "?Name=" + pName, inputStr, 0); + } + finally + { + if (!String.IsNullOrEmpty(((IWSManSession)sessionobj).Error)) + { + AssertError(((IWSManSession)sessionobj).Error, true); + } + } + } + else if (path.EndsWith(strPathCheck + WSManStringLiterals.containerListener, StringComparison.OrdinalIgnoreCase)) + { + throwerror = false; + RemoveListenerOrCertMapping(sessionobj, uri, ChildName, PKeyListener, true); + } + else if (path.EndsWith(strPathCheck + WSManStringLiterals.containerClientCertificate, StringComparison.OrdinalIgnoreCase)) + { + throwerror = false; + RemoveListenerOrCertMapping(sessionobj, uri, ChildName, PKeyCertMapping, false); + } + if (throwerror) + { + AssertError(helper.GetResourceMsgFromResourcetext("RemoveItemNotSupported"), false); + return; + } + } + } + + /// + /// This method creates a new item of listener,clientcertificate etc. + /// + /// + /// + /// + protected override void NewItem(string path, string itemTypeName, object newItemValue) + { + string inputStr = String.Empty; + object sessionobj; + + //if endswith '\', removes it. + if (path.EndsWith(WSManStringLiterals.DefaultPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase)) + { + path = path.Remove(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator)); + return; + } + + + if (path.Length == 0 || !path.Contains(WSManStringLiterals.DefaultPathSeparator.ToString())) + { + NewItemCreateComputerConnection(path); + return; + } + + //Get the wsman host name to find the session object + string host = GetHostName(path); + + if (string.IsNullOrEmpty(host)) + { + throw new ArgumentException(helper.GetResourceMsgFromResourcetext("InvalidPath")); + } + + //Chk for Winrm Service + if (IsPathLocalMachine(host)) + { + if (!IsWSManServiceRunning()) + { + WSManHelper.ThrowIfNotAdministrator(); + StartWSManService(this.Force); + } + } + string uri = NormalizePath(path, host); + + lock(WSManHelper.AutoSession) + { + Dictionary SessionObjCache = WSManHelper.GetSessionObjCache(); + SessionObjCache.TryGetValue(host, out sessionobj); + + + string strPathChk = host + WSManStringLiterals.DefaultPathSeparator; + if (path.Contains(strPathChk + WSManStringLiterals.containerPlugin))//(path.Contains(@"\plugin")) + { + NewItemPluginOrPluginChild(sessionobj, path, host, uri); + } + else if (path.EndsWith(strPathChk + WSManStringLiterals.containerListener, StringComparison.OrdinalIgnoreCase)) + { + WSManProvidersListenerParameters niParams = DynamicParameters as WSManProvidersListenerParameters; + Hashtable listenerparams = new Hashtable(); + listenerparams.Add("Address", niParams.Address); + listenerparams.Add("Transport", niParams.Transport); + listenerparams.Add("Enabled", niParams.Enabled); + if (niParams.HostName != null) + { + listenerparams.Add("Hostname", niParams.HostName); + } + if (niParams.URLPrefix != null) + { + listenerparams.Add("URLPrefix", niParams.URLPrefix); + } + if (niParams.IsPortSpecified) + { + listenerparams.Add("Port", niParams.Port); + } + if (niParams.CertificateThumbPrint != null) + { + listenerparams.Add("CertificateThumbPrint", niParams.CertificateThumbPrint); + } + NewItemContainerListenerOrCertMapping(sessionobj, path, uri, host, listenerparams, WSManStringLiterals.containerListener, helper.GetResourceMsgFromResourcetext("NewItemShouldContinueListenerQuery"), helper.GetResourceMsgFromResourcetext("NewItemShouldContinueListenerCaption")); + } + else if (path.EndsWith(strPathChk + WSManStringLiterals.containerClientCertificate, StringComparison.OrdinalIgnoreCase)) + { + WSManProviderClientCertificateParameters dynParams = DynamicParameters as WSManProviderClientCertificateParameters; + SessionObjCache.TryGetValue(host, out sessionobj); + Hashtable Certparams = new Hashtable(); + Certparams.Add("Issuer", dynParams.Issuer); + Certparams.Add("Subject", dynParams.Subject); + Certparams.Add("Uri", dynParams.URI); + if (this.Credential.UserName != null) + { + System.Net.NetworkCredential nwCredentials = this.Credential.GetNetworkCredential(); + Certparams.Add("UserName", nwCredentials.UserName); + Certparams.Add("Password", nwCredentials.Password); + } + Certparams.Add("Enabled", dynParams.Enabled); + NewItemContainerListenerOrCertMapping(sessionobj, path, uri, host, Certparams, WSManStringLiterals.containerClientCertificate, helper.GetResourceMsgFromResourcetext("NewItemShouldContinueClientCertQuery"), helper.GetResourceMsgFromResourcetext("NewItemShouldContinueClientCertCaption")); + } + else + { + AssertError(helper.GetResourceMsgFromResourcetext("NewItemNotSupported"), false); + return; + } + } + } + + /// + /// Dynamic parameter used by New-Item. According to different path. This method return the + /// required dynamic parameters + /// + /// + /// + /// + /// + protected override object NewItemDynamicParameters(string path, string itemTypeName, object newItemValue) + { + if (path.Length == 0) + { + return new WSManProviderNewItemComputerParameters(); + } + string hostname = GetHostName(path); + string strpathchk = hostname + WSManStringLiterals.DefaultPathSeparator; + if (path.EndsWith(strpathchk + WSManStringLiterals.containerPlugin, StringComparison.OrdinalIgnoreCase)) + { + return new WSManProviderNewItemPluginParameters(); + } + if (path.EndsWith(WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerInitParameters, StringComparison.OrdinalIgnoreCase)) + { + return new WSManProviderInitializeParameters(); + } + if (path.EndsWith(WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerResources, StringComparison.OrdinalIgnoreCase)) + { + return new WSManProviderNewItemResourceParameters(); + } + if (path.EndsWith(WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase)) + { + return new WSManProviderNewItemSecurityParameters(); + } + if (path.EndsWith(strpathchk + WSManStringLiterals.containerListener, StringComparison.OrdinalIgnoreCase)) + { + return new WSManProvidersListenerParameters(); + } + if (path.EndsWith(strpathchk + WSManStringLiterals.containerClientCertificate, StringComparison.OrdinalIgnoreCase)) + { + return new WSManProviderClientCertificateParameters(); + } + return null; + } + + #endregion + + #region Private + + /// + /// this method creates the connection to new machine in wsman provider. + /// This is called from New-Item. + /// + /// + private void NewItemCreateComputerConnection(string Name) + { + helper = new WSManHelper(this); + WSManProviderNewItemComputerParameters dynParams = DynamicParameters as WSManProviderNewItemComputerParameters; + string parametersetName = "ComputerName"; + if (dynParams != null) + { + if (dynParams.ConnectionURI != null) + { + parametersetName = "URI"; + + } + helper.CreateWsManConnection(parametersetName, dynParams.ConnectionURI, dynParams.Port, Name, dynParams.ApplicationName, dynParams.UseSSL, dynParams.Authentication, dynParams.SessionOption, this.Credential, dynParams.CertificateThumbprint); + if (dynParams.ConnectionURI != null) + { + string[] constrsplit = dynParams.ConnectionURI.OriginalString.Split(new string[] { ":" + dynParams.Port + "/" + dynParams.ApplicationName }, StringSplitOptions.None); + string[] constrsplit1 = constrsplit[0].Split(new string[] { "//" }, StringSplitOptions.None); + Name = constrsplit1[1].Trim(); + } + WriteItemObject(GetItemPSObjectWithTypeName(Name, WSManStringLiterals.ContainerChildValue, null, null, "ComputerLevel", WsManElementObjectTypes.WSManConfigContainerElement), WSManStringLiterals.rootpath + WSManStringLiterals.DefaultPathSeparator + Name, true); + } + else + { + dynParams = new WSManProviderNewItemComputerParameters(); + helper.CreateWsManConnection(parametersetName, dynParams.ConnectionURI, dynParams.Port, Name, dynParams.ApplicationName, dynParams.UseSSL, dynParams.Authentication, dynParams.SessionOption, this.Credential, dynParams.CertificateThumbprint); + WriteItemObject(GetItemPSObjectWithTypeName(Name, WSManStringLiterals.ContainerChildValue, null, null, "ComputerLevel", WsManElementObjectTypes.WSManConfigContainerElement), WSManStringLiterals.rootpath + WSManStringLiterals.DefaultPathSeparator + Name, true); + } + } + + /// + /// this method creates the Listener or ClientCertificate in wsman provider. + /// This is called from New-Item. + /// + /// + /// + /// + /// + /// + /// + /// + /// + private void NewItemContainerListenerOrCertMapping(object sessionobj, string path, string uri, string host, Hashtable InputParams, string ContainerListenerOrCertMapping, string ShouldContinueQuery, string ShouldContinueCaption) + { + if (!Force) + { + if (!ShouldContinue(ShouldContinueQuery, ShouldContinueCaption)) + { + return; + } + } + string inputstr = GetInputStringForCreate(uri, InputParams, host); + CreateResourceValue(sessionobj, uri, inputstr, InputParams); + XmlDocument xmlResource = GetResourceValue(sessionobj, uri, InputParams); + Hashtable CCache = null; + Hashtable kCache = null; + if (ContainerListenerOrCertMapping.Equals(WSManStringLiterals.containerClientCertificate)) + { + ProcessCertMappingObjects(xmlResource, out CCache, out kCache); + } + else if (ContainerListenerOrCertMapping.Equals(WSManStringLiterals.containerListener)) + { + ProcessListernerObjects(xmlResource, out CCache, out kCache); + } + if (CCache != null && CCache.Count > 0) + { + foreach (DictionaryEntry resource in CCache) + { + WriteItemObject(GetItemPSObjectWithTypeName(resource.Key.ToString(), WSManStringLiterals.ContainerChildValue, null, (string[])kCache[resource.Key], string.Empty, WsManElementObjectTypes.WSManConfigContainerElement), path + WSManStringLiterals.DefaultPathSeparator + resource.Key.ToString(), true); + } + } + + } + + /// + /// this method creates the Plugin and its child items in wsman provider. + /// This is called from New-Item. + /// + /// + /// + /// + /// + private void NewItemPluginOrPluginChild(object sessionobj, string path, string host, string uri) + { + PSObject mshObj = new PSObject(); + string PluginName = string.Empty; + string inputStr = String.Empty; + + string strPathChk = host + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerPlugin; + if (!path.Equals(strPathChk)) + { + int separatorindex = path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathChk.Length + 1); + if (separatorindex == -1) + { + PluginName = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1); + path = path.Remove(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator)); + } + } + // to create a new plugin + if (path.EndsWith(strPathChk, StringComparison.OrdinalIgnoreCase)) + { + WSManProviderNewItemPluginParameters niParams = DynamicParameters as WSManProviderNewItemPluginParameters; + if (niParams != null) + { + if (String.IsNullOrEmpty(niParams.File)) + { + mshObj.Properties.Add(new PSNoteProperty("Name", niParams.Plugin)); + mshObj.Properties.Add(new PSNoteProperty("Filename", niParams.FileName)); + mshObj.Properties.Add(new PSNoteProperty("Resource", niParams.Resource)); + mshObj.Properties.Add(new PSNoteProperty("SDKVersion", niParams.SDKVersion)); + mshObj.Properties.Add(new PSNoteProperty("Capability", niParams.Capability)); + + if (niParams.RunAsCredential != null) + { + mshObj.Properties.Add(new PSNoteProperty(WSManStringLiterals.ConfigRunAsUserName, niParams.RunAsCredential.UserName)); + mshObj.Properties.Add(new PSNoteProperty(WSManStringLiterals.ConfigRunAsPasswordName, niParams.RunAsCredential.Password)); + } + + if (niParams.AutoRestart) + { + mshObj.Properties.Add(new PSNoteProperty(WSManStringLiterals.ConfigAutoRestart, niParams.AutoRestart)); + } + + if (niParams.ProcessIdleTimeoutSec.HasValue) + { + mshObj.Properties.Add(new PSNoteProperty(WSManStringLiterals.ConfigProcessIdleTimeoutSec, niParams.ProcessIdleTimeoutSec.Value)); + } + + if (niParams.UseSharedProcess) + { + mshObj.Properties.Add(new PSNoteProperty(WSManStringLiterals.ConfigUseSharedProcess, niParams.UseSharedProcess)); + } + + if (niParams.XMLRenderingType != null) + { + mshObj.Properties.Add(new PSNoteProperty("XmlRenderingType", niParams.XMLRenderingType)); + } + else + { + mshObj.Properties.Add(new PSNoteProperty("XmlRenderingType", "Text")); + } + inputStr = ConstructPluginXml(mshObj, uri, host, "New", null, null, null); + PluginName = niParams.Plugin; + } + else + { + inputStr = ReadFile(niParams.File); + } + } + else + { + ErrorRecord er = new ErrorRecord(new InvalidOperationException(helper.GetResourceMsgFromResourcetext("NewItemNotSupported")), "InvalidOperationException", ErrorCategory.InvalidOperation, null); + WriteError(er); + return; + } + string filter = uri + "?Name=" + PluginName; + CreateResourceValue(sessionobj, filter, inputStr, null); + WriteItemObject(GetItemPSObjectWithTypeName(PluginName, WSManStringLiterals.ContainerChildValue, null, new string[] { "Name=" + PluginName }, string.Empty, WsManElementObjectTypes.WSManConfigContainerElement), path + WSManStringLiterals.DefaultPathSeparator + PluginName, true); + } + else + {// to create an internal item of as plugin + string pName = string.Empty; + string NewItem = String.Empty; + string[] Keys = null; + + + int pos = path.LastIndexOf(strPathChk + WSManStringLiterals.DefaultPathSeparator, StringComparison.OrdinalIgnoreCase) + strPathChk.Length + 1; + int pindex = path.IndexOf(WSManStringLiterals.DefaultPathSeparator, pos); + if (pindex != -1) + { + pName = path.Substring(pos, path.IndexOf(WSManStringLiterals.DefaultPathSeparator, pos) - pos); + } + else + { + pName = path.Substring(pos); + } + + string filter = uri + "?Name=" + pName; + XmlDocument pxml = GetResourceValue(sessionobj, filter, null); + + ArrayList SecurityArray = null; + PSObject ps = ProcessPluginConfigurationLevel(pxml); + ArrayList ResourceArray = ProcessPluginResourceLevel(pxml, out SecurityArray); + ArrayList InitParamArray = ProcessPluginInitParamLevel(pxml); + + + strPathChk = strPathChk + WSManStringLiterals.DefaultPathSeparator + pName + WSManStringLiterals.DefaultPathSeparator; + if (path.Contains(strPathChk + WSManStringLiterals.containerResources)) + { + strPathChk = strPathChk + WSManStringLiterals.containerResources; + if (path.EndsWith(strPathChk, StringComparison.OrdinalIgnoreCase)) + { + WSManProviderNewItemResourceParameters niParams = DynamicParameters as WSManProviderNewItemResourceParameters; + if (niParams != null) + { + mshObj.Properties.Add(new PSNoteProperty("Resource", niParams.ResourceUri)); + mshObj.Properties.Add(new PSNoteProperty("Capability", niParams.Capability)); + + inputStr = ConstructResourceXml(mshObj, null, null); + XmlDocument xdoc = new XmlDocument(); + xdoc.LoadXml(inputStr); + + ArrayList arrList = null; + ArrayList NewResource = ProcessPluginResourceLevel(xdoc, out arrList); + + NewItem = ((PSObject)NewResource[0]).Properties["ResourceDir"].Value.ToString(); + Keys = new string[] { "Uri=" + ((PSObject)NewResource[0]).Properties["ResourceURI"].Value.ToString() }; + + if (ResourceArray != null) + { + ResourceArray.Add(NewResource[0]); + } + else + { + ResourceArray = NewResource; + } + } + } + int Sepindex = path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathChk.Length); + string sResourceDirName = string.Empty; + if (Sepindex != -1) + { + sResourceDirName = path.Substring(strPathChk.Length + 1, path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathChk.Length + 1) - (strPathChk.Length + 1)); + } + strPathChk = strPathChk + WSManStringLiterals.DefaultPathSeparator + sResourceDirName; + + if (path.EndsWith(strPathChk + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase)) + { + if (!Force) + { + string query = helper.GetResourceMsgFromResourcetext("ShouldContinueSecurityQuery"); + query = String.Format(CultureInfo.CurrentCulture, query, pName); + if (!ShouldContinue(query, helper.GetResourceMsgFromResourcetext("ShouldContinueSecurityCaption"))) + { + return; + } + } + // Construct the Uri from Resource_XXXX resource dir. + PSObject resourceDirProperties = GetItemValue(strPathChk); + if ((null == resourceDirProperties) || (null == resourceDirProperties.Properties["ResourceUri"])) + { + string message = helper.FormatResourceMsgFromResourcetext("ResourceURIMissingInResourceDir", + "ResourceUri", strPathChk); + AssertError(message, false); + return; // AssertError is going to throw - return silences some static analysis tools + } + + WSManProviderNewItemSecurityParameters niParams = DynamicParameters as WSManProviderNewItemSecurityParameters; + mshObj.Properties.Add(new PSNoteProperty("Uri", resourceDirProperties.Properties["ResourceUri"].Value)); + mshObj.Properties.Add(new PSNoteProperty("Sddl", niParams.Sddl)); + + inputStr = ConstructSecurityXml(mshObj, null, string.Empty); + XmlDocument xdoc = new XmlDocument(); + xdoc.LoadXml(inputStr); + + ArrayList newSecurity = new ArrayList(); + newSecurity = ProcessPluginSecurityLevel(newSecurity, xdoc, sResourceDirName, resourceDirProperties.Properties["ResourceUri"].Value.ToString()); + + NewItem = ((PSObject)newSecurity[0]).Properties["SecurityDIR"].Value.ToString(); + Keys = new string[] { "Uri=" + ((PSObject)newSecurity[0]).Properties["Uri"].Value.ToString() }; + + if (SecurityArray != null) + { + SecurityArray.Add(newSecurity[0]); + } + else + { + SecurityArray = newSecurity; + } + } + + } + if (path.EndsWith(strPathChk + WSManStringLiterals.containerInitParameters, StringComparison.OrdinalIgnoreCase)) + { + + WSManProviderInitializeParameters niParams = DynamicParameters as WSManProviderInitializeParameters; + mshObj.Properties.Add(new PSNoteProperty(niParams.ParamName, niParams.ParamValue)); + inputStr = ConstructInitParamsXml(mshObj, null); + XmlDocument xdoc = new XmlDocument(); + xdoc.LoadXml(inputStr); + ArrayList newInitParam = ProcessPluginInitParamLevel(xdoc); + NewItem = niParams.ParamName; + if (InitParamArray != null) + { + InitParamArray.Add(newInitParam[0]); + } + else + { + InitParamArray = ProcessPluginInitParamLevel(xdoc); + } + } + inputStr = ConstructPluginXml(ps, uri, host, "Set", ResourceArray, SecurityArray, InitParamArray); + try + { + ((IWSManSession)sessionobj).Put(uri + "?" + "Name=" + pName, inputStr.ToString(), 0); + if (path.EndsWith(strPathChk + WSManStringLiterals.containerInitParameters, StringComparison.OrdinalIgnoreCase)) + { + WriteItemObject(GetItemPSObjectWithTypeName(mshObj.Properties[NewItem].Name, mshObj.Properties[NewItem].TypeNameOfValue, mshObj.Properties[NewItem].Value, null, "InitParams", WsManElementObjectTypes.WSManConfigLeafElement), path + WSManStringLiterals.DefaultPathSeparator + mshObj.Properties[NewItem].Name, false); + } + else + { + WriteItemObject(GetItemPSObjectWithTypeName(NewItem, WSManStringLiterals.ContainerChildValue, null, Keys, string.Empty, WsManElementObjectTypes.WSManConfigContainerElement), path + WSManStringLiterals.DefaultPathSeparator + NewItem, true); + } + } + finally + { + if (!String.IsNullOrEmpty(((IWSManSession)sessionobj).Error)) + { + AssertError(((IWSManSession)sessionobj).Error, true); + } + } + } + } + + /// + /// Returns the object to be written to the console. + /// + /// + /// + /// + /// + /// + /// + /// + /// + private PSObject GetItemPSObjectWithTypeName(string Name, string TypeNameOfElement, object Value, string[] keys, string ExtendedTypeName, WsManElementObjectTypes WSManElementObjectType, PSObject input = null) + { + PSObject mshObject = null; + if (WSManElementObjectType.Equals(WsManElementObjectTypes.WSManConfigElement)) + { + WSManConfigElement element = new WSManConfigElement(Name, TypeNameOfElement); + mshObject = new PSObject(element); + } + if (WSManElementObjectType.Equals(WsManElementObjectTypes.WSManConfigContainerElement)) + { + WSManConfigContainerElement element = new WSManConfigContainerElement(Name, TypeNameOfElement, keys); + mshObject = new PSObject(element); + } + if (WSManElementObjectType.Equals(WsManElementObjectTypes.WSManConfigLeafElement)) + { + object source = null; + + if (input != null) + { + string sourceProp = Name + WSManStringLiterals.HiddenSuffixForSourceOfValue; + if (input.Properties[sourceProp] != null) + { + source = input.Properties[sourceProp].Value; + } + } + + WSManConfigLeafElement element = new WSManConfigLeafElement(Name, Value, TypeNameOfElement, source); + mshObject = new PSObject(element); + } + if (!String.IsNullOrEmpty(ExtendedTypeName)) + { + StringBuilder types = new StringBuilder(""); + if (mshObject != null) + { + types.Append(mshObject.ImmediateBaseObject.GetType().FullName); + types.Append("#"); + types.Append(ExtendedTypeName); + mshObject.TypeNames.Insert(0, types.ToString()); + } + } + return mshObject; + } + + /// + /// Called from setitem. This set the value in Listener and Client Certificate container. + /// + /// + /// + /// + /// + /// + /// + /// + /// + private void SetItemListenerOrClientCertificate(object sessionObj, string ResourceURI, string[] PrimaryKeys, string childName, object value, string path, string parent, string host) + { + Hashtable objcache = null; + Hashtable Keyscache = null; + XmlDocument xmlResource = EnumerateResourceValue(sessionObj, ResourceURI); + + if (xmlResource == null) + { + AssertError(helper.GetResourceMsgFromResourcetext("InvalidPath"), false); + } + + if (ResourceURI.EndsWith(WSManStringLiterals.containerListener, StringComparison.OrdinalIgnoreCase)) + { + ProcessListernerObjects(xmlResource, out objcache, out Keyscache); + } + else if (ResourceURI.EndsWith(WSManStringLiterals.containerCertMapping, StringComparison.OrdinalIgnoreCase)) + { + ProcessCertMappingObjects(xmlResource, out objcache, out Keyscache); + } + if (path.EndsWith(host + WSManStringLiterals.DefaultPathSeparator + parent, StringComparison.OrdinalIgnoreCase)) + { + AssertError(helper.GetResourceMsgFromResourcetext("SetItemNotSupported"), false); + } + else + { + if (!Force) + { + if (!ShouldContinue(helper.GetResourceMsgFromResourcetext("SetItemShouldContinueQuery"), helper.GetResourceMsgFromResourcetext("SetItemShouldContinueCaption"))) + { + return; + } + } + string item = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1); + try + { + Hashtable cmdlinevalue = new Hashtable(); + cmdlinevalue.Add(childName, value); + foreach (string key in PrimaryKeys) + { + cmdlinevalue.Add(key, ((PSObject)objcache[item]).Properties[key].Value); + } + PutResourceValue(sessionObj, ResourceURI, cmdlinevalue, host); + } + catch (COMException e) + { + ErrorRecord er = new ErrorRecord(e, "COMException", ErrorCategory.InvalidOperation, null); + WriteError(er); + return; + } + } + } + + /// + /// Get the input string for create + /// + /// + /// + /// + /// + private string GetInputStringForCreate(string ResourceURI, Hashtable value, string host) + { + + string putstr = String.Empty; + string nilns = String.Empty; + StringBuilder sbvalues = new StringBuilder(); + + if (value.Count > 0) + { + foreach (string key in value.Keys) + { + if (!IsPKey(key, ResourceURI)) + { + sbvalues.Append(""); + sbvalues.Append(EscapeValuesForXML(((Hashtable)value)[key].ToString())); + sbvalues.Append(""); + } + } + } + string root = GetRootNodeName(ResourceURI); + putstr = "" + sbvalues.ToString() + ""; + return putstr; + } + + /// + /// Reads the file. used by New-Item for Plugin creation from file. + /// + /// + /// + private string ReadFile(string path) + { + string putstr = String.Empty; + try + { + string filePath = this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path); + putstr = File.ReadAllText(filePath, System.Text.Encoding.UTF8); + } + //known exceptions + catch (ArgumentNullException e) + { + ErrorRecord er = new ErrorRecord(e, "ArgumentNullException", ErrorCategory.InvalidOperation, null); + WriteError(er); + } + catch (UnauthorizedAccessException e) + { + ErrorRecord er = new ErrorRecord(e, "UnauthorizedAccessException", ErrorCategory.InvalidOperation, null); + WriteError(er); + } + catch (NotSupportedException e) + { + ErrorRecord er = new ErrorRecord(e, "NotSupportedException", ErrorCategory.InvalidOperation, null); + WriteError(er); + } + catch (FileNotFoundException e) + { + ErrorRecord er = new ErrorRecord(e, "FileNotFoundException", ErrorCategory.InvalidOperation, null); + WriteError(er); + } + catch (DirectoryNotFoundException e) + { + ErrorRecord er = new ErrorRecord(e, "DirectoryNotFoundException", ErrorCategory.InvalidOperation, null); + WriteError(er); + } + catch (System.Security.SecurityException e) + { + ErrorRecord er = new ErrorRecord(e, "SecurityException", ErrorCategory.InvalidOperation, null); + WriteError(er); + } + return putstr; + } + + /// + /// Get the host name or the machine to which connected. + /// This is used by most of the methods like GetItem,GetChildItem, NewItem, SetItem,RemoveItem etc... + /// + /// + /// + private string GetHostName(string path) + { + string sHostname = path; + try + { + //HostName is always followed by root name + if (path.Contains(WSManStringLiterals.DefaultPathSeparator.ToString())) + { + sHostname = path.Substring(0, path.IndexOf(WSManStringLiterals.DefaultPathSeparator)); + } + Dictionary SessionObjCache = WSManHelper.GetSessionObjCache(); + if (!SessionObjCache.ContainsKey(sHostname)) + sHostname = null; + + } + catch (ArgumentNullException e) + { + ErrorRecord er = new ErrorRecord(e, "ArgumentNullException", ErrorCategory.InvalidArgument, null); + WriteError(er); + } + return sHostname; + } + + private string GetRootNodeName(string ResourceURI) + { + string tempuri = ""; + if (ResourceURI.Contains("?")) + { + ResourceURI = ResourceURI.Split(new char[] { '?' }).GetValue(0).ToString(); + } + string PTRN_URI_LAST = "([a-z_][-a-z0-9._]*)$"; + Regex objregex = new Regex(PTRN_URI_LAST, RegexOptions.IgnoreCase); + MatchCollection regexmatch = objregex.Matches(ResourceURI); + if (regexmatch.Count > 0) + { + tempuri = regexmatch[0].Value.ToString(); + } + return tempuri; + } + + private string EscapeValuesForXML(string value) + { + StringBuilder esc_str = new StringBuilder(); + for (int i = 0; i <= value.Length - 1; i++) + { + switch (value[i]) + { + case '&': + { + esc_str.Append("&"); + break; + } + case '<': + { + esc_str.Append("<"); + break; + } + case '>': + { + esc_str.Append(">"); + break; + } + case '\"': + { + esc_str.Append("""); + break; + } + case '\'': + { + esc_str.Append("'"); + break; + } + default: + { + esc_str.Append(value[i]); + break; + } + } + } + return esc_str.ToString(); + } + + private bool IsItemContainer(XmlNodeList nodes) + { + bool result = false; + if (nodes.Count != 0) + { + if (nodes[0].ChildNodes.Count != 0) + { + if (!nodes[0].FirstChild.Name.Equals("#text", StringComparison.OrdinalIgnoreCase)) + { + result = true; + } + } + } + return result; + } + + private XmlNodeList SearchXml(XmlDocument resourcexmldocument, string searchitem, string ResourceURI, string path, string host) + { + XmlNodeList nodes = null; + try + { + string xpathString = String.Empty; + if (ResourceURI.EndsWith(WSManStringLiterals.containerWinrs, StringComparison.OrdinalIgnoreCase)) + { + if (path.Equals(host + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerShell, StringComparison.OrdinalIgnoreCase)) + { + searchitem = WSManStringLiterals.containerWinrs.ToLowerInvariant(); + } + } + if (ResourceURI.EndsWith("Config", StringComparison.OrdinalIgnoreCase) || !ResourceURI.EndsWith(searchitem, StringComparison.OrdinalIgnoreCase)) + { + xpathString = @"/*/*[local-name()=""" + searchitem.ToLowerInvariant() + @"""]"; + } + else + { + xpathString = @"/*[local-name()=""" + searchitem.ToLowerInvariant() + @"""]"; + } + nodes = resourcexmldocument.SelectNodes(xpathString); + + } + catch (System.Xml.XPath.XPathException ex) + { + ErrorRecord er = new ErrorRecord(ex, "XPathException", ErrorCategory.InvalidArgument, null); + WriteError(er); + } + return nodes; + } + + #region "WsMan linking Operations" + /// + /// To put a resource value. Wsman put operation + /// + /// + /// + /// + /// + private void PutResourceValue(object sessionobj, string ResourceURI, Hashtable value, string host) + { + XmlDocument inputxml = null; + try + { + inputxml = GetResourceValue(sessionobj, ResourceURI, value); + if (inputxml != null) + { + bool Itemfound = false; + XmlNamespaceManager nsmgr = new XmlNamespaceManager(inputxml.NameTable); + string uri_schema = SetSchemaPath(ResourceURI); + nsmgr.AddNamespace("cfg", uri_schema); + string xpath = SetXPathString(ResourceURI); + XmlNodeList nodelist = inputxml.SelectNodes(xpath, nsmgr); + if (nodelist.Count == 1 && nodelist != null) + { + XmlNode node = (XmlNode)nodelist.Item(0); + if (node.HasChildNodes) + { + for (int i = 0; i < node.ChildNodes.Count; i++) + { + if ( (node.ChildNodes[i].ChildNodes.Count == 0) || node.ChildNodes[i].FirstChild.Name.Equals("#text", StringComparison.OrdinalIgnoreCase)) + { + foreach (string key in value.Keys) + { + //to make sure we dont set values at inner level. + //for eg: when set-item at winrm/config we dont take input at below level + if (!IsPKey(key, ResourceURI)) + { + if (node.ChildNodes[i].LocalName.Equals(key, StringComparison.OrdinalIgnoreCase)) + { + node.ChildNodes[i].InnerText = value[key].ToString(); + Itemfound = true; + } + } + } + } + } + if (Itemfound) + { + ResourceURI = GetURIWithFilter(ResourceURI, value); + ((IWSManSession)sessionobj).Put(ResourceURI, node.OuterXml.ToString(), 0); + } + else + { + AssertError(helper.GetResourceMsgFromResourcetext("ItemDoesNotExist"), false); + return; + } + } + } + } + } + finally + { + if (!String.IsNullOrEmpty(((IWSManSession)sessionobj).Error)) + { + AssertError(((IWSManSession)sessionobj).Error, true); + } + } + } + + private string GetResourceValueInXml(object sessionobj, string ResourceURI, Hashtable cmdlinevalues) + { + try + { + ResourceURI = GetURIWithFilter(ResourceURI, cmdlinevalues); + + string returnValue = String.Empty; + + if (!this.getMapping.TryGetValue(ResourceURI, out returnValue)) + { + returnValue = ((IWSManSession)sessionobj).Get(ResourceURI, 0); + this.getMapping.Add(ResourceURI, returnValue); + } + + return returnValue; + } + finally + { + if (!String.IsNullOrEmpty(((IWSManSession)sessionobj).Error)) + { + AssertError(((IWSManSession)sessionobj).Error, true); + } + } + } + + /// + /// WSMan Get operation. + /// + /// + /// + /// + /// + private XmlDocument GetResourceValue(object sessionobj, string ResourceURI, Hashtable cmdlinevalues) + { + XmlDocument xmlResource = null; + + string strValueXml = this.GetResourceValueInXml(sessionobj, ResourceURI, cmdlinevalues); + xmlResource = new XmlDocument(); + xmlResource.LoadXml(strValueXml); + + return xmlResource; + } + + /// + /// WsMan Enumerate operation + /// + /// + /// + /// + private XmlDocument EnumerateResourceValue(object sessionobj, string ResourceURI) + { + XmlDocument xmlEnumResources = null; + + if (!this.enumarateMapping.TryGetValue(ResourceURI, out xmlEnumResources)) + { + try + { + object value = ((IWSManSession)sessionobj).Enumerate(ResourceURI, "", "", 0); + string strXmlValue = string.Empty; + + while (!((IWSManEnumerator)value).AtEndOfStream) + { + strXmlValue = strXmlValue + ((IWSManEnumerator)value).ReadItem(); + } + + Marshal.ReleaseComObject(value); + + if (!String.IsNullOrEmpty(strXmlValue)) + { + xmlEnumResources = new XmlDocument(); + strXmlValue = "" + strXmlValue + ""; + xmlEnumResources.LoadXml(strXmlValue); + this.enumarateMapping.Add(ResourceURI, xmlEnumResources); + } + + } + finally + { + if (!String.IsNullOrEmpty(((IWSManSession)sessionobj).Error)) + { + AssertError(((IWSManSession)sessionobj).Error, true); + } + } + } + return xmlEnumResources; + + } + + /// + /// WsMan Delete Operation + /// + /// + /// + /// + /// + private void DeleteResourceValue(object sessionobj, string ResourceURI, Hashtable cmdlinevalues, bool recurse) + { + try + { + //Support only for Listener,plugin and ClientCertificate. + if (ResourceURI.Contains(WSManStringLiterals.containerPlugin) || ResourceURI.Contains(WSManStringLiterals.containerListener) || ResourceURI.Contains(WSManStringLiterals.containerCertMapping)) + { + if (cmdlinevalues != null) + { + ResourceURI = GetURIWithFilter(ResourceURI, cmdlinevalues); + } + ((IWSManSession)sessionobj).Delete(ResourceURI, 0); + + } + } + finally + { + if (!String.IsNullOrEmpty(((IWSManSession)sessionobj).Error)) + { + AssertError(((IWSManSession)sessionobj).Error, true); + } + } + } + + /// + /// WsMan Create Operation + /// + /// + /// + /// + /// + private void CreateResourceValue(object sessionobj, string ResourceURI, string resource, Hashtable cmdlinevalues) + { + try + { + if (ResourceURI.Contains(WSManStringLiterals.containerListener) || ResourceURI.Contains(WSManStringLiterals.containerPlugin) || ResourceURI.Contains(WSManStringLiterals.containerCertMapping)) + { + ResourceURI = GetURIWithFilter(ResourceURI, cmdlinevalues); + ((IWSManSession)sessionobj).Create(ResourceURI, resource, 0); + } + } + finally + { + if (!String.IsNullOrEmpty(((IWSManSession)sessionobj).Error)) + { + AssertError(((IWSManSession)sessionobj).Error, true); + } + } + + } + + /// + /// To find a resource value. Both Get and Enumerate works here. + /// + /// + /// + /// + /// + private XmlDocument FindResourceValue(object sessionobj, string ResourceURI, Hashtable cmdlinevalues) + { + XmlDocument outval = null; + if (ResourceURI.Contains(WSManStringLiterals.containerListener) || ResourceURI.Contains(WSManStringLiterals.containerPlugin) || ResourceURI.Contains(WSManStringLiterals.containerCertMapping)) + { + if (null == cmdlinevalues || cmdlinevalues.Count == 0) + { + outval = EnumerateResourceValue(sessionobj, ResourceURI); + } + else + { + outval = GetResourceValue(sessionobj, ResourceURI, cmdlinevalues); + } + } + else + { + outval = GetResourceValue(sessionobj, ResourceURI, cmdlinevalues); + } + return outval; + } + + /// + /// Checks whether a value is present in Wsman config + /// + /// + /// + /// + /// + /// + /// + private bool ContainResourceValue(object sessionobj, string ResourceURI, string childname, string path, string host) + { + bool result = false; + string valuexml = String.Empty; + try + { + if (ResourceURI.Contains(WSManStringLiterals.containerListener) || ResourceURI.Contains(WSManStringLiterals.containerPlugin) || ResourceURI.Contains(WSManStringLiterals.containerCertMapping)) + { + object value = ((IWSManSession)sessionobj).Enumerate(ResourceURI, "", "", 0); + + while (!((IWSManEnumerator)value).AtEndOfStream) + { + valuexml = valuexml + ((IWSManEnumerator)value).ReadItem(); + } + if ((valuexml != "") && !(String.IsNullOrEmpty(valuexml))) + { + valuexml = "" + valuexml + ""; + } + Marshal.ReleaseComObject(value); + } + else + { + valuexml = this.GetResourceValueInXml(((IWSManSession)sessionobj), ResourceURI, null); + } + if (string.IsNullOrEmpty(valuexml)) + { + return false; + } + XmlDocument xmlResourceValues = new XmlDocument(); + xmlResourceValues.LoadXml(valuexml.ToLowerInvariant()); + XmlNodeList nodes = SearchXml(xmlResourceValues, childname, ResourceURI, path, host); + if (nodes.Count > 0) + { + result = true; + } + } + catch (COMException) { result = false; } + return result; + } + + #endregion "WsMan linking Operations" + + private string GetURIWithFilter(string uri, Hashtable cmdlinevalues) + { + StringBuilder sburi = new StringBuilder(uri); + if (cmdlinevalues != null) + { + if (uri.Contains("Config/Listener")) + { + sburi.Append("?"); + sburi.Append(GetFilterString(cmdlinevalues, PKeyListener)); + } + else if (uri.Contains("Config/Service/certmapping")) + { + sburi.Append("?"); + sburi.Append(GetFilterString(cmdlinevalues, PKeyCertMapping)); + } + else if (uri.Contains("Config/Plugin")) + { + sburi.Append("?"); + sburi.Append(GetFilterString(cmdlinevalues, PKeyPlugin)); + } + } + return sburi.ToString(); + } + + private string GetFilterString(Hashtable cmdlinevalues, string[] pkey) + { + StringBuilder filter = new StringBuilder(); + foreach (string key in pkey) + { + if (cmdlinevalues.Contains(key)) + { + filter.Append(key); + filter.Append("="); + filter.Append(cmdlinevalues[key].ToString()); + filter.Append("+"); + } + } + if (filter.ToString().EndsWith("+", StringComparison.OrdinalIgnoreCase)) + filter.Remove(filter.ToString().Length - 1, 1); + return filter.ToString(); + } + + private bool IsPKey(string value, string ResourceURI) + { + bool result = false; + if (ResourceURI.Contains(WSManStringLiterals.containerListener)) + { + result = CheckPkeysArray(null, value, PKeyListener); + } + else if (ResourceURI.Contains(WSManStringLiterals.containerPlugin)) + { + result = CheckPkeysArray(null, value, PKeyPlugin); + } + else if (ResourceURI.Contains(WSManStringLiterals.containerCertMapping)) + { + result = CheckPkeysArray(null, value, PKeyCertMapping); + } + return result; + } + + private bool CheckPkeysArray(Hashtable values, string value, string[] pkeys) + { + bool result = false; + if (values != null) + foreach (string key in pkeys) + { + if (values.Contains(key)) + { + result = true; + } + } + else if (!String.IsNullOrEmpty(value)) + { + foreach (string key in pkeys) + { + if (key.Equals(value, StringComparison.OrdinalIgnoreCase)) + { + result = true; + break; + } + } + } + return result; + } + + private void WritePSObjectPropertyNames(PSObject psobject, string path) + { + foreach (PSPropertyInfo prop in psobject.Properties) + { + if (!prop.Value.ToString().Equals(WSManStringLiterals.ContainerChildValue)) + { + WriteItemObject(prop.Name, path + WSManStringLiterals.DefaultPathSeparator + prop.Name, true); + } + else + { + WriteItemObject(prop.Name, path + WSManStringLiterals.DefaultPathSeparator + prop.Name, false); + } + } + } + + /// + /// Used to Write WSMan objects to the output console. Used by GetChildItem, GetItem and NewItem. + /// + /// + /// + /// + /// + /// + /// + private void WritePSObjectPropertiesAsWSManElementObjects(PSObject psobject, string path, string[] keys, string ExtendedTypeName, WsManElementObjectTypes WSManElementObjectType, bool recurse) + { + PSObject mshObject = null; + Collection directory = new Collection(); + foreach (PSPropertyInfo prop in psobject.Properties) + { + if (prop.Name.EndsWith(WSManStringLiterals.HiddenSuffixForSourceOfValue)) + { + continue; + } + + if (WSManElementObjectType.Equals(WsManElementObjectTypes.WSManConfigElement)) + { + WSManConfigElement element = new WSManConfigElement(prop.Name, prop.Value.ToString()); + mshObject = new PSObject(element); + } + if (WSManElementObjectType.Equals(WsManElementObjectTypes.WSManConfigContainerElement)) + { + WSManConfigContainerElement element = new WSManConfigContainerElement(prop.Name, prop.Value.ToString(), keys); + mshObject = new PSObject(element); + } + if (WSManElementObjectType.Equals(WsManElementObjectTypes.WSManConfigLeafElement)) + { + string sourceProp = prop.Name + WSManStringLiterals.HiddenSuffixForSourceOfValue; + object source = null; + if (psobject.Properties[sourceProp] != null) + { + source = psobject.Properties[sourceProp].Value; + } + + WSManConfigLeafElement element = null; + if (!prop.Value.ToString().Equals(WSManStringLiterals.ContainerChildValue)) + { + element = new WSManConfigLeafElement(prop.Name, prop.Value, prop.TypeNameOfValue, source); + } + else + { + element = new WSManConfigLeafElement(prop.Name, null, prop.Value.ToString()); + } + if (element != null) + { + mshObject = new PSObject(element); + } + } + if (!String.IsNullOrEmpty(ExtendedTypeName)) + { + StringBuilder types = new StringBuilder(""); + if (mshObject != null) + { + types.Append(mshObject.ImmediateBaseObject.GetType().FullName); + types.Append("#"); + types.Append(ExtendedTypeName); + mshObject.TypeNames.Insert(0, types.ToString()); + } + } + if (!prop.Value.ToString().Equals(WSManStringLiterals.ContainerChildValue)) + { + // This path is used by WriteItemObject to construct PSPath. + // PSPath is a provider quailified path and we dont need to specify + // provider root in this path..So I am trying to eliminate provider root + // in this case. + string pathToUse = WSManStringLiterals.rootpath.Equals(path, StringComparison.OrdinalIgnoreCase) ? + prop.Name : + (path + WSManStringLiterals.DefaultPathSeparator + prop.Name); + WriteItemObject(mshObject, pathToUse, false); + } + else + { + // This path is used by WriteItemObject to construct PSPath. + // PSPath is a provider quailified path and we dont need to specify + // provider root in this path..So I am trying to eliminate provider root + // in this case. + string pathToUse = WSManStringLiterals.rootpath.Equals(path, StringComparison.OrdinalIgnoreCase) ? + prop.Name : + (path + WSManStringLiterals.DefaultPathSeparator + prop.Name); + WriteItemObject(mshObject, pathToUse, true); + if (recurse) + { + directory.Add(prop.Name); + } + } + } + if (recurse) + { + foreach (string dir in directory) + { + GetChildItemsRecurse(path, dir, ProviderMethods.GetChildItems, recurse); + } + } + } + + private string SplitAndUpdateStringUsingDelimiter(object sessionobj, string uri, string childname, string value, string Delimiter) + { + XmlDocument xmlResource = GetResourceValue(sessionobj, uri, null); + PSObject mshObject = null; + foreach (XmlNode innerResourceNodes in xmlResource.ChildNodes) + { + mshObject = ConvertToPSObject(innerResourceNodes); + } + string existingvalue = string.Empty; + try + { + if (mshObject != null) + { + existingvalue = mshObject.Properties[childname].Value.ToString(); + } + + if (!String.IsNullOrEmpty(existingvalue)) + { + string[] existingsplitvalues = existingvalue.Split(new string[] { Delimiter }, StringSplitOptions.None); + string[] newvalues = value.Split(new string[] { Delimiter }, StringSplitOptions.None); + foreach (string val in newvalues) + { + if (Array.IndexOf(existingsplitvalues, val) == -1) + { + existingvalue += Delimiter + val; + } + } + } + else + { + existingvalue = value; + } + } + catch (PSArgumentException) + { + + } + return existingvalue; + } + + /// + /// For Host Level or WsMan level + /// WsMan\Localhost:\> + /// WsMan:\> + /// + /// + /// + /// + /// + private PSObject BuildHostLevelPSObjectArrayList(object objSessionObject, string uri, bool IsWsManLevel) + { + PSObject mshobject = new PSObject(); + if (IsWsManLevel) + { + Dictionary SessionObjCache = WSManHelper.GetSessionObjCache(); + foreach (string key in SessionObjCache.Keys) + { + mshobject.Properties.Add(new PSNoteProperty(key, WSManStringLiterals.ContainerChildValue)); + } + } + else + { + if (null != objSessionObject) + { + XmlDocument ConfigXml = GetResourceValue(objSessionObject, uri, null); + //Moving in to + foreach (XmlNode node in ConfigXml.ChildNodes) + { + foreach (XmlNode node1 in node.ChildNodes) + { + //Getting Top Element in + if ( (node1.ChildNodes.Count == 0) || node1.FirstChild.Name.Equals("#text", StringComparison.OrdinalIgnoreCase)) + { + mshobject.Properties.Add(new PSNoteProperty(node1.LocalName, node1.InnerText)); + } + } + } + } + //Getting the Fixed root nodes. + foreach (string root in WinRmRootConfigs) + { + mshobject.Properties.Add(new PSNoteProperty(root, WSManStringLiterals.ContainerChildValue)); + + } + } + return mshobject; + } + + /// + /// Converts XmlNodes ChildNodes to Properties of PSObject + /// + /// + /// + private PSObject ConvertToPSObject(XmlNode xmlnode) + { + PSObject mshObject = new PSObject(); + foreach (XmlNode node in xmlnode.ChildNodes) + { + //If node contains 0 child-nodes, it is empty node, if it's name = "#text" then it's a simple node. + if ( (node.ChildNodes.Count == 0) || node.FirstChild.Name.Equals("#text", StringComparison.OrdinalIgnoreCase)) + { + XmlAttribute attrSource = null; + foreach (XmlAttribute attr in node.Attributes) + { + if (attr.LocalName.Equals("Source", StringComparison.OrdinalIgnoreCase)) + { + attrSource = attr; + break; + } + } + + mshObject.Properties.Add(new PSNoteProperty(node.LocalName, node.InnerText)); + + if (attrSource != null) + { + String propName = node.LocalName + WSManStringLiterals.HiddenSuffixForSourceOfValue; + mshObject.Properties.Remove(propName); + mshObject.Properties.Add(new PSNoteProperty(propName, attrSource.Value)); + } + } + else + { + mshObject.Properties.Add(new PSNoteProperty(node.LocalName, WSManStringLiterals.ContainerChildValue)); + } + } + return mshObject; + + } + + private string SetXPathString(string uri) + { + string parent = uri.Substring(uri.LastIndexOf(WSManStringLiterals.WinrmPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase) + 1); + if (parent.Equals(WSManStringLiterals.containerWinrs, StringComparison.OrdinalIgnoreCase)) + { + parent = WSManStringLiterals.containerWinrs; + } + else if (parent.Equals(WSManStringLiterals.containerAuth, StringComparison.OrdinalIgnoreCase)) + { + parent = WSManStringLiterals.containerAuth; + } + else if (parent.Equals("certmapping", StringComparison.OrdinalIgnoreCase)) + { + parent = "CertMapping"; + } + else if (parent.Equals(WSManStringLiterals.containerService, StringComparison.OrdinalIgnoreCase)) + { + parent = WSManStringLiterals.containerService; + } + else if (parent.Equals(WSManStringLiterals.containerDefaultPorts, StringComparison.OrdinalIgnoreCase)) + { + parent = WSManStringLiterals.containerDefaultPorts; + } + else if (parent.Equals(WSManStringLiterals.containerPlugin, StringComparison.OrdinalIgnoreCase)) + { + parent = WSManStringLiterals.containerPlugin; + } + parent = "/cfg:" + parent; + return parent; + } + + private string SetSchemaPath(string uri) + { + string schemapath = String.Empty; + uri = uri.Remove(0, WinrmRootName[0].Length); + if (uri.Contains(WSManStringLiterals.containerPlugin)) + { + schemapath = WSManStringLiterals.WsMan_Schema + "/plugin"; + } + else if (uri.Contains(WSManStringLiterals.containerClientCertificate)) + { + uri = uri.Replace(WSManStringLiterals.containerClientCertificate, "/service/certmapping"); + schemapath = WSManStringLiterals.WsMan_Schema + uri.ToLowerInvariant(); + } + else + { + schemapath = WSManStringLiterals.WsMan_Schema + uri.ToLowerInvariant(); + } + + return schemapath; + } + + /// + /// Get the Uri for the operation from a path. + /// + /// + /// + /// + private string NormalizePath(string path, string host) + { + string uri = string.Empty; ; + if (path.StartsWith(host, StringComparison.OrdinalIgnoreCase)) + { + if (path.EndsWith(WSManStringLiterals.DefaultPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase)) + path = path.TrimEnd(WSManStringLiterals.DefaultPathSeparator); + + if (path.Equals(host, StringComparison.OrdinalIgnoreCase)) + { + uri = WinrmRootName[0].ToString(); + return uri; + } + + uri = path.Substring(host.Length); + uri = uri.Replace(WSManStringLiterals.DefaultPathSeparator, WSManStringLiterals.WinrmPathSeparator); + string host_prefix = host + WSManStringLiterals.DefaultPathSeparator; + if (path.StartsWith(host_prefix + WSManStringLiterals.containerClientCertificate, StringComparison.OrdinalIgnoreCase)) + { + uri = WinrmRootName[0].ToString() + WSManStringLiterals.WinrmPathSeparator + WSManStringLiterals.containerCertMapping; + } + else if (path.StartsWith(host_prefix + WSManStringLiterals.containerPlugin, StringComparison.OrdinalIgnoreCase)) + { + uri = WinrmRootName[0].ToString() + WSManStringLiterals.WinrmPathSeparator + WSManStringLiterals.containerPlugin; + } + else if (path.StartsWith(host_prefix + WSManStringLiterals.containerShell, StringComparison.OrdinalIgnoreCase)) + { + uri = WinrmRootName[0].ToString() + WSManStringLiterals.WinrmPathSeparator + WSManStringLiterals.containerWinrs; + } + else if (path.StartsWith(host_prefix + WSManStringLiterals.containerListener, StringComparison.OrdinalIgnoreCase)) + { + uri = WinrmRootName[0].ToString() + WSManStringLiterals.WinrmPathSeparator + WSManStringLiterals.containerListener; + } + else + { + if (!(path.Equals(host_prefix + WSManStringLiterals.containerService, StringComparison.OrdinalIgnoreCase) + || path.Equals(host_prefix + WSManStringLiterals.containerClient, StringComparison.OrdinalIgnoreCase) || path.EndsWith(WSManStringLiterals.containerDefaultPorts, StringComparison.OrdinalIgnoreCase) + || path.EndsWith(WSManStringLiterals.containerAuth, StringComparison.OrdinalIgnoreCase))) + { + int index = uri.LastIndexOf(WSManStringLiterals.WinrmPathSeparator); + if (index != -1) + { + uri = uri.Remove(index); + } + } + uri = WinrmRootName[0].ToString() + uri; + } + return uri; + } + return uri; + } + + /// + /// Given wsman config path, gets the value of the leaf present. + /// If path is not valid or not present throws an exception. + /// + /// Currently this supports only retreiving Rescource_XXXX dir contents. + /// if you need support at other levels implement them. + /// Example resource dir: WSMan:\localhost\Plugin\someplugin\Resources\Resource_XXXXXXX + /// + /// + /// + /// A PSObject representing the contents of the path if successfull, + /// Otherwise null. + /// + /// + /// 1. path is null or empty. + /// + /// + /// 1. should be of form + /// WSMan:\localhost\Plugin\someplugin\Resources\Resource_XXXXXXX + /// Other paths are not supported currently. If you want you can + /// add them later. + /// + private PSObject GetItemValue(string path) + { + if (string.IsNullOrEmpty(path) || (path.Length == 0)) + { + throw new ArgumentNullException(path); + } + + //if endswith '\', removes it. + if (path.EndsWith(WSManStringLiterals.DefaultPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase)) + { + path = path.Remove(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator)); + } + + //Get the wsman host name to find the session object + string host = GetHostName(path); + if (String.IsNullOrEmpty(host)) + { + throw new InvalidOperationException("InvalidPath"); + } + + //Chks the WinRM Service + if (IsPathLocalMachine(host) && (!IsWSManServiceRunning())) + { + AssertError("WinRMServiceError", false); + } + + lock(WSManHelper.AutoSession) + { + object sessionobj; + //gets the sessionobject + Dictionary SessionObjCache = WSManHelper.GetSessionObjCache(); + SessionObjCache.TryGetValue(host, out sessionobj); + + //Normalize to the required uri + string uri = NormalizePath(path, host); + + string strPathchk = host + WSManStringLiterals.DefaultPathSeparator; + + if (path.EndsWith(host, StringComparison.OrdinalIgnoreCase)) + { + PSObject result = BuildHostLevelPSObjectArrayList(sessionobj, uri, false); + return result; + } + + // Get the XML for the resource path we are looking for. + XmlDocument outxml = FindResourceValue(sessionobj, uri, null); + if (outxml == null || !outxml.HasChildNodes) + { + return null; + } + + if (path.Contains(strPathchk + WSManStringLiterals.containerListener)) + { + // Implement the necessary functionality here when needed. + throw new NotSupportedException(); + } + else if (path.Contains(strPathchk + WSManStringLiterals.containerClientCertificate)) + { + // Implement the necessary functionality here when needed. + throw new NotSupportedException(); + } + else if (path.Contains(strPathchk + WSManStringLiterals.containerPlugin)) + { + string currentpluginname = String.Empty; + GetPluginNames(outxml, out objPluginNames, out currentpluginname, path); + if (path.EndsWith(strPathchk + WSManStringLiterals.containerPlugin, StringComparison.OrdinalIgnoreCase)) + { + return objPluginNames; + } + else + { + // Currently this supports only retreiving Rescource_XXXX dir contents. + // if you need support at other levels implement them. + // Example resource dir: WSMan:\localhost\Plugin\someplugin\Resources\Resource_67830040 + string filter = uri + "?Name=" + currentpluginname; + XmlDocument CurrentPluginXML = GetResourceValue(sessionobj, filter, null); + if (null == CurrentPluginXML) + { + return null; + } + PSObject objPluginlevel = ProcessPluginConfigurationLevel(CurrentPluginXML); + ArrayList arrSecurity = null; + ArrayList arrResources = ProcessPluginResourceLevel(CurrentPluginXML, out arrSecurity); + ArrayList arrInitParams = ProcessPluginInitParamLevel(CurrentPluginXML); + strPathchk = strPathchk + WSManStringLiterals.containerPlugin + WSManStringLiterals.DefaultPathSeparator; + strPathchk = strPathchk + currentpluginname + WSManStringLiterals.DefaultPathSeparator; + + // We support only retrieving Resource_XXX dir properties only. + // other directory support can be added as needed. + if (null == arrResources) + { + return null; + } + strPathchk = strPathchk + WSManStringLiterals.containerResources + WSManStringLiterals.DefaultPathSeparator; + int Sepindex = path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathchk.Length); + string sResourceDirName = String.Empty; + if (Sepindex == -1) + { + sResourceDirName = path.Substring(strPathchk.Length); + } + else + { + sResourceDirName = path.Substring(strPathchk.Length, + path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathchk.Length) - (strPathchk.Length)); + } + + if (path.EndsWith(strPathchk + sResourceDirName, StringComparison.OrdinalIgnoreCase)) + { + foreach (PSObject p in arrResources) + { + if (sResourceDirName.Equals(p.Properties["ResourceDir"].Value.ToString())) + { + p.Properties.Remove("ResourceDir"); + return p; + } + } + } + } + } + } + return null; + } + + private string GetCorrectCaseOfPath(string path) + { + if (!path.Contains(WSManStringLiterals.DefaultPathSeparator.ToString())) + { + return GetChildName(path); + } + + string[] splitpath = path.Split(WSManStringLiterals.DefaultPathSeparator); + StringBuilder sbPath = new StringBuilder(); + bool first = true; + StringBuilder tempPath = new StringBuilder(); + foreach (string strpath in splitpath) + { + if (first) + { + first = false; + tempPath.Append(GetChildName(strpath)); + sbPath.Append(tempPath); + } + else + { + tempPath.Append(WSManStringLiterals.DefaultPathSeparator); + tempPath.Append(strpath); + sbPath.Append(WSManStringLiterals.DefaultPathSeparator); + sbPath.Append(GetChildName(tempPath.ToString())); + } + } + return sbPath.ToString(); + } + + private string GetCorrectCaseOfName(string ChildName, string hostname, string path) + { + string result = ChildName; + if (ChildName != null) + { + if (!ChildName.Contains("_")) + { + if (ChildName.Equals(WSManStringLiterals.containerQuotasParameters, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerQuotasParameters; + else if (ChildName.Equals(WSManStringLiterals.containerPlugin, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerPlugin; + else if (ChildName.Equals(WSManStringLiterals.containerResources, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerResources; + else if (ChildName.Equals(WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerSecurity; + else if (ChildName.Equals(WSManStringLiterals.containerService, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerService; + else if (ChildName.Equals(WSManStringLiterals.containerShell, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerShell; + else if (ChildName.Equals(WSManStringLiterals.containerTrustedHosts, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerTrustedHosts; + else if (ChildName.Equals(WSManStringLiterals.containerAuth, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerAuth; + else if (ChildName.Equals(WSManStringLiterals.containerClient, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerClient; + else if (ChildName.Equals(WSManStringLiterals.containerClientCertificate, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerClientCertificate; + else if (ChildName.Equals(WSManStringLiterals.containerDefaultPorts, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerDefaultPorts; + else if (ChildName.Equals(WSManStringLiterals.containerInitParameters, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerInitParameters; + else if (ChildName.Equals(WSManStringLiterals.containerListener, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerListener; + else + { + if (!String.IsNullOrEmpty(hostname)) + { + Dictionary SessionObjCache = WSManHelper.GetSessionObjCache(); + if (ChildName.Equals(hostname, StringComparison.OrdinalIgnoreCase)) + { + foreach (string key in SessionObjCache.Keys) + if (ChildName.Equals(key, StringComparison.OrdinalIgnoreCase)) + result = key; + } + else if (path.Contains(hostname + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerPlugin)) + { + if (IsPathLocalMachine(hostname)) + { + if (!IsWSManServiceRunning()) + { + WSManHelper.ThrowIfNotAdministrator(); + StartWSManService(this.Force); + } + } + string uri = NormalizePath(path, hostname); + + lock(WSManHelper.AutoSession) + { + object sessionobj; + SessionObjCache.TryGetValue(hostname, out sessionobj); + XmlDocument outxml = FindResourceValue(sessionobj, uri, null); + if (outxml != null) + { + string currentPluginName = String.Empty; + GetPluginNames(outxml, out objPluginNames, out currentPluginName, path); + if (path.EndsWith(hostname + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerPlugin + WSManStringLiterals.DefaultPathSeparator + currentPluginName, StringComparison.OrdinalIgnoreCase)) + { + result = currentPluginName; + } + } + } + } + } + } + } + else + { + if (ChildName.StartsWith(WSManStringLiterals.containerListener, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerListener + "_" + ChildName.Substring(ChildName.IndexOf('_') + 1); + if (ChildName.StartsWith(WSManStringLiterals.containerSingleResource, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerSingleResource + "_" + ChildName.Substring(ChildName.IndexOf('_') + 1); + if (ChildName.StartsWith(WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerSecurity + "_" + ChildName.Substring(ChildName.IndexOf('_') + 1); + if (ChildName.StartsWith(WSManStringLiterals.containerClientCertificate, StringComparison.OrdinalIgnoreCase)) + result = WSManStringLiterals.containerClientCertificate + "_" + ChildName.Substring(ChildName.IndexOf('_') + 1); + } + } + return result; + } + + private ArrayList RemoveItemfromResourceArray(ArrayList resourceArray, string ChildName, string type, string property) + { + if (resourceArray != null) + { + bool itemfound = false; + int index = 0; + foreach (PSObject obj in resourceArray) + { + if (type.Equals("InitParams")) + { + if (obj.Properties.Match(ChildName).Count > 0) + { + itemfound = true; + break; + } + } + else + { + if (obj.Properties[property].Value.ToString().Equals(ChildName, StringComparison.OrdinalIgnoreCase)) + { + itemfound = true; + break; + } + } + index++; + } + if (itemfound) + resourceArray.RemoveAt(index); + } + return resourceArray; + } + + /// + /// Get Child Items of Listener and Client Certificate. Used by Getchilditem or getchildname. + /// + /// + /// + /// + /// + /// + /// + private void GetChildItemOrNamesForListenerOrCertMapping(XmlDocument xmlResource, string ListenerOrCerMapping, string path, string host, ProviderMethods methodname, bool recurse) + { + Hashtable Objcache, Keyscache; + string PathEnd = String.Empty; + if (ListenerOrCerMapping.Equals(WSManStringLiterals.containerClientCertificate)) + { + ProcessCertMappingObjects(xmlResource, out Objcache, out Keyscache); + } + else if (ListenerOrCerMapping.Equals(WSManStringLiterals.containerListener)) + { + ProcessListernerObjects(xmlResource, out Objcache, out Keyscache); + } + else + { return; } + if (null == Objcache || null == Keyscache) + { + return; + } + if (path.EndsWith(host + WSManStringLiterals.DefaultPathSeparator + ListenerOrCerMapping, StringComparison.OrdinalIgnoreCase)) + { + foreach (string key in Keyscache.Keys) + { + switch (methodname) + { + //Get the items at Config level + case ProviderMethods.GetChildItems: + PSObject obj = new PSObject(); + obj.Properties.Add(new PSNoteProperty(key, WSManStringLiterals.ContainerChildValue)); + WritePSObjectPropertiesAsWSManElementObjects(obj, path, (string[])Keyscache[key], null, WsManElementObjectTypes.WSManConfigContainerElement, recurse); + //WriteItemObject(new WSManConfigContainerElement(key, WSManStringLiterals.ContainerChildValue, (string[])Keyscache[key]), path, true); + break; + //Get the names of container at config level + case ProviderMethods.GetChildNames: + WriteItemObject(key, path, true); + break; + } + } + return; + } + else + { + string item = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1); + if (methodname.Equals(ProviderMethods.GetChildItems)) + { + WritePSObjectPropertiesAsWSManElementObjects((PSObject)Objcache[item], path, null, null, WsManElementObjectTypes.WSManConfigLeafElement, recurse); + } + else if (methodname.Equals(ProviderMethods.GetChildNames)) + { + foreach (PSPropertyInfo prop in ((PSObject)Objcache[item]).Properties) + { + WriteItemObject(prop.Name, path + WSManStringLiterals.DefaultPathSeparator + prop.Name, false); + } + } + return; + } + + } + + /// + /// Get a Listener or ClientCertificate Item. Used by GEt-Item. + /// + /// + /// + /// + /// + /// + private void GetItemListenerOrCertMapping(string path, XmlDocument xmlResource, string ContainerListenerOrClientCert, string childname, string host) + { + Hashtable Objcache, Keyscache; + if (ContainerListenerOrClientCert.Equals(WSManStringLiterals.containerListener, StringComparison.OrdinalIgnoreCase)) + { + ProcessListernerObjects(xmlResource, out Objcache, out Keyscache); + } + else if (ContainerListenerOrClientCert.Equals(WSManStringLiterals.containerClientCertificate, StringComparison.OrdinalIgnoreCase)) + { + ProcessCertMappingObjects(xmlResource, out Objcache, out Keyscache); + } + else + { return; } + if (null == Objcache || null == Keyscache) + { + return; + } + if (path.EndsWith(host + WSManStringLiterals.DefaultPathSeparator + ContainerListenerOrClientCert, StringComparison.OrdinalIgnoreCase)) + { + if (Objcache.ContainsKey(childname)) + + WriteItemObject(GetItemPSObjectWithTypeName(childname, WSManStringLiterals.ContainerChildValue, null, (string[])Keyscache[childname], null, WsManElementObjectTypes.WSManConfigContainerElement), path + WSManStringLiterals.DefaultPathSeparator + childname, true); + } + else + { + string item = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1); + try + { + WriteItemObject(GetItemPSObjectWithTypeName(((PSObject)Objcache[item]).Properties[childname].Name, ((PSObject)Objcache[item]).Properties[childname].TypeNameOfValue, ((PSObject)Objcache[item]).Properties[childname].Value, null, null, WsManElementObjectTypes.WSManConfigLeafElement), path + WSManStringLiterals.DefaultPathSeparator + childname, false); + } + catch (PSArgumentException) { return; } + } + } + + /// + /// Removes a Listerner or ClientCertificate object. Used by Remove-Item cmdlets. + /// + /// + /// + /// + /// + /// + private void RemoveListenerOrCertMapping(object sessionobj, string WsManUri, string childname, string[] primarykeys, bool IsListener) + { + XmlDocument xmlresources = EnumerateResourceValue(sessionobj, WsManUri); + + if (xmlresources != null) + { + Hashtable KeysCache, ResourcesCache; + if (!IsListener) + { + ProcessCertMappingObjects(xmlresources, out ResourcesCache, out KeysCache); + } + else + { + ProcessListernerObjects(xmlresources, out ResourcesCache, out KeysCache); + } + if (KeysCache.Contains(childname)) + { + PSObject objResource = (PSObject)ResourcesCache[childname]; + Hashtable SelectorParams = new Hashtable(); + foreach (string pKey in primarykeys) + { + SelectorParams.Add(pKey, objResource.Properties[pKey].Value); + } + DeleteResourceValue(sessionobj, WsManUri, SelectorParams, false); + } + } + } + + + /// + /// Used By ItemExists, HasChildItem,IsValidPath, IsItemContainer + /// + /// + /// + private bool CheckValidContainerOrPath(string path) + { + if (path.Length == 0) + { + return true; + } + //if endswith '\', removes it. + + if (path.EndsWith(WSManStringLiterals.DefaultPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase)) + path = path.Remove(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator)); + + string ChildName = String.Empty; + string strpathChk = string.Empty; + + if (path.Contains(WSManStringLiterals.DefaultPathSeparator.ToString())) + { + ChildName = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1); + } + else + { + ChildName = path; + } + + + //Get the wsman host name to find the session object + string host = GetHostName(path); + + if (String.IsNullOrEmpty(host)) + { + return false; + + } + + //Chks the WinRM Service + if (IsPathLocalMachine(host)) + { + if (!IsWSManServiceRunning()) + { + WSManHelper.ThrowIfNotAdministrator(); + StartWSManService(Force); + } + } + + //Get URI to pass to WsMan Automation API + string uri = NormalizePath(path, host); + + if (String.IsNullOrEmpty(uri)) + { + return false; + } + + lock(WSManHelper.AutoSession) + { + object sessionobj = null; + Dictionary SessionObjCache = WSManHelper.GetSessionObjCache(); + SessionObjCache.TryGetValue(host, out sessionobj); + + strpathChk = host + WSManStringLiterals.DefaultPathSeparator; + //Check for host path + if (path.Equals(host, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + if (path.StartsWith(strpathChk + WSManStringLiterals.containerPlugin, StringComparison.OrdinalIgnoreCase)) + { + //Check for Plugin path + if (path.Equals(strpathChk + WSManStringLiterals.containerPlugin, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + XmlDocument outxml = FindResourceValue(sessionobj, uri, null); + string currentpluginname = String.Empty; + GetPluginNames(outxml, out objPluginNames, out currentpluginname, path); + if (String.IsNullOrEmpty(currentpluginname)) + { + return false; + } + string filter = uri + "?Name=" + currentpluginname; + XmlDocument CurrentPluginXML = GetResourceValue(sessionobj, filter, null); + PSObject mshPluginLvl = ProcessPluginConfigurationLevel(CurrentPluginXML); + ArrayList arrSecurities = null; + ArrayList arrResources = ProcessPluginResourceLevel(CurrentPluginXML, out arrSecurities); + ArrayList arrInitParams = ProcessPluginInitParamLevel(CurrentPluginXML); + strpathChk = strpathChk + WSManStringLiterals.containerPlugin + WSManStringLiterals.DefaultPathSeparator + currentpluginname; + if (path.Equals(strpathChk, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + if (path.StartsWith(strpathChk + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerQuotasParameters, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + if (path.StartsWith(strpathChk + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerResources, StringComparison.OrdinalIgnoreCase)) + { + if (path.Equals(strpathChk + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerResources, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + if (null != arrResources) + { + strpathChk = strpathChk + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerResources; + foreach (PSObject objresource in arrResources) + { + string sResourceDirName = objresource.Properties["ResourceDir"].Value.ToString(); + if (path.StartsWith(strpathChk + WSManStringLiterals.DefaultPathSeparator + sResourceDirName, StringComparison.OrdinalIgnoreCase)) + { + if (path.Equals(strpathChk + WSManStringLiterals.DefaultPathSeparator + sResourceDirName, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + else + { + if (objresource.Properties.Match(ChildName).Count > 0) + { + return true; + } + } + if (path.StartsWith(strpathChk + WSManStringLiterals.DefaultPathSeparator + sResourceDirName + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase)) + { + if (path.Equals(strpathChk + WSManStringLiterals.DefaultPathSeparator + sResourceDirName + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + strpathChk = strpathChk + WSManStringLiterals.DefaultPathSeparator + sResourceDirName + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerSecurity + WSManStringLiterals.DefaultPathSeparator; + if (null == arrSecurities) + { + return false; + } + foreach (PSObject security in arrSecurities) + { + string sSecurity = security.Properties["SecurityDIR"].Value.ToString(); + + if (path.Equals(strpathChk + sSecurity, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + else + { + if (security.Properties.Match(ChildName).Count > 0) + { + return true; + } + } + } + + } + } + } + } + } + else if (path.StartsWith(strpathChk + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerInitParameters, StringComparison.OrdinalIgnoreCase)) + { + if (path.Equals(strpathChk + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerInitParameters, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + else + { + if (null != arrInitParams) + { + foreach (PSObject obj in arrInitParams) + { + if (obj.Properties.Match(ChildName).Count > 0) + { + return true; + } + } + } + } + } + else + { + if (mshPluginLvl.Properties.Match(ChildName).Count > 0) + { + return true; + } + } + } + else if (path.StartsWith(strpathChk + WSManStringLiterals.containerListener, StringComparison.OrdinalIgnoreCase)) + { + return ItemExistListenerOrClientCertificate(sessionobj, uri, path, WSManStringLiterals.containerListener, host); + } + else if (path.StartsWith(strpathChk + WSManStringLiterals.containerClientCertificate, StringComparison.OrdinalIgnoreCase)) + { + return ItemExistListenerOrClientCertificate(sessionobj, uri, path, WSManStringLiterals.containerClientCertificate, host); + } + else + { + return (ContainResourceValue(sessionobj, uri, ChildName, path, host)); + } + return false; + } + } + + private bool ItemExistListenerOrClientCertificate(object sessionobj, string ResourceURI, string path, string parentListenerOrCert, string host) + { + XmlDocument outxml = EnumerateResourceValue(sessionobj, ResourceURI); + if (path.Equals(host + WSManStringLiterals.DefaultPathSeparator + parentListenerOrCert, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + if (null == outxml) + { + return false; + } + Hashtable KeysCache=null, objcache=null; + if (parentListenerOrCert.Equals(WSManStringLiterals.containerClientCertificate, StringComparison.OrdinalIgnoreCase)) + { + ProcessCertMappingObjects(outxml, out objcache, out KeysCache); + } + else + { + ProcessListernerObjects(outxml, out objcache, out KeysCache); + } + + String PathChecked = host + WSManStringLiterals.DefaultPathSeparator + parentListenerOrCert; + int pos = PathChecked.Length + 1; + String RemainingPath = path.Substring(pos); + String CurrentNode = null; + pos = RemainingPath.IndexOf(WSManStringLiterals.DefaultPathSeparator); + if (pos == -1) + { + CurrentNode = RemainingPath; + } + else + { + CurrentNode = RemainingPath.Substring(0, pos); + } + + if (objcache.Contains(CurrentNode) == false) + { + return false; + } + + if (pos == -1) + { + //means the path was only till the CurrentNode. Nothing ahead + return true; + } + + //Get the object cache from the listener object + PSObject obj = (PSObject)objcache[CurrentNode]; + + CurrentNode = RemainingPath.Substring(pos+1); + if (CurrentNode.IndexOf(WSManStringLiterals.DefaultPathSeparator) != -1) + { + //No more directories allowed after listeners objects + return false; + } + + if (obj.Properties.Match(CurrentNode).Count > 0) + { + return true; + } + return false; + } + + /// + /// for the recurse operation of Get-ChildItems. + /// + /// + /// + /// + /// + private void GetChildItemsRecurse(string path, string childname, ProviderMethods methodname, bool recurse) + { + if (path.Equals(WSManStringLiterals.rootpath)) + { + path = childname; + } + else + { + path = path + WSManStringLiterals.DefaultPathSeparator + childname; + } + if (HasChildItems(path)) + { + GetChildItemsOrNames(path, ProviderMethods.GetChildItems, recurse); + } + + } + + /// + /// Get the child items or Names. Used by GetChildItems and GetChildNames. + /// + /// + /// + /// + [SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode")] + private void GetChildItemsOrNames(string path, ProviderMethods methodname, bool recurse) + { + Dictionary SessionObjCache = WSManHelper.GetSessionObjCache(); + if (path.Length == 0) + { + switch (methodname) + { + case ProviderMethods.GetChildItems: + PSObject obj = BuildHostLevelPSObjectArrayList(null, "", true); + WritePSObjectPropertiesAsWSManElementObjects(obj, WSManStringLiterals.rootpath, null, + "ComputerLevel", WsManElementObjectTypes.WSManConfigContainerElement, recurse); + break; + case ProviderMethods.GetChildNames: + foreach (string hostname in SessionObjCache.Keys) + { + WriteItemObject(hostname, WSManStringLiterals.rootpath, true); + } + break; + } + return; + } + + //if endswith '\', removes it. + if (path.EndsWith(WSManStringLiterals.DefaultPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase)) + { + path = path.Remove(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator)); + } + + //Get the wsman host name to find the session object + string host = GetHostName(path); + if (String.IsNullOrEmpty(host)) + { + throw new InvalidOperationException("InvalidPath"); + } + + + //Checks the WinRM Service + if (IsPathLocalMachine(host)) + { + if (!IsWSManServiceRunning()) + { + if (methodname.Equals(ProviderMethods.GetChildItems)) + { + WSManHelper.ThrowIfNotAdministrator(); + StartWSManService(Force); + } + else if (methodname.Equals(ProviderMethods.GetChildNames)) + { + AssertError("WinRMServiceError", false); + } + } + } + lock(WSManHelper.AutoSession) + { + object sessionobj; + //gets the sessionobject + SessionObjCache.TryGetValue(host, out sessionobj); + + //Normalize to the required uri + string uri = NormalizePath(path, host); + + string strPathchk = host + WSManStringLiterals.DefaultPathSeparator; + + if (path.EndsWith(host, StringComparison.OrdinalIgnoreCase)) + { + PSObject obj = BuildHostLevelPSObjectArrayList(sessionobj, uri, false); + switch (methodname) + { + //Get the items at Config level + case ProviderMethods.GetChildItems: + WritePSObjectPropertiesAsWSManElementObjects(obj, path, null, null, WsManElementObjectTypes.WSManConfigLeafElement, recurse); + break; + //Get the names of container at config level + case ProviderMethods.GetChildNames: + WritePSObjectPropertyNames(obj, path); + break; + } + return; + } + XmlDocument outxml = FindResourceValue(sessionobj, uri, null); + if (outxml == null || !outxml.HasChildNodes) + { + return; + } + if (path.Contains(strPathchk + WSManStringLiterals.containerListener)) + { + GetChildItemOrNamesForListenerOrCertMapping(outxml, WSManStringLiterals.containerListener, path, host, methodname, recurse); + } + else if (path.Contains(strPathchk + WSManStringLiterals.containerClientCertificate)) + { + GetChildItemOrNamesForListenerOrCertMapping(outxml, WSManStringLiterals.containerClientCertificate, path, host, methodname, recurse); + } + else if (path.Contains(strPathchk + WSManStringLiterals.containerPlugin)) + { + string currentpluginname = String.Empty; + GetPluginNames(outxml, out objPluginNames, out currentpluginname, path); + if (path.EndsWith(strPathchk + WSManStringLiterals.containerPlugin, StringComparison.OrdinalIgnoreCase)) + { + switch (methodname) + { + //Get the items at Plugin level + case ProviderMethods.GetChildItems: + foreach (PSPropertyInfo p in objPluginNames.Properties) + { + PSObject obj = new PSObject(); + obj.Properties.Add(new PSNoteProperty(p.Name, p.Value)); + WritePSObjectPropertiesAsWSManElementObjects(obj, path, new string[] { "Name=" + p.Name }, null, WsManElementObjectTypes.WSManConfigContainerElement, recurse); + //WriteItemObject(new PSObject(new WSManConfigContainerElement(p.Name, p.Value.ToString(), new string[] { "Name=" + p.Name })), path + WSManStringLiterals.DefaultPathSeparator + p.Name, true); + } + break; + //Get the names of container at Plugin level + case ProviderMethods.GetChildNames: + WritePSObjectPropertyNames(objPluginNames, path); + break; + } + return; + } + else + { + string filter = uri + "?Name=" + currentpluginname; + XmlDocument CurrentPluginXML = GetResourceValue(sessionobj, filter, null); + if (null == CurrentPluginXML) + { + return; + } + PSObject objPluginlevel = ProcessPluginConfigurationLevel(CurrentPluginXML, true); + ArrayList arrSecurity = null; + ArrayList arrResources = ProcessPluginResourceLevel(CurrentPluginXML, out arrSecurity); + ArrayList arrInitParams = ProcessPluginInitParamLevel(CurrentPluginXML); + strPathchk = strPathchk + WSManStringLiterals.containerPlugin + WSManStringLiterals.DefaultPathSeparator; + if (path.EndsWith(strPathchk + currentpluginname, StringComparison.OrdinalIgnoreCase)) + { + switch (methodname) + { + //Get the items at Plugin level + case ProviderMethods.GetChildItems: + WritePSObjectPropertiesAsWSManElementObjects(objPluginlevel, path, null, null, WsManElementObjectTypes.WSManConfigLeafElement, recurse); + break; + //Get the names of container at Plugin level + case ProviderMethods.GetChildNames: + WritePSObjectPropertyNames(objPluginlevel, path); + break; + } + return; + + } + else if(path.EndsWith(WSManStringLiterals.containerQuotasParameters, StringComparison.OrdinalIgnoreCase)) + { + // Get the Quotas element from the config XML. + XmlNodeList nodeListForQuotas = CurrentPluginXML.GetElementsByTagName(WSManStringLiterals.containerQuotasParameters); + if (nodeListForQuotas.Count > 0) + { + XmlNode pluginQuotas = nodeListForQuotas[0]; + foreach (XmlAttribute attrOfQuotas in pluginQuotas.Attributes) + { + String pathToAdd = + String.Format( + CultureInfo.InvariantCulture, + "{0}{1}{2}", + path, + WSManStringLiterals.DefaultPathSeparator, + attrOfQuotas.Name); + if (methodname == ProviderMethods.GetChildNames) + { + WriteItemObject(attrOfQuotas.Name, pathToAdd, false); + } + else + { + PSObject objectToAdd = + GetItemPSObjectWithTypeName( + attrOfQuotas.Name, + attrOfQuotas.Value.GetType().ToString(), + attrOfQuotas.Value, + null, + null, + WsManElementObjectTypes.WSManConfigLeafElement); + + WriteItemObject(objectToAdd, pathToAdd, false); + } + } + } + } + else if (path.Contains(strPathchk + currentpluginname + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerResources)) + { + strPathchk = strPathchk + currentpluginname + WSManStringLiterals.DefaultPathSeparator; + if (path.EndsWith(strPathchk + WSManStringLiterals.containerResources, StringComparison.OrdinalIgnoreCase)) + { + if (null != arrResources) + { + foreach (PSObject p in arrResources) + { + switch (methodname) + { + //Get the items at Plugin level + case ProviderMethods.GetChildItems: + string[] key = new string[] { "Uri" + WSManStringLiterals.Equalto + p.Properties["ResourceURI"].Value.ToString() }; + PSObject obj = new PSObject(); + obj.Properties.Add(new PSNoteProperty(p.Properties["ResourceDir"].Value.ToString(), WSManStringLiterals.ContainerChildValue)); + WritePSObjectPropertiesAsWSManElementObjects(obj, path, key, null, WsManElementObjectTypes.WSManConfigContainerElement, recurse); + + + + //WriteItemObject(new WSManConfigContainerElement(p.Properties["ResourceDir"].Value.ToString(), WSManStringLiterals.ContainerChildValue, key), path + WSManStringLiterals.DefaultPathSeparator + p.Properties["ResourceDir"].Value.ToString(), true); + break; + case ProviderMethods.GetChildNames: + WriteItemObject(p.Properties["ResourceDir"].Value.ToString(), path, true); + break; + } + } + return; + } + } + strPathchk = strPathchk + WSManStringLiterals.containerResources + WSManStringLiterals.DefaultPathSeparator; + int Sepindex = path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathchk.Length); + string sResourceDirName = String.Empty; + if (Sepindex == -1) + { + sResourceDirName = path.Substring(strPathchk.Length); + } + else + { + sResourceDirName = path.Substring(strPathchk.Length, path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathchk.Length) - (strPathchk.Length)); + } + + if (null == arrResources) + { + return; + } + if (path.Contains(strPathchk + sResourceDirName)) + { + if (path.EndsWith(strPathchk + sResourceDirName, StringComparison.OrdinalIgnoreCase)) + { + foreach (PSObject p in arrResources) + { + if (sResourceDirName.Equals(p.Properties["ResourceDir"].Value.ToString())) + { + p.Properties.Remove("ResourceDir"); + switch (methodname) + { + //Get the items at Initparams level + case ProviderMethods.GetChildItems: + WritePSObjectPropertiesAsWSManElementObjects(p, path, null, null, WsManElementObjectTypes.WSManConfigLeafElement, recurse); + break; + case ProviderMethods.GetChildNames: + WritePSObjectPropertyNames(p, path); + break; + } + } + } + return; + } + strPathchk = strPathchk + sResourceDirName + WSManStringLiterals.DefaultPathSeparator; + if (path.EndsWith(strPathchk + WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase) || path.Contains(WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerSecurity + "_")) + { + if (null != arrSecurity) + { + foreach (PSObject objsecurity in arrSecurity) + { + if (sResourceDirName.Equals(objsecurity.Properties["ResourceDir"].Value.ToString(), StringComparison.OrdinalIgnoreCase)) + { + if (path.EndsWith(strPathchk + WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase)) + { + objsecurity.Properties.Remove("ResourceDir"); + switch (methodname) + { + //Get the items at Security level + case ProviderMethods.GetChildItems: + string key = "Uri" + WSManStringLiterals.Equalto + objsecurity.Properties["Uri"].Value.ToString(); + PSObject obj = new PSObject(); + obj.Properties.Add(new PSNoteProperty(objsecurity.Properties["SecurityDIR"].Value.ToString(), WSManStringLiterals.ContainerChildValue)); + WritePSObjectPropertiesAsWSManElementObjects(obj, path, new string[] { key }, null, WsManElementObjectTypes.WSManConfigContainerElement, recurse); + //WriteItemObject(new WSManConfigContainerElement(objsecurity.Properties["SecurityDIR"].Value.ToString(), WSManStringLiterals.ContainerChildValue, new string[] { key }), path + WSManStringLiterals.DefaultPathSeparator + objsecurity.Properties["SecurityDIR"].Value.ToString(), true); + + break; + case ProviderMethods.GetChildNames: + WriteItemObject(objsecurity.Properties["SecurityDIR"].Value.ToString(), path, true); + break; + } + } + else + { + string sSecurityDirName = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1, path.Length - (path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1)); + if (sSecurityDirName.Equals(objsecurity.Properties["SecurityDIR"].Value.ToString(), StringComparison.OrdinalIgnoreCase)) + { + objsecurity.Properties.Remove("ResourceDir"); + objsecurity.Properties.Remove("SecurityDIR"); + switch (methodname) + { + //Get the items at Security level + case ProviderMethods.GetChildItems: + WritePSObjectPropertiesAsWSManElementObjects(objsecurity, path, null, null, WsManElementObjectTypes.WSManConfigLeafElement, recurse); + break; + case ProviderMethods.GetChildNames: + WritePSObjectPropertyNames(objsecurity, path); + break; + } + } + } + } + } + } + } + } + } + else if (path.EndsWith(host + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerPlugin + WSManStringLiterals.DefaultPathSeparator + currentpluginname + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerInitParameters, StringComparison.OrdinalIgnoreCase)) + { + if (null == arrInitParams) + { + return; + } + foreach (PSObject p in arrInitParams) + { + switch (methodname) + { + //Get the items at Initparams level + case ProviderMethods.GetChildItems: + WritePSObjectPropertiesAsWSManElementObjects(p, path, null, "InitParams", WsManElementObjectTypes.WSManConfigLeafElement, recurse); + break; + case ProviderMethods.GetChildNames: + WritePSObjectPropertyNames(p, path); + break; + } + } + } + + } + } + else + { + if ((path.EndsWith(WSManStringLiterals.containerService, StringComparison.OrdinalIgnoreCase) || path.EndsWith(WSManStringLiterals.containerTrustedHosts, StringComparison.OrdinalIgnoreCase) + || path.EndsWith(WSManStringLiterals.containerClient, StringComparison.OrdinalIgnoreCase) || path.EndsWith(WSManStringLiterals.containerDefaultPorts, StringComparison.OrdinalIgnoreCase) + || path.EndsWith(WSManStringLiterals.containerAuth, StringComparison.OrdinalIgnoreCase) || path.EndsWith(WSManStringLiterals.containerShell, StringComparison.OrdinalIgnoreCase))) + { + foreach (XmlNode node in outxml.ChildNodes) + { + PSObject mshObject = ConvertToPSObject(node); + switch (methodname) + { + case ProviderMethods.GetChildItems: + WritePSObjectPropertiesAsWSManElementObjects(mshObject, path, null, null, WsManElementObjectTypes.WSManConfigLeafElement, recurse); + break; + case ProviderMethods.GetChildNames: + WritePSObjectPropertyNames(mshObject, path); + break; + } + } + } + } + } + } + + /// + /// Get the Plugin names from the WsMan Config file. + /// + /// + /// + /// + /// + /// + private int GetPluginNames(XmlDocument xmlPlugins, out PSObject PluginNames, out string CurrentPluginName, string path) + { + PluginNames = new PSObject(); + CurrentPluginName = String.Empty; + + // If the execution is reached this point ... that means the path should for plugins directory (..\Plugins...). + if (!path.Contains(WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerPlugin)) + { + return 0; + } + + // The path will be something like \Plugin\\... + string[] splitPath = path.Split(WSManStringLiterals.DefaultPathSeparator); + + XmlNodeList pluginNodeList = xmlPlugins.GetElementsByTagName("PlugInConfiguration"); + + foreach (XmlElement e in pluginNodeList) + { + for (int i = 0; i <= e.Attributes.Count - 1; i++) + { + if (e.Attributes[i].LocalName.Equals("Name")) + { + PluginNames.Properties.Add(new PSNoteProperty(e.Attributes[i].Value, WSManStringLiterals.ContainerChildValue)); + + // If the path contains \plugin and splitLength is greater than 3 then splitLenght[2] will be plugin Name. + if (splitPath.Length >= 3 && splitPath[2].Equals(e.Attributes[i].Value, StringComparison.OrdinalIgnoreCase)) + { + CurrentPluginName = e.Attributes[i].Value; + } + } + } + } + + return pluginNodeList.Count; + } + + /// + /// All Error are thrown using this method. + /// + /// + /// + private void AssertError(string ErrorMessage, bool IsWSManError) + { + if (IsWSManError) + { + XmlDocument ErrorDoc = new XmlDocument(); + ErrorDoc.LoadXml(ErrorMessage); + XmlNodeList errornodelist = ErrorDoc.GetElementsByTagName("f:Message"); + foreach (XmlNode node in errornodelist) + { + InvalidOperationException ex = new InvalidOperationException(node.InnerText); + ErrorRecord er = new ErrorRecord(ex, "WsManError", ErrorCategory.InvalidOperation, null); + ThrowTerminatingError(er); + } + } + else + { + InvalidOperationException ex = new InvalidOperationException(ErrorMessage); + ErrorRecord er = new ErrorRecord(ex, "WsManError", ErrorCategory.InvalidOperation, null); + ThrowTerminatingError(er); + } + } + + /// + /// Checks whether WsMan Service is running. + /// + /// + private bool IsWSManServiceRunning() + { +#if CORECLR + // TODO once s78 comes in undo this + return true; +#else + ServiceController svc = new ServiceController("WinRM"); + if (svc != null) + { + if (svc.Status.Equals(ServiceControllerStatus.Running)) + { + return true; + } + } + return false; +#endif + } + + /// + /// Starts the WsMan service. + /// + /// + private void StartWSManService(bool force) + { + try + { + string startserviceScript = string.Format(CultureInfo.InvariantCulture, WSManStringLiterals.StartWinrmServiceSBFormat); + ScriptBlock startserviceSb = ScriptBlock.Create(startserviceScript); + Collection result = startserviceSb.Invoke(force, helper.GetResourceMsgFromResourcetext("WSManServiceStartCaption"), helper.GetResourceMsgFromResourcetext("WSManServiceStartQuery")); + if (!(bool)result[0].ImmediateBaseObject) + { + AssertError(helper.GetResourceMsgFromResourcetext("WinRMServiceError"), false); + } + } + catch (CmdletInvocationException) + { + //Eating cmdlet invocation exception. The exception is thrown when No is given. + } + } + + /// + /// Checks whether localmachine or not. If this returns true only we start the service. + /// + /// + /// + private bool IsPathLocalMachine(string host) + { + bool hostfound = false; + //Check is Localhost + if (host.Equals("localhost", StringComparison.OrdinalIgnoreCase)) + { + hostfound = true; + } + + // Domain look up not available on CoreCLR? +#if !CORECLR + //Check is TestMac + if (!hostfound) + { + if (host.Equals(System.Net.Dns.GetHostName(), StringComparison.OrdinalIgnoreCase)) + { + hostfound = true; + } + } + + //Check is TestMac.redmond.microsoft.corp.com + if (!hostfound) + { + System.Net.IPHostEntry hostentry = System.Net.Dns.GetHostEntry("localhost"); + if (host.Equals(hostentry.HostName, StringComparison.OrdinalIgnoreCase)) + { + hostfound = true; + } + + //Check is 127.0.0.1 or ::1 + if (!hostfound) + { + foreach (System.Net.IPAddress ipaddress in hostentry.AddressList) + { + if (ipaddress.ToString().Equals(host, StringComparison.OrdinalIgnoreCase)) + { + hostfound = true; + } + } + } + } + + //check if any IPAddress. + if (!hostfound) + { + foreach (System.Net.IPAddress ipaddress in System.Net.Dns.GetHostAddresses(System.Net.Dns.GetHostName())) + { + if (ipaddress.ToString().Equals(host, StringComparison.OrdinalIgnoreCase)) + { + hostfound = true; + } + } + } +#endif + return hostfound; + } + + #region Plugin private functions + + private void GenerateObjectNameAndKeys(Hashtable InputAttributes, string ResourceURI, string ContainerItem, out string ItemName, out string[] keys) + { + StringBuilder sbHashKey = new StringBuilder(); + string keysColumns = String.Empty; + foreach (DictionaryEntry attribute in InputAttributes) + { + if (IsPKey(attribute.Key.ToString(), ResourceURI)) + { + sbHashKey.Append(attribute.Key.ToString()); + sbHashKey.Append(WSManStringLiterals.Equalto); + sbHashKey.Append(attribute.Value.ToString()); + keysColumns = keysColumns + attribute.Key.ToString() + WSManStringLiterals.Equalto + attribute.Value.ToString() + "|"; + } + else + { + if (ContainerItem.Equals("Listener", StringComparison.OrdinalIgnoreCase) + && attribute.Key.ToString().Equals("Port", StringComparison.OrdinalIgnoreCase)) + { + // we add the Port number when generating the name in order + // be distinguish compatiblity listeners which might have the same + // real key (address and port) as a real listener + sbHashKey.Append(attribute.Key.ToString()); + sbHashKey.Append(WSManStringLiterals.Equalto); + sbHashKey.Append(attribute.Value.ToString()); + } + } + } + + keysColumns = keysColumns.Substring(0, keysColumns.LastIndexOf('|')); + ItemName = ContainerItem + "_" + Math.Abs(sbHashKey.ToString().GetHashCode()); + keys = keysColumns.Split('|'); + } + + + private void ProcessCertMappingObjects(XmlDocument xmlCerts, out Hashtable Certcache, out Hashtable Keyscache) + { + Hashtable lCache = new Hashtable(); + Hashtable kCache = new Hashtable(); + XmlNodeList xmlnodesCerts = xmlCerts.GetElementsByTagName("cfg:" + "CertMapping"); + if (null == xmlnodesCerts) + { + Certcache = null; + Keyscache = null; + return; + } + foreach (XmlNode node in xmlnodesCerts) + { + Hashtable InputAttributes = new Hashtable(); + PSObject objCerts = new PSObject(); + string[] keys = null; + string ItemName = String.Empty; + foreach (XmlNode childnode in node.ChildNodes) + { + // if (childnode.LocalName.Equals("URI")) + // { + + // //sbCerts.Append(childnode.LocalName); + // //sbCerts.Append(WSManStringLiterals.Equalto); + // //sbCerts.Append(childnode.InnerText); + // //keys[0] = childnode.LocalName + WSManStringLiterals.Equalto + childnode.InnerText; + // } + // else if (childnode.LocalName.Equals("Subject")) + // { + // //sbCerts.Append(childnode.LocalName); + // //sbCerts.Append(WSManStringLiterals.Equalto); + // //sbCerts.Append(childnode.InnerText); + // //keys[1] = childnode.LocalName + WSManStringLiterals.Equalto + childnode.InnerText; + // } + // else if (childnode.LocalName.Equals("Issuer")) + // { + // //sbCerts.Append(childnode.LocalName); + // //sbCerts.Append(WSManStringLiterals.Equalto); + // //sbCerts.Append(childnode.InnerText); + // //keys[2] = childnode.LocalName + WSManStringLiterals.Equalto + childnode.InnerText; + // } + InputAttributes.Add(childnode.LocalName, childnode.InnerText); + objCerts.Properties.Add(new PSNoteProperty(childnode.LocalName, childnode.InnerText)); + } + GenerateObjectNameAndKeys(InputAttributes, WSManStringLiterals.containerCertMapping, WSManStringLiterals.containerClientCertificate, out ItemName, out keys); + //lCache.Add(WSManStringLiterals.containerClientCertificate + "_" + Math.Abs(sbCerts.ToString().GetHashCode()), objCerts); + lCache.Add(ItemName, objCerts); + kCache.Add(ItemName, keys); + //kCache.Add(WSManStringLiterals.containerClientCertificate + "_" + Math.Abs(sbCerts.ToString().GetHashCode()), keys); + } + Certcache = lCache; + Keyscache = kCache; + } + + private void ProcessListernerObjects(XmlDocument xmlListeners, out Hashtable listenercache, out Hashtable Keyscache) + { + Hashtable lCache = new Hashtable(); + Hashtable kCache = new Hashtable(); + XmlNodeList xmlnodesListeners = xmlListeners.GetElementsByTagName("cfg:" + WSManStringLiterals.containerListener); + if (null == xmlnodesListeners) + { + listenercache = null; + Keyscache = null; + return; + } + foreach (XmlNode node in xmlnodesListeners) + { + Hashtable InputAttributes = new Hashtable(); + PSObject objListener = new PSObject(); + string[] Keys = null; + string ItemName = String.Empty; + foreach (XmlNode childnode in node.ChildNodes) + { + //if (childnode.LocalName.Equals("Address")) + //{ + // sbListener.Append(childnode.LocalName); + // sbListener.Append(WSManStringLiterals.Equalto); + // sbListener.Append(childnode.InnerText); + // Keys[0] = childnode.LocalName + WSManStringLiterals.Equalto + childnode.InnerText; + // objListener.Properties.Add(new PSNoteProperty(childnode.LocalName, childnode.InnerText)); + //} + //else if (childnode.LocalName.Equals("Transport")) + //{ + // sbListener.Append(childnode.LocalName); + // sbListener.Append(WSManStringLiterals.Equalto); + // sbListener.Append(childnode.InnerText); + // Keys[1] = childnode.LocalName + WSManStringLiterals.Equalto + childnode.InnerText; + // objListener.Properties.Add(new PSNoteProperty(childnode.LocalName, childnode.InnerText)); + //} + if (childnode.LocalName.Equals("ListeningOn")) + { + string ListeningOnItem = childnode.LocalName + "_" + Math.Abs(childnode.InnerText.GetHashCode()); + objListener.Properties.Add(new PSNoteProperty(ListeningOnItem, childnode.InnerText)); + InputAttributes.Add(ListeningOnItem, childnode.InnerText); + } + else + { + InputAttributes.Add(childnode.LocalName, childnode.InnerText); + objListener.Properties.Add(new PSNoteProperty(childnode.LocalName, childnode.InnerText)); + } + } + GenerateObjectNameAndKeys(InputAttributes, WSManStringLiterals.containerListener, WSManStringLiterals.containerListener, out ItemName, out Keys); + //lCache.Add(WSManStringLiterals.containerListener + "_" + Math.Abs(sbListener.ToString().GetHashCode()), objListener); + lCache.Add(ItemName, objListener); + kCache.Add(ItemName, Keys); + //kCache.Add(WSManStringLiterals.containerListener + "_" + Math.Abs(sbListener.ToString().GetHashCode()), Keys); + } + listenercache = lCache; + Keyscache = kCache; + } + + private PSObject ProcessPluginConfigurationLevel(XmlDocument xmldoc, bool setRunasPasswordAsSecureString = false) + { + PSObject objConfiglvl = null; + + if (null != xmldoc) + { + XmlNodeList nodelistPlugin = xmldoc.GetElementsByTagName("PlugInConfiguration"); + if (nodelistPlugin.Count > 0) + { + objConfiglvl = new PSObject(); + XmlAttributeCollection attributecol = nodelistPlugin.Item(0).Attributes; + + XmlNode runAsUserNode = attributecol.GetNamedItem(WSManStringLiterals.ConfigRunAsUserName); + bool runAsUserPresent = runAsUserNode != null && !String.IsNullOrEmpty(runAsUserNode.Value); + + for (int i = 0; i <= attributecol.Count - 1; i++) + { + if (String.Equals(attributecol[i].LocalName, WSManStringLiterals.ConfigRunAsPasswordName, StringComparison.OrdinalIgnoreCase) + && runAsUserPresent + && setRunasPasswordAsSecureString) + { + objConfiglvl.Properties.Add(new PSNoteProperty(attributecol[i].LocalName, new SecureString())); + } + else + { + objConfiglvl.Properties.Add(new PSNoteProperty(attributecol[i].LocalName, attributecol[i].Value)); + } + } + } + //Containers in Plugin Level Configs + if (objConfiglvl != null) + { + objConfiglvl.Properties.Add(new PSNoteProperty("InitializationParameters", WSManStringLiterals.ContainerChildValue)); + objConfiglvl.Properties.Add(new PSNoteProperty("Resources", WSManStringLiterals.ContainerChildValue)); + objConfiglvl.Properties.Add(new PSNoteProperty(WSManStringLiterals.containerQuotasParameters, WSManStringLiterals.ContainerChildValue)); + } + } + + return objConfiglvl; + } + + private ArrayList ProcessPluginResourceLevel(XmlDocument xmldoc, out ArrayList arrSecurity) + { + ArrayList Resources = null; + ArrayList nSecurity = null; + if (null != xmldoc) + { + XmlNodeList xmlpluginResource = xmldoc.GetElementsByTagName("Resource"); + if (xmlpluginResource.Count > 0) + { + Resources = new ArrayList(); + nSecurity = new ArrayList(); + foreach (XmlElement xe in xmlpluginResource) + { + PSObject objResource = new PSObject(); + string strUniqueResourceId = string.Empty; + XmlAttributeCollection attributecol = xe.Attributes; + bool ExactMatchFound = false; + bool SupportsOptionsFound = false; + string resourceUri = String.Empty; + + for (int i = 0; i <= attributecol.Count - 1; i++) + { + if (attributecol[i].LocalName.Equals("ResourceUri", StringComparison.OrdinalIgnoreCase)) + { + resourceUri = attributecol[i].Value; + strUniqueResourceId = "Resource_" + Convert.ToString(Math.Abs(attributecol[i].Value.GetHashCode()), CultureInfo.InvariantCulture); + objResource.Properties.Add(new PSNoteProperty("ResourceDir", strUniqueResourceId)); + + } + if (attributecol[i].LocalName.Equals("ExactMatch", StringComparison.OrdinalIgnoreCase)) + { + objResource.Properties.Add(new PSNoteProperty(attributecol[i].LocalName, attributecol[i].Value)); + ExactMatchFound = true; + continue; + } + if (attributecol[i].LocalName.Equals("SupportsOptions", StringComparison.OrdinalIgnoreCase)) + { + objResource.Properties.Add(new PSNoteProperty(attributecol[i].LocalName, attributecol[i].Value)); + SupportsOptionsFound = true; + continue; + } + objResource.Properties.Add(new PSNoteProperty(attributecol[i].LocalName, attributecol[i].Value)); + } + if (!ExactMatchFound) + { + objResource.Properties.Add(new PSNoteProperty("ExactMatch", false)); + } + if (!SupportsOptionsFound) + { + objResource.Properties.Add(new PSNoteProperty("SupportsOptions", false)); + } + + + //Processing capabilities + + XmlDocument xmlCapabilities = new XmlDocument(); + xmlCapabilities.LoadXml("" + xe.InnerXml + ""); + XmlNodeList nodeCapabilities = xmlCapabilities.GetElementsByTagName("Capability"); + object[] enumcapability = null; + if (nodeCapabilities.Count > 0) + { + enumcapability = new object[nodeCapabilities.Count]; + for (int i = 0; i < nodeCapabilities.Count; i++) + { + enumcapability.SetValue(nodeCapabilities[i].Attributes["Type"].Value, i); + } + } + objResource.Properties.Add(new PSNoteProperty("Capability", enumcapability)); + objResource.Properties.Add(new PSNoteProperty(WSManStringLiterals.containerSecurity, WSManStringLiterals.ContainerChildValue)); + + //Process Security in Resources. We add the resource Unique ID in to each security to + //identify in the Provider methods. + nSecurity = ProcessPluginSecurityLevel(nSecurity, xmlCapabilities, strUniqueResourceId, resourceUri); + Resources.Add(objResource); + } + + } + } + arrSecurity = nSecurity; + return Resources; + } + + private ArrayList ProcessPluginInitParamLevel(XmlDocument xmldoc) + { + ArrayList InitParamLvl = null; + if (null != xmldoc) + { + XmlNodeList nodelistInitParam = xmldoc.GetElementsByTagName("Param"); + if (nodelistInitParam.Count > 0) + { + InitParamLvl = new ArrayList(); + foreach (XmlElement xe in nodelistInitParam) + { + PSObject objInitParam = new PSObject(); + XmlAttributeCollection attributecol = xe.Attributes; + String Name = String.Empty; + String Value = String.Empty; + for (int i = 0; i <= attributecol.Count - 1; i++) + { + if (attributecol[i].LocalName.Equals("Name", StringComparison.OrdinalIgnoreCase)) + { + Name = attributecol[i].Value; + } + if (attributecol[i].LocalName.Equals("Value", StringComparison.OrdinalIgnoreCase)) + { + String ValueAsXML = attributecol[i].Value; +#if CORECLR + //SecurityElement.Escape() not supported on .NET Core, use WebUtility.HtmlEncode() to replace. + //During the encoding, single quote "\'" convert to "'", then manually convert "'" to "'" since we are encode xml not html; + Value = System.Net.WebUtility.HtmlEncode(ValueAsXML); + Value = Value.Replace("'", "'"); +#else + Value = SecurityElement.Escape(ValueAsXML); +#endif + } + } + objInitParam.Properties.Add(new PSNoteProperty(Name, Value)); + InitParamLvl.Add(objInitParam); + } + } + } + return InitParamLvl; + } + + private ArrayList ProcessPluginSecurityLevel(ArrayList arrSecurity, XmlDocument xmlSecurity, string UniqueResourceID, string ParentResourceUri) + { + // ArrayList SecurityLvl = null; + if (xmlSecurity != null) + { + XmlNodeList nodelistSecutiry = xmlSecurity.GetElementsByTagName(WSManStringLiterals.containerSecurity); + if (nodelistSecutiry.Count > 0) + { + //SecurityLvl = new ArrayList(); + foreach (XmlElement xe in nodelistSecutiry) + { + bool ExactMatchFound = false; + PSObject objSecurity = new PSObject(); + XmlAttributeCollection attributecol = xe.Attributes; + + for (int i = 0; i <= attributecol.Count - 1; i++) + { + if (attributecol[i].LocalName.Equals("Uri", StringComparison.OrdinalIgnoreCase)) + { + objSecurity.Properties.Add(new PSNoteProperty("SecurityDIR", "Security_" + Math.Abs(UniqueResourceID.GetHashCode()))); + } + if (attributecol[i].LocalName.Equals("ExactMatch", StringComparison.OrdinalIgnoreCase)) + { + objSecurity.Properties.Add(new PSNoteProperty(attributecol[i].LocalName, attributecol[i].Value)); + ExactMatchFound = true; + continue; + } + objSecurity.Properties.Add(new PSNoteProperty(attributecol[i].LocalName, attributecol[i].Value)); + } + if (!ExactMatchFound) + { + objSecurity.Properties.Add(new PSNoteProperty("ExactMatch", false)); + } + objSecurity.Properties.Add(new PSNoteProperty("ResourceDir", UniqueResourceID)); + objSecurity.Properties.Add(new PSNoteProperty("ParentResourceUri", ParentResourceUri)); + + arrSecurity.Add(objSecurity); + } + } + } + return arrSecurity; + } + + /// + /// This method constructs the Configuration XML from the PSObject. + /// For RunAsPassword, if the value is not of type SecureString or the value is not present + /// then an Empty string is added as value. The caller of this method MUST make sure that + /// the RunAsPassword (if updated) is of type SecureString. + /// + /// PSObject, from which XML will be produced. + /// Resource URI for the XML. + /// Name of the Host. + /// Type of Operation. + ///List of Resources. + ///List of Securities + ///List of initialization parameters. + /// An Configuration XML, ready to send to server. + private string ConstructPluginXml(PSObject objinputparam, string ResourceURI, string host, string Operation, ArrayList resources, ArrayList securities, ArrayList initParams) + { + + StringBuilder sbvalues = new StringBuilder(); + sbvalues.Append(" + sbvalues.Append(WSManStringLiterals.GreaterThan); + if (Operation.Equals("New")) + { + if (objinputparam != null) + sbvalues.Append(ConstructResourceXml(objinputparam, null, null)); + else + sbvalues.Append(ConstructResourceXml(null, resources, null)); + } + else if (Operation.Equals("Set")) + { + if (initParams != null) + sbvalues.Append(ConstructInitParamsXml(null, initParams)); + if (resources != null) + sbvalues.Append(ConstructResourceXml(null, resources, securities)); + } + sbvalues.Append(""); + return sbvalues.ToString(); + } + + /// + /// PS wraps most of the parameters to Item cmdlets in PSObject. These values are passed as 'Object'. + /// This method unwraps the PSObjects and returns the base object as the required Type for the given + /// configuration name as follows: + /// RunAsUser - PSCredential + /// RunAsPassword - SecureString + /// If the object provided by user is not of required type the method return Null. + /// If the object is not PSObject, the method returns the 'value'. + /// + /// Name of the configuration setting. + /// Object provided by User. + /// Object of the required type or Null. + private object ValidateAndGetUserObject(string configurationName, object value) + { + PSObject basePsObject = value as PSObject; + + if (configurationName.Equals(WSManStringLiterals.ConfigRunAsPasswordName, StringComparison.OrdinalIgnoreCase)) + { + if (basePsObject != null && basePsObject.BaseObject is SecureString) + { + return basePsObject.BaseObject as SecureString; + } + else + { + string error = String.Format( + helper.GetResourceMsgFromResourcetext("InvalidValueType"), + WSManStringLiterals.ConfigRunAsPasswordName, + typeof(SecureString).FullName); + + AssertError(error, false); + return null; + } + } + else if (configurationName.Equals(WSManStringLiterals.ConfigRunAsUserName, StringComparison.OrdinalIgnoreCase)) + { + if (basePsObject != null && basePsObject.BaseObject is PSCredential) + { + return basePsObject.BaseObject as PSCredential; + } + else + { + string error = String.Format( + helper.GetResourceMsgFromResourcetext("InvalidValueType"), + WSManStringLiterals.ConfigRunAsUserName, + typeof(PSCredential).FullName); + + AssertError(error, false); + return null; + } + } + + return value; + } + + /// + /// Appends the plain text value of a SecureString variable to the StringBuilder. + /// if the propertyValue provided is not SecureString appends empty string. + /// + /// Value to append + private string GetStringFromSecureString(object propertyValue) + { + SecureString value = propertyValue as SecureString; + string passwordValueToAdd = String.Empty; + + if (value != null) + { +#if !CORECLR + //coreCLR only supports marshal for unicode + IntPtr ptr = Marshal.SecureStringToBSTR(value); + passwordValueToAdd = Marshal.PtrToStringAuto(ptr); + Marshal.ZeroFreeBSTR(ptr); +#else + IntPtr ptr = SecureStringMarshal.SecureStringToCoTaskMemUnicode(value); + passwordValueToAdd = Marshal.PtrToStringUni(ptr); + Marshal.ZeroFreeCoTaskMemAnsi(ptr); +#endif + + + } + + return passwordValueToAdd; + } + + private string ConstructResourceXml(PSObject objinputparams, ArrayList resources, ArrayList securities) + { + StringBuilder sbvalues = new StringBuilder(""); + if (objinputparams == null && resources == null) + { + return sbvalues.ToString(); + } + object[] capability = null; + sbvalues.Append(""); + if (objinputparams != null) + { + sbvalues.Append(""); + } + else + { + foreach (PSObject p in resources) + { + sbvalues.Append(""); + } + } + sbvalues.Append(""); + return sbvalues.ToString(); + } + + private string ConstructSecurityXml(PSObject objinputparams, ArrayList securities, string strResourceIdentity) + { + // + StringBuilder sbvalues = new StringBuilder(""); + if (objinputparams == null && securities == null) + { + return sbvalues.ToString(); + } + if (objinputparams != null) + { + AddSecurityProperties(objinputparams.Properties, sbvalues); + } + else + { + foreach (PSObject p in securities) + { + if (p.Properties["ResourceDir"].Value.ToString().Equals(strResourceIdentity)) + { + AddSecurityProperties(p.Properties, sbvalues); + } + } + } + return sbvalues.ToString(); + } + + private void AddSecurityProperties( + PSMemberInfoCollection properties, + StringBuilder sbValues) + { + sbValues.Append(""); + } + + private string ConstructInitParamsXml(PSObject objinputparams, ArrayList initparams) + { + // + // + // + StringBuilder sbvalues = new StringBuilder(""); + if (objinputparams == null && initparams == null) + { + return sbvalues.ToString(); + } + sbvalues.Append(""); + if (objinputparams != null) + { + foreach (PSPropertyInfo prop in objinputparams.Properties) + { + sbvalues.Append(""); + return sbvalues.ToString(); + } + + private string ConstructCapabilityXml(object[] capabilities) + { + StringBuilder sbvalues = new StringBuilder(""); + foreach (object cap in capabilities) + { + sbvalues.Append(""); + } + return sbvalues.ToString(); + } + + private bool IsValueOfParamList(string name, string[] paramcontainer) + { + bool result = false; + foreach (string value in paramcontainer) + { + if (value.Equals(name, StringComparison.OrdinalIgnoreCase)) + { + result = true; + break; + } + } + return result; + } + +#endregion Plugin private functions + + enum ProviderMethods + { + GetChildItems, + GetChildNames + + }; + + enum WsManElementObjectTypes + { + WSManConfigElement, + WSManConfigContainerElement, + WSManConfigLeafElement + }; + +#region def + private static readonly string[] WinrmRootName = new string[] { "winrm/Config" }; + private static readonly string[] WinRmRootConfigs = new string[] { + "Client", + "Service", + "Shell", + "Listener", + "Plugin", + "ClientCertificate" + + }; + + //Defining Primarykeys for resource uri's + private static readonly string[] PKeyListener = new string[] { "Address", "Transport" }; + private static readonly string[] PKeyPlugin = new string[] { "Name" }; + private static readonly string[] PKeyCertMapping = new string[] { "Issuer", "Subject", "Uri" }; + + /// + /// In PPQ display warnings for these configurations. + /// + private static readonly List ppqWarningConfigurations = new List + { + "idletimeoutms", + "maxprocessespershell", + "maxmemorypershellmb", + "maxshellsperuser", + "maxconcurrentusers" + }; + + /// + /// Display warning for these configurations. + /// + private static readonly List globalWarningConfigurations = new List + { + "maxconcurrentoperationsperuser", + "idletimeout", + "maxprocessespershell", + "maxmemorypershellmb", + "maxshellsperuser", + "maxconcurrentusers" + }; + + /// + /// Display warning for these URIs. + /// + private static readonly List globalWarningUris = + new List { + WinrmRootName[0].ToString() + WSManStringLiterals.WinrmPathSeparator + WSManStringLiterals.containerWinrs, + WinrmRootName[0].ToString() + WSManStringLiterals.WinrmPathSeparator + WSManStringLiterals.containerService}; + +#endregion def + +#endregion private + + } + +#region "Dynamic Parameter Classes" + +#region "New-Item Dynamic Parameters" + + /// + /// Computer dynamic parameters. This is similar to connect-wsman parameters. + /// Available path wsman:\> + /// + public class WSManProviderNewItemComputerParameters + { + + /// + /// The following is the definition of the input parameter "OptionSet". + /// OptionSet is a hash table and is used to pass a set of switches to the + /// service to modify or refine the nature of the request. + /// + [Parameter] + [ValidateNotNullOrEmpty] + [Alias("OS")] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public Hashtable OptionSet + { + get { return optionset; } + set { optionset = value; } + } + private Hashtable optionset; + + + /// + /// The following is the definition of the input parameter "Authentication". + /// This parameter takes a set of authentication methods the user can select + /// from. The available method are an enum called Authentication in the + /// System.Management.Automation.Runspaces namespace. The available options + /// should be as follows: + /// - Default : Use the default authentication (ad defined by the underlying + /// protocol) for establishing a remote connection. + /// - Negotiate + /// - Kerberos + /// - Basic: Use basic authentication for establishing a remote connection. + /// -CredSSP: Use CredSSP authentication for establishing a remote connection + /// which will enable the user to perform credential delegation. (i.e. second + /// hop) + /// + [Parameter] + [ValidateNotNullOrEmpty] + public AuthenticationMechanism Authentication + { + get { return authentication; } + set { authentication = value; } + } + private AuthenticationMechanism authentication = AuthenticationMechanism.Default; + + /// + /// Specifies the certificate thumbprint to be used to impersonate the user on the + /// remote machine. + /// + [Parameter] + [ValidateNotNullOrEmpty] + public string CertificateThumbprint + { + get { return thumbPrint; } + set { thumbPrint = value; } + } + private string thumbPrint = null; + + /// + /// The following is the definition of the input parameter "SessionOption". + /// Defines a set of extended options for the WSMan session. This hashtable can + /// be created using New-WSManSessionOption + /// + [Parameter] + [ValidateNotNullOrEmpty] + [Alias("SO")] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public SessionOption SessionOption + { + get { return sessionoption; } + set { sessionoption = value; } + } + private SessionOption sessionoption; + + /// + /// The following is the definition of the input parameter "ApplicationName". + /// ApplicationName identifies the remote endpoint. + /// + [Parameter(ParameterSetName = "nameSet")] + [ValidateNotNullOrEmpty] + public String ApplicationName + { + get { return applicationname; } + set { applicationname = value; } + } + private String applicationname = "wsman"; + + /// + /// The following is the definition of the input parameter "Port". + /// Specifies the port to be used when connecting to the ws management service. + /// + [Parameter] + [ValidateNotNullOrEmpty] + [Parameter(ParameterSetName = "nameSet")] + [ValidateRange(1, Int32.MaxValue)] + public Int32 Port + { + get { return port; } + set { port = value; } + } + private Int32 port = 0; + + /// + /// The following is the definition of the input parameter "UseSSL". + /// Uses the Secure Sockets Layer (SSL) protocol to establish a connnection to + /// the remote computer. If SSL is not available on the port specified by the + /// Port parameter, the command fails. + /// + [Parameter(ParameterSetName = "nameSet")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SSL")] + public SwitchParameter UseSSL + { + get { return usessl; } + set { usessl = value; } + } + private SwitchParameter usessl; + + /// + /// The following is the definition of the input parameter "ConnectionURI". + /// Specifies the transport, server, port, and ApplicationName of the new + /// runspace. The format of this string is: + /// transport://server:port/ApplicationName. + /// + [Parameter(ParameterSetName = "pathSet", Mandatory = true)] + [ValidateNotNullOrEmpty] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")] + public Uri ConnectionURI + { + get { return connectionuri; } + set { connectionuri = value; } + } + private Uri connectionuri; + + } + + /// + /// Plugin Dynamic parameter. There are 2 parameter sets. + /// Path - WSMan:\Localhost\Plugin> + /// + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Plugin")] + public class WSManProviderNewItemPluginParameters + { + /// + /// Parameter Plugin. + /// + [Parameter(Mandatory = true, ParameterSetName = "pathSet")] + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Plugin")] + [ValidateNotNullOrEmpty] + public string Plugin + { + get { return _plugin; } + set { _plugin = value; } + } + private string _plugin; + + /// + /// Parameter FileName. + /// + [Parameter(Mandatory = true, ParameterSetName = "pathSet")] + [ValidateNotNullOrEmpty] + public string FileName + { + get { return _filename; } + set { _filename = value; } + } + private string _filename; + + /// + /// Parameter SDKVersion. + /// + [Parameter(Mandatory = true, ParameterSetName = "pathSet")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SDK")] + [ValidateNotNullOrEmpty] + public string SDKVersion + { + get { return _sdkversion; } + set { _sdkversion = value; } + } + private string _sdkversion; + + /// + /// Parameter Resource. + /// + [Parameter(Mandatory = true, ParameterSetName = "pathSet")] + [ValidateNotNullOrEmpty] + public System.Uri Resource + { + get { return _resourceuri; } + set { _resourceuri = value; } + } + private System.Uri _resourceuri; + + /// + /// Parameter Capability. + /// + [Parameter(Mandatory = true, ParameterSetName = "pathSet")] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + [ValidateNotNullOrEmpty] + public object[] Capability + { + get { return _capability; } + set { _capability = value; } + } + private object[] _capability; + + /// + /// Parameter XMLRenderingType. + /// + [Parameter(Mandatory = true, ParameterSetName = "pathSet")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "XML")] + [ValidateNotNullOrEmpty] + public string XMLRenderingType + { + get { return _xmlRenderingtype; } + set { _xmlRenderingtype = value; } + } + private string _xmlRenderingtype; + + /// + /// Parameter File. + /// + [Parameter(Mandatory = true, ParameterSetName = "nameSet")] + [ValidateNotNullOrEmpty] + public string File + { + get { return _file; } + set { _file = value; } + } + private string _file; + + /// + /// Parameter for RunAs credentials for a Plugin. + /// + [ValidateNotNull] + [Parameter()] + public PSCredential RunAsCredential + { + get { return this.runAsCredentials; } + set { this.runAsCredentials = value; } + } + private PSCredential runAsCredentials; + + /// + /// Parameter for Plugin Host Process configuration (Shared or Saperate). + /// + [Parameter()] + public SwitchParameter UseSharedProcess + { + get { return this.sharedHost; } + set { this.sharedHost = value; } + } + private bool sharedHost; + + /// + /// Parameter for Auto Restart configuration for Plugin. + /// + [Parameter()] + public SwitchParameter AutoRestart + { + get { return this.autoRestart; } + set { this.autoRestart = value; } + } + private bool autoRestart; + + /// + /// Parameter for Idle timeout for HostProcess. + /// + [Parameter()] + public uint? ProcessIdleTimeoutSec + { + get + { + return this.processIdleTimeoutSeconds; + } + set + { + this.processIdleTimeoutSeconds = value; + } + } + private uint? processIdleTimeoutSeconds; + } + + /// + /// Initparameters dynamic parameters + /// Path - wsman:\localhost\plugin\[specified plugin]\Initializationparameters> + /// + public class WSManProviderInitializeParameters + { + + /// + /// Parameter ParamName. + /// + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Param")] + [Parameter(Mandatory = true, Position = 0)] + [ValidateNotNullOrEmpty] + public string ParamName + { + get { return _paramname; } + set { _paramname = value; } + } + private string _paramname; + + /// + /// Parameter ParamValue. + /// + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Param")] + [Parameter(Mandatory = true, Position = 1)] + [ValidateNotNullOrEmpty] + public string ParamValue + { + get { return _paramvalue; } + set { _paramvalue = value; } + } + private string _paramvalue; + } + + /// + /// Dynamic parameter for Resource Item. + /// Path - WsMAn:\localhost\Plugin\[Specified Plugin]\Resources> + /// + public class WSManProviderNewItemResourceParameters + { + /// + /// Parameter ResourceUri. + /// + [Parameter(Mandatory = true)] + [ValidateNotNullOrEmpty] + public System.Uri ResourceUri + { + get { return _resourceuri; } + set { _resourceuri = value; } + } + private System.Uri _resourceuri; + + /// + /// Parameter Capability. + /// + [Parameter(Mandatory = true)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + [ValidateNotNullOrEmpty] + public object[] Capability + { + get { return _capability; } + set { _capability = value; } + } + private object[] _capability; + } + + /// + /// Security Dynamic Parameters + /// Path - WsMan:\Localhost\Plugin\[Specified Plugin]\Resources\[Specified Resource]\Security> + /// + public class WSManProviderNewItemSecurityParameters + { + /// + /// Parameter Sddl. + /// + [Parameter(Mandatory = true)] + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sddl")] + public string Sddl + { + get { return _sddl; } + set { _sddl = value; } + } + private string _sddl; + } + +#region "ClientCertificate Dynamic Parameters" + /// + /// Client Certificate Dynamic Parameters + /// Path - WsMan:\Localhost\ClientCertificate + /// + public class WSManProviderClientCertificateParameters + { + /// + /// Parameter Issuer. + /// + [Parameter(Mandatory = true)] + [ValidateNotNullOrEmpty] + public string Issuer + { + get + { + return _issuer; + } + set + { + _issuer = value; + } + } + private string _issuer; + + /// + /// Parameter Subject. + /// + [Parameter()] + [ValidateNotNullOrEmpty] + public string Subject + { + get + { + return _subject; + } + set + { + _subject = value; + } + } + private string _subject = "*"; + + /// + /// Parameter URI. + /// + [Parameter] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")] + [ValidateNotNullOrEmpty] + public System.Uri URI + { + get + { + return _uri; + } + set + { + _uri = value; + } + } + private System.Uri _uri = new Uri("*", UriKind.RelativeOrAbsolute); + + /// + /// Parameter Enabled. + /// + [Parameter] + public bool Enabled + { + get + { + return _enabled; + } + set + { + _enabled = value; + } + } + private bool _enabled = true; + + } + + +#endregion + +#region Listener Dynamic Parameters + + /// + /// Listener Dyanamic parameters + /// Path - WsMan:\Localhost\Listener> + /// + public class WSManProvidersListenerParameters + { + /// + /// Parameter Address. + /// + [Parameter(Mandatory = true)] + [ValidateNotNullOrEmpty] + public string Address + { + get + { + return _address; + } + set + { + _address = value; + } + } + private string _address; + + /// + /// Parameter Transport. + /// + [Parameter(Mandatory = true)] + [ValidateNotNullOrEmpty] + public string Transport + { + get + { + return _transport; + } + set + { + _transport = value; + } + } + private string _transport = "http"; + + /// + /// Parameter Port. + /// + [Parameter] + [ValidateNotNullOrEmpty] + public int Port + { + get + { + return _port; + } + set + { + _port = value; + _IsPortSpecified = true; + } + } + private int _port = 0; + + /// + /// Parameter HostName. + /// + [Parameter] + [ValidateNotNullOrEmpty] + public string HostName + { + get + { + return _hostName; + } + set + { + _hostName = value; + } + } + private string _hostName; + + /// + /// Parameter Enabled. + /// + [Parameter] + public bool Enabled + { + get + { + return _enabled; + } + set + { + _enabled = value; + } + } + private bool _enabled = true; + + /// + /// Parameter URLPrefix. + /// + [Parameter] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URL")] + [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")] + [ValidateNotNullOrEmpty] + public string URLPrefix + { + get + { + return _urlprefix; + } + set + { + _urlprefix = value; + } + } + private string _urlprefix = "wsman"; + + /// + /// Parameter CertificateThumbPrint. + /// + [Parameter] + [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "ThumbPrint")] + [ValidateNotNullOrEmpty] + public string CertificateThumbPrint + { + get + { + return _certificatethumbprint; + } + set + { + _certificatethumbprint = value; + } + } + private string _certificatethumbprint; + + /// + /// Variable IsPortSpecified. + /// + public bool IsPortSpecified + { + get + { + return _IsPortSpecified; + } + set + { + _IsPortSpecified = value; + } + + } + private bool _IsPortSpecified = false; + } + +#endregion + +#endregion + +#region SetItemDynamicParameters + + /// + /// Set-Item Dynamic parameters + /// Path - WsMan:\Localhost\Client> Set-Item .\TrustedHosts + /// + public class WSManProviderSetItemDynamicParameters + { + /// + /// Parameter Concatenate. + /// + [Parameter()] + public SwitchParameter Concatenate + { + get { return _concatenate; } + set { _concatenate = value; } + } + private SwitchParameter _concatenate = false; + } + + +#endregion SetItemDynamicParameters + +#endregion + +#region "String Literals" + + internal static class WSManStringLiterals + { + // constants + + /// + /// The default path separator used by the base implementation of the providers. + /// + /// + internal const char DefaultPathSeparator = '\\'; + + /// + /// The alternate path separator used by the base implementation of the providers. + /// + /// + internal const char AlternatePathSeparator = '/'; + /// + /// Double Quotes used while constructing XML + /// + internal const char EnclosingDoubleQuotes = '\"'; + /// + /// Equalto Used while constructing XML + /// + internal const char Equalto = '='; + /// + /// For XML Construction + /// + internal const char GreaterThan = '>'; + /// + /// XML Closing Tag + /// + internal const string XmlClosingTag = "/>"; + /// + /// White space used while constructing XML + /// + internal const char SingleWhiteSpace = ' '; + + /// + /// Root node of WsMan + /// + internal const string ProviderName = "WSMan"; + + /// + /// + /// + internal const string WsMan_Schema = "http://schemas.microsoft.com/wbem/wsman/1/config"; + /// + /// + /// + internal const string NS_XSI = "xmlns:xsi=" + "\"http://www.w3.org/2001/XMLSchema-instance\""; + /// + /// + /// + internal const string ATTR_NIL = "xsi:nil=" + "\"true\""; + /// + /// + /// + internal const string ATTR_NIL_NAME = "xsi:nil"; + /// + /// + /// + internal const char WinrmPathSeparator = '/'; + /// + /// + /// + internal const string rootpath = "WSMan"; + + /// + /// + /// + internal const string ContainerChildValue = "Container"; + +#region WsMan Containers + + /// + /// Plugin Container + /// + internal const string containerPlugin = "Plugin"; + /// + /// Client Container + /// + internal const string containerClient = "Client"; + /// + /// Shell Container + /// + internal const string containerShell = "Shell"; + /// + /// ClientCertificate Container + /// + internal const string containerClientCertificate = "ClientCertificate"; + /// + /// Listener Container + /// + internal const string containerListener = "Listener"; + /// + /// Service Container + /// + internal const string containerService = "Service"; + /// + /// Auth Container - Under Client,Serive + /// + internal const string containerAuth = "Auth"; + /// + /// DefaultPorts Container - Under Client,Serive + /// + internal const string containerDefaultPorts = "DefaultPorts"; + /// + /// TrustedHosts Container - Under Client,Serive + /// + internal const string containerTrustedHosts = "TrustedHosts"; + /// + /// Security Container - Under Plugin + /// + internal const string containerSecurity = "Security"; + /// + /// Resources Container - Under Plugin + /// + internal const string containerResources = "Resources"; + + /// + /// Resource in Resources Container - Under Plugin + /// + internal const string containerSingleResource = "Resource"; + /// + /// InitParameters Container - Under Plugin + /// + internal const string containerInitParameters = "InitializationParameters"; + + /// + /// Quotas Container - Under Plugin + /// + internal const string containerQuotasParameters = "Quotas"; + + /// + /// Winrs Container - Exposed as Shell + /// + internal const string containerWinrs = "Winrs"; + + /// + /// certmapping Container - Exposed as ClientCertificate in the provider. + /// + internal const string containerCertMapping = "Service/certmapping"; + + + /// + /// Possible Values in Plugin Top Level XML + /// + internal static readonly string[] NewItemPluginConfigParams = + new string[] { + "Name", + "Filename", + "SDKVersion", + "XmlRenderingType", + "Enabled", + "Architecture", + WSManStringLiterals.ConfigRunAsPasswordName, + WSManStringLiterals.ConfigRunAsUserName, + WSManStringLiterals.ConfigAutoRestart, + WSManStringLiterals.ConfigProcessIdleTimeoutSec, + WSManStringLiterals.ConfigUseSharedProcess, + }; + + /// Possible Values in Plugin Top Resources XML + internal static readonly string[] NewItemResourceParams = new string[] { "Resource", "ResourceUri", "Capability", "ExactMatch", "SupportsOptions" }; + + /// Possible Values in Plugin Top Init Param XML + internal static readonly string[] NewItemInitParamsParams = new string[] { "Name", "Value" }; + + /// Possible Values in Plugin Top Security XML + internal static readonly string[] NewItemSecurityParams = new string[] { "Uri", "Sddl", "ExactMatch" }; + +#endregion WsMan Containers + +#region WSMAN Config Names + /// + /// Name of the configuration which represents RunAs Password. + /// + internal const string ConfigRunAsPasswordName = "RunAsPassword"; + + /// + /// Name of the configuration which represents RunAs Name. + /// + internal const string ConfigRunAsUserName = "RunAsUser"; + + /// + /// Name of the configuration which represents if HostProcess is shared or saperate. + /// + internal const string ConfigUseSharedProcess = "UseSharedProcess"; + + /// + /// Name of the configuration which represents if AutoRestart is enabled or not. + /// + internal const string ConfigAutoRestart = "AutoRestart"; + + /// + /// Name of the configuration which represents the Host Idle Timeout in seconds. + /// + internal const string ConfigProcessIdleTimeoutSec = "ProcessIdleTimeoutSec"; + + /// + /// Name of the configuration which represents the Resource URI for a Resource. + /// + internal const string ConfigResourceUriName = "ResourceUri"; + + /// + /// Name of the tag which represents a initialization parameter. + /// + internal const string ConfigInitializeParameterTag = "Param"; + + /// + /// Name of the tag which represents Name of the parameter. + /// + internal const string ConfigInitializeParameterName = "Name"; + + /// + /// Name of the tag which represents Value of the parameter. + /// + internal const string ConfigInitializeParameterValue = "Value"; + + /// + /// Name of the tag which represents a Security URI. + /// + internal const string ConfigSecurityUri = "Uri"; + + /// + /// Name of the tag which represents a Security URI. + /// + internal const string HiddenSuffixForSourceOfValue = "___Source"; + +#endregion + + /// + /// This is used to start the service. return a bool value. if false we throw error. + /// + public const string StartWinrmServiceSBFormat = @" +function Start-WSManServiceD15A7957836142a18627D7E1D342DD82 +{{ +[CmdletBinding()] +param( + [Parameter()] + [bool] + $Force, + + [Parameter()] + [string] + $captionForStart, + + [Parameter()] + [string] + $queryForStart) + + begin + {{ + if ($force -or $pscmdlet.ShouldContinue($queryForStart, $captionForStart)) + {{ + Restart WinRM -Force -Confirm:$false + return $true + }} + return $false + }} #end of Begin block +}} +$_ | Start-WSManServiceD15A7957836142a18627D7E1D342DD82 -force $args[0] -captionForStart $args[1] -queryForStart $args[2] +"; + + } + +#endregion "String Literals" + +#region "WsMan Output Objects" + + /// + /// Base Output object + /// + public class WSManConfigElement + { + internal WSManConfigElement() + { + } + internal WSManConfigElement(string name, string typenameofelement) + { + _name = name; + _typenameofelement = typenameofelement; + } + + /// + /// Variable Name. + /// + public string Name + { + get { return _name; } + set { _name = value; } + + } + private string _name; + + /// + /// Variable TypeNameOfElement. + /// + public string TypeNameOfElement + { + get { return _typenameofelement; } + set { _typenameofelement = value; } + } + private string _typenameofelement; + + /// + /// Gets or Sets the type if the object. + /// + public string Type + { + get { return _typenameofelement; } + set { _typenameofelement = value; } + } + } + /// + /// Leaf Element + /// + public class WSManConfigLeafElement : WSManConfigElement + { + internal WSManConfigLeafElement() + { + } + internal WSManConfigLeafElement(string Name, object Value, string TypeNameOfElement, object SourceOfValue = null) + { + _value = Value; + _SourceOfValue = SourceOfValue; + base.Name = Name; + base.Type = TypeNameOfElement; + } + + /// + /// Variable Value. + /// + public object SourceOfValue + { + get { return _SourceOfValue; } + set { _SourceOfValue = value; } + + } + private object _SourceOfValue; + + /// + /// Variable Value. + /// + public object Value + { + get { return _value; } + set { _value = value; } + + } + private object _value; + } + /// + /// Container Element + /// + public class WSManConfigContainerElement : WSManConfigElement + { + internal WSManConfigContainerElement(string Name, string TypeNameOfElement, string[] keys) + { + _keys = keys; + base.Name = Name; + base.Type = TypeNameOfElement; + } + + /// + /// Variable Keys. + /// + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public string[] Keys + { + get { return _keys; } + set { _keys = value; } + + } + private string[] _keys; + } + + + +#endregion "WsMan Outpu tObjects" + + +} + + diff --git a/src/Microsoft.WSMan.Management/CredSSP.cs b/src/Microsoft.WSMan.Management/CredSSP.cs new file mode 100644 index 000000000..7c8ce4ace --- /dev/null +++ b/src/Microsoft.WSMan.Management/CredSSP.cs @@ -0,0 +1,1063 @@ +/********************************************************************++ +Copyright (c) Microsoft Corporation. All rights reserved. +--********************************************************************/ +using System; +using System.IO; +using System.Reflection; +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Management.Automation; +using System.Management.Automation.Provider; +using System.Xml; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Microsoft.Win32; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Security; +using System.Threading; +#if CORECLR +using System.Xml.XPath; +#endif + +using Dbg = System.Management.Automation; + +namespace Microsoft.WSMan.Management +{ + #region WSManCredSSP cmdlet base + + /// + /// Base class used *-WSManCredSSP cmdlets (Enable-WSManCredSSP, Disable-WSManCredSSP) + /// + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Cred")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SSP")] + public class WSManCredSSPCommandBase : PSCmdlet + { + #region Protected / Internal Data + + internal const string Server = "Server"; + internal const string Client = "Client"; + + #endregion + + #region Parameters + + /// + /// Role can either "Client" or "Server". + /// + [Parameter(Mandatory = true, Position = 0)] + [ValidateSet(Client, Server)] + public string Role + { + get { return role; } + set { role = value; } + } + private string role; + + /*/// + /// Role can either "Client" or "Server". + /// + [Parameter(ParameterSetName = Client, Mandatory = true, Position = 0)] + public SwitchParameter ClientRole + { + get { return isClient; } + set { isClient = value; } + } + private bool isClient; + + /// + /// + /// + [Parameter(ParameterSetName = Server, Mandatory = true, Position = 0)] + public SwitchParameter ServerRole + { + get { return isServer; } + set { isServer = value; } + } + private bool isServer;*/ + + #endregion + + #region Utilities + + /// + /// + /// + /// + /// Returns a session object upon successful creation..otherwise + /// writes an error using WriteError and returns null. + /// + internal IWSManSession CreateWSManSession() + { + IWSManEx wsmanObject = (IWSManEx)new WSManClass(); + IWSManSession m_SessionObj = null; + + try + { + m_SessionObj = (IWSManSession)wsmanObject.CreateSession(null, 0, null); + return m_SessionObj; + } + catch (COMException ex) + { + ErrorRecord er = new ErrorRecord(ex, "COMException", ErrorCategory.InvalidOperation, null); + WriteError(er); + } + + return null; + } + + #endregion + } + + #endregion + + #region DisableWsManCredSsp + + /// + /// Disables CredSSP authentication on the client. CredSSP authentication + /// enables an application to delegate the user's credentials from the client to + /// the server, hence allowing the user to perform management operations that + /// access a second hop + /// + + + [Cmdlet(VerbsLifecycle.Disable, "WSManCredSSP", HelpUri = "http://go.microsoft.com/fwlink/?LinkId=141438")] + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Cred")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SSP")] + public class DisableWSManCredSSPCommand : WSManCredSSPCommandBase, IDisposable + { + #region private + + // The application name MUST be "wsman" as wsman got approval from security + // folks who suggested to register the SPN with name "wsman". + private const string applicationname = "wsman"; + + private void DisableClientSideSettings() + { + WSManHelper helper = new WSManHelper(this); + IWSManSession m_SessionObj = CreateWSManSession(); + if (null == m_SessionObj) + { + return; + } + + try + { + string result = m_SessionObj.Get(helper.CredSSP_RUri, 0); + XmlDocument resultopxml = new XmlDocument(); + string inputXml = null; + resultopxml.LoadXml(result); + XmlNamespaceManager nsmgr = new XmlNamespaceManager(resultopxml.NameTable); + nsmgr.AddNamespace("cfg", helper.CredSSP_XMLNmsp); + XmlNode xNode = resultopxml.SelectSingleNode(helper.CredSSP_SNode, nsmgr); + if (!(xNode == null)) + { + inputXml = @"false"; + } + else + { + InvalidOperationException ex = new InvalidOperationException(); + ErrorRecord er = new ErrorRecord(ex, helper.GetResourceMsgFromResourcetext("WinrmNotConfigured"), ErrorCategory.InvalidOperation, null); + WriteError(er); + return; + } + m_SessionObj.Put(helper.CredSSP_RUri, inputXml, 0); + +#if !CORECLR + if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA) + { + this.DeleteUserDelegateSettings(); + } + else + { + ThreadStart start = new ThreadStart(this.DeleteUserDelegateSettings); + Thread thread = new Thread(start); + thread.SetApartmentState(ApartmentState.STA); + thread.Start(); + thread.Join(); + } +#else + { + ThreadStart start = new ThreadStart(this.DeleteUserDelegateSettings); + Thread thread = new Thread(start); + thread.Start(); + thread.Join(); + } +#endif + + if (!helper.ValidateCreadSSPRegistryRetry(false, null, applicationname)) + { + helper.AssertError(helper.GetResourceMsgFromResourcetext("DisableCredSSPPolicyValidateError"), false, null); + } + } + catch (System.Xml.XPath.XPathException ex) + { + ErrorRecord er = new ErrorRecord(ex, "XpathException", ErrorCategory.InvalidOperation, null); + WriteError(er); + } + finally + { + if (!String.IsNullOrEmpty(m_SessionObj.Error)) + { + helper.AssertError(m_SessionObj.Error, true, null); + } + + if (m_SessionObj != null) + Dispose(m_SessionObj); + } + } + + private void DisableServerSideSettings() + { + WSManHelper helper = new WSManHelper(this); + IWSManSession m_SessionObj = CreateWSManSession(); + if (null == m_SessionObj) + { + return; + } + + try + { + string result = m_SessionObj.Get(helper.Service_CredSSP_Uri, 0); + XmlDocument resultopxml = new XmlDocument(); + string inputXml = null; + resultopxml.LoadXml(result); + + XmlNamespaceManager nsmgr = new XmlNamespaceManager(resultopxml.NameTable); + nsmgr.AddNamespace("cfg", helper.Service_CredSSP_XMLNmsp); + XmlNode xNode = resultopxml.SelectSingleNode(helper.CredSSP_SNode, nsmgr); + if (!(xNode == null)) + { + inputXml = string.Format(CultureInfo.InvariantCulture, + @"false", + helper.Service_CredSSP_XMLNmsp); + } + else + { + InvalidOperationException ex = new InvalidOperationException(); + ErrorRecord er = new ErrorRecord(ex, + helper.GetResourceMsgFromResourcetext("WinrmNotConfigured"), + ErrorCategory.InvalidOperation, null); + WriteError(er); + return; + } + + m_SessionObj.Put(helper.Service_CredSSP_Uri, inputXml, 0); + } + finally + { + if (!String.IsNullOrEmpty(m_SessionObj.Error)) + { + helper.AssertError(m_SessionObj.Error, true, null); + } + + if (m_SessionObj != null) + { + Dispose(m_SessionObj); + } + } + } + + private void DeleteUserDelegateSettings() + { + System.IntPtr KeyHandle = System.IntPtr.Zero; + IGroupPolicyObject GPO = (IGroupPolicyObject)new GPClass(); + GPO.OpenLocalMachineGPO(1); + KeyHandle = GPO.GetRegistryKey(2); + RegistryKey rootKey = Registry.CurrentUser; + string GPOpath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy Objects"; + RegistryKey GPOKey = rootKey.OpenSubKey(GPOpath, true); + foreach (string keyname in GPOKey.GetSubKeyNames()) + { + if (keyname.EndsWith("Machine", StringComparison.OrdinalIgnoreCase)) + { + string key = GPOpath + "\\" + keyname + "\\" + @"Software\Policies\Microsoft\Windows"; + DeleteDelegateSettings(applicationname, Registry.CurrentUser, key, GPO); + } + } + KeyHandle = System.IntPtr.Zero; + } + + private void DeleteDelegateSettings(string applicationname, RegistryKey rootKey, string Registry_Path, IGroupPolicyObject GPO) + { + WSManHelper helper = new WSManHelper(this); + RegistryKey rKey; + int i = 0; + bool otherkeys = false; + try + { + + string Registry_Path_Credentials_Delegation = Registry_Path + @"\CredentialsDelegation"; + RegistryKey Allow_Fresh_Credential_Key = rootKey.OpenSubKey(Registry_Path_Credentials_Delegation + @"\" + helper.Key_Allow_Fresh_Credentials, true); + if (Allow_Fresh_Credential_Key != null) + { + string[] valuenames = Allow_Fresh_Credential_Key.GetValueNames(); + if (valuenames.Length > 0) + { + Collection KeyCollection = new Collection(); + foreach (string value in valuenames) + { + object keyvalue = Allow_Fresh_Credential_Key.GetValue(value); + if (keyvalue != null) + { + if (!keyvalue.ToString().StartsWith(applicationname, StringComparison.OrdinalIgnoreCase)) + { + KeyCollection.Add(keyvalue.ToString()); + otherkeys = true; + } + } + Allow_Fresh_Credential_Key.DeleteValue(value); + } + foreach (string keyvalue in KeyCollection) + { + Allow_Fresh_Credential_Key.SetValue(Convert.ToString(i + 1, CultureInfo.InvariantCulture), keyvalue, RegistryValueKind.String); + i++; + } + } + } + if (!otherkeys) + { + rKey = rootKey.OpenSubKey(Registry_Path_Credentials_Delegation, true); + if (rKey != null) + { + object regval1 = rKey.GetValue(helper.Key_Allow_Fresh_Credentials); + if (regval1 != null) + { + rKey.DeleteValue(helper.Key_Allow_Fresh_Credentials, false); + } + object regval2 = rKey.GetValue(helper.Key_Concatenate_Defaults_AllowFresh); + if (regval2 != null) + { + rKey.DeleteValue(helper.Key_Concatenate_Defaults_AllowFresh, false); + } + if (rKey.OpenSubKey(helper.Key_Allow_Fresh_Credentials) != null) + { + rKey.DeleteSubKeyTree(helper.Key_Allow_Fresh_Credentials); + } + } + } + GPO.Save(true, true, new Guid("35378EAC-683F-11D2-A89A-00C04FBBCFA2"), new Guid("6AD20875-336C-4e22-968F-C709ACB15814")); + } + catch (InvalidOperationException ex) + { + ErrorRecord er = new ErrorRecord(ex, "InvalidOperation", ErrorCategory.InvalidOperation, null); + WriteError(er); + } + catch (ArgumentException ex) + { + ErrorRecord er = new ErrorRecord(ex, "InvalidArgument", ErrorCategory.InvalidArgument, null); + WriteError(er); + } + catch (SecurityException ex) + { + ErrorRecord er = new ErrorRecord(ex, "SecurityException", ErrorCategory.SecurityError, null); + WriteError(er); + } + catch (UnauthorizedAccessException ex) + { + ErrorRecord er = new ErrorRecord(ex, "UnauthorizedAccess", ErrorCategory.SecurityError, null); + WriteError(er); + } + } + #endregion private + /// + /// begin processing method. + /// + protected override void BeginProcessing() + { +#if !CORECLR + if (Environment.OSVersion.Version.Major < 6) + { + //OS is XP/Win2k3. Throw error. + WSManHelper helper = new WSManHelper(this); + string message = helper.FormatResourceMsgFromResourcetext("CmdletNotAvailable"); + throw new InvalidOperationException(message); + } +#endif + //If not running elevated, then throw an "elevation required" error message. + WSManHelper.ThrowIfNotAdministrator(); + + if (Role.Equals(Client, StringComparison.OrdinalIgnoreCase)) + { + DisableClientSideSettings(); + } + + if (Role.Equals(Server, StringComparison.OrdinalIgnoreCase)) + { + DisableServerSideSettings(); + } + }//End BeginProcessing() + + #region IDisposable Members + + /// + /// public dispose method + /// + public + void + Dispose() + { + //CleanUp(); + GC.SuppressFinalize(this); + } + /// + /// public dispose method + /// + public + void + Dispose(IWSManSession sessionObject) + { + sessionObject = null; + this.Dispose(); + } + + #endregion IDisposable Members + }//End Class + #endregion DisableWsManCredSSP + + #region EnableCredSSP + /// + /// Enables CredSSP authentication on the client. CredSSP authentication enables + /// an application to delegate the user's credentials from the client to the + /// server, hence allowing the user to perform management operations that access + /// a second hop. + /// This cmdlt performs the following: + /// + /// On the client: + /// 1. Enables WSMan local configuration on client to enable CredSSP + /// 2. Sets CredSSP policy AllowFreshCredentials to wsman/Delegate. This policy + /// allows delegating explicit credentials to a server when server + /// authentication is achieved via a trusted X509 certificate or Kerberos + /// + [Cmdlet(VerbsLifecycle.Enable, "WSManCredSSP", HelpUri = "http://go.microsoft.com/fwlink/?LinkId=141442")] + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Cred")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SSP")] + public class EnableWSManCredSSPCommand : WSManCredSSPCommandBase, IDisposable/*, IDynamicParameters*/ + { + #region Private Data + + //private const string DelegateComputerParam = "DelegateComputer"; + //private String[] delegatecomputer; + //private RuntimeDefinedParameterDictionary dyanmicParameters = new RuntimeDefinedParameterDictionary(); + + #endregion + + /// + /// delegate parameter + /// + [Parameter(Position = 1)] + [ValidateNotNullOrEmpty] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public String[] DelegateComputer + { + get { return delegatecomputer; } + set { delegatecomputer = value; } + } + private String[] delegatecomputer; + + /// + /// Property that sets force parameter. + /// + [Parameter()] + public SwitchParameter Force + { + get { return force; } + set { force = value; } + } + private bool force = false; + + //helper variable + private WSManHelper helper; + + // The application name MUST be "wsman" as wsman got approval from security + // folks who suggested to register the SPN with name "wsman". + private const string applicationname = "wsman"; + + #region Cmdlet Overloads + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + //If not running elevated, then throw an "elevation required" error message. + WSManHelper.ThrowIfNotAdministrator(); + helper = new WSManHelper(this); +#if !CORECLR + if (Environment.OSVersion.Version.Major < 6) + { + //OS is XP/Win2k3. Throw error. + string message = helper.FormatResourceMsgFromResourcetext("CmdletNotAvailable"); + throw new InvalidOperationException(message); + } +#endif + //If not running elevated, then throw an "elevation required" error message. + WSManHelper.ThrowIfNotAdministrator(); + + // DelegateComputer cannot be specified when Role is other than client + if ((delegatecomputer != null) && !Role.Equals(Client, StringComparison.OrdinalIgnoreCase)) + { + string message = helper.FormatResourceMsgFromResourcetext("CredSSPRoleAndDelegateCannotBeSpecified", + "DelegateComputer", + "Role", + Role, + Client); + + throw new InvalidOperationException(message); + } + + // DelegateComputer must be specified when Role is client + if (Role.Equals(Client, StringComparison.OrdinalIgnoreCase) && (delegatecomputer == null)) + { + string message = helper.FormatResourceMsgFromResourcetext("CredSSPClientAndDelegateMustBeSpecified", + "DelegateComputer", + "Role", + Client); + + throw new InvalidOperationException(message); + } + + if (Role.Equals(Client, StringComparison.OrdinalIgnoreCase)) + { + EnableClientSideSettings(); + } + + if (Role.Equals(Server, StringComparison.OrdinalIgnoreCase)) + { + EnableServerSideSettings(); + } + }//End BeginProcessing() + + /* + /// + /// This method returns DynamicParameters used for Enable-WSManCredSSP cmdlet. Enable-WSManCredSSP + /// supports -DelegateComputer parameter when -Role is client. + /// + /// + /// An object representing the dynamic parameters for the cmdlet or null if there + /// are none. + /// + object IDynamicParameters.GetDynamicParameters() + { + // return null if the role is not client. + if (!Role.Equals(ClientRole, StringComparison.OrdinalIgnoreCase)) + { + return dyanmicParameters; + } + + // Construct attributes for the DelegateComputer paramter + Collection delegateComputerAttributeCollection = new Collection(); + ParameterAttribute paramAttribute = new ParameterAttribute(); + paramAttribute.Mandatory = true; + paramAttribute.Position = 1; + ValidateNotNullOrEmptyAttribute notNullAttribute = new ValidateNotNullOrEmptyAttribute(); + delegateComputerAttributeCollection.Add(paramAttribute); + delegateComputerAttributeCollection.Add(notNullAttribute); + + // Construct the parameter and return. + RuntimeDefinedParameter delegateComputer = new RuntimeDefinedParameter( + DelegateComputerParam, + typeof(string[]), + delegateComputerAttributeCollection); + dyanmicParameters.Add(DelegateComputerParam, delegateComputer); + + return dyanmicParameters; + + } // GetDynamicParameters*/ + + #endregion + + /// + /// + /// + /// + /// + private void EnableClientSideSettings() + { + String query = helper.GetResourceMsgFromResourcetext("CredSSPContinueQuery"); + String caption = helper.GetResourceMsgFromResourcetext("CredSSPContinueCaption"); + if (!force && !ShouldContinue(query, caption)) + { + return; + } + + IWSManSession m_SessionObj = CreateWSManSession(); + if (null == m_SessionObj) + { + return; + } + + try + { + //get the credssp node to check if wsman is configured on this machine + string result = m_SessionObj.Get(helper.CredSSP_RUri, 0); + XmlNode node = helper.GetXmlNode(result, helper.CredSSP_SNode, helper.CredSSP_XMLNmsp); + + if (node == null) + { + InvalidOperationException ex = new InvalidOperationException(); + ErrorRecord er = new ErrorRecord(ex, helper.GetResourceMsgFromResourcetext("WinrmNotConfigured"), ErrorCategory.InvalidOperation, null); + WriteError(er); + return; + } + // Extract delegateComputer information from dynamic parameters collection + //RuntimeDefinedParameter delegateComputerParameter = dyanmicParameters[DelegateComputerParam]; + //delegatecomputer = (string[])delegateComputerParameter.Value; + + string newxmlcontent = @"true"; + try + { + XmlDocument xmldoc = new XmlDocument(); + //push the xml string with credssp enabled + xmldoc.LoadXml(m_SessionObj.Put(helper.CredSSP_RUri, newxmlcontent, 0)); + +#if !CORECLR // No ApartmentState In CoreCLR + // set the Registry using GroupPolicyObject + if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA) + { + this.UpdateCurrentUserRegistrySettings(); + } + else + { + ThreadStart start = new ThreadStart(this.UpdateCurrentUserRegistrySettings); + Thread thread = new Thread(start); + thread.SetApartmentState(ApartmentState.STA); + thread.Start(); + thread.Join(); + } +#else + { + ThreadStart start = new ThreadStart(this.UpdateCurrentUserRegistrySettings); + Thread thread = new Thread(start); + thread.Start(); + thread.Join(); + } +#endif + + if (helper.ValidateCreadSSPRegistryRetry(true, delegatecomputer, applicationname)) + { + WriteObject(xmldoc.FirstChild); + } + else + { + helper.AssertError(helper.GetResourceMsgFromResourcetext("EnableCredSSPPolicyValidateError"), false, delegatecomputer); + } + } + catch (COMException) + { + helper.AssertError(m_SessionObj.Error, true, delegatecomputer); + } + } + finally + { + if (!String.IsNullOrEmpty(m_SessionObj.Error)) + { + helper.AssertError(m_SessionObj.Error, true, delegatecomputer); + } + + if (m_SessionObj != null) + { + Dispose(m_SessionObj); + } + } + } + + private void EnableServerSideSettings() + { + String query = helper.GetResourceMsgFromResourcetext("CredSSPServerContinueQuery"); + String caption = helper.GetResourceMsgFromResourcetext("CredSSPContinueCaption"); + if (!force && !ShouldContinue(query, caption)) + { + return; + } + + IWSManSession m_SessionObj = CreateWSManSession(); + if (null == m_SessionObj) + { + return; + } + + try + { + //get the credssp node to check if wsman is configured on this machine + string result = m_SessionObj.Get(helper.Service_CredSSP_Uri, 0); + XmlNode node = helper.GetXmlNode(result, + helper.CredSSP_SNode, + helper.Service_CredSSP_XMLNmsp); + + if (node == null) + { + InvalidOperationException ex = new InvalidOperationException(); + ErrorRecord er = new ErrorRecord(ex, helper.GetResourceMsgFromResourcetext("WinrmNotConfigured"), ErrorCategory.InvalidOperation, null); + WriteError(er); + return; + } + + try + { + XmlDocument xmldoc = new XmlDocument(); + string newxmlcontent = string.Format(CultureInfo.InvariantCulture, + @"true", + helper.Service_CredSSP_XMLNmsp); + //push the xml string with credssp enabled + xmldoc.LoadXml(m_SessionObj.Put(helper.Service_CredSSP_Uri, newxmlcontent, 0)); + WriteObject(xmldoc.FirstChild); + } + catch (COMException) + { + helper.AssertError(m_SessionObj.Error, true, delegatecomputer); + } + } + finally + { + if (!String.IsNullOrEmpty(m_SessionObj.Error)) + { + helper.AssertError(m_SessionObj.Error, true, delegatecomputer); + } + + if (m_SessionObj != null) + { + Dispose(m_SessionObj); + } + } + } + + /// + /// + /// + private void UpdateCurrentUserRegistrySettings() + { + System.IntPtr KeyHandle = System.IntPtr.Zero; + IGroupPolicyObject GPO = (IGroupPolicyObject)new GPClass(); + GPO.OpenLocalMachineGPO(1); + KeyHandle = GPO.GetRegistryKey(2); + RegistryKey rootKey = Registry.CurrentUser; + string GPOpath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy Objects"; + RegistryKey GPOKey = rootKey.OpenSubKey(GPOpath, true); + foreach (string keyname in GPOKey.GetSubKeyNames()) + { + if (keyname.EndsWith("Machine", StringComparison.OrdinalIgnoreCase)) + { + string key = GPOpath + "\\" + keyname + "\\" + @"Software\Policies\Microsoft\Windows"; + UpdateGPORegistrySettings(applicationname, this.delegatecomputer, Registry.CurrentUser, key); + + } + } + //saving gpo settings + GPO.Save(true, true, new Guid("35378EAC-683F-11D2-A89A-00C04FBBCFA2"), new Guid("7A9206BD-33AF-47af-B832-D4128730E990")); + } + + /// + /// Updates the grouppolicy registry settings + /// + /// + /// + /// + /// + private void UpdateGPORegistrySettings(string applicationname, string[] delegatestring, RegistryKey rootKey, string Registry_Path) + { + //RegistryKey rootKey = Registry.LocalMachine; + RegistryKey Credential_Delegation_Key; + RegistryKey Allow_Fresh_Credential_Key; + int i = 0; + try + { + string Registry_Path_Credentials_Delegation = Registry_Path + @"\CredentialsDelegation"; + //open the registry key.If key is not present,create a new one + Credential_Delegation_Key = rootKey.OpenSubKey(Registry_Path_Credentials_Delegation, true); + if (Credential_Delegation_Key == null) + Credential_Delegation_Key = rootKey.CreateSubKey(Registry_Path_Credentials_Delegation +#if !CORECLR + , RegistryKeyPermissionCheck.ReadWriteSubTree +#endif + ); + + Credential_Delegation_Key.SetValue(helper.Key_Allow_Fresh_Credentials, 1, RegistryValueKind.DWord); + Credential_Delegation_Key.SetValue(helper.Key_Concatenate_Defaults_AllowFresh, 1, RegistryValueKind.DWord); + + // add the delegate value + Allow_Fresh_Credential_Key = rootKey.OpenSubKey(Registry_Path_Credentials_Delegation + @"\" + helper.Key_Allow_Fresh_Credentials, true); + if (Allow_Fresh_Credential_Key == null) + Allow_Fresh_Credential_Key = rootKey.CreateSubKey(Registry_Path_Credentials_Delegation + @"\" + helper.Key_Allow_Fresh_Credentials +#if !CORECLR + , RegistryKeyPermissionCheck.ReadWriteSubTree +#endif + ); + + if (Allow_Fresh_Credential_Key != null) + { + i = Allow_Fresh_Credential_Key.ValueCount; + foreach (string del in delegatestring) + { + Allow_Fresh_Credential_Key.SetValue(Convert.ToString(i + 1, CultureInfo.InvariantCulture), applicationname + @"/" + del, RegistryValueKind.String); + i++; + } + } + } + catch (UnauthorizedAccessException ex) + { + ErrorRecord er = new ErrorRecord(ex, "UnauthorizedAccessException", ErrorCategory.PermissionDenied, null); + WriteError(er); + } + catch (SecurityException ex) + { + ErrorRecord er = new ErrorRecord(ex, "SecurityException", ErrorCategory.InvalidOperation, null); + WriteError(er); + } + catch (ArgumentException ex) + { + ErrorRecord er = new ErrorRecord(ex, "ArgumentException", ErrorCategory.InvalidOperation, null); + WriteError(er); + } + + } + + #region IDisposable Members + + /// + /// public dispose method + /// + public + void + Dispose() + { + //CleanUp(); + GC.SuppressFinalize(this); + } + /// + /// public dispose method + /// + public + void + Dispose(IWSManSession sessionObject) + { + sessionObject = null; + this.Dispose(); + } + + #endregion IDisposable Members + }//End Class + #endregion EnableCredSSP + + #region Get-CredSSP + + /// + /// Gets the CredSSP related configuration on the client. CredSSP authentication + /// enables an application to delegate the user's credentials from the client to + /// the server, hence allowing the user to perform management operations that + /// access a second hop. + /// This cmdlt performs the following: + /// 1. Gets the configuration for WSMan policy on client to enable/disable + /// CredSSP + /// 2. Gets the configuration information for the CredSSP policy + /// AllowFreshCredentials . This policy allows delegating explicit credentials + /// to a server when server authentication is achieved via a trusted X509 + /// certificate or Kerberos + /// + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Cred")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SSP")] + [Cmdlet(VerbsCommon.Get, "WSManCredSSP", HelpUri = "http://go.microsoft.com/fwlink/?LinkId=141443")] + public class GetWSManCredSSPCommand : PSCmdlet, IDisposable + { + # region private + WSManHelper helper = null; + /// + /// method to get the values. + /// + private string GetDelegateSettings(string applicationname) + { + RegistryKey rootKey = Registry.LocalMachine; + RegistryKey rKey; + string result = string.Empty; + string[] valuenames = null; + try + { + string Reg_key = helper.Registry_Path_Credentials_Delegation + @"\CredentialsDelegation"; + rKey = rootKey.OpenSubKey(Reg_key); + if (rKey != null) + { + rKey = rKey.OpenSubKey(helper.Key_Allow_Fresh_Credentials); + if (rKey != null) + { + valuenames = rKey.GetValueNames(); + if (valuenames.Length > 0) + { + string listvalue = CultureInfo.CurrentCulture.TextInfo.ListSeparator; + foreach (string value in valuenames) + { + object keyvalue = rKey.GetValue(value); + if (keyvalue != null) + { + if (keyvalue.ToString().StartsWith(applicationname, StringComparison.OrdinalIgnoreCase)) + { + result = keyvalue.ToString() + listvalue + result; + } + } + } + if (result.EndsWith(listvalue, StringComparison.OrdinalIgnoreCase)) + { + result = result.Remove(result.Length - 1); + } + } + } + } + } + catch (ArgumentException ex) + { + ErrorRecord er = new ErrorRecord(ex, "ArgumentException", ErrorCategory.PermissionDenied, null); + WriteError(er); + } + catch (SecurityException ex) + { + ErrorRecord er = new ErrorRecord(ex, "SecurityException", ErrorCategory.PermissionDenied, null); + WriteError(er); + } + catch (ObjectDisposedException ex) + { + ErrorRecord er = new ErrorRecord(ex, "ObjectDisposedException", ErrorCategory.PermissionDenied, null); + WriteError(er); + } + return result; + } + # endregion private + + # region overrides + /// + /// Method to begin processing. + /// + protected override void BeginProcessing() + { + //If not running elevated, then throw an "elevation required" error message. + WSManHelper.ThrowIfNotAdministrator(); + + helper = new WSManHelper(this); +#if !CORECLR + if (Environment.OSVersion.Version.Major < 6) + { + //OS is XP/Win2k3. Throw error. + string message = helper.FormatResourceMsgFromResourcetext("CmdletNotAvailable"); + throw new InvalidOperationException(message); + } +#endif + //If not running elevated, then throw an "elevation required" error message. + WSManHelper.ThrowIfNotAdministrator(); + + IWSManSession m_SessionObj = null; + try + { + IWSManEx wsmanObject = (IWSManEx)new WSManClass(); + m_SessionObj = (IWSManSession)wsmanObject.CreateSession(null, 0, null); + string result = m_SessionObj.Get(helper.CredSSP_RUri, 0); + XmlNode node = helper.GetXmlNode(result, helper.CredSSP_SNode, helper.CredSSP_XMLNmsp); + if (node == null) + { + InvalidOperationException ex = new InvalidOperationException(); + ErrorRecord er = new ErrorRecord(ex, helper.GetResourceMsgFromResourcetext("WinrmNotConfigured"), ErrorCategory.InvalidOperation, null); + WriteError(er); + return; + } + // The application name MUST be "wsman" as wsman got approval from security + // folks who suggested to register the SPN with name "wsman". + string applicationname = "wsman"; + string credsspResult = GetDelegateSettings(applicationname); + if (string.IsNullOrEmpty(credsspResult)) + { + WriteObject(helper.GetResourceMsgFromResourcetext("NoDelegateFreshCred")); + } + else + { + WriteObject(helper.GetResourceMsgFromResourcetext("DelegateFreshCred") + credsspResult); + } + + // Get the server side settings + result = m_SessionObj.Get(helper.Service_CredSSP_Uri, 0); + node = helper.GetXmlNode(result, helper.CredSSP_SNode, helper.Service_CredSSP_XMLNmsp); + if (node == null) + { + InvalidOperationException ex = new InvalidOperationException(); + ErrorRecord er = new ErrorRecord(ex, helper.GetResourceMsgFromResourcetext("WinrmNotConfigured"), ErrorCategory.InvalidOperation, null); + WriteError(er); + return; + } + + if (node.InnerText.Equals("true", StringComparison.OrdinalIgnoreCase)) + { + WriteObject(helper.GetResourceMsgFromResourcetext("CredSSPServiceConfigured")); + } + else + { + WriteObject(helper.GetResourceMsgFromResourcetext("CredSSPServiceNotConfigured")); + } + } + catch (UnauthorizedAccessException ex) + { + ErrorRecord er = new ErrorRecord(ex, "UnauthorizedAccess", ErrorCategory.PermissionDenied, null); + WriteError(er); + } + catch (SecurityException ex) + { + ErrorRecord er = new ErrorRecord(ex, "SecurityException", ErrorCategory.InvalidOperation, null); + WriteError(er); + } + catch (ArgumentException ex) + { + ErrorRecord er = new ErrorRecord(ex, "InvalidArgument", ErrorCategory.InvalidOperation, null); + WriteError(er); + } + catch (System.Xml.XPath.XPathException ex) + { + ErrorRecord er = new ErrorRecord(ex, "XPathException", ErrorCategory.InvalidOperation, null); + WriteError(er); + } + finally + { + if (!String.IsNullOrEmpty(m_SessionObj.Error)) + { + helper.AssertError(m_SessionObj.Error, true, null); + } + + if (m_SessionObj != null) + { + Dispose(m_SessionObj); + } + } + } + #endregion overrides + #region IDisposable Members + + /// + /// public dispose method + /// + public + void + Dispose() + { + //CleanUp(); + GC.SuppressFinalize(this); + } + /// + /// public dispose method + /// + public + void + Dispose(IWSManSession sessionObject) + { + sessionObject = null; + this.Dispose(); + } + + #endregion IDisposable Members + + + + + + } + + + + + #endregion +} diff --git a/src/Microsoft.WSMan.Management/CurrentConfigurations.cs b/src/Microsoft.WSMan.Management/CurrentConfigurations.cs new file mode 100644 index 000000000..a288cb430 --- /dev/null +++ b/src/Microsoft.WSMan.Management/CurrentConfigurations.cs @@ -0,0 +1,243 @@ +//------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// +// +// Pankaj Sarda +// +// +// +// Class that queries the server and gets current configurations. +// Also provides a generic way to update the configurations. +// +// +// +//------------------------------------------------------------------ + +namespace Microsoft.WSMan.Management +{ + using System; + using System.Globalization; + using System.Xml; + #if CORECLR + using System.Xml.XPath; + #endif + + /// + /// Class that queries the server and gets current configurations. + /// Also provides a generic way to update the configurations. + /// + internal class CurrentConfigurations + { + /// + /// Prefix used to add NameSpace of root element to namespace manager. + /// + public const string DefaultNameSpacePrefix = "defaultNameSpace"; + + /// + /// This holds the current configurations XML. + /// + private XmlDocument rootDocument; + + /// + /// Holds the referance to the current document element. + /// + private XmlElement documentElement; + + /// + /// Holds the Namespace Manager to use for XPATH queries. + /// + private XmlNamespaceManager nameSpaceManger; + + /// + /// Session of the WsMan sserver. + /// + private IWSManSession serverSession; + + /// + /// Gets the server session associated with the configuration. + /// + public IWSManSession ServerSession + { + get { return serverSession; } + } + + /// + /// Gets the current configuration XML. + /// + public XmlDocument RootDocument + { + get { return this.rootDocument; } + } + + /// + /// Gets the current configuration on the given server and for given URI. + /// This issues a GET request to the server. + /// + /// Current server session. + public CurrentConfigurations(IWSManSession serverSession) + { + if (serverSession == null) + { + throw new ArgumentNullException("serverSession"); + } + + this.rootDocument = new XmlDocument(); + this.serverSession = serverSession; + } + + /// + /// Refresh the CurrentConfiguration. This method calls GET operation for the given + /// URI on the server and update the current configuraition. It also intialize some + /// of required class members. + /// + /// Plugin configuration. + /// False, if operation failed. + public bool RefreshCurrentConfiguration(string responseOfGet) + { + if (String.IsNullOrEmpty(responseOfGet)) + { + throw new ArgumentNullException("responseOfGet"); + } + + this.rootDocument.LoadXml(responseOfGet); + this.documentElement = this.rootDocument.DocumentElement; + + this.nameSpaceManger = new XmlNamespaceManager(this.rootDocument.NameTable); + this.nameSpaceManger.AddNamespace(CurrentConfigurations.DefaultNameSpacePrefix, this.documentElement.NamespaceURI); + + return String.IsNullOrEmpty(this.serverSession.Error); + } + + /// + /// Update the server with updated XML. + /// Issues a PUT request with the ResourceUri provided. + /// + /// Resource URI to use. + /// Fales, if operation is not succesful. + public void PutConfiguraitonOnServer(string resourceUri) + { + if (String.IsNullOrEmpty(resourceUri)) + { + throw new ArgumentNullException("resourceUri"); + } + + this.serverSession.Put(resourceUri, this.rootDocument.InnerXml, 0); + } + + /// + /// This method will remove the configuration from the XML. + /// Currently the method will only remove the attributes. But it is extensible enough to support + /// Node removals in future. + /// + /// Path with namespace to the node from Root element. Must not end with '/'. + public void RemoveOneConfiguration(string pathToNodeFromRoot) + { + if (pathToNodeFromRoot == null) + { + throw new ArgumentNullException("pathToNodeFromRoot"); + } + + XmlNode nodeToRemove = + this.documentElement.SelectSingleNode( + pathToNodeFromRoot, + this.nameSpaceManger); + + if (nodeToRemove != null) + { + if (nodeToRemove is XmlAttribute) + { + this.RemoveAttribute(nodeToRemove as XmlAttribute); + } + } + else + { + throw new ArgumentException("Node is not present in the XML, Please give valid XPath", "pathToNodeFromRoot"); + } + } + + /// + /// Create or Update the value of the configuration on the given Node. Currently this + /// method is supported for updating attributes, but can be easily updated for nodes. + /// Caller should call this method to add a new attribute to the Node. + /// + /// Path with namespace to the node from Root element. Must not end with '/'. + /// Name of the configuration with name space to update or create. + /// Value of the configurations. + public void UpdateOneConfiguration(string pathToNodeFromRoot, string configurationName, string configurationValue) + { + if (pathToNodeFromRoot == null) + { + throw new ArgumentNullException("pathToNodeFromRoot"); + } + + if (String.IsNullOrEmpty(configurationName)) + { + throw new ArgumentNullException("configurationName"); + } + + if (configurationValue == null) + { + throw new ArgumentNullException("configurationValue"); + } + + XmlNode nodeToUpdate = + this.documentElement.SelectSingleNode( + pathToNodeFromRoot, + this.nameSpaceManger); + + if (nodeToUpdate != null) + { + foreach (XmlAttribute attribute in nodeToUpdate.Attributes) + { + if (attribute.Name.Equals(configurationName, StringComparison.OrdinalIgnoreCase)) + { + attribute.Value = configurationValue; + return; + } + } + + XmlNode attr = this.rootDocument.CreateNode(XmlNodeType.Attribute, configurationName, String.Empty); + attr.Value = configurationValue; + + nodeToUpdate.Attributes.SetNamedItem(attr); + } + } + + /// + /// Gets the value of the configuration on the given Node or attribute. + /// + /// Path with namespace to the node from Root element. + /// Value of the Node, or Null if no node present. + public string GetOneConfiguration(string pathFromRoot) + { + if (pathFromRoot == null) + { + throw new ArgumentNullException("pathFromRoot"); + } + + XmlNode requiredNode = + this.documentElement.SelectSingleNode( + pathFromRoot, + this.nameSpaceManger); + + if (requiredNode != null) + { + return requiredNode.Value; + } + + return null; + } + + /// + /// Removes the attribute from OwnerNode. + /// + /// Attribute to Remove. + private void RemoveAttribute(XmlAttribute attributeToRemove) + { + XmlElement ownerElement = attributeToRemove.OwnerElement; + ownerElement.RemoveAttribute(attributeToRemove.Name); + } + } +} diff --git a/src/Microsoft.WSMan.Management/Interop.cs b/src/Microsoft.WSMan.Management/Interop.cs new file mode 100644 index 000000000..096f5625c --- /dev/null +++ b/src/Microsoft.WSMan.Management/Interop.cs @@ -0,0 +1,1181 @@ +/********************************************************************++ +Copyright (c) Microsoft Corporation. All rights reserved. +--********************************************************************/ +using System; +using System.IO; +using System.Reflection; +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Management.Automation; +using System.Management.Automation.Provider; +using System.Xml; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text; +#if CORECLR +// Use stub for TypeLibTypeAttribute +using Microsoft.PowerShell.CoreClr.Stubs; +#endif + +#pragma warning disable 1591 + +namespace Microsoft.WSMan.Management +{ + + #region "public Api" + + + + #region WsManEnumFlags + /// _WSManEnumFlags enumeration. + + [SuppressMessage("Microsoft.Design", "CA1027:MarkEnumsWithFlags")] + [TypeLibType((short)0)] + public enum WSManEnumFlags + { + /// WSManFlagNonXmlText constant of _WSManEnumFlags enumeration. Constant value is 1. + WSManFlagNonXmlText = 1, + + /// WSManFlagReturnObject constant of _WSManEnumFlags enumeration. Constant value is 0. + WSManFlagReturnObject = 0, + + /// WSManFlagReturnEPR constant of _WSManEnumFlags enumeration. Constant value is 2. + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "EPR")] + WSManFlagReturnEPR = 2, + + /// WSManFlagReturnObjectAndEPR constant of _WSManEnumFlags enumeration. Constant value is 4. + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "EPR")] + WSManFlagReturnObjectAndEPR = 4, + + /// WSManFlagHierarchyDeep constant of _WSManEnumFlags enumeration. Constant value is 0. + WSManFlagHierarchyDeep = 0, + + /// WSManFlagHierarchyShallow constant of _WSManEnumFlags enumeration. Constant value is 32. + WSManFlagHierarchyShallow = 32, + + /// WSManFlagHierarchyDeepBasePropsOnly constant of _WSManEnumFlags enumeration. Constant value is 64. + WSManFlagHierarchyDeepBasePropsOnly = 64, + + /// WSManFlagAssociationInstance constant of _WSManEnumFlags enumeration. Constant value is 64. + WSManFlagAssociationInstance = 128 + } + + #endregion WsManEnumFlags + + + + + #region WsManSessionFlags + /// WSManSessionFlags enumeration. + /// + [SuppressMessage("Microsoft.Design", "CA1027:MarkEnumsWithFlags")] + [TypeLibType((short)0)] + public enum WSManSessionFlags + { + /// no flag constant of _WSManSessionFlags enumeration. Constant value is 1. + WSManNone = 0, + + /// WSManFlagUTF8 constant of _WSManSessionFlags enumeration. Constant value is 1. + WSManFlagUtf8 = 1, + + /// WSManFlagCredUsernamePassword constant of _WSManSessionFlags enumeration. Constant value is 4096. + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Cred")] + WSManFlagCredUserNamePassword = 4096, + + /// WSManFlagSkipCACheck constant of _WSManSessionFlags enumeration. Constant value is 8192. + WSManFlagSkipCACheck = 8192, + + /// WSManFlagSkipCNCheck constant of _WSManSessionFlags enumeration. Constant value is 16384. + WSManFlagSkipCNCheck = 16384, + + /// WSManFlagUseNoAuthentication constant of _WSManSessionFlags enumeration. Constant value is 32768. + WSManFlagUseNoAuthentication = 32768, + + /// WSManFlagUseDigest constant of _WSManSessionFlags enumeration. Constant value is 65536. + WSManFlagUseDigest = 65536, + + /// WSManFlagUseNegotiate constant of _WSManSessionFlags enumeration. Constant value is 131072. + WSManFlagUseNegotiate = 131072, + + /// WSManFlagUseBasic constant of _WSManSessionFlags enumeration. Constant value is 262144. + WSManFlagUseBasic = 262144, + + /// WSManFlagUseKerberos constant of _WSManSessionFlags enumeration. Constant value is 524288. + WSManFlagUseKerberos = 524288, + + /// WSManFlagNoEncryption constant of _WSManSessionFlags enumeration. Constant value is 1048576. + WSManFlagNoEncryption = 1048576, + + /// WSManFlagEnableSPNServerPort constant of _WSManSessionFlags enumeration. Constant value is 4194304. + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Spn")] + WSManFlagEnableSpnServerPort = 4194304, + + /// WSManFlagUTF16 constant of _WSManSessionFlags enumeration. Constant value is 8388608. + WSManFlagUtf16 = 8388608, + + /// WSManFlagUseCredSsp constant of _WSManSessionFlags enumeration. Constant value is 16777216. + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ssp")] + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Cred")] + WSManFlagUseCredSsp = 16777216, + + /// WSManFlagUseClientCertificate constant of _WSManSessionFlags enumeration. Constant value is 2097152. + WSManFlagUseClientCertificate = 2097152, + + /// WSManFlagSkipRevocationCheck constant of _WSManSessionFlags enumeration. Constant value is 33554432. + WSManFlagSkipRevocationCheck = 33554432, + + /// WSManFlagAllowNegotiateImplicitCredentials constant of _WSManSessionFlags enumeration. Constant value is 67108864. + WSManFlagAllowNegotiateImplicitCredentials = 67108864, + + /// WSManFlagUseSsl constant of _WSManSessionFlags enumeration. Constant value is 134217728. + WSManFlagUseSsl = 134217728 + } + #endregion WsManSessionFlags + + #region AuthenticationMechanism + /// WSManEnumFlags enumeration + /// + [SuppressMessage("Microsoft.Design", "CA1027:MarkEnumsWithFlags")] + public enum AuthenticationMechanism + { + /// + /// Use no authentication + /// + None = 0x0, + /// + /// Use Default authentication + /// + Default = 0x1, + /// + /// Use digest authentication for a remote operation + /// + Digest = 0x2, + /// + /// Use negotiate authentication for a remote operation (may use kerboros or ntlm) + /// + Negotiate = 0x4, + /// + /// Use basic authentication for a remote operation + /// + Basic = 0x8, + /// + /// Use kerberos authentication for a remote operation + /// + Kerberos = 0x10, + /// + /// Use client certificate authentication for a remote operation + /// + ClientCertificate = 0x20, + /// + /// Use CredSSP authentication for a remote operation + /// + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Credssp")] + Credssp = 0x80, + } + + #endregion AuthenticationMechanism + + #region IWsMan + + /// IWSMan interface. + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Error")] + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get")] + [Guid("190D8637-5CD3-496D-AD24-69636BB5A3B5")] + [ComImport] + [TypeLibType((short)4304)] +#if CORECLR + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] +#else + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] +#endif + + public interface IWSMan + { +#if CORECLR + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetTypeInfoCount(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetTypeInfo(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetIDsOfNames(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object Invoke(); +#endif + + /// CreateSession method of IWSMan interface. + /// An original IDL definition of CreateSession method was the following: HRESULT CreateSession ([optional, defaultvalue("")] BSTR connection, [optional, defaultvalue(0)] long flags, [optional] IDispatch* connectionOptions, [out, retval] IDispatch** ReturnValue); + // IDL: HRESULT CreateSession ([optional, defaultvalue("")] BSTR connection, [optional, defaultvalue(0)] long flags, [optional] IDispatch* connectionOptions, [out, retval] IDispatch** ReturnValue); + + [DispId(1)] +#if CORECLR + [return: MarshalAs(UnmanagedType.IUnknown)] + object CreateSession([MarshalAs(UnmanagedType.BStr)] string connection, int flags, [MarshalAs(UnmanagedType.IUnknown)] object connectionOptions); +#else + [return: MarshalAs(UnmanagedType.IDispatch)] + object CreateSession([MarshalAs(UnmanagedType.BStr)] string connection, int flags, [MarshalAs(UnmanagedType.IDispatch)] object connectionOptions); +#endif + /// CreateConnectionOptions method of IWSMan interface. + /// An original IDL definition of CreateConnectionOptions method was the following: HRESULT CreateConnectionOptions ([out, retval] IDispatch** ReturnValue); + // IDL: HRESULT CreateConnectionOptions ([out, retval] IDispatch** ReturnValue); + // + [DispId(2)] +#if CORECLR + [return: MarshalAs(UnmanagedType.IUnknown)] +#else + [return: MarshalAs(UnmanagedType.IDispatch)] +#endif + object CreateConnectionOptions(); + + /// CommandLine property of IWSMan interface. + /// An original IDL definition of CommandLine property was the following: BSTR CommandLine; + // IDL: BSTR CommandLine; + // + string CommandLine + { + // IDL: HRESULT CommandLine ([out, retval] BSTR* ReturnValue); + + [DispId(3)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + /// Error property of IWSMan interface. + /// An original IDL definition of Error property was the following: BSTR Error; + // IDL: BSTR Error; + // + + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Error")] + string Error + { + // IDL: HRESULT Error ([out, retval] BSTR* ReturnValue); + + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Error")] + [DispId(4)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + } + #endregion IWsMan + + #region IWSManConnectionOptions + /// IWSManConnectionOptions interface. + [Guid("F704E861-9E52-464F-B786-DA5EB2320FDD")] + [ComImport] + [TypeLibType((short)4288)] +#if CORECLR + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] +#else + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] +#endif + [SuppressMessage("Microsoft.Design", "CA1044:PropertiesShouldNotBeWriteOnly")] + public interface IWSManConnectionOptions + { +#if CORECLR + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetTypeInfoCount(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetTypeInfo(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetIDsOfNames(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object Invoke(); +#endif + /// UserName property of IWSManConnectionOptions interface. + /// An original IDL definition of UserName property was the following: BSTR UserName; + // IDL: BSTR UserName; + + string UserName + { + // IDL: HRESULT UserName ([out, retval] BSTR* ReturnValue); + + [DispId(1)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT UserName (BSTR value); + + [DispId(1)] + set; + } + + /// Password property of IWSManConnectionOptions interface. + /// An original IDL definition of Password property was the following: BSTR Password; + // IDL: BSTR Password; + + [SuppressMessage("Microsoft.Design", "CA1044:PropertiesShouldNotBeWriteOnly")] + string Password + { + // IDL: HRESULT Password (BSTR value); + + [SuppressMessage("Microsoft.Design", "CA1044:PropertiesShouldNotBeWriteOnly")] + [DispId(2)] + set; + } + } + + /// IWSManConnectionOptions interface. + [Guid("EF43EDF7-2A48-4d93-9526-8BD6AB6D4A6B")] + [ComImport] + [TypeLibType((short)4288)] +#if CORECLR + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] +#else + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] +#endif + [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] + public interface IWSManConnectionOptionsEx : IWSManConnectionOptions + { + /// CertificateThumbprint property of IWSManConnectionOptionsEx interface. + string CertificateThumbprint + { + [DispId(3)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + + [DispId(1)] + set; + } + + } + + /// IWSManConnectionOptions interface. + [Guid("F500C9EC-24EE-48ab-B38D-FC9A164C658E")] + [ComImport] + [TypeLibType((short)4288)] +#if CORECLR + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] +#else + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] +#endif + public interface IWSManConnectionOptionsEx2 : IWSManConnectionOptionsEx + { + /// SetProxy method of IWSManConnectionOptionsEx2 interface. + [DispId(4)] + void SetProxy(int accessType, + int authenticationMechanism, + [In, MarshalAs(UnmanagedType.BStr)] string userName, + [In, MarshalAs(UnmanagedType.BStr)] string password); + + /// ProxyIEConfig method of IWSManConnectionOptionsEx2 interface. + [DispId(5)] + int ProxyIEConfig(); + + /// ProxyWinHttpConfig method of IWSManConnectionOptionsEx2 interface. + [DispId(6)] + int ProxyWinHttpConfig(); + + /// ProxyAutoDetect method of IWSManConnectionOptionsEx2 interface. + [DispId(7)] + int ProxyAutoDetect(); + + /// ProxyNoProxyServer method of IWSManConnectionOptionsEx2 interface. + [DispId(8)] + int ProxyNoProxyServer(); + + /// ProxyAuthenticationUseNegotiate method of IWSManConnectionOptionsEx2 interface. + [DispId(9)] + int ProxyAuthenticationUseNegotiate(); + + /// ProxyAuthenticationUseBasic method of IWSManConnectionOptionsEx2 interface. + [DispId(10)] + int ProxyAuthenticationUseBasic(); + + /// ProxyAuthenticationUseDigest method of IWSManConnectionOptionsEx2 interface. + [DispId(11)] + int ProxyAuthenticationUseDigest(); + }; + + + #endregion IWSManConnectionOptions + + #region IWSManEnumerator + /// IWSManEnumerator interface. + [Guid("F3457CA9-ABB9-4FA5-B850-90E8CA300E7F")] + [ComImport] + [TypeLibType((short)4288)] +#if CORECLR + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] +#else + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] +#endif + + public interface IWSManEnumerator + { +#if CORECLR + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetTypeInfoCount(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetTypeInfo(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetIDsOfNames(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object Invoke(); +#endif + + /// ReadItem method of IWSManEnumerator interface. + /// An original IDL definition of ReadItem method was the following: HRESULT ReadItem ([out, retval] BSTR* ReturnValue); + // IDL: HRESULT ReadItem ([out, retval] BSTR* ReturnValue); + + [DispId(1)] + [return: MarshalAs(UnmanagedType.BStr)] + string ReadItem(); + + /// AtEndOfStream property of IWSManEnumerator interface. + /// An original IDL definition of AtEndOfStream property was the following: BOOL AtEndOfStream; + // IDL: BOOL AtEndOfStream; + + bool AtEndOfStream + { + // IDL: HRESULT AtEndOfStream ([out, retval] BOOL* ReturnValue); + + [DispId(2)] + [return: MarshalAs(UnmanagedType.Bool)] + get; + } + + /// Error property of IWSManEnumerator interface. + /// An original IDL definition of Error property was the following: BSTR Error; + // IDL: BSTR Error; + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Error")] + string Error + { + // IDL: HRESULT Error ([out, retval] BSTR* ReturnValue); + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Error")] + [DispId(8)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + } + #endregion IWSManEnumerator + + #region IWSManEx + /// IWSManEx interface. + [Guid("2D53BDAA-798E-49E6-A1AA-74D01256F411")] + [ComImport] + [TypeLibType((short)4304)] + [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] +#if CORECLR + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] +#else + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] +#endif + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "str")] + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Cred")] + [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Username")] + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Error")] + public interface IWSManEx + { +#if CORECLR + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetTypeInfoCount(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetTypeInfo(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetIDsOfNames(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object Invoke(); +#endif + + /// CreateSession method of IWSManEx interface. + /// An original IDL definition of CreateSession method was the following: HRESULT CreateSession ([optional, defaultvalue("")] BSTR connection, [optional, defaultvalue(0)] long flags, [optional] IDispatch* connectionOptions, [out, retval] IDispatch** ReturnValue); + // IDL: HRESULT CreateSession ([optional, defaultvalue("")] BSTR connection, [optional, defaultvalue(0)] long flags, [optional] IDispatch* connectionOptions, [out, retval] IDispatch** ReturnValue); + + [DispId(1)] +#if CORECLR + [return: MarshalAs(UnmanagedType.IUnknown)] + object CreateSession([MarshalAs(UnmanagedType.BStr)] string connection, int flags, [MarshalAs(UnmanagedType.IUnknown)] object connectionOptions); +#else + [return: MarshalAs(UnmanagedType.IDispatch)] + object CreateSession([MarshalAs(UnmanagedType.BStr)] string connection, int flags, [MarshalAs(UnmanagedType.IDispatch)] object connectionOptions); +#endif + + + /// CreateConnectionOptions method of IWSManEx interface. + /// An original IDL definition of CreateConnectionOptions method was the following: HRESULT CreateConnectionOptions ([out, retval] IDispatch** ReturnValue); + // IDL: HRESULT CreateConnectionOptions ([out, retval] IDispatch** ReturnValue); + + [DispId(2)] +#if CORECLR + [return: MarshalAs(UnmanagedType.IUnknown)] +#else + [return: MarshalAs(UnmanagedType.IDispatch)] +#endif + object CreateConnectionOptions(); + + + /// + /// + /// + /// + string CommandLine + { + // IDL: HRESULT CommandLine ([out, retval] BSTR* ReturnValue); + + [DispId(3)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + /// Error property of IWSManEx interface. + /// An original IDL definition of Error property was the following: BSTR Error; + // IDL: BSTR Error; + + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Error")] + string Error + { + // IDL: HRESULT Error ([out, retval] BSTR* ReturnValue); + + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Error")] + [DispId(4)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + + /// CreateResourceLocator method of IWSManEx interface. + /// An original IDL definition of CreateResourceLocator method was the following: HRESULT CreateResourceLocator ([optional, defaultvalue("")] BSTR strResourceLocator, [out, retval] IDispatch** ReturnValue); + // IDL: HRESULT CreateResourceLocator ([optional, defaultvalue("")] BSTR strResourceLocator, [out, retval] IDispatch** ReturnValue); + + + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "str")] + [DispId(5)] +#if CORECLR + [return: MarshalAs(UnmanagedType.IUnknown)] +#else + [return: MarshalAs(UnmanagedType.IDispatch)] +#endif + object CreateResourceLocator([MarshalAs(UnmanagedType.BStr)] string strResourceLocator); + + /// SessionFlagUTF8 method of IWSManEx interface. + /// An original IDL definition of SessionFlagUTF8 method was the following: HRESULT SessionFlagUTF8 ([out, retval] long* ReturnValue); + // IDL: HRESULT SessionFlagUTF8 ([out, retval] long* ReturnValue); + + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "UTF")] + [DispId(6)] + int SessionFlagUTF8(); + + /// SessionFlagCredUsernamePassword method of IWSManEx interface. + /// An original IDL definition of SessionFlagCredUsernamePassword method was the following: HRESULT SessionFlagCredUsernamePassword ([out, retval] long* ReturnValue); + // IDL: HRESULT SessionFlagCredUsernamePassword ([out, retval] long* ReturnValue); + + + [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Username")] + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Cred")] + [DispId(7)] + int SessionFlagCredUsernamePassword(); + + /// SessionFlagSkipCACheck method of IWSManEx interface. + /// An original IDL definition of SessionFlagSkipCACheck method was the following: HRESULT SessionFlagSkipCACheck ([out, retval] long* ReturnValue); + // IDL: HRESULT SessionFlagSkipCACheck ([out, retval] long* ReturnValue); + + [DispId(8)] + int SessionFlagSkipCACheck(); + + /// SessionFlagSkipCNCheck method of IWSManEx interface. + /// An original IDL definition of SessionFlagSkipCNCheck method was the following: HRESULT SessionFlagSkipCNCheck ([out, retval] long* ReturnValue); + // IDL: HRESULT SessionFlagSkipCNCheck ([out, retval] long* ReturnValue); + + [DispId(9)] + int SessionFlagSkipCNCheck(); + + /// SessionFlagUseDigest method of IWSManEx interface. + /// An original IDL definition of SessionFlagUseDigest method was the following: HRESULT SessionFlagUseDigest ([out, retval] long* ReturnValue); + // IDL: HRESULT SessionFlagUseDigest ([out, retval] long* ReturnValue); + + [DispId(10)] + int SessionFlagUseDigest(); + + /// SessionFlagUseNegotiate method of IWSManEx interface. + /// An original IDL definition of SessionFlagUseNegotiate method was the following: HRESULT SessionFlagUseNegotiate ([out, retval] long* ReturnValue); + // IDL: HRESULT SessionFlagUseNegotiate ([out, retval] long* ReturnValue); + + [DispId(11)] + int SessionFlagUseNegotiate(); + + /// SessionFlagUseBasic method of IWSManEx interface. + /// An original IDL definition of SessionFlagUseBasic method was the following: HRESULT SessionFlagUseBasic ([out, retval] long* ReturnValue); + // IDL: HRESULT SessionFlagUseBasic ([out, retval] long* ReturnValue); + + [DispId(12)] + int SessionFlagUseBasic(); + + /// SessionFlagUseKerberos method of IWSManEx interface. + /// An original IDL definition of SessionFlagUseKerberos method was the following: HRESULT SessionFlagUseKerberos ([out, retval] long* ReturnValue); + // IDL: HRESULT SessionFlagUseKerberos ([out, retval] long* ReturnValue); + + [DispId(13)] + int SessionFlagUseKerberos(); + + /// SessionFlagNoEncryption method of IWSManEx interface. + /// An original IDL definition of SessionFlagNoEncryption method was the following: HRESULT SessionFlagNoEncryption ([out, retval] long* ReturnValue); + // IDL: HRESULT SessionFlagNoEncryption ([out, retval] long* ReturnValue); + + [DispId(14)] + int SessionFlagNoEncryption(); + + /// SessionFlagEnableSPNServerPort method of IWSManEx interface. + /// An original IDL definition of SessionFlagEnableSPNServerPort method was the following: HRESULT SessionFlagEnableSPNServerPort ([out, retval] long* ReturnValue); + // IDL: HRESULT SessionFlagEnableSPNServerPort ([out, retval] long* ReturnValue); + + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SPN")] + [DispId(15)] + int SessionFlagEnableSPNServerPort(); + + /// SessionFlagUseNoAuthentication method of IWSManEx interface. + /// An original IDL definition of SessionFlagUseNoAuthentication method was the following: HRESULT SessionFlagUseNoAuthentication ([out, retval] long* ReturnValue); + // IDL: HRESULT SessionFlagUseNoAuthentication ([out, retval] long* ReturnValue); + + [DispId(16)] + int SessionFlagUseNoAuthentication(); + + /// EnumerationFlagNonXmlText method of IWSManEx interface. + /// An original IDL definition of EnumerationFlagNonXmlText method was the following: HRESULT EnumerationFlagNonXmlText ([out, retval] long* ReturnValue); + // IDL: HRESULT EnumerationFlagNonXmlText ([out, retval] long* ReturnValue); + + [DispId(17)] + int EnumerationFlagNonXmlText(); + + /// EnumerationFlagReturnEPR method of IWSManEx interface. + /// An original IDL definition of EnumerationFlagReturnEPR method was the following: HRESULT EnumerationFlagReturnEPR ([out, retval] long* ReturnValue); + // IDL: HRESULT EnumerationFlagReturnEPR ([out, retval] long* ReturnValue); + + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "EPR")] + [DispId(18)] + int EnumerationFlagReturnEPR(); + + /// EnumerationFlagReturnObjectAndEPR method of IWSManEx interface. + /// An original IDL definition of EnumerationFlagReturnObjectAndEPR method was the following: HRESULT EnumerationFlagReturnObjectAndEPR ([out, retval] long* ReturnValue); + // IDL: HRESULT EnumerationFlagReturnObjectAndEPR ([out, retval] long* ReturnValue); + + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "EPR")] + [DispId(19)] + int EnumerationFlagReturnObjectAndEPR(); + + /// GetErrorMessage method of IWSManEx interface. + /// An original IDL definition of GetErrorMessage method was the following: HRESULT GetErrorMessage (unsigned long errorNumber, [out, retval] BSTR* ReturnValue); + // IDL: HRESULT GetErrorMessage (unsigned long errorNumber, [out, retval] BSTR* ReturnValue); + + [DispId(20)] + [return: MarshalAs(UnmanagedType.BStr)] + string GetErrorMessage(uint errorNumber); + + /// EnumerationFlagHierarchyDeep method of IWSManEx interface. + /// An original IDL definition of EnumerationFlagHierarchyDeep method was the following: HRESULT EnumerationFlagHierarchyDeep ([out, retval] long* ReturnValue); + // IDL: HRESULT EnumerationFlagHierarchyDeep ([out, retval] long* ReturnValue); + + [DispId(21)] + int EnumerationFlagHierarchyDeep(); + + /// EnumerationFlagHierarchyShallow method of IWSManEx interface. + /// An original IDL definition of EnumerationFlagHierarchyShallow method was the following: HRESULT EnumerationFlagHierarchyShallow ([out, retval] long* ReturnValue); + // IDL: HRESULT EnumerationFlagHierarchyShallow ([out, retval] long* ReturnValue); + + [DispId(22)] + int EnumerationFlagHierarchyShallow(); + + /// EnumerationFlagHierarchyDeepBasePropsOnly method of IWSManEx interface. + /// An original IDL definition of EnumerationFlagHierarchyDeepBasePropsOnly method was the following: HRESULT EnumerationFlagHierarchyDeepBasePropsOnly ([out, retval] long* ReturnValue); + // IDL: HRESULT EnumerationFlagHierarchyDeepBasePropsOnly ([out, retval] long* ReturnValue); + + [DispId(23)] + int EnumerationFlagHierarchyDeepBasePropsOnly(); + + /// EnumerationFlagReturnObject method of IWSManEx interface. + /// An original IDL definition of EnumerationFlagReturnObject method was the following: HRESULT EnumerationFlagReturnObject ([out, retval] long* ReturnValue); + // IDL: HRESULT EnumerationFlagReturnObject ([out, retval] long* ReturnValue); + + [DispId(24)] + int EnumerationFlagReturnObject(); + + /// CommandLine property of IWSManEx interface. + /// An original IDL definition of CommandLine property was the following: BSTR CommandLine; + // IDL: BSTR CommandLine; + [DispId(28)] + int EnumerationFlagAssociationInstance(); + + /// CommandLine property of IWSManEx interface. + /// An original IDL definition of CommandLine property was the following: BSTR CommandLine; + // IDL: BSTR CommandLine; + [DispId(29)] + int EnumerationFlagAssociatedInstance(); + } +#endregion IWsManEx + +#region IWsManResourceLocator + + /// IWSManResourceLocator interface. + [SuppressMessage("Microsoft.Design", "CA1040:AvoidEmptyInterfaces")] + + [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")] + + + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sel")] + + [Guid("A7A1BA28-DE41-466A-AD0A-C4059EAD7428")] + [ComImport] + [TypeLibType((short)4288)] +#if CORECLR + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] +#else + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] +#endif + + + public interface IWSManResourceLocator + { +#if CORECLR + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetTypeInfoCount(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetTypeInfo(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetIDsOfNames(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object Invoke(); +#endif + /// resourceUri property of IWSManResourceLocator interface. Set the resource URI. Must contain path only -- query string is not allowed here. + /// An original IDL definition of resourceUri property was the following: BSTR resourceUri; + // Set the resource URI. Must contain path only -- query string is not allowed here. + // IDL: BSTR resourceUri; + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "resource")] + [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")] + string ResourceUri + { + + // IDL: HRESULT resourceUri (BSTR value); + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "resource")] + [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")] + [DispId(1)] + set; + + // IDL: HRESULT resourceUri ([out, retval] BSTR* ReturnValue); + + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "resource")] + [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")] + [DispId(1)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + + } + + /// AddSelector method of IWSManResourceLocator interface. Add selector to resource locator + /// An original IDL definition of AddSelector method was the following: HRESULT AddSelector (BSTR resourceSelName, VARIANT selValue); + // Add selector to resource locator + // IDL: HRESULT AddSelector (BSTR resourceSelName, VARIANT selValue); + + + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "resource")] + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "sel")] + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sel")] + [DispId(2)] + void AddSelector([MarshalAs(UnmanagedType.BStr)] string resourceSelName, object selValue); + + /// ClearSelectors method of IWSManResourceLocator interface. Clear all selectors + /// An original IDL definition of ClearSelectors method was the following: HRESULT ClearSelectors (void); + // Clear all selectors + // IDL: HRESULT ClearSelectors (void); + + + + [DispId(3)] + void ClearSelectors(); + + /// FragmentPath property of IWSManResourceLocator interface. Gets the fragment path + /// An original IDL definition of FragmentPath property was the following: BSTR FragmentPath; + // Gets the fragment path + // IDL: BSTR FragmentPath; + + string FragmentPath + { + // IDL: HRESULT FragmentPath ([out, retval] BSTR* ReturnValue); + + [DispId(4)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT FragmentPath (BSTR value); + + [DispId(4)] + set; + } + + + /// FragmentDialect property of IWSManResourceLocator interface. Gets the Fragment dialect + /// An original IDL definition of FragmentDialect property was the following: BSTR FragmentDialect; + // Gets the Fragment dialect + // IDL: BSTR FragmentDialect; + + string FragmentDialect + { + // IDL: HRESULT FragmentDialect ([out, retval] BSTR* ReturnValue); + + [DispId(5)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT FragmentDialect (BSTR value); + + [DispId(5)] + set; + } + + /// AddOption method of IWSManResourceLocator interface. Add option to resource locator + /// An original IDL definition of AddOption method was the following: HRESULT AddOption (BSTR OptionName, VARIANT OptionValue, [optional, defaultvalue(0)] long mustComply); + // Add option to resource locator + // IDL: HRESULT AddOption (BSTR OptionName, VARIANT OptionValue, [optional, defaultvalue(0)] long mustComply); + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Option")] + [DispId(6)] + void AddOption([MarshalAs(UnmanagedType.BStr)] string OptionName, object OptionValue, int mustComply); + + + /// MustUnderstandOptions property of IWSManResourceLocator interface. Sets the MustUnderstandOptions value + /// An original IDL definition of MustUnderstandOptions property was the following: long MustUnderstandOptions; + // Sets the MustUnderstandOptions value + // IDL: long MustUnderstandOptions; + + int MustUnderstandOptions + { + // IDL: HRESULT MustUnderstandOptions ([out, retval] long* ReturnValue); + + [DispId(7)] + get; + // IDL: HRESULT MustUnderstandOptions (long value); + + [DispId(7)] + set; + } + + + /// ClearOptions method of IWSManResourceLocator interface. Clear all options + /// An original IDL definition of ClearOptions method was the following: HRESULT ClearOptions (void); + // Clear all options + // IDL: HRESULT ClearOptions (void); + + [DispId(8)] + void ClearOptions(); + + + + /// Error property of IWSManResourceLocator interface. + /// An original IDL definition of Error property was the following: BSTR Error; + // IDL: BSTR Error; + + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Error")] + string Error + { + // IDL: HRESULT Error ([out, retval] BSTR* ReturnValue); + + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Error")] + [DispId(9)] + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Error")] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + + + } +#endregion IWsManResourceLocator + +#region IWSManSession + /// IWSManSession interface. + [Guid("FC84FC58-1286-40C4-9DA0-C8EF6EC241E0")] + [ComImport] + [TypeLibType((short)4288)] +#if CORECLR + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] +#else + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] +#endif + + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Error")] + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get")] + [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")] + public interface IWSManSession + { +#if CORECLR + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetTypeInfoCount(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetTypeInfo(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetIDsOfNames(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object Invoke(); +#endif + + /// Get method of IWSManSession interface. + /// An original IDL definition of Get method was the following: HRESULT Get (VARIANT resourceUri, [optional, defaultvalue(0)] long flags, [out, retval] BSTR* ReturnValue); + // IDL: HRESULT Get (VARIANT resourceUri, [optional, defaultvalue(0)] long flags, [out, retval] BSTR* ReturnValue); + + + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get")] + [DispId(1)] + [return: MarshalAs(UnmanagedType.BStr)] + string Get(object resourceUri, int flags); + + /// Put method of IWSManSession interface. + /// An original IDL definition of Put method was the following: HRESULT Put (VARIANT resourceUri, BSTR resource, [optional, defaultvalue(0)] long flags, [out, retval] BSTR* ReturnValue); + // IDL: HRESULT Put (VARIANT resourceUri, BSTR resource, [optional, defaultvalue(0)] long flags, [out, retval] BSTR* ReturnValue); + + [DispId(2)] + [return: MarshalAs(UnmanagedType.BStr)] + string Put(object resourceUri, [MarshalAs(UnmanagedType.BStr)] string resource, int flags); + + /// Create method of IWSManSession interface. + /// An original IDL definition of Create method was the following: HRESULT Create (VARIANT resourceUri, BSTR resource, [optional, defaultvalue(0)] long flags, [out, retval] BSTR* ReturnValue); + // IDL: HRESULT Create (VARIANT resourceUri, BSTR resource, [optional, defaultvalue(0)] long flags, [out, retval] BSTR* ReturnValue); + + [DispId(3)] + [return: MarshalAs(UnmanagedType.BStr)] + string Create(object resourceUri, [MarshalAs(UnmanagedType.BStr)] string resource, int flags); + + /// Delete method of IWSManSession interface. + /// An original IDL definition of Delete method was the following: HRESULT Delete (VARIANT resourceUri, [optional, defaultvalue(0)] long flags); + // IDL: HRESULT Delete (VARIANT resourceUri, [optional, defaultvalue(0)] long flags); + + [DispId(4)] + void Delete(object resourceUri, int flags); + + /// + /// + /// + /// + /// + /// + /// + /// + + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")] + [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")] + [DispId(5)] + String Invoke([MarshalAs(UnmanagedType.BStr)] string actionURI, [In] object resourceUri, [MarshalAs(UnmanagedType.BStr)] string parameters, [In] int flags); + + + /// Enumerate method of IWSManSession interface. + /// An original IDL definition of Enumerate method was the following: HRESULT Enumerate (VARIANT resourceUri, [optional, defaultvalue("")] BSTR filter, [optional, defaultvalue("")] BSTR dialect, [optional, defaultvalue(0)] long flags, [out, retval] IDispatch** ReturnValue); + // IDL: HRESULT Enumerate (VARIANT resourceUri, [optional, defaultvalue("")] BSTR filter, [optional, defaultvalue("")] BSTR dialect, [optional, defaultvalue(0)] long flags, [out, retval] IDispatch** ReturnValue); + + [DispId(6)] +#if CORECLR + [return: MarshalAs(UnmanagedType.IUnknown)] +#else + [return: MarshalAs(UnmanagedType.IDispatch)] +#endif + object Enumerate(object resourceUri, [MarshalAs(UnmanagedType.BStr)] string filter, [MarshalAs(UnmanagedType.BStr)] string dialect, int flags); + + /// Identify method of IWSManSession interface. + /// An original IDL definition of Identify method was the following: HRESULT Identify ([optional, defaultvalue(0)] long flags, [out, retval] BSTR* ReturnValue); + // IDL: HRESULT Identify ([optional, defaultvalue(0)] long flags, [out, retval] BSTR* ReturnValue); + + [DispId(7)] + [return: MarshalAs(UnmanagedType.BStr)] + string Identify(int flags); + + /// Error property of IWSManSession interface. + /// An original IDL definition of Error property was the following: BSTR Error; + // IDL: BSTR Error; + + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Error")] + string Error + { + // IDL: HRESULT Error ([out, retval] BSTR* ReturnValue); + + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Error")] + [DispId(8)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + + /// BatchItems property of IWSManSession interface. + /// An original IDL definition of BatchItems property was the following: long BatchItems; + // IDL: long BatchItems; + + int BatchItems + { + // IDL: HRESULT BatchItems ([out, retval] long* ReturnValue); + + [DispId(9)] + get; + // IDL: HRESULT BatchItems (long value); + + [DispId(9)] + set; + } + + + /// Timeout property of IWSManSession interface. + /// An original IDL definition of Timeout property was the following: long Timeout; + // IDL: long Timeout; + + int Timeout + { + // IDL: HRESULT Timeout ([out, retval] long* ReturnValue); + + [DispId(10)] + get; + // IDL: HRESULT Timeout (long value); + + [DispId(10)] + set; + } + } + +#endregion IWSManSession + +#region IWSManResourceLocatorInternal + /// IWSManResourceLocatorInternal interface. + [Guid("EFFAEAD7-7EC8-4716-B9BE-F2E7E9FB4ADB")] + [ComImport] + [TypeLibType((short)400)] +#if CORECLR + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] +#else + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] +#endif + [SuppressMessage("Microsoft.Design", "CA1040:AvoidEmptyInterfaces")] + public interface IWSManResourceLocatorInternal + { +#if CORECLR + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetTypeInfoCount(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetTypeInfo(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetIDsOfNames(); + + [return: MarshalAs(UnmanagedType.IUnknown)] + object Invoke(); +#endif + } + + #endregion IWSManResourceLocatorInternal + + + /// WSMan interface. + [Guid("BCED617B-EC03-420b-8508-977DC7A686BD")] + [ComImport] +#if CORECLR + [ClassInterface(ClassInterfaceType.None)] +#else + [ClassInterface(ClassInterfaceType.AutoDual)] +#endif + public class WSManClass + { + } + + #region IGroupPolicyObject + + /// GPClass interface. + [Guid("EA502722-A23D-11d1-A7D3-0000F87571E3")] + [ComImport] + [ClassInterface(ClassInterfaceType.None)] + public class GPClass + { + } + [ComImport, Guid("EA502723-A23D-11d1-A7D3-0000F87571E3"), + InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + interface IGroupPolicyObject + { + void New( + [MarshalAs(UnmanagedType.LPWStr)] string pszDomainName, + [MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, + uint dwFlags); + + void OpenDSGPO( + [MarshalAs(UnmanagedType.LPWStr)] string pszPath, + uint dwFlags); + + void OpenLocalMachineGPO(uint dwFlags); + + void OpenRemoteMachineGPO( + [MarshalAs(UnmanagedType.LPWStr)] string pszComputerName, + uint dwFlags); + + void Save( + [MarshalAs(UnmanagedType.Bool)] bool bMachine, + [MarshalAs(UnmanagedType.Bool)] bool bAdd, + [MarshalAs(UnmanagedType.LPStruct)] Guid pGuidExtension, + [MarshalAs(UnmanagedType.LPStruct)] Guid pGuid); + + void Delete(); + + void GetName( + [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, + int cchMaxLength); + + void GetDisplayName( + [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, + int cchMaxLength); + + void SetDisplayName( + [MarshalAs(UnmanagedType.LPWStr)] string pszName); + + void GetPath( + [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszPath, + int cchMaxPath); + + void GetDSPath( + uint dwSection, + [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszPath, + int cchMaxPath); + + void GetFileSysPath( + uint dwSection, + [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszPath, + int cchMaxPath); + + IntPtr GetRegistryKey(uint dwSection); + + uint GetOptions(); + + void SetOptions(uint dwOptions, uint dwMask); + + void GetMachineName( + [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, + int cchMaxLength); + + uint GetPropertySheetPages(out IntPtr hPages); + } + +#endregion IGroupPolicyObject + + /// GpoNativeApi + public sealed class GpoNativeApi + { + private GpoNativeApi() { } + + [DllImport("Userenv.dll", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern System.IntPtr EnterCriticalPolicySection( + [In, MarshalAs(UnmanagedType.Bool)] bool bMachine); + + [DllImport("Userenv.dll", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern bool LeaveCriticalPolicySection( + [In] System.IntPtr hSection); + } +#endregion + +} + +#pragma warning restore 1591 diff --git a/src/Microsoft.WSMan.Management/InvokeWSManAction.cs b/src/Microsoft.WSMan.Management/InvokeWSManAction.cs new file mode 100644 index 000000000..c26f93c43 --- /dev/null +++ b/src/Microsoft.WSMan.Management/InvokeWSManAction.cs @@ -0,0 +1,329 @@ +/********************************************************************++ +Copyright (c) Microsoft Corporation. All rights reserved. +--********************************************************************/ +using System; +using System.IO; +using System.Reflection; +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Management.Automation; +using System.Management.Automation.Provider; +using System.Xml; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + + + +namespace Microsoft.WSMan.Management +{ + /// + /// Executes action on a target object specified by RESOURCE_URI, where + /// parameters are specified by key value pairs. + /// eg., Call StartService method on the spooler service + /// Invoke-WSManAction -Action StartService -ResourceURI wmicimv2/Win32_Service + /// -SelectorSet {Name=Spooler} + /// + + [Cmdlet(VerbsLifecycle.Invoke, "WSManAction", DefaultParameterSetName = "URI", HelpUri = "http://go.microsoft.com/fwlink/?LinkId=141446")] + public class InvokeWSManActionCommand : AuthenticatingWSManCommand, IDisposable + { + /// + /// The following is the definition of the input parameter "Action". + /// Indicates the method which needs to be executed on the management object + /// specified by the ResourceURI and selectors + /// + [Parameter(Mandatory = true, + Position = 1)] + [ValidateNotNullOrEmpty] + public String Action + { + get { return action; } + set { action = value; } + } + private String action; + + /// + /// The following is the definition of the input parameter "ApplicationName". + /// ApplicationName identifies the remote endpoint. + /// + [Parameter(ParameterSetName = "ComputerName")] + [ValidateNotNullOrEmpty] + public String ApplicationName + { + get { return applicationname; } + set { applicationname = value; } + } + private String applicationname = null; + + /// + /// The following is the definition of the input parameter "ComputerName". + /// Executes the management operation on the specified computer(s). The default + /// is the local computer. Type the fully qualified domain name, NETBIOS name or + /// IP address to indicate the remote host(s) + /// + [Parameter(ParameterSetName = "ComputerName")] + [Alias("cn")] + public String ComputerName + { + get { return computername; } + set + { + computername = value; + if ((string.IsNullOrEmpty(computername)) || (computername.Equals(".", StringComparison.CurrentCultureIgnoreCase))) + { + computername = "localhost"; + } + + } + } + private String computername = null; + + /// + /// The following is the definition of the input parameter "ConnectionURI". + /// Specifies the transport, server, port, and ApplicationName of the new + /// runspace. The format of this string is: + /// transport://server:port/ApplicationName. + /// + [Parameter(ParameterSetName = "URI")] + [ValidateNotNullOrEmpty] + [Alias("CURI", "CU")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")] + public Uri ConnectionURI + { + get { return connectionuri; } + set { connectionuri = value; } + } + private Uri connectionuri; + + /// + /// The following is the definition of the input parameter "FilePath". + /// Updates the management resource specified by the ResourceURI and SelectorSet + /// via this input file + /// + [Parameter] + [ValidateNotNullOrEmpty] + public String FilePath + { + get { return filepath; } + set { filepath = value; } + } + private String filepath; + + /// + /// The following is the definition of the input parameter "OptionSet". + /// OptionSet is a hashtable and is used to pass a set of switches to the + /// service to modify or refine the nature of the request. + /// + [Parameter(ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true)] + [ValidateNotNullOrEmpty] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + [Alias("os")] + public Hashtable OptionSet + { + get { return optionset; } + set { optionset = value; } + } + private Hashtable optionset; + + /// + /// The following is the definition of the input parameter "Port". + /// Specifies the port to be used when connecting to the ws management service. + /// + [Parameter(ParameterSetName = "ComputerName")] + [ValidateNotNullOrEmpty] + [ValidateRange(1, Int32.MaxValue)] + public Int32 Port + { + get { return port; } + set { port = value; } + } + private Int32 port = 0; + + /// + /// The following is the definition of the input parameter "SelectorSet". + /// SelectorSet is a hash table which helps in identify an instance of the + /// management resource if there are are more than 1 instance of the resource + /// class + /// + [Parameter(Position = 2, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true)] + [ValidateNotNullOrEmpty] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public Hashtable SelectorSet + { + get { return selectorset; } + set { selectorset = value; } + } + private Hashtable selectorset; + + /// + /// The following is the definition of the input parameter "SessionOption". + /// Defines a set of extended options for the WSMan session. This hashtable can + /// be created using New-WSManSessionOption + /// + [Parameter] + [ValidateNotNullOrEmpty] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + [Alias("so")] + public SessionOption SessionOption + { + get { return sessionoption; } + set { sessionoption = value; } + } + private SessionOption sessionoption; + + /// + /// The following is the definition of the input parameter "UseSSL". + /// Uses the Secure Sockets Layer (SSL) protocol to establish a connnection to + /// the remote computer. If SSL is not available on the port specified by the + /// Port parameter, the command fails. + /// + [Parameter(ParameterSetName = "ComputerName")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SSL")] + public SwitchParameter UseSSL + { + get { return usessl; } + set { usessl = value; } + } + private SwitchParameter usessl; + + /// + /// The following is the definition of the input parameter "ValueSet". + /// ValueSet is a hahs table which helps to modify resource represented by the + /// ResourceURI and SelectorSet. + /// + [Parameter] + [ValidateNotNullOrEmpty] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public Hashtable ValueSet + { + get { return valueset; } + set { valueset = value; } + } + private Hashtable valueset; + + + /// + /// The following is the definition of the input parameter "ResourceURI". + /// URI of the resource class/instance representation + /// + [Parameter(Mandatory = true, Position = 0, ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true)] + [ValidateNotNullOrEmpty] + [Alias("ruri")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")] + public Uri ResourceURI + { + get { return resourceuri; } + set { resourceuri = value; } + } + private Uri resourceuri; + + + private WSManHelper helper; + IWSManEx m_wsmanObject = (IWSManEx)new WSManClass(); + IWSManSession m_session = null; + string connectionStr = string.Empty; + + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + helper = new WSManHelper(this); + + helper.WSManOp = "invoke"; + + //create the connection string + connectionStr = helper.CreateConnectionString(connectionuri, port, computername, applicationname); + + + } + + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + + + try + { + //create the resourcelocator object + IWSManResourceLocator m_resource = helper.InitializeResourceLocator(optionset, selectorset, null, null, m_wsmanObject, resourceuri); + + //create the session object + m_session = helper.CreateSessionObject(m_wsmanObject, Authentication, sessionoption, Credential, connectionStr, CertificateThumbprint, usessl.IsPresent); + + string rootNode = helper.GetRootNodeName(helper.WSManOp, m_resource.ResourceUri, action); + string input = helper.ProcessInput(m_wsmanObject, filepath, helper.WSManOp, rootNode, valueset, m_resource, m_session); + string resultXml = m_session.Invoke(action, m_resource, input, 0); + + XmlDocument xmldoc = new XmlDocument(); + xmldoc.LoadXml(resultXml); + WriteObject(xmldoc.DocumentElement); + + } + finally + { + if (!String.IsNullOrEmpty(m_wsmanObject.Error)) + { + helper.AssertError(m_wsmanObject.Error, true, resourceuri); + } + if (!String.IsNullOrEmpty(m_session.Error)) + { + helper.AssertError(m_session.Error, true, resourceuri); + } + if (m_session != null) + Dispose(m_session); + + } + + }//End ProcessRecord() + + #region IDisposable Members + + /// + /// public dispose method + /// + public + void + Dispose() + { + //CleanUp(); + GC.SuppressFinalize(this); + } + /// + /// public dispose method + /// + public + void + Dispose(IWSManSession sessionObject) + { + sessionObject = null; + this.Dispose(); + } + + #endregion IDisposable Members + + /// + /// BeginProcessing method. + /// + protected override void EndProcessing() + { + // WSManHelper helper = new WSManHelper(); + helper.CleanUp(); + } + + + + + + + }//End Class +} diff --git a/src/Microsoft.WSMan.Management/NewWSManSession.cs b/src/Microsoft.WSMan.Management/NewWSManSession.cs new file mode 100644 index 000000000..342a9b679 --- /dev/null +++ b/src/Microsoft.WSMan.Management/NewWSManSession.cs @@ -0,0 +1,272 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +using System; +using System.IO; +using System.Reflection; +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Management.Automation; +using System.Management.Automation.Provider; +using System.Xml; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Net; + + + +namespace Microsoft.WSMan.Management +{ + /// + /// Creates a WSMan Session option hashtable which can be passed into WSMan + /// cmdlets: + /// Get-WSManInstance + /// Set-WSManInstance + /// Invoke-WSManAction + /// Connect-WSMan + /// + + + [Cmdlet(VerbsCommon.New, "WSManSessionOption", HelpUri = "http://go.microsoft.com/fwlink/?LinkId=141449")] + public class NewWSManSessionOptionCommand : PSCmdlet + { + /// + /// + /// + [Parameter] + [ValidateNotNullOrEmpty] + public ProxyAccessType ProxyAccessType + { + get + { + return _proxyacesstype; + } + set + { + _proxyacesstype = value; + } + } + private ProxyAccessType _proxyacesstype; + + /// + /// The following is the definition of the input parameter "ProxyAuthentication". + /// This parameter takes a set of authentication methods the user can select + /// from. The available options should be as follows: + /// - Negotiate: Use the default authentication (ad defined by the underlying + /// protocol) for establishing a remote connection. + /// - Basic: Use basic authentication for establishing a remote connection + /// - Digest: Use Digest authentication for establishing a remote connection + /// + [Parameter] + [ValidateNotNullOrEmpty] + public ProxyAuthentication ProxyAuthentication + { + get { return proxyauthentication; } + set + { + proxyauthentication = value; + } + } + private ProxyAuthentication proxyauthentication; + + /// + /// The following is the definition of the input parameter "ProxyCredential". + /// + [Parameter] + [ValidateNotNullOrEmpty] + [Credential] + public PSCredential ProxyCredential + { + get { return _proxycredential; } + set + { + _proxycredential = value; + } + } + private PSCredential _proxycredential; + + + /// + /// The following is the definition of the input parameter "SkipCACheck". + /// When connecting over HTTPS, the client does not validate that the server + /// certificate is signed by a trusted certificate authority (CA). Use only when + /// the remote computer is trusted by other means, for example, if the remote + /// computer is part of a network that is physically secure and isolated or the + /// remote computer is listed as a trusted host in WinRM configuration + /// + [Parameter] + public SwitchParameter SkipCACheck + { + get { return skipcacheck; } + set + { + skipcacheck = value; + } + } + private bool skipcacheck; + + /// + /// The following is the definition of the input parameter "SkipCNCheck". + /// Indicates that certificate common name (CN) of the server need not match the + /// hostname of the server. Used only in remote operations using https. This + /// option should only be used for trusted machines + /// + [Parameter] + public SwitchParameter SkipCNCheck + { + get { return skipcncheck; } + set + { + skipcncheck = value; + } + } + private bool skipcncheck; + + /// + /// The following is the definition of the input parameter "SkipRevocation". + /// Indicates that certificate common name (CN) of the server need not match the + /// hostname of the server. Used only in remote operations using https. This + /// option should only be used for trusted machines + /// + [Parameter] + public SwitchParameter SkipRevocationCheck + { + get { return skiprevocationcheck; } + set + { + skiprevocationcheck = value; + } + } + private bool skiprevocationcheck; + + /// + /// The following is the definition of the input parameter "SPNPort". + /// Appends port number to the connection Service Principal Name SPN of the + /// remote server. + /// SPN is used when authentication mechanism is Kerberos or Negotiate + /// + [Parameter] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SPN")] + [ValidateRange(0, Int32.MaxValue)] + public Int32 SPNPort + { + get { return spnport; } + set + { + spnport = value; + } + } + private Int32 spnport; + + /// + /// The following is the definition of the input parameter "Timeout". + /// Defines the timeout in ms for the wsman operation + /// + [Parameter] + [Alias("OperationTimeoutMSec")] + [ValidateRange(0, Int32.MaxValue)] + public Int32 OperationTimeout + { + get { return operationtimeout; } + set + { + operationtimeout = value; + } + } + private Int32 operationtimeout; + + /// + /// The following is the definition of the input parameter "UnEncrypted". + /// Specifies that no encryption will be used when doing remote operations over + /// http. Unencrypted traffix is not allowed by default and must be enabled in + /// the local configuration + /// + [Parameter] + public SwitchParameter NoEncryption + { + get { return noencryption; } + set + { + noencryption = value; + } + } + private bool noencryption; + + /// + /// The following is the definition of the input parameter "UTF16". + /// Indicates the request is encoded in UTF16 format rather than UTF8 format; + /// UTF8 is the default. + /// + [Parameter] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "UTF")] + public SwitchParameter UseUTF16 + { + get { return useutf16; } + set + { + useutf16 = value; + } + } + private bool useutf16; + + + + + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + WSManHelper helper = new WSManHelper(this); + + if (proxyauthentication.Equals(ProxyAuthentication.Basic) || proxyauthentication.Equals(ProxyAuthentication.Digest)) + { + if (_proxycredential == null) + { + InvalidOperationException ex = new InvalidOperationException(helper.GetResourceMsgFromResourcetext("NewWSManSessionOptionCred")); + ErrorRecord er = new ErrorRecord(ex, "InvalidOperationException", ErrorCategory.InvalidOperation, null); + WriteError(er); + return; + } + } + + if ((_proxycredential != null) && (proxyauthentication == 0)) + { + InvalidOperationException ex = new InvalidOperationException(helper.GetResourceMsgFromResourcetext("NewWSManSessionOptionAuth")); + ErrorRecord er = new ErrorRecord(ex, "InvalidOperationException", ErrorCategory.InvalidOperation, null); + WriteError(er); + return; + } + + + + //Creating the Session Object + SessionOption objSessionOption = new SessionOption(); + + objSessionOption.SPNPort = spnport; + objSessionOption.UseUtf16 = useutf16; + objSessionOption.SkipCNCheck = skipcncheck; + objSessionOption.SkipCACheck = skipcacheck; + objSessionOption.OperationTimeout = operationtimeout; + objSessionOption.SkipRevocationCheck = skiprevocationcheck; + //Proxy Settings + objSessionOption.ProxyAccessType = _proxyacesstype; + objSessionOption.ProxyAuthentication = proxyauthentication; + + if (noencryption) + { + objSessionOption.UseEncryption = false; + } + if (_proxycredential != null) + { + NetworkCredential nwCredentials = _proxycredential.GetNetworkCredential(); + objSessionOption.ProxyCredential = nwCredentials; + } + WriteObject(objSessionOption); + + }//End BeginProcessing() + }//End Class +} diff --git a/src/Microsoft.WSMan.Management/PingWSMan.cs b/src/Microsoft.WSMan.Management/PingWSMan.cs new file mode 100644 index 000000000..a5fd77819 --- /dev/null +++ b/src/Microsoft.WSMan.Management/PingWSMan.cs @@ -0,0 +1,197 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +using System; +using System.IO; +using System.Reflection; +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Management.Automation; +using System.Management.Automation.Provider; +using System.Xml; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + + +namespace Microsoft.WSMan.Management +{ + + #region Test-WSMAN + + /// + /// Issues an operation against the remote machine to ensure that the wsman + /// service is running + /// + + [Cmdlet(VerbsDiagnostic.Test, "WSMan", HelpUri = "http://go.microsoft.com/fwlink/?LinkId=141464")] + public class TestWSManCommand : AuthenticatingWSManCommand, IDisposable + { + /// + /// The following is the definition of the input parameter "ComputerName". + /// Executes the management operation on the specified computer. The default is + /// the local computer. Type the fully qualified domain name, NETBIOS name or IP + /// address to indicate the remote host + /// + [Parameter(Position = 0, ValueFromPipeline = true)] + [Alias("cn")] + public String ComputerName + { + get { return computername; } + set + { + computername = value; + if ((string.IsNullOrEmpty(computername)) || (computername.Equals(".", StringComparison.CurrentCultureIgnoreCase))) + { + computername = "localhost"; + } + } + } + private String computername = null; + + /// + /// The following is the definition of the input parameter "Authentication". + /// This parameter takes a set of authentication methods the user can select + /// from. The available method are an enum called AuthenticationMechanism in the + /// System.Management.Automation.Runspaces namespace. The available options + /// should be as follows: + /// - Default : Use the default authentication (ad defined by the underlying + /// protocol) for establishing a remote connection. + /// - Negotiate + /// - Kerberos + /// - Basic: Use basic authentication for establishing a remote connection. + /// -CredSSP: Use CredSSP authentication for establishing a remote connection + /// which will enable the user to perform credential delegation. (i.e. second + /// hop) + /// + /// + /// Overriding to use a different default than the one in AuthenticatingWSManCommand base class + /// + [Parameter] + [ValidateNotNullOrEmpty] + [Alias("auth", "am")] + public override AuthenticationMechanism Authentication + { + get { return authentication; } + set + { + authentication = value; + ValidateSpecifiedAuthentication(); + } + } + private AuthenticationMechanism authentication = AuthenticationMechanism.None; + + /// + /// The following is the definition of the input parameter "Port". + /// Specifies the port to be used when connecting to the ws management service. + /// + [Parameter(ParameterSetName = "ComputerName")] + [ValidateNotNullOrEmpty] + [ValidateRange(1, Int32.MaxValue)] + public Int32 Port + { + get { return port; } + set { port = value; } + } + private Int32 port = 0; + + /// + /// The following is the definition of the input parameter "UseSSL". + /// Uses the Secure Sockets Layer (SSL) protocol to establish a connnection to + /// the remote computer. If SSL is not available on the port specified by the + /// Port parameter, the command fails. + /// + [Parameter(ParameterSetName = "ComputerName")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SSL")] + public SwitchParameter UseSSL + { + get { return usessl; } + set { usessl = value; } + } + private SwitchParameter usessl; + + /// + /// The following is the definition of the input parameter "ApplicationName". + /// ApplicationName identifies the remote endpoint. + /// + [Parameter(ParameterSetName = "ComputerName")] + [ValidateNotNullOrEmpty] + public String ApplicationName + { + get { return applicationname; } + set { applicationname = value; } + } + private String applicationname = null; + + + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + + WSManHelper helper = new WSManHelper(this); + IWSManEx wsmanObject = (IWSManEx)new WSManClass(); + string connectionStr = String.Empty; + connectionStr = helper.CreateConnectionString(null, port, computername, applicationname); + IWSManSession m_SessionObj = null; + try + { + m_SessionObj = helper.CreateSessionObject(wsmanObject, Authentication, null, Credential, connectionStr, CertificateThumbprint, usessl.IsPresent); + m_SessionObj.Timeout = 1000; //1 sec. we are putting this low so that Test-WSMan can return promptly if the server goes unresponsive. + XmlDocument xmldoc = new XmlDocument(); + xmldoc.LoadXml(m_SessionObj.Identify(0)); + WriteObject(xmldoc.DocumentElement); + } + catch(Exception) + { + try + { + if (!String.IsNullOrEmpty(m_SessionObj.Error)) + { + XmlDocument ErrorDoc = new XmlDocument(); + ErrorDoc.LoadXml(m_SessionObj.Error); + InvalidOperationException ex = new InvalidOperationException(ErrorDoc.OuterXml); + ErrorRecord er = new ErrorRecord(ex, "WsManError", ErrorCategory.InvalidOperation, computername); + this.WriteError(er); + } + } + catch(Exception) + {} + } + finally + { + if (m_SessionObj != null) + Dispose(m_SessionObj); + } + }//End BeginProcessing() + + #region IDisposable Members + + /// + /// public dispose method + /// + public + void + Dispose() + { + //CleanUp(); + GC.SuppressFinalize(this); + } + /// + /// public dispose method + /// + public + void + Dispose(IWSManSession sessionObject) + { + sessionObject = null; + this.Dispose(); + } + + #endregion IDisposable Members + + }//End Class + #endregion +} diff --git a/src/Microsoft.WSMan.Management/Set-QuickConfig.cs b/src/Microsoft.WSMan.Management/Set-QuickConfig.cs new file mode 100644 index 000000000..cd7613636 --- /dev/null +++ b/src/Microsoft.WSMan.Management/Set-QuickConfig.cs @@ -0,0 +1,293 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +using System; +using System.IO; +using System.Reflection; +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Management.Automation; +using System.Management.Automation.Provider; +using System.Xml; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +#if CORECLR +using System.Xml.XPath; +#endif + + +namespace Microsoft.WSMan.Management +{ + #region Set-WsManQuickConfig + + // + + /// + /// Performs configuration actions to enable the local machine for remote + /// management. Steps include: + /// 1. Check if WinRM service is running. If not start the WinRM service + /// 2. Set the WinRM service type to auto start + /// 3. Create a listener to accept request on any IP address. By default + /// transport is http + /// 4. Enable firewall exception for WS-Management traffic + /// + [Cmdlet(VerbsCommon.Set, "WSManQuickConfig", HelpUri = "http://go.microsoft.com/fwlink/?LinkID=141463")] + public class SetWSManQuickConfigCommand : PSCmdlet, IDisposable + { + /// + /// The following is the definition of the input parameter "UseSSL". + /// Indicates a https listener to be created. If this switch is not specified + /// then by default a http listener will be created + /// + [Parameter] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SSL")] + public SwitchParameter UseSSL + { + get { return usessl; } + set { usessl = value; } + } + private SwitchParameter usessl; + + //helper variable + private WSManHelper helper; + + /// + /// Property that sets force parameter. This will allow + /// configuring WinRM without prompting the user. + /// + [Parameter()] + public SwitchParameter Force + { + get { return force; } + set { force = value; } + } + private bool force = false; + + /// + /// Property that will allow configuring WinRM with Public profile exception enabled. + /// + [Parameter()] + public SwitchParameter SkipNetworkProfileCheck + { + get { return skipNetworkProfileCheck; } + set { skipNetworkProfileCheck = value; } + } + private bool skipNetworkProfileCheck = false; + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + //If not running elevated, then throw an "elevation required" error message. + WSManHelper.ThrowIfNotAdministrator(); + helper = new WSManHelper(this); + String query = helper.GetResourceMsgFromResourcetext("QuickConfigContinueQuery"); + String caption = helper.GetResourceMsgFromResourcetext("QuickConfigContinueCaption"); + if (!force && !ShouldContinue(query, caption)) + { + return; + } + QuickConfigRemoting(true); + QuickConfigRemoting(false); + }//End BeginProcessing() + + + + #region private + + + private void QuickConfigRemoting(bool serviceonly) + { + IWSManSession m_SessionObj = null; + try + { + string transport; + IWSManEx wsmanObject = (IWSManEx)new WSManClass(); + m_SessionObj = (IWSManSession)wsmanObject.CreateSession(null, 0, null); + string xpathEnabled = string.Empty; + string xpathText = string.Empty; + string xpathUpdate = string.Empty; + string analysisInputXml = string.Empty; + string action = string.Empty; + string xpathStatus = string.Empty; + string xpathResult = string.Empty; + + + if (!usessl) + { + transport = "http"; + } + else + { + transport = "https"; + } + + if (serviceonly) + { + analysisInputXml = @""; + action = "AnalyzeService"; + } + else + { + string openAllProfiles = skipNetworkProfileCheck ? "" : String.Empty; + analysisInputXml = @"" + transport + "" + openAllProfiles + ""; + action = "Analyze"; + } + + + string analysisOutputXml = m_SessionObj.Invoke(action, "winrm/config/service", analysisInputXml, 0); + XmlDocument resultopxml = new XmlDocument(); + resultopxml.LoadXml(analysisOutputXml); + + if (serviceonly) + { + xpathEnabled = "/cfg:AnalyzeService_OUTPUT/cfg:RemotingEnabled"; + xpathText = "/cfg:AnalyzeService_OUTPUT/cfg:Results"; + xpathUpdate = "/cfg:AnalyzeService_OUTPUT/cfg:EnableService_INPUT"; + } + else + { + xpathEnabled = "/cfg:Analyze_OUTPUT/cfg:RemotingEnabled"; + xpathText = "/cfg:Analyze_OUTPUT/cfg:Results"; + xpathUpdate = "/cfg:Analyze_OUTPUT/cfg:EnableRemoting_INPUT"; + } + + + + XmlNamespaceManager nsmgr = new XmlNamespaceManager(resultopxml.NameTable); + nsmgr.AddNamespace("cfg", "http://schemas.microsoft.com/wbem/wsman/1/config/service"); + string enabled = resultopxml.SelectSingleNode(xpathEnabled, nsmgr).InnerText; + XmlNode sourceAttribute = resultopxml.SelectSingleNode(xpathEnabled, nsmgr).Attributes.GetNamedItem("Source"); + string source = null; + if (sourceAttribute != null) + { + source = sourceAttribute.Value; + } + string rxml = ""; + if (enabled.Equals("true")) + { + string Err_Msg = ""; + if (serviceonly) + { + Err_Msg = WSManResourceLoader.GetResourceString("L_QuickConfigNoServiceChangesNeeded_Message"); + } + else + { + Err_Msg = WSManResourceLoader.GetResourceString("L_QuickConfigNoChangesNeeded_Message"); + } + // ArgumentException e = new ArgumentException(Err_Msg); + // ErrorRecord er = new ErrorRecord(e, "InvalidOperation", ErrorCategory.InvalidOperation, null); + // WriteError(er); + WriteObject(Err_Msg); + return; + } + if (!enabled.Equals("false")) + { + ArgumentException e = new ArgumentException(WSManResourceLoader.GetResourceString("L_QuickConfig_InvalidBool_0_ErrorMessage")); + ErrorRecord er = new ErrorRecord(e, "InvalidOperation", ErrorCategory.InvalidOperation, null); + WriteError(er); + return; + } + + string resultAction = resultopxml.SelectSingleNode(xpathText, nsmgr).InnerText; + if ( source != null && source.Equals("GPO")) + { + String Info_Msg = WSManResourceLoader.GetResourceString("L_QuickConfig_RemotingDisabledbyGP_00_ErrorMessage"); + Info_Msg += " " + resultAction; + ArgumentException e = new ArgumentException(Info_Msg); + WriteError(new ErrorRecord(e, "NotSpecified", ErrorCategory.NotSpecified, null)); + return; + } + + string inputXml = resultopxml.SelectSingleNode(xpathUpdate, nsmgr).OuterXml; + if (resultAction.Equals("") || inputXml.Equals("")) + { + ArgumentException e = new ArgumentException(WSManResourceLoader.GetResourceString("L_ERR_Message") + WSManResourceLoader.GetResourceString("L_QuickConfig_MissingUpdateXml_0_ErrorMessage")); + ErrorRecord er = new ErrorRecord(e, "InvalidOperation", ErrorCategory.InvalidOperation, null); + WriteError(er); + return; + } + + if (serviceonly) + { + action = "EnableService"; + } + else + { + action = "EnableRemoting"; + } + rxml = m_SessionObj.Invoke(action, "winrm/config/service", inputXml, 0); + XmlDocument finalxml = new XmlDocument(); + finalxml.LoadXml(rxml); + + if (serviceonly) + { + xpathStatus = "/cfg:EnableService_OUTPUT/cfg:Status"; + xpathResult = "/cfg:EnableService_OUTPUT/cfg:Results"; + } + else + { + xpathStatus = "/cfg:EnableRemoting_OUTPUT/cfg:Status"; + xpathResult = "/cfg:EnableRemoting_OUTPUT/cfg:Results"; + } + if (finalxml.SelectSingleNode(xpathStatus, nsmgr).InnerText.ToString().Equals("succeeded")) + { + if (serviceonly) + { + WriteObject(WSManResourceLoader.GetResourceString("L_QuickConfigUpdatedService_Message")); + } + else + { + WriteObject(WSManResourceLoader.GetResourceString("L_QuickConfigUpdated_Message")); + } + WriteObject(finalxml.SelectSingleNode(xpathResult, nsmgr).InnerText); + } + else + { + helper.AssertError(WSManResourceLoader.GetResourceString("L_ERR_Message") + WSManResourceLoader.GetResourceString("L_QuickConfigUpdateFailed_ErrorMessage"), false, null); + } + } + finally + { + if (!String.IsNullOrEmpty(m_SessionObj.Error)) + { + helper.AssertError(m_SessionObj.Error, true, null); + } + if (m_SessionObj != null) + Dispose(m_SessionObj); + + } + } + #endregion private + + #region IDisposable Members + + /// + /// public dispose method + /// + public + void + Dispose() + { + //CleanUp(); + GC.SuppressFinalize(this); + } + /// + /// public dispose method + /// + public + void + Dispose(IWSManSession sessionObject) + { + sessionObject = null; + this.Dispose(); + } + + #endregion IDisposable Members + + }//End Class + #endregion Set-WsManQuickConfig +} diff --git a/src/Microsoft.WSMan.Management/WSManConnections.cs b/src/Microsoft.WSMan.Management/WSManConnections.cs new file mode 100644 index 000000000..4d657ae75 --- /dev/null +++ b/src/Microsoft.WSMan.Management/WSManConnections.cs @@ -0,0 +1,363 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +using System; +using System.IO; +using System.Reflection; +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Management.Automation; +using System.Management.Automation.Provider; +using System.Xml; +using System.Collections; +using System.Collections.Generic; +using System.Management.Automation.Runspaces; +using System.Diagnostics.CodeAnalysis; +using Dbg = System.Management.Automation; + + +namespace Microsoft.WSMan.Management +{ + #region Base class for cmdlets taking credential, authentication, certificatethumbprint + + /// + /// Common base class for all WSMan cmdlets that + /// take Authentication, CertificateThumbprint and Credential parameters + /// + public class AuthenticatingWSManCommand : PSCmdlet + { + /// + /// The following is the definition of the input parameter "Credential". + /// Specifies a user account that has permission to perform this action. The + /// default is the current user. + /// + [Parameter(ValueFromPipelineByPropertyName = true)] + [ValidateNotNullOrEmpty] + [Credential] + [Alias("cred", "c")] + public virtual PSCredential Credential + { + get { return credential; } + set + { + credential = value; + ValidateSpecifiedAuthentication(); + } + } + private PSCredential credential; + + /// + /// The following is the definition of the input parameter "Authentication". + /// This parameter takes a set of authentication methods the user can select + /// from. The available method are an enum called Authentication in the + /// System.Management.Automation.Runspaces namespace. The available options + /// should be as follows: + /// - Default : Use the default authentication (ad defined by the underlying + /// protocol) for establishing a remote connection. + /// - Negotiate + /// - Kerberos + /// - Basic: Use basic authentication for establishing a remote connection. + /// -CredSSP: Use CredSSP authentication for establishing a remote connection + /// which will enable the user to perform credential delegation. (i.e. second + /// hop) + /// + [Parameter] + [ValidateNotNullOrEmpty] + [Alias("auth", "am")] + public virtual AuthenticationMechanism Authentication + { + get { return authentication; } + set + { + authentication = value; + ValidateSpecifiedAuthentication(); + } + } + private AuthenticationMechanism authentication = AuthenticationMechanism.Default; + + /// + /// Specifies the certificate thumbprint to be used to impersonate the user on the + /// remote machine. + /// + [Parameter] + [ValidateNotNullOrEmpty] + public virtual string CertificateThumbprint + { + get { return thumbPrint; } + set + { + thumbPrint = value; + ValidateSpecifiedAuthentication(); + } + } + private string thumbPrint = null; + + internal void ValidateSpecifiedAuthentication() + { + WSManHelper.ValidateSpecifiedAuthentication( + this.Authentication, + this.Credential, + this.CertificateThumbprint); + } + } + + #endregion + + #region Connect-WsMan + /// + /// connect wsman cmdlet + /// + [Cmdlet(VerbsCommunications.Connect, "WSMan", DefaultParameterSetName = "ComputerName", HelpUri = "http://go.microsoft.com/fwlink/?LinkId=141437")] + public class ConnectWSManCommand : AuthenticatingWSManCommand + { + + #region Parameters + + /// + /// The following is the definition of the input parameter "ApplicationName". + /// ApplicationName identifies the remote endpoint. + /// + [Parameter(ParameterSetName = "ComputerName")] + [ValidateNotNullOrEmpty] + public String ApplicationName + { + get { return applicationname; } + set { applicationname = value; } + } + private String applicationname = null; + + /// + /// The following is the definition of the input parameter "ComputerName". + /// Executes the management operation on the specified computer(s). The default + /// is the local computer. Type the fully qualified domain name, NETBIOS name or + /// IP address to indicate the remote host(s) + /// + [Parameter(ParameterSetName = "ComputerName", Position = 0)] + [Alias("cn")] + public String ComputerName + { + get { return computername; } + set + { + computername = value; + if ((string.IsNullOrEmpty(computername)) || (computername.Equals(".", StringComparison.CurrentCultureIgnoreCase))) + { + computername = "localhost"; + } + } + } + private String computername = null; + + /// + /// The following is the definition of the input parameter "ConnectionURI". + /// Specifies the transport, server, port, and ApplicationName of the new + /// runspace. The format of this string is: + /// transport://server:port/ApplicationName. + /// + [Parameter(ParameterSetName = "URI")] + [ValidateNotNullOrEmpty] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")] + public Uri ConnectionURI + { + get { return connectionuri; } + set { connectionuri = value; } + } + private Uri connectionuri; + + /// + /// The following is the definition of the input parameter "OptionSet". + /// OptionSet is a hash table and is used to pass a set of switches to the + /// service to modify or refine the nature of the request. + /// + [Parameter] + [ValidateNotNullOrEmpty] + [Alias("os")] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public Hashtable OptionSet + { + get { return optionset; } + set { optionset = value; } + } + private Hashtable optionset; + + /// + /// The following is the definition of the input parameter "Port". + /// Specifies the port to be used when connecting to the ws management service. + /// + [Parameter] + [ValidateNotNullOrEmpty] + [Parameter(ParameterSetName = "ComputerName")] + [ValidateRange(1, Int32.MaxValue)] + public Int32 Port + { + get { return port; } + set { port = value; } + } + private Int32 port = 0; + + /// + /// The following is the definition of the input parameter "SessionOption". + /// Defines a set of extended options for the WSMan session. This hashtable can + /// be created using New-WSManSessionOption + /// + [Parameter] + [ValidateNotNullOrEmpty] + [Alias("so")] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public SessionOption SessionOption + { + get { return sessionoption; } + set { sessionoption = value; } + } + private SessionOption sessionoption; + + /// + /// The following is the definition of the input parameter "UseSSL". + /// Uses the Secure Sockets Layer (SSL) protocol to establish a connnection to + /// the remote computer. If SSL is not available on the port specified by the + /// Port parameter, the command fails. + /// + [Parameter(ParameterSetName = "ComputerName")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SSL")] + public SwitchParameter UseSSL + { + get { return usessl; } + set { usessl = value; } + } + private SwitchParameter usessl; + + + + #endregion + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + + WSManHelper helper = new WSManHelper(this); + if (connectionuri != null) + { + try + { + //always in the format http://server:port/applicationname + string[] constrsplit = connectionuri.OriginalString.Split(new string[] { ":" + port + "/" + applicationname }, StringSplitOptions.None); + string[] constrsplit1 = constrsplit[0].Split(new string[] { "//" }, StringSplitOptions.None); + computername = constrsplit1[1].Trim(); + } + catch (IndexOutOfRangeException) + { + helper.AssertError(helper.GetResourceMsgFromResourcetext("NotProperURI"), false, connectionuri); + } + } + string crtComputerName = computername; + if (crtComputerName == null) + { + crtComputerName = "localhost"; + } + if (this.SessionState.Path.CurrentProviderLocation(WSManStringLiterals.rootpath).Path.StartsWith(this.SessionState.Drive.Current.Name + ":" + WSManStringLiterals.DefaultPathSeparator + crtComputerName, StringComparison.CurrentCultureIgnoreCase)) + { + helper.AssertError(helper.GetResourceMsgFromResourcetext("ConnectFailure"), false, computername); + } + helper.CreateWsManConnection(ParameterSetName, connectionuri, port, computername, applicationname, usessl.IsPresent, Authentication, sessionoption, Credential, CertificateThumbprint); + }//End BeginProcessing() + + }//end class + #endregion + + # region Disconnect-WSMAN + /// + /// The following is the definition of the input parameter "ComputerName". + /// Executes the management operation on the specified computer(s). The default + /// is the local computer. Type the fully qualified domain name, NETBIOS name or + /// IP address to indicate the remote host(s) + /// + + [Cmdlet(VerbsCommunications.Disconnect, "WSMan", HelpUri = "http://go.microsoft.com/fwlink/?LinkId=141439")] + public class DisconnectWSManCommand : PSCmdlet, IDisposable + { + /// + /// The following is the definition of the input parameter "ComputerName". + /// Executes the management operation on the specified computer(s). The default + /// is the local computer. Type the fully qualified domain name, NETBIOS name or + /// IP address to indicate the remote host(s) + /// + [Parameter(Position = 0)] + public String ComputerName + { + get { return computername; } + set + { + + computername = value; + if ((string.IsNullOrEmpty(computername)) || (computername.Equals(".", StringComparison.CurrentCultureIgnoreCase))) + { + computername = "localhost"; + } + } + } + private String computername = null; + + #region IDisposable Members + + /// + /// public dispose method + /// + public + void + Dispose() + { + //CleanUp(); + GC.SuppressFinalize(this); + } + /// + /// public dispose method + /// + public + void + Dispose(object session) + { + session = null; + this.Dispose(); + + } + + #endregion IDisposable Members + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + WSManHelper helper = new WSManHelper(this); + if (computername == null) + { + computername = "localhost"; + } + if (this.SessionState.Path.CurrentProviderLocation(WSManStringLiterals.rootpath).Path.StartsWith(WSManStringLiterals.rootpath + ":" + WSManStringLiterals.DefaultPathSeparator + computername, StringComparison.CurrentCultureIgnoreCase)) + { + helper.AssertError(helper.GetResourceMsgFromResourcetext("DisconnectFailure"), false, computername); + } + if (computername.Equals("localhost", StringComparison.CurrentCultureIgnoreCase)) + { + helper.AssertError(helper.GetResourceMsgFromResourcetext("LocalHost"), false, computername); + } + + object _ws = helper.RemoveFromDictionary(computername); + if (_ws != null) + { + Dispose(_ws); + } + else + { + helper.AssertError(helper.GetResourceMsgFromResourcetext("InvalidComputerName"), false, computername); + } + }//End BeginProcessing() + + + + }//End Class + #endregion Disconnect-WSMAN +} diff --git a/src/Microsoft.WSMan.Management/WSManInstance.cs b/src/Microsoft.WSMan.Management/WSManInstance.cs new file mode 100644 index 000000000..5d89af9fd --- /dev/null +++ b/src/Microsoft.WSMan.Management/WSManInstance.cs @@ -0,0 +1,1501 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +using System; +using System.IO; +using System.Reflection; +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Management.Automation; +using System.Management.Automation.Provider; +using System.Xml; +using System.Collections; +using System.Collections.Generic; +using System.Management.Automation.Runspaces; +using System.Diagnostics.CodeAnalysis; +using Dbg = System.Management.Automation; +using System.Globalization; + + +namespace Microsoft.WSMan.Management +{ + #region Get-WSManInstance + /// + /// Executes action on a target object specified by RESOURCE_URI, where + /// parameters are specified by key value pairs. + /// eg., Call StartService method on the spooler service + /// Invoke-WSManAction -Action StartService -ResourceURI wmicimv2/Win32_Service + /// -SelectorSet {Name=Spooler} + /// + + [Cmdlet(VerbsCommon.Get, "WSManInstance", DefaultParameterSetName = "GetInstance", HelpUri = "http://go.microsoft.com/fwlink/?LinkId=141444")] + public class GetWSManInstanceCommand : AuthenticatingWSManCommand, IDisposable + { + #region parameter + /// + /// The following is the definition of the input parameter "ApplicationName". + /// ApplicationName identifies the remote endpoint. + /// + [Parameter(ParameterSetName = "GetInstance")] + [Parameter(ParameterSetName = "Enumerate")] + public String ApplicationName + { + get { return applicationname; } + set + { + { applicationname = value; } + } + } + private String applicationname = null; + + /// + /// The following is the definition of the input parameter "BasePropertiesOnly". + /// Enumerate only those properties that are part of the base class + /// specification in the Resource URI. When + /// Shallow is specified then this flag has no effect + /// + [Parameter(ParameterSetName = "Enumerate")] + [Alias("UBPO", "Base")] + public SwitchParameter BasePropertiesOnly + { + get { return basepropertiesonly; } + set + { + { basepropertiesonly = value; } + } + } + private SwitchParameter basepropertiesonly; + + /// + /// The following is the definition of the input parameter "ComputerName". + /// Executes the management operation on the specified computer(s). The default + /// is the local computer. Type the fully qualified domain name, NETBIOS name or + /// IP address to indicate the remote host(s) + /// + [Parameter(ParameterSetName = "GetInstance")] + [Parameter(ParameterSetName = "Enumerate")] + [Alias("CN")] + public String ComputerName + { + get { return computername; } + set + { + computername = value; + if ((string.IsNullOrEmpty(computername)) || (computername.Equals(".", StringComparison.CurrentCultureIgnoreCase))) + { + computername = "localhost"; + } + } + } + private String computername = null; + + /// + /// The following is the definition of the input parameter "ConnectionURI". + /// Specifies the transport, server, port, and Prefix, needed to connect to the + /// remote machine. The format of this string is: + /// transport://server:port/Prefix. + /// + + [Parameter( + ParameterSetName = "GetInstance")] + [Parameter( + ParameterSetName = "Enumerate")] + [Alias("CURI", "CU")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")] + public Uri ConnectionURI + { + get { return connectionuri; } + set + { + { connectionuri = value; } + } + } + private Uri connectionuri; + + /// + /// The following is the definition of the input parameter "Dialect". + /// Defines the dialect for the filter predicate + /// + [Parameter] + public Uri Dialect + { + get { return dialect; } + set + { + { dialect = value; } + } + } + private Uri dialect; + + /// + /// The following is the definition of the input parameter "Enumerate". + /// Switch indicates list all instances of a management resource. Equivalent to + /// WSManagement Enumerate + /// + + [Parameter(Mandatory = true, + ParameterSetName = "Enumerate")] + public SwitchParameter Enumerate + { + get { return enumerate; } + set + { + { enumerate = value; } + } + } + private SwitchParameter enumerate; + + /// + /// The following is the definition of the input parameter "Filter". + /// Indicates the filter expression for the enumeration + /// + [Parameter(ParameterSetName = "Enumerate")] + [ValidateNotNullOrEmpty] + public String Filter + { + get { return filter; } + set + { + { filter = value; } + } + } + private String filter; + + /// + /// The following is the definition of the input parameter "Fragment". + /// Specifies a section inside the instance that is to be updated or retrieved + /// for the given operation + /// + + [Parameter(ParameterSetName = "GetInstance")] + [ValidateNotNullOrEmpty] + public String Fragment + { + get { return fragment; } + set + { + { fragment = value; } + } + } + private String fragment; + + /// + /// The following is the definition of the input parameter "OptionSet". + /// OptionSet is a hashtable and is used to pass a set of switches to the + /// service to modify or refine the nature of the request. + /// + [Parameter(ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true)] + [ValidateNotNullOrEmpty] + [Alias("OS")] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public Hashtable OptionSet + { + get { return optionset; } + set + { + { optionset = value; } + } + } + private Hashtable optionset; + + /// + /// The following is the definition of the input parameter "Port". + /// Specifies the port to be used when connecting to the ws management service. + /// + [Parameter(ParameterSetName = "Enumerate")] + [Parameter(ParameterSetName = "GetInstance")] + public Int32 Port + { + get { return port; } + set + { + { port = value; } + } + } + private Int32 port = 0; + + /// + /// The following is the definition of the input parameter "Associations". + /// Associations indicates retrieval of association instances as opposed to + /// associated instances. This can only be used when specifying the Dialect as + /// Association + /// + + [Parameter(ParameterSetName = "Enumerate")] + public SwitchParameter Associations + { + get { return associations; } + set + { + { associations = value; } + } + } + private SwitchParameter associations; + + /// + /// The following is the definition of the input parameter "ResourceURI". + /// URI of the resource class/instance representation + /// + [Parameter(Mandatory = true, + Position = 0, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true)] + + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")] + [Alias("RURI")] + public Uri ResourceURI + { + get { return resourceuri; } + set + { + { resourceuri = value; } + } + } + private Uri resourceuri; + + /// + /// The following is the definition of the input parameter "ReturnType". + /// Indicates the type of data returned. Possible options are 'Object', 'EPR', + /// and 'ObjectAndEPR'. Default is Object. + /// If Object is specified or if this parameter is absent then only the objects + /// are returned + /// If EPR is specified then only the EPRs of the objects + /// are returned. EPRs contain information about the Resource URI and selectors + /// for the instance + /// If ObjectAndEPR is specified, then both the object and the associated EPRs + /// are returned + /// + [Parameter(ParameterSetName = "Enumerate")] + + [ValidateNotNullOrEmpty] + [ValidateSetAttribute(new string[] { "object", "epr", "objectandepr" })] + [Alias("RT")] + public String ReturnType + { + get { return returntype; } + set + { + { returntype = value; } + } + } + private String returntype="object"; + + /// + /// The following is the definition of the input parameter "SelectorSet". + /// SelectorSet is a hash table which helps in identify an instance of the + /// management resource if there are are more than 1 instance of the resource + /// class + /// + [Parameter( + ParameterSetName = "GetInstance")] + + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public Hashtable SelectorSet + { + get { return selectorset; } + set + { + { selectorset = value; } + } + } + private Hashtable selectorset; + + /// + /// The following is the definition of the input parameter "SessionOption". + /// Defines a set of extended options for the WSMan session. This can be + /// created by using the cmdlet New-WSManSessionOption + /// + [Parameter] + [ValidateNotNullOrEmpty] + [Alias("SO")] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public SessionOption SessionOption + { + get { return sessionoption; } + set + { + { sessionoption = value; } + } + } + private SessionOption sessionoption; + + /// + /// The following is the definition of the input parameter "Shallow". + /// Enumerate only instances of the base class specified in the resource URI. If + /// this flag is not specified, instances of the base class specified in the URI + /// and all its derived classes are returned + /// + [Parameter(ParameterSetName = "Enumerate")] + + public SwitchParameter Shallow + { + get { return shallow; } + set + { + { shallow = value; } + } + } + private SwitchParameter shallow; + + /// + /// The following is the definition of the input parameter "UseSSL". + /// Uses the Secure Sockets Layer (SSL) protocol to establish a connnection to + /// the remote computer. If SSL is not available on the port specified by the + /// Port parameter, the command fails. + /// + [Parameter(ParameterSetName = "GetInstance")] + [Parameter(ParameterSetName = "Enumerate")] + + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SSL")] + [Alias("SSL")] + public SwitchParameter UseSSL + { + get { return usessl; } + set + { + { usessl = value; } + } + } + private SwitchParameter usessl; + + #endregion parameter + + # region private + WSManHelper helper; + private string GetFilter() + { + string name; + string value; + string[] Split = filter.Trim().Split(new Char[] { '=', ';' }); + if ((Split.Length)%2 != 0) + { + //missmatched property name/value pair + return null; + } + filter = ""; + for (int i = 0; i" + value + ""; + } + filter = filter + ""; + return (filter.ToString()); + } + + private void ReturnEnumeration(IWSManEx wsmanObject, IWSManResourceLocator wsmanResourceLocator, IWSManSession wsmanSession) + { + string fragment; + try + { + int flags = 0; + IWSManEnumerator obj; + if (returntype != null) + { + if (returntype.Equals("object", StringComparison.CurrentCultureIgnoreCase)) + { + flags = wsmanObject.EnumerationFlagReturnObject(); + } + else if (returntype.Equals("epr", StringComparison.CurrentCultureIgnoreCase)) + { + flags = wsmanObject.EnumerationFlagReturnEPR(); + } + else + { + flags = wsmanObject.EnumerationFlagReturnObjectAndEPR(); + } + } + + if (shallow) + { + flags |= wsmanObject.EnumerationFlagHierarchyShallow(); + } + else if (basepropertiesonly) + { + flags |= wsmanObject.EnumerationFlagHierarchyDeepBasePropsOnly(); + } + else + { + flags |= wsmanObject.EnumerationFlagHierarchyDeep(); + } + if (dialect != null && filter != null) + { + + if (dialect.ToString().Equals(helper.ALIAS_WQL, StringComparison.CurrentCultureIgnoreCase) || dialect.ToString().Equals(helper.URI_WQL_DIALECT, StringComparison.CurrentCultureIgnoreCase)) + { + fragment = helper.URI_WQL_DIALECT; + dialect = new Uri(fragment); + } + else if (dialect.ToString().Equals(helper.ALIAS_ASSOCIATION, StringComparison.CurrentCultureIgnoreCase) || dialect.ToString().Equals(helper.URI_ASSOCIATION_DIALECT, StringComparison.CurrentCultureIgnoreCase)) + { + if (associations) + { + flags |= wsmanObject.EnumerationFlagAssociationInstance(); + } + else + { + flags |= wsmanObject.EnumerationFlagAssociatedInstance(); + } + fragment = helper.URI_ASSOCIATION_DIALECT; + dialect = new Uri(fragment); + } + else if (dialect.ToString().Equals(helper.ALIAS_SELECTOR, StringComparison.CurrentCultureIgnoreCase) || dialect.ToString().Equals(helper.URI_SELECTOR_DIALECT, StringComparison.CurrentCultureIgnoreCase)) + { + filter = GetFilter(); + fragment = helper.URI_SELECTOR_DIALECT; + dialect = new Uri(fragment); + } + obj = (IWSManEnumerator)wsmanSession.Enumerate(wsmanResourceLocator, filter, dialect.ToString(), flags); + } + else if (filter != null) + { + fragment = helper.URI_WQL_DIALECT; + dialect = new Uri(fragment); + obj = (IWSManEnumerator)wsmanSession.Enumerate(wsmanResourceLocator, filter, dialect.ToString(), flags); + } + else + { + obj = (IWSManEnumerator)wsmanSession.Enumerate(wsmanResourceLocator, filter, null, flags); + } + while (!obj.AtEndOfStream) + { + XmlDocument xmldoc = new XmlDocument(); + xmldoc.LoadXml(obj.ReadItem()); + WriteObject(xmldoc.FirstChild); + } + } + catch (Exception ex) + { + ErrorRecord er = new ErrorRecord(ex, "Exception", ErrorCategory.InvalidOperation, null); + WriteError(er); + } + } + # endregion private + # region override + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + IWSManSession m_session = null; + IWSManEx m_wsmanObject = (IWSManEx)new WSManClass(); + helper = new WSManHelper(this); + helper.WSManOp = "Get"; + string connectionStr = null; + connectionStr = helper.CreateConnectionString(connectionuri, port, computername, applicationname); + if (connectionuri != null) + { + try + { + //in the format http(s)://server[:port/applicationname] + string[] constrsplit = connectionuri.OriginalString.Split(new string[] { ":" + port + "/" + applicationname }, StringSplitOptions.None); + string[] constrsplit1 = constrsplit[0].Split(new string[] { "//" }, StringSplitOptions.None); + computername = constrsplit1[1].Trim(); + } + catch (IndexOutOfRangeException) + { + helper.AssertError(helper.GetResourceMsgFromResourcetext("NotProperURI"), false, connectionuri); + } + + } + try + { + IWSManResourceLocator m_resource = helper.InitializeResourceLocator(optionset, selectorset, fragment, dialect, m_wsmanObject, resourceuri); + m_session = helper.CreateSessionObject(m_wsmanObject, Authentication, sessionoption, Credential, connectionStr, CertificateThumbprint, usessl.IsPresent); + + if (!enumerate) + { + XmlDocument xmldoc = new XmlDocument(); + try + { + xmldoc.LoadXml(m_session.Get(m_resource, 0)); + } + catch(XmlException ex) + { + helper.AssertError(ex.Message, false, computername); + } + + if (!string.IsNullOrEmpty(fragment)) + { + WriteObject(xmldoc.FirstChild.LocalName + "=" + xmldoc.FirstChild.InnerText); + } + else + { + WriteObject(xmldoc.FirstChild); + } + } + else + { + try + { + ReturnEnumeration(m_wsmanObject, m_resource, m_session); + } + catch (Exception ex) + { + helper.AssertError(ex.Message, false, computername); + } + } + + } + finally + { + if (!String.IsNullOrEmpty(m_wsmanObject.Error)) + { + helper.AssertError(m_wsmanObject.Error, true, resourceuri); + } + if (!String.IsNullOrEmpty(m_session.Error)) + { + helper.AssertError(m_session.Error, true, resourceuri); + } + if (m_session != null) + Dispose(m_session); + } + } + #endregion override + #region IDisposable Members + + /// + /// public dispose method + /// + public + void + Dispose() + { + //CleanUp(); + GC.SuppressFinalize(this); + } + /// + /// public dispose method + /// + public + void + Dispose(IWSManSession sessionObject) + { + sessionObject = null; + this.Dispose(); + } + + #endregion IDisposable Members + + + /// + /// BeginProcessing method. + /// + protected override void EndProcessing() + { + + helper.CleanUp(); + } + + + } + #endregion + + #region Set-WsManInstance + + /// + /// Executes action on a target object specified by RESOURCE_URI, where + /// parameters are specified by key value pairs. + /// eg., Call StartService method on the spooler service + /// Set-WSManInstance -Action StartService -ResourceURI wmicimv2/Win32_Service + /// -SelectorSet {Name=Spooler} + /// + [Cmdlet(VerbsCommon.Set, "WSManInstance", DefaultParameterSetName = "ComputerName", HelpUri = "http://go.microsoft.com/fwlink/?LinkId=141458")] + public class SetWSManInstanceCommand : AuthenticatingWSManCommand, IDisposable + { + + #region Parameters + /// + /// The following is the definition of the input parameter "ApplicationName". + /// ApplicationName identifies the remote endpoint. + /// + [Parameter(ParameterSetName = "ComputerName")] + [ValidateNotNullOrEmpty] + public String ApplicationName + { + get { return applicationname; } + set { applicationname = value; } + } + private String applicationname = null; + + /// + /// The following is the definition of the input parameter "ComputerName". + /// Executes the management operation on the specified computer(s). The default + /// is the local computer. Type the fully qualified domain name, NETBIOS name or + /// IP address to indicate the remote host(s) + /// + [Parameter(ParameterSetName = "ComputerName")] + [Alias("cn")] + public String ComputerName + { + get { return computername; } + set + { + computername = value; + if ((string.IsNullOrEmpty(computername)) || (computername.Equals(".", StringComparison.CurrentCultureIgnoreCase))) + { + computername = "localhost"; + } + } + } + private String computername = null; + + /// + /// The following is the definition of the input parameter "ConnectionURI". + /// Specifies the transport, server, port, and ApplicationName of the new + /// runspace. The format of this string is: + /// transport://server:port/ApplicationName. + /// + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")] + [Parameter(ParameterSetName = "URI")] + [ValidateNotNullOrEmpty] + public Uri ConnectionURI + { + get { return connectionuri; } + set { connectionuri = value; } + } + private Uri connectionuri; + + /// + /// The following is the definition of the input parameter "Dialect". + /// Defines the dialect for the filter predicate + /// + [Parameter] + [ValidateNotNullOrEmpty] + public Uri Dialect + { + get { return dialect; } + set { dialect = value; } + } + private Uri dialect; + + /// + /// The following is the definition of the input parameter "FilePath". + /// Updates the management resource specified by the ResourceURI and SelectorSet + /// via this input file + /// + [Parameter(ValueFromPipelineByPropertyName = true)] + [ValidateNotNullOrEmpty] + public string FilePath + { + get { return filepath; } + set { filepath = value; } + } + private string filepath; + + + /// + /// The following is the definition of the input parameter "Fragment". + /// Specifies a section inside the instance that is to be updated or retrieved + /// for the given operation + /// + [Parameter(ParameterSetName = "ComputerName")] + [Parameter(ParameterSetName = "URI")] + [ValidateNotNullOrEmpty] + public String Fragment + { + get { return fragment; } + set { fragment = value; } + } + private String fragment; + + /// + /// The following is the definition of the input parameter "OptionSet". + /// OptionSet is a hahs table which help modify or refine the nature of the + /// request. These are similar to switches used in command line shells in that + /// they are service-specific + /// + + [Parameter] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + [Alias("os")] + [ValidateNotNullOrEmpty] + public Hashtable OptionSet + { + get { return optionset; } + set { optionset = value; } + } + private Hashtable optionset; + + /// + /// The following is the definition of the input parameter "Port". + /// Specifies the port to be used when connecting to the ws management service. + /// + [Parameter(ParameterSetName = "ComputerName")] + [ValidateNotNullOrEmpty] + [ValidateRange(1, Int32.MaxValue)] + public Int32 Port + { + get { return port; } + set { port = value; } + } + private Int32 port = 0; + + /// + /// The following is the definition of the input parameter "ResourceURI". + /// URI of the resource class/instance representation + /// + + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")] + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Resourceuri")] + + [Parameter(Mandatory = true, Position = 0)] + [Alias("ruri")] + [ValidateNotNullOrEmpty] + public Uri ResourceURI + { + get { return resourceuri; } + set { resourceuri = value; } + } + private Uri resourceuri; + + /// + /// The following is the definition of the input parameter "SelectorSet". + /// SelectorSet is a hash table which helps in identify an instance of the + /// management resource if there are are more than 1 instance of the resource + /// class + /// + [Parameter(Position = 1, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true)] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + [ValidateNotNullOrEmpty] + public Hashtable SelectorSet + { + get { return selectorset; } + set { selectorset = value; } + } + private Hashtable selectorset; + + /// + /// The following is the definition of the input parameter "SessionOption". + /// Defines a set of extended options for the WSMan session. This can be created + /// by using the cmdlet New-WSManSessionOption + /// + [Parameter] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + [Alias("so")] + [ValidateNotNullOrEmpty] + public SessionOption SessionOption + { + get { return sessionoption; } + set { sessionoption = value; } + } + private SessionOption sessionoption; + + /// + /// The following is the definition of the input parameter "UseSSL". + /// Uses the Secure Sockets Layer (SSL) protocol to establish a connnection to + /// the remote computer. If SSL is not available on the port specified by the + /// Port parameter, the command fails. + /// + [Parameter(ParameterSetName = "ComputerName")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SSL")] + [Alias("ssl")] + public SwitchParameter UseSSL + { + get { return usessl; } + set { usessl = value; } + } + private SwitchParameter usessl; + + /// + /// The following is the definition of the input parameter "ValueSet". + /// ValueSet is a hash table which helps to modify resource represented by the + /// ResourceURI and SelectorSet. + /// + [Parameter(ValueFromPipelineByPropertyName = true)] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + [ValidateNotNullOrEmpty] + public Hashtable ValueSet + { + get { return valueset; } + set { valueset = value; } + } + private Hashtable valueset; + + + + #endregion + + private WSManHelper helper ; + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + IWSManEx m_wsmanObject = (IWSManEx)new WSManClass(); + helper = new WSManHelper(this); + helper.WSManOp = "set"; + IWSManSession m_session = null; + + + if (dialect != null) + { + if (dialect.ToString().Equals(helper.ALIAS_WQL, StringComparison.CurrentCultureIgnoreCase)) + dialect = new Uri(helper.URI_WQL_DIALECT); + if (dialect.ToString().Equals(helper.ALIAS_SELECTOR, StringComparison.CurrentCultureIgnoreCase)) + dialect = new Uri(helper.URI_SELECTOR_DIALECT); + if (dialect.ToString().Equals(helper.ALIAS_ASSOCIATION, StringComparison.CurrentCultureIgnoreCase)) + dialect = new Uri(helper.URI_ASSOCIATION_DIALECT); + } + + try + { + string connectionStr = String.Empty; + connectionStr = helper.CreateConnectionString(connectionuri, port, computername, applicationname); + if (connectionuri != null) + { + try + { + //in the format http(s)://server[:port/applicationname] + string[] constrsplit = connectionuri.OriginalString.Split(new string[] { ":" + port + "/" + applicationname }, StringSplitOptions.None); + string[] constrsplit1 = constrsplit[0].Split(new string[] { "//" }, StringSplitOptions.None); + computername = constrsplit1[1].Trim(); + } + catch (IndexOutOfRangeException) + { + helper.AssertError(helper.GetResourceMsgFromResourcetext("NotProperURI"), false, connectionuri); + } + + } + IWSManResourceLocator m_resource = helper.InitializeResourceLocator(optionset, selectorset, fragment, dialect, m_wsmanObject, resourceuri); + m_session = helper.CreateSessionObject(m_wsmanObject, Authentication, sessionoption, Credential, connectionStr, CertificateThumbprint, usessl.IsPresent); + string rootNode = helper.GetRootNodeName(helper.WSManOp, m_resource.ResourceUri, null); + string input = helper.ProcessInput(m_wsmanObject, filepath, helper.WSManOp, rootNode, valueset, m_resource, m_session); + + XmlDocument xmldoc = new XmlDocument(); + try + { + xmldoc.LoadXml(m_session.Put(m_resource, input, 0)); + } + catch(XmlException ex) + { + helper.AssertError(ex.Message, false, computername); + } + + if (!string.IsNullOrEmpty(fragment)) + { + if (xmldoc.DocumentElement.ChildNodes.Count > 0) + { + foreach (XmlNode node in xmldoc.DocumentElement.ChildNodes) + { + if (node.Name.Equals(fragment, StringComparison.CurrentCultureIgnoreCase)) + WriteObject(node.Name + " = " + node.InnerText); + } + } + } + else + WriteObject(xmldoc.DocumentElement); + + } + finally + { + if (!String.IsNullOrEmpty(m_wsmanObject.Error)) + { + helper.AssertError(m_wsmanObject.Error, true, resourceuri); + } + if (!String.IsNullOrEmpty(m_session.Error)) + { + helper.AssertError(m_session.Error, true, resourceuri); + } + if (m_session != null) + Dispose(m_session); + } + }//End ProcessRecord() + + #region IDisposable Members + + /// + /// public dispose method + /// + public + void + Dispose() + { + //CleanUp(); + GC.SuppressFinalize(this); + } + /// + /// public dispose method + /// + public + void + Dispose(IWSManSession sessionObject) + { + sessionObject = null; + this.Dispose(); + } + + #endregion IDisposable Members + + /// + /// BeginProcessing method. + /// + protected override void EndProcessing() + { + helper.CleanUp(); + } + + } + + + + #endregion + + + #region Remove-WsManInstance + + /// + /// Executes action on a target object specified by RESOURCE_URI, where + /// parameters are specified by key value pairs. + /// eg., Call StartService method on the spooler service + /// Set-WSManInstance -Action StartService -ResourceURI wmicimv2/Win32_Service + /// -SelectorSet {Name=Spooler} + /// + [Cmdlet(VerbsCommon.Remove, "WSManInstance", DefaultParameterSetName = "ComputerName", HelpUri = "http://go.microsoft.com/fwlink/?LinkId=141453")] + public class RemoveWSManInstanceCommand : AuthenticatingWSManCommand, IDisposable + { + + #region Parameters + /// + /// The following is the definition of the input parameter "ApplicationName". + /// ApplicationName identifies the remote endpoint. + /// + [Parameter(ParameterSetName = "ComputerName")] + [ValidateNotNullOrEmpty] + public String ApplicationName + { + get { return applicationname; } + set { applicationname = value; } + } + private String applicationname = null; + + /// + /// The following is the definition of the input parameter "ComputerName". + /// Executes the management operation on the specified computer(s). The default + /// is the local computer. Type the fully qualified domain name, NETBIOS name or + /// IP address to indicate the remote host(s) + /// + [Parameter(ParameterSetName = "ComputerName")] + [Alias("cn")] + public String ComputerName + { + get { return computername; } + set + { + computername = value; + if ((string.IsNullOrEmpty(computername)) || (computername.Equals(".", StringComparison.CurrentCultureIgnoreCase))) + { + computername = "localhost"; + } + } + } + private String computername = null; + + /// + /// The following is the definition of the input parameter "ConnectionURI". + /// Specifies the transport, server, port, and ApplicationName of the new + /// runspace. The format of this string is: + /// transport://server:port/ApplicationName. + /// + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")] + [Parameter(ParameterSetName = "URI")] + [ValidateNotNullOrEmpty] + public Uri ConnectionURI + { + get { return connectionuri; } + set { connectionuri = value; } + } + private Uri connectionuri; + + /// + /// The following is the definition of the input parameter "OptionSet". + /// OptionSet is a hahs table which help modify or refine the nature of the + /// request. These are similar to switches used in command line shells in that + /// they are service-specific + /// + + [Parameter] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + [Alias("os")] + [ValidateNotNullOrEmpty] + public Hashtable OptionSet + { + get { return optionset; } + set { optionset = value; } + } + private Hashtable optionset; + + /// + /// The following is the definition of the input parameter "Port". + /// Specifies the port to be used when connecting to the ws management service. + /// + [Parameter(ParameterSetName = "ComputerName")] + [ValidateNotNullOrEmpty] + [ValidateRange(1, Int32.MaxValue)] + public Int32 Port + { + get { return port; } + set { port = value; } + } + private Int32 port = 0; + + /// + /// The following is the definition of the input parameter "ResourceURI". + /// URI of the resource class/instance representation + /// + + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")] + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Resourceuri")] + + [Parameter(Mandatory = true, Position = 0)] + [Alias("ruri")] + [ValidateNotNullOrEmpty] + public Uri ResourceURI + { + get { return resourceuri; } + set { resourceuri = value; } + } + private Uri resourceuri; + + /// + /// The following is the definition of the input parameter "SelectorSet". + /// SelectorSet is a hash table which helps in identify an instance of the + /// management resource if there are are more than 1 instance of the resource + /// class + /// + [Parameter(Position = 1, Mandatory = true, + ValueFromPipeline = true, + ValueFromPipelineByPropertyName = true)] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + [ValidateNotNullOrEmpty] + public Hashtable SelectorSet + { + get { return selectorset; } + set { selectorset = value; } + } + private Hashtable selectorset; + + /// + /// The following is the definition of the input parameter "SessionOption". + /// Defines a set of extended options for the WSMan session. This can be created + /// by using the cmdlet New-WSManSessionOption + /// + [Parameter] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + [Alias("so")] + [ValidateNotNullOrEmpty] + public SessionOption SessionOption + { + get { return sessionoption; } + set { sessionoption = value; } + } + private SessionOption sessionoption; + + /// + /// The following is the definition of the input parameter "UseSSL". + /// Uses the Secure Sockets Layer (SSL) protocol to establish a connnection to + /// the remote computer. If SSL is not available on the port specified by the + /// Port parameter, the command fails. + /// + [Parameter(ParameterSetName = "ComputerName")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SSL")] + [Alias("ssl")] + public SwitchParameter UseSSL + { + get { return usessl; } + set { usessl = value; } + } + private SwitchParameter usessl; + + + + + #endregion + + + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + WSManHelper helper = new WSManHelper(this); + IWSManEx m_wsmanObject = (IWSManEx)new WSManClass(); + helper.WSManOp = "remove"; + IWSManSession m_session = null; + try + { + string connectionStr = String.Empty; + connectionStr = helper.CreateConnectionString(connectionuri, port, computername, applicationname); + if (connectionuri != null) + { + try + { + //in the format http(s)://server[:port/applicationname] + string[] constrsplit = connectionuri.OriginalString.Split(new string[] { ":" + port + "/" + applicationname }, StringSplitOptions.None); + string[] constrsplit1 = constrsplit[0].Split(new string[] { "//" }, StringSplitOptions.None); + computername = constrsplit1[1].Trim(); + } + catch (IndexOutOfRangeException) + { + helper.AssertError(helper.GetResourceMsgFromResourcetext("NotProperURI"), false, connectionuri); + } + + } + IWSManResourceLocator m_resource = helper.InitializeResourceLocator(optionset, selectorset, null, null, m_wsmanObject, resourceuri); + m_session = helper.CreateSessionObject(m_wsmanObject, Authentication, sessionoption, Credential, connectionStr, CertificateThumbprint, usessl.IsPresent); + string ResourceURI = helper.GetURIWithFilter(resourceuri.ToString(), null, selectorset, helper.WSManOp); + try + { + ((IWSManSession)m_session).Delete(ResourceURI, 0); + } + catch (Exception ex) + { + helper.AssertError(ex.Message, false, computername); + } + + } + finally + { + if (!String.IsNullOrEmpty(m_session.Error)) + { + helper.AssertError(m_session.Error, true, resourceuri); + } + if (!String.IsNullOrEmpty(m_wsmanObject.Error)) + { + helper.AssertError(m_wsmanObject.Error, true, resourceuri); + } + if (m_session != null) + Dispose(m_session); + + } + + }//End ProcessRecord() + + #region IDisposable Members + + /// + /// public dispose method + /// + public + void + Dispose() + { + //CleanUp(); + GC.SuppressFinalize(this); + } + /// + /// public dispose method + /// + public + void + Dispose(IWSManSession sessionObject) + { + sessionObject = null; + this.Dispose(); + } + + #endregion IDisposable Members + + + } + + + #endregion + + #region New-WsManInstance + /// + /// Creates an instance of a management resource identified by the resource URI + /// using specified ValueSet or input File + /// + + [Cmdlet(VerbsCommon.New, "WSManInstance", DefaultParameterSetName = "ComputerName", HelpUri = "http://go.microsoft.com/fwlink/?LinkId=141448")] + public class NewWSManInstanceCommand : AuthenticatingWSManCommand, IDisposable + { + /// + /// The following is the definition of the input parameter "ApplicationName". + /// ApplicationName identifies the remote endpoint. + /// + [Parameter(ParameterSetName = "ComputerName")] + [ValidateNotNullOrEmpty] + public String ApplicationName + { + get { return applicationname; } + set { applicationname = value; } + } + private String applicationname = null; + + /// + /// The following is the definition of the input parameter "ComputerName". + /// Executes the management operation on the specified computer(s). The default + /// is the local computer. Type the fully qualified domain name, NETBIOS name or + /// IP address to indicate the remote host(s) + /// + [Parameter(ParameterSetName = "ComputerName")] + [Alias("cn")] + public String ComputerName + { + get { return computername; } + set + { + computername = value; + if ((string.IsNullOrEmpty(computername)) || (computername.Equals(".", StringComparison.CurrentCultureIgnoreCase))) + { + computername = "localhost"; + } + } + } + private String computername = null; + + /// + /// The following is the definition of the input parameter "ConnectionURI". + /// Specifies the transport, server, port, and ApplicationName of the new + /// runspace. The format of this string is: + /// transport://server:port/ApplicationName. + /// + [Parameter(ParameterSetName = "URI")] + [ValidateNotNullOrEmpty] + [Alias("CURI", "CU")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")] + public Uri ConnectionURI + { + get { return connectionuri; } + set { connectionuri = value; } + } + private Uri connectionuri; + + /// + /// The following is the definition of the input parameter "FilePath". + /// Updates the management resource specified by the ResourceURI and SelectorSet + /// via this input file + /// + [Parameter] + [ValidateNotNullOrEmpty] + public String FilePath + { + get { return filepath; } + set { filepath = value; } + } + private String filepath; + + /// + /// The following is the definition of the input parameter "OptionSet". + /// OptionSet is a hash table and is used to pass a set of switches to the + /// service to modify or refine the nature of the request. + /// + [Parameter] + [ValidateNotNullOrEmpty] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + [Alias("os")] + public Hashtable OptionSet + { + get { return optionset; } + set { optionset = value; } + } + private Hashtable optionset; + + /// + /// The following is the definition of the input parameter "Port". + /// Specifies the port to be used when connecting to the ws management service. + /// + [Parameter(ParameterSetName = "ComputerName")] + [ValidateNotNullOrEmpty] + [ValidateRange(1, Int32.MaxValue)] + public Int32 Port + { + get { return port; } + set { port = value; } + } + private Int32 port = 0; + + /// + /// The following is the definition of the input parameter "ResourceURI". + /// URI of the resource class/instance representation + /// + [Parameter(Mandatory = true, Position = 0)] + [ValidateNotNullOrEmpty] + [Alias("ruri")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")] + public Uri ResourceURI + { + get { return resourceuri; } + set { resourceuri = value; } + } + private Uri resourceuri; + + /// + /// The following is the definition of the input parameter "SelectorSet". + /// SelectorSet is a hash table which helps in identify an instance of the + /// management resource if there are are more than 1 instance of the resource + /// class + /// + [Parameter(Mandatory = true, Position = 1, + ValueFromPipeline = true)] + [ValidateNotNullOrEmpty] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public Hashtable SelectorSet + { + get { return selectorset; } + set { selectorset = value; } + } + private Hashtable selectorset; + + /// + /// The following is the definition of the input parameter "SessionOption". + /// Defines a set of extended options for the WSMan session. + /// + [Parameter] + [ValidateNotNullOrEmpty] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + [Alias("so")] + public SessionOption SessionOption + { + get { return sessionoption; } + set { sessionoption = value; } + } + private SessionOption sessionoption; + + /// + /// The following is the definition of the input parameter "UseSSL". + /// Uses the Secure Sockets Layer (SSL) protocol to establish a connnection to + /// the remote computer. If SSL is not available on the port specified by the + /// Port parameter, the command fails. + /// + [Parameter(ParameterSetName = "ComputerName")] + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SSL")] + public SwitchParameter UseSSL + { + get { return usessl; } + set { usessl = value; } + } + private SwitchParameter usessl; + + /// + /// The following is the definition of the input parameter "ValueSet". + /// ValueSet is a hash table which helps to modify resource represented by the + /// ResourceURI and SelectorSet. + /// + [Parameter] + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public Hashtable ValueSet + { + get { return valueset; } + set { valueset = value; } + } + private Hashtable valueset; + + private WSManHelper helper; + IWSManEx m_wsmanObject = (IWSManEx)new WSManClass(); + IWSManSession m_session = null; + string connectionStr = String.Empty; + + /// + /// BeginProcessing method. + /// + protected override void BeginProcessing() + { + helper = new WSManHelper(this ); + helper.WSManOp = "new"; + connectionStr = helper.CreateConnectionString(connectionuri, port, computername, applicationname); + if (connectionuri != null) + { + try + { + //in the format http(s)://server[:port/applicationname] + string[] constrsplit = connectionuri.OriginalString.Split(new string[] { ":" + port + "/" + applicationname }, StringSplitOptions.None); + string[] constrsplit1 = constrsplit[0].Split(new string[] { "//" }, StringSplitOptions.None); + computername = constrsplit1[1].Trim(); + } + catch (IndexOutOfRangeException) + { + helper.AssertError(helper.GetResourceMsgFromResourcetext("NotProperURI"), false, connectionuri); + } + + } + + }//End BeginProcessing() + + + /// + /// ProcessRecord method. + /// + protected override void ProcessRecord() + { + try + { + IWSManResourceLocator m_resource = helper.InitializeResourceLocator(optionset, selectorset, null, null, m_wsmanObject, resourceuri); + //create the session object + m_session = helper.CreateSessionObject(m_wsmanObject, Authentication, sessionoption, Credential, connectionStr, CertificateThumbprint, usessl.IsPresent); + string rootNode = helper.GetRootNodeName(helper.WSManOp, m_resource.ResourceUri, null); + string input = helper.ProcessInput(m_wsmanObject, filepath, helper.WSManOp, rootNode, valueset, m_resource, m_session); + + try + { + string resultXml = m_session.Create(m_resource, input, 0); + XmlDocument xmldoc = new XmlDocument(); + xmldoc.LoadXml(resultXml); + WriteObject(xmldoc.DocumentElement); + } + catch (Exception ex) + { + helper.AssertError(ex.Message, false, computername); + } + } + finally + { + if (!String.IsNullOrEmpty(m_wsmanObject.Error)) + { + helper.AssertError(m_wsmanObject.Error, true, resourceuri); + } + if (!String.IsNullOrEmpty(m_session.Error)) + { + helper.AssertError(m_session.Error, true, resourceuri); + } + if (m_session != null) + { + Dispose(m_session); + } + } + + }//End ProcessRecord() + + #region IDisposable Members + + /// + /// public dispose method + /// + public + void + Dispose() + { + //CleanUp(); + GC.SuppressFinalize(this); + } + /// + /// public dispose method + /// + public + void + Dispose(IWSManSession sessionObject) + { + sessionObject = null; + this.Dispose(); + } + + #endregion IDisposable Members + + /// + /// EndProcessing method. + /// + protected override void EndProcessing() + { + helper.CleanUp(); + + }//End EndProcessing() + }//End Class + + #endregion +} diff --git a/src/Microsoft.WSMan.Management/WsManHelper.cs b/src/Microsoft.WSMan.Management/WsManHelper.cs new file mode 100644 index 000000000..5de81324b --- /dev/null +++ b/src/Microsoft.WSMan.Management/WsManHelper.cs @@ -0,0 +1,1145 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Text.RegularExpressions; +using System.Collections; +using System.Xml; +using System.Runtime.InteropServices; +using System.Reflection; +using System.Resources; +using System.Globalization; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Win32; +using System.Management.Automation; +using System.Management.Automation.Provider; +using System.Threading; +#if CORECLR +using System.Xml.XPath; +#endif + +namespace Microsoft.WSMan.Management +{ + [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")] + internal class WSManHelper + { + //regular expressions + private const string PTRN_URI_LAST = @"([a-z_][-a-z0-9._]*)$"; + private const string PTRN_OPT = @"^-([a-z]+):(.*)"; + private const string PTRN_HASH_TOK = @"\s*([\w:]+)\s*=\s*(\$null|""([^""]*)"")\s*"; + + //schemas + private const string URI_IPMI = @"http://schemas.dmtf.org/wbem/wscim/1/cim-schema"; + private const string URI_WMI = @"http://schemas.microsoft.com/wbem/wsman/1/wmi"; + private const string NS_IPMI = @"http://schemas.dmtf.org/wbem/wscim/1/cim-schema"; + private const string NS_CIMBASE = @"http://schemas.dmtf.org/wbem/wsman/1/base"; + private const string NS_WSMANL = @"http://schemas.microsoft.com"; + private const string NS_XSI = @"xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"""; + private const string ATTR_NIL = @"xsi:nil=""true"""; + private const string ATTR_NIL_NAME = @"xsi:nil"; + private const string NS_XSI_URI = @"http://www.w3.org/2001/XMLSchema-instance"; + private const string ALIAS_XPATH = @"xpath"; + private const string URI_XPATH_DIALECT = @"http://www.w3.org/TR/1999/REC-xpath-19991116"; + + //credSSP strings + internal string CredSSP_RUri = "winrm/config/client/auth"; + internal string CredSSP_XMLNmsp = "http://schemas.microsoft.com/wbem/wsman/1/config/client/auth"; + internal string CredSSP_SNode = "/cfg:Auth/cfg:CredSSP"; + internal string Client_uri = "winrm/config/client"; + internal string urlprefix_node = "/cfg:Client/cfg:URLPrefix"; + internal string Client_XMLNmsp = "http://schemas.microsoft.com/wbem/wsman/1/config/client"; + + internal string Service_Uri = "winrm/config/service"; + internal string Service_UrlPrefix_Node = "/cfg:Service/cfg:URLPrefix"; + internal string Service_XMLNmsp = "http://schemas.microsoft.com/wbem/wsman/1/config/service"; + internal string Service_CredSSP_Uri = "winrm/config/service/auth"; + internal string Service_CredSSP_XMLNmsp = "http://schemas.microsoft.com/wbem/wsman/1/config/service/auth"; + + //gpo registry path and keys + internal string Registry_Path_Credentials_Delegation = @"SOFTWARE\Policies\Microsoft\Windows"; + internal string Key_Allow_Fresh_Credentials = "AllowFreshCredentials"; + internal string Key_Concatenate_Defaults_AllowFresh = "ConcatenateDefaults_AllowFresh"; + internal string Delegate = "delegate"; + internal string keyAllowcredssp = "AllowCredSSP"; + + //'Constants for MS-XML + private const string NODE_ATTRIBUTE = "2"; + private const int NODE_TEXT = 3; + + //strings for dialects + internal string ALIAS_WQL = @"wql"; + internal string ALIAS_ASSOCIATION = @"association"; + internal string ALIAS_SELECTOR = @"selector"; + internal string URI_WQL_DIALECT = @"http://schemas.microsoft.com/wbem/wsman/1/WQL"; + internal string URI_SELECTOR_DIALECT = @"http://schemas.dmtf.org/wbem/wsman/1/wsman/SelectorFilter"; + internal string URI_ASSOCIATION_DIALECT = @" http://schemas.dmtf.org/wbem/wsman/1/cimbinding/associationFilter"; + + //string for operation + internal string WSManOp = null; + + private ResourceManager _resourceMgr = null; + private PSCmdlet cmdletname; + private NavigationCmdletProvider _provider; + + private FileStream _fs; + private StreamReader _sr; + + private static ResourceManager g_resourceMgr = new ResourceManager("Microsoft.WSMan.Management.resources.WsManResources", typeof(WSManHelper).GetTypeInfo().Assembly); + + + // + // + //Below class is just a static container which would release sessions in case this DLL is unloaded. + internal class Sessions + { + /// + /// dictionary object to store the connection + /// + internal static Dictionary SessionObjCache = new Dictionary(); + + ~Sessions() + { + ReleaseSessions(); + } + } + internal static Sessions AutoSession = new Sessions(); + // + // + // + + + internal static void ReleaseSessions() + { + lock (Sessions.SessionObjCache) + { + object sessionobj; + foreach (string key in Sessions.SessionObjCache.Keys) + { + Sessions.SessionObjCache.TryGetValue(key, out sessionobj); + try + { + Marshal.ReleaseComObject(sessionobj); + } + catch (ArgumentException) + { + //Somehow the object was a null reference. Ignore the error + } + sessionobj=null; + } + Sessions.SessionObjCache.Clear(); + } + } + + internal WSManHelper() + { + } + + internal WSManHelper(PSCmdlet cmdlet) + { + cmdletname = cmdlet; + } + + internal WSManHelper(NavigationCmdletProvider provider) + { + _provider = provider; + } + + internal static void ThrowIfNotAdministrator() + { + System.Security.Principal.WindowsIdentity currentIdentity = System.Security.Principal.WindowsIdentity.GetCurrent(); + System.Security.Principal.WindowsPrincipal principal = new System.Security.Principal.WindowsPrincipal(currentIdentity); + if (!principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator)) + { + string message = g_resourceMgr.GetString("ErrorElevationNeeded"); + throw new InvalidOperationException(message); + } + } + + internal string GetResourceMsgFromResourcetext(string rscname) + { + return g_resourceMgr.GetString(rscname); + } + + static internal string FormatResourceMsgFromResourcetextS(string rscname, + params object[] args) + { + return FormatResourceMsgFromResourcetextS(g_resourceMgr, rscname, args); + } + + internal string FormatResourceMsgFromResourcetext(string resourceName, + params object[] args) + { + return FormatResourceMsgFromResourcetextS(this._resourceMgr, resourceName, args); + } + + static private string FormatResourceMsgFromResourcetextS( + ResourceManager resourceManager, + string resourceName, + object[] args) + { + if (resourceManager == null) + { + throw new ArgumentNullException("resourceManager"); + } + + if (String.IsNullOrEmpty(resourceName)) + { + throw new ArgumentNullException("resourceName"); + } + + string template = resourceManager.GetString(resourceName); + + string result = null; + if (null != template) + { + result = String.Format(CultureInfo.CurrentCulture, + template, args); + } + return result; + } + + + /// + /// add a session to dictioanry + /// + /// connection string + /// session object + internal void AddtoDictionary(string key, Object value) + { + key = key.ToLowerInvariant(); + lock (Sessions.SessionObjCache) + { + if (!Sessions.SessionObjCache.ContainsKey(key)) + { + Sessions.SessionObjCache.Add(key, value); + } + else + { + object objsession = null; + Sessions.SessionObjCache.TryGetValue(key, out objsession); + try + { + Marshal.ReleaseComObject(objsession); + } + catch (ArgumentException) + { + //Somehow the object was a null reference. Ignore the error + } + Sessions.SessionObjCache.Remove(key); + Sessions.SessionObjCache.Add(key, value); + } + } + + } + + internal object RemoveFromDictionary(string computer) + { + object objsession = null; + computer = computer.ToLowerInvariant(); + lock (Sessions.SessionObjCache) + { + if (Sessions.SessionObjCache.ContainsKey(computer)) + { + Sessions.SessionObjCache.TryGetValue(computer, out objsession); + try + { + Marshal.ReleaseComObject(objsession); + } + catch (ArgumentException) + { + //Somehow the object was a null reference. Ignore the error + } + Sessions.SessionObjCache.Remove(computer); + } + } + return objsession; + } + + internal static Dictionary GetSessionObjCache() + { + try + { + lock (Sessions.SessionObjCache) + { + if (!Sessions.SessionObjCache.ContainsKey("localhost")) + { + IWSManEx wsmanObject = (IWSManEx)new WSManClass(); + IWSManSession SessionObj = (IWSManSession)wsmanObject.CreateSession(null, 0, null); + Sessions.SessionObjCache.Add("localhost", SessionObj); + } + } + } + catch (IOException) + { + } + catch (System.Security.SecurityException) + { + } + catch (System.UnauthorizedAccessException) + { + } + catch (COMException) + { + } + return Sessions.SessionObjCache; + } + + internal string GetRootNodeName(string operation, string resourceUri, string actionStr) + { + string resultStr = null, sfx = null; + if (resourceUri != null) + { + resultStr = resourceUri; + resultStr = StripParams(resultStr); + + Regex regexpr = new Regex(PTRN_URI_LAST, RegexOptions.IgnoreCase); + MatchCollection matches = regexpr.Matches(resultStr); + if (matches.Count > 0) + { + if (operation.Equals("invoke", StringComparison.OrdinalIgnoreCase)) + { + sfx = "_INPUT"; + resultStr = String.Concat(actionStr, sfx); + } + else + { + resultStr = matches[0].ToString(); + } + } + else + { + //error + } + } + return resultStr; + } + + internal string StripParams(string uri) + { + int pos = uri.IndexOf('?'); + if (pos > 0) + return uri.Substring(pos, uri.Length - pos); + else + return uri; + } + + internal string ReadFile(string path) + { + if (!File.Exists(path)) + { + throw new ArgumentException(GetResourceMsgFromResourcetext("InvalidFileName")); + } + string strOut = null; + try + { + + _fs = new FileStream(path, FileMode.Open, FileAccess.Read); + // create stream Reader + _sr = new StreamReader(_fs); + strOut = _sr.ReadToEnd(); + } + + catch (ArgumentNullException e) + { + ErrorRecord er = new ErrorRecord(e, "ArgumentNullException", ErrorCategory.InvalidArgument, null); + cmdletname.ThrowTerminatingError(er); + + } + catch (UnauthorizedAccessException e) + { + ErrorRecord er = new ErrorRecord(e, "UnauthorizedAccessException", ErrorCategory.PermissionDenied, null); + cmdletname.ThrowTerminatingError(er); + } + catch (FileNotFoundException e) + { + ErrorRecord er = new ErrorRecord(e, "FileNotFoundException", ErrorCategory.ObjectNotFound, null); + cmdletname.ThrowTerminatingError(er); + } + catch (DirectoryNotFoundException e) + { + ErrorRecord er = new ErrorRecord(e, "DirectoryNotFoundException", ErrorCategory.ObjectNotFound, null); + cmdletname.ThrowTerminatingError(er); + } + catch (System.Security.SecurityException e) + { + ErrorRecord er = new ErrorRecord(e, "SecurityException", ErrorCategory.SecurityError, null); + cmdletname.ThrowTerminatingError(er); + } + finally + { + if (_sr != null) + { + // _sr.Close(); + _sr.Dispose(); + } + if (_fs != null) + { + //_fs.Close(); + _fs.Dispose(); + } + } + return strOut; + } + + internal string ProcessInput(IWSManEx wsman, string filepath, string operation, string root, Hashtable valueset, IWSManResourceLocator resourceUri, IWSManSession sessionObj) + { + + string resultString = null; + + //if file path is given + if (!string.IsNullOrEmpty(filepath) && valueset == null) + { + if (!File.Exists(filepath)) + { + throw new FileNotFoundException(_resourceMgr.GetString("InvalidFileName")); + } + resultString = ReadFile(filepath); + return resultString; + } + + switch (operation) + { + case "new": + case "invoke": + + string parameters = null, nilns = null; + string xmlns = GetXmlNs(resourceUri.ResourceUri); + + //if valueset is given, i.e hastable + if (valueset != null) + { + foreach (DictionaryEntry entry in valueset) + { + parameters = parameters + "" + entry.Value.ToString() + ""; + } + } + resultString = "" + parameters + ""; + + break; + case "set": + + string getResult = sessionObj.Get(resourceUri, 0); + XmlDocument xmlfile = new XmlDocument(); + xmlfile.LoadXml(getResult); + + string xpathString = null; + if (valueset != null) + { + foreach (DictionaryEntry entry in valueset) + { + xpathString = @"/*/*[local-name()=""" + entry.Key + @"""]"; + if (entry.Key.ToString().Equals("location", StringComparison.OrdinalIgnoreCase)) + { + //'Ignore cim:Location + xpathString = @"/*/*[local-name()=""" + entry.Key + @""" and namespace-uri() != """ + NS_CIMBASE + @"""]"; + } + + XmlNodeList nodes = xmlfile.SelectNodes(xpathString); + if (nodes.Count == 0) + { + throw new ArgumentException(_resourceMgr.GetString("NoResourceMatch")); + } + else if (nodes.Count > 1) + { + throw new ArgumentException(_resourceMgr.GetString("MultipleResourceMatch")); + } + else + { + XmlNode node = nodes[0]; + if (node.HasChildNodes) + { + if (node.ChildNodes.Count > 1) + { + throw new ArgumentException(_resourceMgr.GetString("NOAttributeMatch")); + } + else + { + XmlNode tmpNode = node.ChildNodes[0];//.Item[0]; + if (!tmpNode.NodeType.ToString().Equals("text", StringComparison.OrdinalIgnoreCase)) + { + throw new ArgumentException(_resourceMgr.GetString("NOAttributeMatch")); + } + } + } + if (string.IsNullOrEmpty(entry.Key.ToString())) + { + //XmlNode newnode = xmlfile.CreateNode(XmlNodeType.Attribute, ATTR_NIL_NAME, NS_XSI_URI); + XmlAttribute newnode = xmlfile.CreateAttribute(XmlNodeType.Attribute.ToString(), ATTR_NIL_NAME, NS_XSI_URI); + newnode.Value = "true"; + node.Attributes.Append(newnode); + //(newnode.Attributes.Item(0).FirstChild ); + node.Value = ""; + } + else + { + node.Attributes.RemoveNamedItem(ATTR_NIL_NAME); + node.InnerText = entry.Value.ToString(); + } + } + + }//end for + }//end if valueset + resultString = xmlfile.OuterXml; + break; + }//end switch + return resultString; + } + + internal string GetXmlNs(string resUri) + { + + string tmpNs = null; + + if (resUri.ToLowerInvariant().Contains(URI_IPMI) || (resUri.ToLowerInvariant().Contains(URI_WMI))) + tmpNs = StripParams(resUri); + else + { + //tmpNs = StripParams(resUri) + ".xsd"; + //This was reported by Intel as an interop issue. So now we are not appending a .xsd in the end. + tmpNs = StripParams(resUri); + } + + return (@"xmlns:p=""" + tmpNs + @""""); + + } + + internal XmlNode GetXmlNode(string xmlString, string xpathpattern, string xmlnamespace) + { + XmlNode node = null; + XmlDocument xDoc = new XmlDocument(); + xDoc.LoadXml(xmlString); + XmlNamespaceManager nsmgr = new XmlNamespaceManager(xDoc.NameTable); + if (!string.IsNullOrEmpty(xmlnamespace)) + { + nsmgr.AddNamespace("cfg", xmlnamespace); + } + node = xDoc.SelectSingleNode(xpathpattern, nsmgr); + return node; + } + + internal string CreateConnectionString(Uri ConnUri, int port, string computername, string applicationname) + { + string ConnectionString = null; + if (ConnUri != null) + { + ConnectionString = ConnUri.OriginalString; + } + else + { + if (computername == null && (port != 0 || applicationname != null)) + { + // the user didn't give us a computer name but he gave a port and/or application name; + // in this case we need to have a computer name, to form the connection string; + // assume localhost + computername = "localhost"; + } + + ConnectionString = computername; + if (port != 0) + { + ConnectionString = ConnectionString + ":" + port; + } + if (applicationname != null) + { + ConnectionString = ConnectionString + "/" + applicationname; + } + } + return ConnectionString; + + } + + internal IWSManResourceLocator InitializeResourceLocator(Hashtable optionset, Hashtable selectorset, string fragment, Uri dialect, IWSManEx wsmanObj, Uri resourceuri) + { + + string resource = null; + if (resourceuri != null) + { + resource = resourceuri.ToString(); + } + if (selectorset != null) + { + resource = resource + "?"; + int i = 0; + foreach (DictionaryEntry entry in selectorset) + { + i++; + resource = resource + entry.Key.ToString() + "=" + entry.Value.ToString(); + if (i < selectorset.Count) + resource += "+"; + } + } + IWSManResourceLocator m_resource = null; + try + { + m_resource = (IWSManResourceLocator)wsmanObj.CreateResourceLocator(resource); + + + if (optionset != null) + { + foreach (DictionaryEntry entry in optionset) + { + if (entry.Value.ToString() == null) + { + m_resource.AddOption(entry.Key.ToString(), null, 1); + } + else + { + m_resource.AddOption(entry.Key.ToString(), entry.Value, 1); + } + } + } + + if (!string.IsNullOrEmpty(fragment)) + { + m_resource.FragmentPath = fragment; + } + + if (dialect != null) + { + m_resource.FragmentDialect = dialect.ToString(); + } + } + catch (COMException ex) + { + AssertError(ex.Message, false, null); + } + return m_resource; + } + + /// + /// Used to resolve authentication from the parameters chosen by the user. + /// User has the following options: + /// 1. AuthMechanism + Credential + /// 2. CertiticateThumbPrint + /// + /// All the above are mutually exclusive. + /// + /// + /// If there is ambiguity as specified above. + /// + static internal void ValidateSpecifiedAuthentication(AuthenticationMechanism authentication, PSCredential credential, string certificateThumbprint) + { + if ((credential != null) && (certificateThumbprint != null)) + { + String message = FormatResourceMsgFromResourcetextS( + "AmbiguosAuthentication", + "CertificateThumbPrint", "credential"); + + throw new InvalidOperationException(message); + } + + if ((authentication != AuthenticationMechanism.Default) && + (authentication != AuthenticationMechanism.ClientCertificate) && + (certificateThumbprint != null)) + { + String message = FormatResourceMsgFromResourcetextS( + "AmbiguosAuthentication", + "CertificateThumbPrint", authentication.ToString()); + + throw new InvalidOperationException(message); + } + } + + internal IWSManSession CreateSessionObject(IWSManEx wsmanObject, AuthenticationMechanism authentication, SessionOption sessionoption, PSCredential credential, string connectionString, string certificateThumbprint, bool usessl) + { + ValidateSpecifiedAuthentication(authentication, credential, certificateThumbprint); + + ////if authentication is given + int sessionFlags = 0; + + if (authentication.ToString() != null) + { + if (authentication.Equals(AuthenticationMechanism.None)) + { + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUseNoAuthentication; + } + if (authentication.Equals(AuthenticationMechanism.Basic)) + { + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUseBasic | (int)WSManSessionFlags.WSManFlagCredUserNamePassword; + } + if (authentication.Equals(AuthenticationMechanism.Negotiate)) + { + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUseNegotiate; + } + if (authentication.Equals(AuthenticationMechanism.Kerberos)) + { + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUseKerberos; + } + if (authentication.Equals(AuthenticationMechanism.Digest)) + { + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUseDigest | (int)WSManSessionFlags.WSManFlagCredUserNamePassword; + } + if (authentication.Equals(AuthenticationMechanism.Credssp)) + { + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUseCredSsp | (int)WSManSessionFlags.WSManFlagCredUserNamePassword; + } + if (authentication.Equals(AuthenticationMechanism.ClientCertificate)) + { + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUseClientCertificate; + } + + } + + IWSManConnectionOptionsEx2 connObject = (IWSManConnectionOptionsEx2)wsmanObject.CreateConnectionOptions(); + if (credential != null) + { + //connObject = (IWSManConnectionOptionsEx2)wsmanObject.CreateConnectionOptions(); + System.Net.NetworkCredential nwCredential = new System.Net.NetworkCredential(); + if (credential.UserName != null) + { + nwCredential = credential.GetNetworkCredential(); + if (String.IsNullOrEmpty(nwCredential.Domain)) + { + if ( authentication.Equals(AuthenticationMechanism.Digest) || authentication.Equals(AuthenticationMechanism.Basic) ) + { + connObject.UserName = nwCredential.UserName; + } + else + { + // just wanted to not use null domain, empty is actually fine + connObject.UserName = "\\" + nwCredential.UserName; + } + } + else + { + connObject.UserName = nwCredential.Domain + "\\" + nwCredential.UserName; + } + connObject.Password = nwCredential.Password; + if (!authentication.Equals(AuthenticationMechanism.Credssp) || !authentication.Equals(AuthenticationMechanism.Digest) || authentication.Equals(AuthenticationMechanism.Basic)) + { + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagCredUserNamePassword; + } + } + } + + if (certificateThumbprint != null) + { + connObject.CertificateThumbprint = certificateThumbprint; + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUseClientCertificate; + } + + if (sessionoption != null) + { + + if (sessionoption.ProxyAuthentication != 0) + { + int ProxyAccessflags = 0; + int ProxyAuthenticationFlags = 0; + if (sessionoption.ProxyAccessType.Equals(ProxyAccessType.ProxyIEConfig)) + { + ProxyAccessflags = connObject.ProxyIEConfig(); + } + else if (sessionoption.ProxyAccessType.Equals(ProxyAccessType.ProxyAutoDetect)) + { + ProxyAccessflags = connObject.ProxyAutoDetect(); + } + else if (sessionoption.ProxyAccessType.Equals(ProxyAccessType.ProxyNoProxyServer)) + { + ProxyAccessflags = connObject.ProxyNoProxyServer(); + } + else if (sessionoption.ProxyAccessType.Equals(ProxyAccessType.ProxyWinHttpConfig)) + { + ProxyAccessflags = connObject.ProxyWinHttpConfig(); + } + + if (sessionoption.ProxyAuthentication.Equals(ProxyAuthentication.Basic)) + { + ProxyAuthenticationFlags = connObject.ProxyAuthenticationUseBasic(); + } + else if (sessionoption.ProxyAuthentication.Equals(ProxyAuthentication.Negotiate)) + { + ProxyAuthenticationFlags = connObject.ProxyAuthenticationUseNegotiate(); + } + else if (sessionoption.ProxyAuthentication.Equals(ProxyAuthentication.Digest)) + { + ProxyAuthenticationFlags = connObject.ProxyAuthenticationUseDigest(); + } + if (sessionoption.ProxyCredential != null) + { + try + { + connObject.SetProxy(ProxyAccessflags, ProxyAuthenticationFlags, sessionoption.ProxyCredential.UserName, sessionoption.ProxyCredential.Password); + } + catch (Exception ex) + { + AssertError(ex.Message, false, null); + } + } + else + { + connObject.SetProxy((int)sessionoption.ProxyAccessType, (int)sessionoption.ProxyAuthentication, null, null); + } + + + } + if (sessionoption.SkipCACheck) + { + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagSkipCACheck; + } + if (sessionoption.SkipCNCheck) + { + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagSkipCNCheck; + } + if (sessionoption.SPNPort > 0) + { + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagEnableSpnServerPort; + } + if (sessionoption.UseUtf16) + { + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUtf16; + } + else + { + //If UseUtf16 is false, then default Encoding is Utf8 + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUtf8; + } + if (!sessionoption.UseEncryption) + { + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagNoEncryption; + } + if (sessionoption.SkipRevocationCheck) + { + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagSkipRevocationCheck; + } + } + else + { + //If SessionOption is null then, default Encoding is Utf8 + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUtf8; + } + + if (usessl) + { + sessionFlags = sessionFlags | (int)WSManSessionFlags.WSManFlagUseSsl; + } + + IWSManSession m_SessionObj = null; + try + { + m_SessionObj = (IWSManSession)wsmanObject.CreateSession(connectionString, sessionFlags, connObject); + if (sessionoption != null) + { + if (sessionoption.OperationTimeout > 0) + { + m_SessionObj.Timeout = sessionoption.OperationTimeout; + } + } + } + catch (COMException ex) + { + AssertError(ex.Message, false, null); + } + return m_SessionObj; + } + + internal void CleanUp() + { + + + if (_sr != null) + { + _sr.Dispose(); + _sr = null; + } + if (_fs != null) + { + _fs.Dispose(); + _fs = null; + } + + } + + internal string GetFilterString(Hashtable seletorset) + { + StringBuilder filter = new StringBuilder(); + foreach (DictionaryEntry entry in seletorset) + { + if (entry.Key != null && entry.Value != null) + { + filter.Append(entry.Key.ToString()); + filter.Append("="); + filter.Append(entry.Value.ToString()); + filter.Append("+"); + } + } + filter.Remove(filter.ToString().Length - 1, 1); + return filter.ToString(); + } + + internal void AssertError(string ErrorMessage, bool IsWSManError, object targetobject) + { + if (IsWSManError) + { + XmlDocument ErrorDoc = new XmlDocument(); + ErrorDoc.LoadXml(ErrorMessage); + InvalidOperationException ex = new InvalidOperationException(ErrorDoc.OuterXml); + ErrorRecord er = new ErrorRecord(ex, "WsManError", ErrorCategory.InvalidOperation, targetobject); + if (cmdletname != null) + { + cmdletname.ThrowTerminatingError(er); + } + else + { + _provider.ThrowTerminatingError(er); + } + } + else + { + InvalidOperationException ex = new InvalidOperationException(ErrorMessage); + ErrorRecord er = new ErrorRecord(ex, "WsManError", ErrorCategory.InvalidOperation, targetobject); + if (cmdletname != null) + { + cmdletname.ThrowTerminatingError(er); + } + else + { + _provider.ThrowTerminatingError(er); + } + } + } + + internal string GetURIWithFilter(string uri, string filter, Hashtable selectorset, string operation) + { + StringBuilder sburi = new StringBuilder(); + sburi.Append(uri); + sburi.Append("?"); + + if (operation.Equals("remove", StringComparison.OrdinalIgnoreCase)) + { + sburi.Append(GetFilterString(selectorset)); + if (sburi.ToString().EndsWith("?", StringComparison.OrdinalIgnoreCase)) + { + sburi.Remove(sburi.Length - 1, 1); + } + } + + return sburi.ToString(); + } + + /// + /// This method is used by Connect-WsMan Cmdlet and New-Item of WsMan Provider to create connection to WsMan + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + internal void CreateWsManConnection(string ParameterSetName, Uri connectionuri, int port, string computername, string applicationname, bool usessl, AuthenticationMechanism authentication, SessionOption sessionoption, PSCredential credential, string certificateThumbprint) + { + IWSManEx m_wsmanObject = (IWSManEx)new WSManClass(); + try + { + string connectionStr = CreateConnectionString(connectionuri, port, computername, applicationname); + if (connectionuri != null) + { + //in the format http(s)://server[:port/applicationname] + string[] constrsplit = connectionStr.Split(new string[] { ":" + port + "/" + applicationname }, StringSplitOptions.None); + string[] constrsplit1 = constrsplit[0].Split(new string[] { "//" }, StringSplitOptions.None); + computername = constrsplit1[1].Trim(); + } + IWSManSession m_session = CreateSessionObject(m_wsmanObject, authentication, sessionoption, credential, connectionStr, certificateThumbprint, usessl); + m_session.Identify(0); + string key = computername; + if (key == null) + { + key = "localhost"; + } + AddtoDictionary(key, m_session); + } + catch (IndexOutOfRangeException) + { + AssertError(_resourceMgr.GetString("NotProperURI"), false, connectionuri); + } + catch (Exception ex) + { + AssertError(ex.Message, false, computername); + } + finally + { + if (!String.IsNullOrEmpty(m_wsmanObject.Error)) + { + AssertError(m_wsmanObject.Error, true, computername); + } + + } + } + + /// + /// Verifies all the registry keys are set as expected. In case of failure .. try ecery second for 60 seconds before returning false. + /// + /// True if trying to Enable CredSSP. + /// Names of the degate computer. + /// Name of the application. + /// True if valid. + internal bool ValidateCreadSSPRegistryRetry(bool AllowFreshCredentialsValueShouldBePresent, string[] DelegateComputer, string applicationname) + { + for (int i = 0; i < 60; i++) + { + if (!ValidateCredSSPRegistry(AllowFreshCredentialsValueShouldBePresent, DelegateComputer, applicationname)) + { + Thread.Sleep(1000); + } + else + { + return true; + } + } + + return false; + } + + internal bool ValidateCredSSPRegistry(bool AllowFreshCredentialsValueShouldBePresent, string[] DelegateComputer, string applicationname) + { + System.IntPtr NakedGPOCriticalSection = GpoNativeApi.EnterCriticalPolicySection(true); + + try + { + RegistryKey rGPOLocalMachineKey = Registry.LocalMachine.OpenSubKey( + Registry_Path_Credentials_Delegation + @"\CredentialsDelegation", +#if !CORECLR + RegistryKeyPermissionCheck.ReadWriteSubTree, +#endif + System.Security.AccessControl.RegistryRights.FullControl); + + if (rGPOLocalMachineKey != null) + { + rGPOLocalMachineKey = rGPOLocalMachineKey.OpenSubKey(Key_Allow_Fresh_Credentials, +#if !CORECLR + RegistryKeyPermissionCheck.ReadWriteSubTree, +#endif + System.Security.AccessControl.RegistryRights.FullControl); + if (rGPOLocalMachineKey == null) + { + return !AllowFreshCredentialsValueShouldBePresent; + } + + string[] valuenames = rGPOLocalMachineKey.GetValueNames(); + if (valuenames.Length <= 0) + { + return !AllowFreshCredentialsValueShouldBePresent; + } + + List RegValues = new List(); + foreach (string value in valuenames) + { + object keyvalue = rGPOLocalMachineKey.GetValue(value); + + if (keyvalue != null && keyvalue.ToString().StartsWith(applicationname, StringComparison.OrdinalIgnoreCase)) + { + if (!AllowFreshCredentialsValueShouldBePresent) + { + // If calling Disable-CredSSP .. no value should start with "applicationName" regardless of the computer. + return false; + } + + RegValues.Add(keyvalue.ToString()); + } + } + + if (AllowFreshCredentialsValueShouldBePresent) + { + // For all the keys that starts with "applicationName" make sure the delegated computer is listed. + foreach (string comp in DelegateComputer) + { + if (!RegValues.Contains(applicationname + "/" + comp)) + { + return false; + } + } + } + } + } + finally + { + bool GPOReleaseCriticalSection = GpoNativeApi.LeaveCriticalPolicySection(NakedGPOCriticalSection); + } + + return true; + } + } + + internal static class WSManResourceLoader + { + internal static void LoadResourceData() + { + try + { + string filepath = System.Environment.ExpandEnvironmentVariables("%Windir%") + "\\System32\\Winrm\\" + +#if CORECLR + "0409" /* TODO: don't assume it is always English on CSS? */ +#else + String.Concat("0", String.Format(CultureInfo.CurrentCulture, "{0:x2}", checked((uint)CultureInfo.CurrentUICulture.LCID))) +#endif + + "\\" + "winrm.ini"; + if (File.Exists(filepath)) + { + FileStream _fs = new FileStream(filepath, FileMode.Open, FileAccess.Read); + StreamReader _sr = new StreamReader(_fs); + while (!_sr.EndOfStream) + { + string Line = _sr.ReadLine(); + if (Line.Contains("=")) + { + string[] arr = Line.Split(new char[] { '=' }, 2); + if (!ResourceValueCache.ContainsKey(arr[0].Trim())) + { + string value = arr[1].TrimStart(new char[] { '"' }).TrimEnd(new char[] { '"' }); + ResourceValueCache.Add(arr[0].Trim(), value.Trim()); + } + } + } + } + } + + catch (IOException e) + { + + throw (e); + } + + + } + + /// + /// Get the resource value from WinRm.ini + /// from %windir%\system32\winrm\[Hexadecimal Language Folder]\winrm.ini + /// + /// + /// + internal static string GetResourceString(string Key) + { + //Checks whether resource values already loaded and loads. + if (ResourceValueCache.Count <= 0) + { + LoadResourceData(); + } + string value = ""; + if (ResourceValueCache.ContainsKey(Key.Trim())) + { + ResourceValueCache.TryGetValue(Key.Trim(), out value); + } + return value.Trim(); + } + + /// + /// + /// + private static Dictionary ResourceValueCache = new Dictionary(); + + + } +} diff --git a/src/Microsoft.WSMan.Management/WsManSnapin.cs b/src/Microsoft.WSMan.Management/WsManSnapin.cs new file mode 100644 index 000000000..568b833d5 --- /dev/null +++ b/src/Microsoft.WSMan.Management/WsManSnapin.cs @@ -0,0 +1,92 @@ +/********************************************************************++ +Copyright (c) Microsoft Corporation. All rights reserved. +--********************************************************************/ +using System; +using System.Diagnostics; +using System.Text; +using System.Management; +using System.Management.Automation; +using System.ComponentModel; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace Microsoft.WSMan.Management +{ + #region SnapIn + + /// + /// Create the PowerShell snap-in used to register the + /// WsManPSSnapIn cmdlets. Declaring the PSSnapIn class identifies + /// this .cs file as a PowerShell snap-in. + /// + [RunInstaller(true)] + public class WSManPSSnapIn : PSSnapIn + { + /// + /// Create an instance of the WsManSnapin class. + /// + public WSManPSSnapIn() + : base() + { + } + + /// + /// Specify the name of the PowerShell snap-in. + /// + public override string Name + { + get + { + return "WsManPSSnapIn"; + } + } + + /// + /// Specify the vendor for the PowerShell snap-in. + /// + public override string Vendor + { + get + { + return "Microsoft"; + } + } + + /// + /// Specify the localization resource information for the vendor. + /// Use the format: resourceBaseName,VendorName. + /// + public override string VendorResource + { + get + { + return "WsManPSSnapIn,Microsoft"; + } + } + + /// + /// Specify a description of the PowerShell snap-in. + /// + public override string Description + { + get + { + return "This is a PowerShell snap-in that includes the WsMan cmdlets."; + } + } + + /// + /// Specify the localization resource information for the description. + /// Use the format: resourceBaseName,Description. + /// + public override string DescriptionResource + { + get + { + return "WsManPSSnapIn,This is a PowerShell snap-in that includes the WsMan cmdlets."; + } + } + } + + #endregion SnapIn +} diff --git a/src/Microsoft.WSMan.Management/map.json b/src/Microsoft.WSMan.Management/map.json new file mode 100644 index 000000000..abdf1ee17 --- /dev/null +++ b/src/Microsoft.WSMan.Management/map.json @@ -0,0 +1,15 @@ +{ + "wmi/wmx/cmdlets/Management/ConfigProvider.cs" : "ConfigProvider.cs", + "wmi/wmx/cmdlets/Management/CredSSP.cs" : "CredSSP.cs", + "wmi/wmx/cmdlets/Management/CurrentConfigurations.cs" : "CurrentConfigurations.cs", + "wmi/wmx/cmdlets/Management/Interop.cs" : "Interop.cs", + "wmi/wmx/cmdlets/Management/InvokeWSManAction.cs" : "InvokeWSManAction.cs", + "wmi/wmx/cmdlets/Management/NewWSManSession.cs" : "NewWSManSession.cs", + "wmi/wmx/cmdlets/Management/PingWSMan.cs" : "PingWSMan.cs", + "wmi/wmx/cmdlets/Management/Set-QuickConfig.cs" : "Set-QuickConfig.cs", + "wmi/wmx/cmdlets/Management/WSManConnections.cs" : "WSManConnections.cs", + "wmi/wmx/cmdlets/Management/WsManHelper.cs" : "WsManHelper.cs", + "wmi/wmx/cmdlets/Management/WSManInstance.cs" : "WSManInstance.cs", + "wmi/wmx/cmdlets/Snapin/WsManSnapin.cs" : "WsManSnapin.cs", + "wmi/wmx/cmdlets/Management/resources/WsManResources.txt" : "resources/WsManResources.txt" +} diff --git a/src/Microsoft.WSMan.Management/project.json b/src/Microsoft.WSMan.Management/project.json new file mode 100644 index 000000000..9e5504fc1 --- /dev/null +++ b/src/Microsoft.WSMan.Management/project.json @@ -0,0 +1,38 @@ +{ + "name": "Microsoft.WSMan.Management", + "version": "1.0.0-*", + + "buildOptions": { + "keyFile": "../signing/visualstudiopublic.snk", + "delaySign": true, + "publicSign": false, + "warningsAsErrors": true + }, + + "dependencies": { + "System.Management.Automation": "1.0.0-*", + "Microsoft.WSMan.Runtime": "1.0.0-*" + }, + + "frameworks": { + "netstandard1.6": { + "imports": [ "dnxcore50" ], + "buildOptions": { + "define": [ "CORECLR" ], + "compile": { + "exclude": [ + "WsManSnapin.cs" + ] + } + }, + "dependencies": { + "NETStandard.Library": "1.6.0", + } + }, + "net451": { + "frameworkAssemblies": { + "System.ServiceProcess": "" + } + } + } +} diff --git a/src/Microsoft.WSMan.Management/resources/WsManResources.resx b/src/Microsoft.WSMan.Management/resources/WsManResources.resx new file mode 100644 index 000000000..8f835f5ac --- /dev/null +++ b/src/Microsoft.WSMan.Management/resources/WsManResources.resx @@ -0,0 +1,331 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + This command cannot be used because file does not exist.Check the file existence and run your command. + + + Creates a new ClientCertificate item. + + + This command cannot be executed because the Connection URI is not in correct format. Please check the connection uri and Run your command again. + + + CredSSP authentication allows the user credentials on this computer to be sent to a remote computer. If you use CredSSP authentication for a connection to a malicious or compromised computer, that computer will have access to your user name and password. For more information, see the Enable-WSManCredSSP Help topic. +Do you want to enable CredSSP authentication? + + + Creates a new Listener item. + + + This command modifies the security settings on a resource in the following WinRM plug-in: {0}. +Do you want to continue? + + + "Set-Item" on the WinRM configuration setting "{0}" to update the value to "{1}" + + + This command cannot be executed because the setting cannot be enabled. + + + This command creates a new Listener item. + +Do you want to continue? + + + Access is denied. You need to run this cmdlet from an elevated process. + + + This command cannot be used because WsMan drive root is not supported on this version of Windows OS. + + + Start WinRM Service + + + CredSSP authentication allows the server to accept user credentials from a remote computer. If you enable CredSSP authentication on the server, the server will have access to the user name and password of the client computer if the client computer sends them. For more information, see the Enable-WSManCredSSP Help topic. +Do you want to enable CredSSP authentication? + + + WinRM Quick Configuration + + + Microsoft + + + This command cannot set the input value because these values are Primary keys or Container items of the resource object. Change the input value and Run your command. + + + CredSSP Authentication Configuration for WS-Management + + + Set the value of the item + + + Cannot convert 'System.Object[]' to the type 'System.String' required by the parameter. Specified method is not supported. + + + This computer is not configured to receive credentials from a remote client computer. + + + This command cannot be used from the current path. Move to root path of the provider using cd\ and run your command again. + + + This PowerShell cmdlet is not available on for Windows XP and Windows Server 2003. + + + This command cannot be used because the parameter matches a non-text property on the ResourceURI.Check the input parameters and run your command. + + + A {0} cannot be specified when {1} is specified. + + + The WinRM client cannot complete the operation.Check if the computer name is valid. + + + The {0} parameter is mandatory when the {1} parameter value is {2}. + + + This command cannot be used because Parameter Value is not supplied. Check the value again and run your command. + + + This command cannot be used because path does not exist.Check the path existence and run your command. + + + Security Configuration for WinRM Plug-in. + + + This command cannot be used in the current path because this cmdlet is not supported at this level of Provider path. + + + The machine is not configured to allow delegating fresh credentials. + + + The configuration changes you made will only be effective after the WinRM service is restarted. To restart the WinRM service, run the following command: 'Restart-Service winrm' + + + Running the Set-WSManQuickConfig command has significant security implications, as it enables remote management through the WinRM service on this computer. +This command: + 1. Checks whether the WinRM service is running. If the WinRM service is not running, the service is started. + 2. Sets the WinRM service startup type to automatic. + 3. Creates a listener to accept requests on any IP address. By default, the transport is HTTP. + 4. Enables a firewall exception for WS-Management traffic. + 5. Enables Kerberos and Negotiate service authentication. +Do you want to enable remote management through the WinRM service on this computer? + + + The value for RunAsPassword cannot be set without a value set for RunAsUser. Set the value for both RunAsUser and RunAsPassword in Powershell by calling the Set-Item cmdlet with the value for -Path attribute equal to the value of RunAsUser. + + + The updated configuration might affect the operation of the plugins having a per plugin quota value greater than {0}. Verify the configuration of all the registered plugins and change the per plugin quota values for the affected plugins. + + + This command set the value of the Item. + +Do you want to continue? + + + The machine is configured to allow delegating fresh credentials to the following target(s): + + + Root of WsMan Config Storage. + + + This command cannot be executed because the WinRM Service is not started. + + + This command cannot be used because root path does not exist.Check the root path and run your command. + + + This command cannot be used in the current path because Remove-Item is not supported at this level of Provider path. + + + This command modifies the TrustedHosts list for the WinRM client. The computers in the TrustedHosts list might not be authenticated. The client might send credential information to these computers. Are you sure that you want to modify this list? + + + This command modifies the RootSDDL setting for the WinRM service. The RootSDDL stores the default security settings for any WinRM securable resource that does not specify its own SDDL. Changing the SDDL might affect security for many WinRM resources. Are you sure that you want to modify these default settings? + + + This command cannot be used without credential because the authentication algorithm is Basic or Digest. Use Credentials parameter to specify value and run your command. + + + The updated configuration is effective only if it is less than or equal to the value of global quota {0}. Verify the value for the global quota using the PowerShell cmdlet "Get-Item {0}". + + + This command cannot be executed because the setting cannot be disabled. + + + Unable to find value for "{0}" element in the path {1}. + + + This command cannot be used without Basic or Digest authentication algorithm because credentials are specified.Use Basic or Digest authentication algorithm and run your command. + + + WinRM Security Configuration. + + + This command cannot be used in the current path because New-Item is not supported at this level of Provider path. + + + This command cannot be used because the configuration is corrupted. Run WinRM invoke Restore WinRM/config to restore the default configuration + + + This command cannot be used because the parameter value type is invalid. {0} configuration expects a value of Type {1}. Verify that the value is correct and try again. + + + WinRM service is not started currently. Running this command will start the WinRM service. + +Do you want to continue? + + + This command cannot be used because the parameter does not match any properties on the ResourceURI.Check the input parameters and run your command. + + + This computer is configured to receive credentials from a remote client computer. + + + The {0} parameter cannot be used when the {1} parameter value is {2}. The {0} parameter can be used only when the {1} parameter value is {3}. + + + The configuration changes you made will only be effective after the WinRM service is restarted on {0}. + + + This command cannot be used from the current path. Move to root path of the provider using cd\ and run your command again. + + + This Windows PowerShell snap-in contains cmdlets (such as Get-WSManInstance and Set-WSManInstance) that are used by the Windows PowerShell host to manage WSMan operations. + + + This command cannot be used to remove the computer 'localhost' because it will always be connected. Give some other connected computer and run your command. + + + This command creates a new ClientCertificate item. + +Do you want to continue? + + + The RunAsPassword value cannot be removed. Remove the values for RunAsUser and RunAsPassword in PowerShell by calling the Clear-Item cmdlet with the value for -Path attribute equal to the value of RunAsUser. + + + Unable to create a drive with the specified root. The root path does not exist. + + + This command cannot be used because the parameter matches multiple properties on the ResourceURI.Check the input parameters and run your command. + + + diff --git a/src/Microsoft.WSMan.Management/resources/WsManResources.txt b/src/Microsoft.WSMan.Management/resources/WsManResources.txt new file mode 100644 index 000000000..7599a12ec --- /dev/null +++ b/src/Microsoft.WSMan.Management/resources/WsManResources.txt @@ -0,0 +1,68 @@ +# Copyright (c) 2008 Microsoft Corporation + +# {0} = Delegate + +Vendor=Microsoft +Description=This Windows PowerShell snap-in contains cmdlets (such as Get-WSManInstance and Set-WSManInstance) that are used by the Windows PowerShell host to manage WSMan operations. +InvalidComputerName=The WinRM client cannot complete the operation.Check if the computer name is valid. +InvalidFileName=This command cannot be used because file does not exist.Check the file existence and run your command. +InvalidPath=This command cannot be used because root path does not exist.Check the root path and run your command. +NoResourceMatch=This command cannot be used because the parameter does not match any properties on the ResourceURI.Check the input parameters and run your command. +MultipleResourceMatch=This command cannot be used because the parameter matches multiple properties on the ResourceURI.Check the input parameters and run your command. +NoAttributeMatch=This command cannot be used because the parameter matches a non-text property on the ResourceURI.Check the input parameters and run your command. +WinrmNotConfigured=This command cannot be used because the configuration is corrupted. Run WinRM invoke Restore WinRM/config to restore the default configuration +DelegateFreshCred=The machine is configured to allow delegating fresh credentials to the following target(s): +NoDelegateFreshCred=The machine is not configured to allow delegating fresh credentials. +LocalHost=This command cannot be used to remove the computer 'localhost' because it will always be connected. Give some other connected computer and run your command. +ConnectFailure=This command cannot be used from the current path. Move to root path of the provider using cd\\ and run your command again. +DisconnectFailure=This command cannot be used from the current path. Move to root path of the provider using cd\\ and run your command again. +value=This command cannot be used because Parameter Value is not supplied. Check the value again and run your command. +SetItemNotSupported=This command cannot be used in the current path because this cmdlet is not supported at this level of Provider path. +RemoveItemNotSupported=This command cannot be used in the current path because Remove-Item is not supported at this level of Provider path. +NewItemNotSupported=This command cannot be used in the current path because New-Item is not supported at this level of Provider path. +NoChangeValue=This command cannot set the input value because these values are Primary keys or Container items of the resource object. Change the input value and Run your command. +ConfigStorage=Root of WsMan Config Storage. +NewWSManSessionOptionCred=This command cannot be used without credential because the authentication algorithm is Basic or Digest. Use Credentials parameter to specify value and run your command. +NewWSManSessionOptionAuth=This command cannot be used without Basic or Digest authentication algorithm because credentials are specified.Use Basic or Digest authentication algorithm and run your command. +DriveRootError=This command cannot be used because WsMan drive root is not supported on this version of Windows OS. +ItemDoesNotExist=This command cannot be used because path does not exist.Check the path existence and run your command. +ErrorElevationNeeded=Access is denied. You need to run this cmdlet from an elevated process. +NewDriveRootDoesNotExist=Unable to create a drive with the specified root. The root path does not exist. +NotProperURI=This command cannot be executed because the Connection URI is not in correct format. Please check the connection uri and Run your command again. +WSManServiceStartCaption=Start WinRM Service +WSManServiceStartQuery=WinRM service is not started currently. Running this command will start the WinRM service.\n\nDo you want to continue? +WinRMServiceError=This command cannot be executed because the WinRM Service is not started. +SetItemShouldContinueCaption=Set the value of the item +SetItemShouldContinueQuery=This command set the value of the Item.\n\nDo you want to continue? +EnableCredSSPPolicyValidateError=This command cannot be executed because the setting cannot be enabled. +DisableCredSSPPolicyValidateError=This command cannot be executed because the setting cannot be disabled. +TrustedHostValueTypeError=Cannot convert 'System.Object[]' to the type 'System.String' required by the parameter. Specified method is not supported. +ShouldContinueSecurityCaption=Security Configuration for WinRM Plug-in. +ShouldContinueSecurityQuery=This command modifies the security settings on a resource in the following WinRM plug-in: {0}.\nDo you want to continue? +NewItemShouldContinueListenerCaption=Creates a new Listener item. +NewItemShouldContinueListenerQuery=This command creates a new Listener item.\n\nDo you want to continue? +NewItemShouldContinueClientCertCaption=Creates a new ClientCertificate item. +NewItemShouldContinueClientCertQuery=This command creates a new ClientCertificate item.\n\nDo you want to continue? +SetItemTrustedHostsWarningQuery=This command modifies the TrustedHosts list for the WinRM client. The computers in the TrustedHosts list might not be authenticated. The client might send credential information to these computers. Are you sure that you want to modify this list? +SetItemRootSDDLWarningQuery=This command modifies the RootSDDL setting for the WinRM service. The RootSDDL stores the default security settings for any WinRM securable resource that does not specify its own SDDL. Changing the SDDL might affect security for many WinRM resources. Are you sure that you want to modify these default settings? +SetItemGeneralSecurityCaption=WinRM Security Configuration. +ResourceURIMissingInResourceDir=Unable to find value for "{0}" element in the path {1}. +CredSSPContinueCaption=CredSSP Authentication Configuration for WS-Management +CredSSPContinueQuery=CredSSP authentication allows the user credentials on this computer to be sent to a remote computer. If you use CredSSP authentication for a connection to a malicious or compromised computer, that computer will have access to your user name and password. For more information, see the Enable-WSManCredSSP Help topic.\nDo you want to enable CredSSP authentication? +CredSSPServerContinueQuery=CredSSP authentication allows the server to accept user credentials from a remote computer. If you enable CredSSP authentication on the server, the server will have access to the user name and password of the client computer if the client computer sends them. For more information, see the Enable-WSManCredSSP Help topic. \nDo you want to enable CredSSP authentication? +CredSSPRoleAndDelegateCannotBeSpecified=The {0} parameter cannot be used when the {1} parameter value is {2}. The {0} parameter can be used only when the {1} parameter value is {3}. +CredSSPClientAndDelegateMustBeSpecified=The {0} parameter is mandatory when the {1} parameter value is {2}. +CredSSPServiceConfigured=This computer is configured to receive credentials from a remote client computer. +CredSSPServiceNotConfigured=This computer is not configured to receive credentials from a remote client computer. +QuickConfigContinueCaption=WinRM Quick Configuration +QuickConfigContinueQuery=Running the Set-WSManQuickConfig command has significant security implications, as it enables remote management through the WinRM service on this computer.\nThis command:\n 1. Checks whether the WinRM service is running. If the WinRM service is not running, the service is started.\n 2. Sets the WinRM service startup type to automatic.\n 3. Creates a listener to accept requests on any IP address. By default, the transport is HTTP.\n 4. Enables a firewall exception for WS-Management traffic.\n 5. Enables Kerberos and Negotiate service authentication.\nDo you want to enable remote management through the WinRM service on this computer? +AmbiguosAuthentication=A {0} cannot be specified when {1} is specified. +CmdletNotAvailable=This PowerShell cmdlet is not available on for Windows XP and Windows Server 2003. +InvalidValueType=This command cannot be used because the parameter value type is invalid. {0} configuration expects a value of Type {1}. Verify that the value is correct and try again. +ClearItemOnRunAsPassword=The RunAsPassword value cannot be removed. Remove the values for RunAsUser and RunAsPassword in PowerShell by calling the Clear-Item cmdlet with the value for -Path attribute equal to the value of RunAsUser. +SetItemOnRunAsPasswordNoRunAsUser=The value for RunAsPassword cannot be set without a value set for RunAsUser. Set the value for both RunAsUser and RunAsPassword in Powershell by calling the Set-Item cmdlet with the value for -Path attribute equal to the value of RunAsUser. +SetItemWhatIfAndConfirmText= "Set-Item" on the WinRM configuration setting "{0}" to update the value to "{1}" +SetItemWarnigForPPQ=The updated configuration is effective only if it is less than or equal to the value of global quota {0}. Verify the value for the global quota using the PowerShell cmdlet "Get-Item {0}". +SetItemWarningForGlobalQuota=The updated configuration might affect the operation of the plugins having a per plugin quota value greater than {0}. Verify the configuration of all the registered plugins and change the per plugin quota values for the affected plugins. +SetItemServiceRestartWarning= The configuration changes you made will only be effective after the WinRM service is restarted. To restart the WinRM service, run the following command: 'Restart-Service winrm' +SetItemServiceRestartWarningRemote= The configuration changes you made will only be effective after the WinRM service is restarted on {0}. \ No newline at end of file diff --git a/src/Microsoft.WSMan.Runtime/AssemblyInfo.cs b/src/Microsoft.WSMan.Runtime/AssemblyInfo.cs new file mode 100644 index 000000000..e55ec824d --- /dev/null +++ b/src/Microsoft.WSMan.Runtime/AssemblyInfo.cs @@ -0,0 +1,4 @@ +using System.Reflection; + +[assembly:AssemblyFileVersionAttribute("3.0.0.0")] +[assembly:AssemblyVersion("3.0.0.0")] diff --git a/src/Microsoft.WSMan.Runtime/WSManSessionOption.cs b/src/Microsoft.WSMan.Runtime/WSManSessionOption.cs new file mode 100644 index 000000000..19b05ca83 --- /dev/null +++ b/src/Microsoft.WSMan.Runtime/WSManSessionOption.cs @@ -0,0 +1,213 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +using System; +using System.IO; +using System.Xml; +using System.Net; +using System.Resources; +using System.Reflection; +using System.ComponentModel; + +using System.Collections; +using System.Collections.Generic; + +using System.Runtime.InteropServices; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + + + + + +[assembly: CLSCompliant(true)] +namespace Microsoft.WSMan.Management +{ + + /// + /// Session option class + /// + + public sealed class SessionOption + { + + /// + /// property + /// + public bool SkipCACheck + { + get { return _SkipCACheck; } + set + { + _SkipCACheck = value; + } + } + private bool _SkipCACheck; + + /// + /// property + /// + public bool SkipCNCheck + { + get { return _SkipCNCheck; } + set + { + _SkipCNCheck = value; + } + } + private bool _SkipCNCheck; + + /// + /// property + /// + /// + public bool SkipRevocationCheck + { + get { return _SkipRevocationCheck; } + set + { + _SkipRevocationCheck = value; + } + + } + private bool _SkipRevocationCheck; + + /// + /// property + /// + public bool UseEncryption + { + get { return _useencryption; } + set + { + _useencryption = value; + } + } + private bool _useencryption = true; + + /// + /// property + /// + public bool UseUtf16 + { + get { return _UTF16; } + set + { + _UTF16 = value; + } + } + private bool _UTF16; + + /// + /// property + /// + public ProxyAuthentication ProxyAuthentication + { + get { return _ProxyAuthentication; } + set + { + _ProxyAuthentication = value; + } + } + private ProxyAuthentication _ProxyAuthentication; + + /// + /// property + /// + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SPN")] + public int SPNPort + { + get { return _SPNPort; } + set + { + _SPNPort = value; + } + } + + private int _SPNPort; + + /// + /// property + /// + public int OperationTimeout + { + get { return _OperationTimeout; } + set + { + _OperationTimeout = value; + } + } + private int _OperationTimeout; + + /// + /// property + /// + public NetworkCredential ProxyCredential + { + get { return _ProxyCredential; } + set + { + _ProxyCredential = value; + } + } + private NetworkCredential _ProxyCredential; + + /// + /// property + /// + public ProxyAccessType ProxyAccessType + { + get { return _proxyaccesstype; } + set + { + _proxyaccesstype = value; + } + } + + private ProxyAccessType _proxyaccesstype; + } + + /// + /// property + /// + public enum ProxyAccessType + { + /// + /// property + /// + ProxyIEConfig = 0, + /// + /// property + /// + ProxyWinHttpConfig = 1, + /// + /// property + /// + ProxyAutoDetect = 2, + /// + /// property + /// + ProxyNoProxyServer = 3 + } + + /// + /// property + /// + [SuppressMessage("Microsoft.Design", "CA1027:MarkEnumsWithFlags")] + [SuppressMessage("Microsoft.Design", "CA1008:EnumsShouldHaveZeroValue")] + public enum ProxyAuthentication + { + /// + /// property + /// + Negotiate = 1, + /// + /// property + /// + Basic = 2, + /// + /// property + /// + Digest = 4 + } +} diff --git a/src/Microsoft.WSMan.Runtime/map.json b/src/Microsoft.WSMan.Runtime/map.json new file mode 100644 index 000000000..6c9d318c8 --- /dev/null +++ b/src/Microsoft.WSMan.Runtime/map.json @@ -0,0 +1,3 @@ +{ + "wmi/wmx/cmdlets/Runtime/WSManSessionOption.cs" : "WSManSessionOption.cs" +} \ No newline at end of file diff --git a/src/Microsoft.WSMan.Runtime/project.json b/src/Microsoft.WSMan.Runtime/project.json new file mode 100644 index 000000000..39294deba --- /dev/null +++ b/src/Microsoft.WSMan.Runtime/project.json @@ -0,0 +1,30 @@ +{ + "name": "Microsoft.WSMan.Runtime", + "version": "1.0.0-*", + + "buildOptions": { + "keyFile": "../signing/visualstudiopublic.snk", + "delaySign": true, + "publicSign": false, + "warningsAsErrors": true + }, + + "frameworks": { + "netstandard1.6": { + "imports": [ "dnxcore50" ], + "buildOptions": { + "define": [ "CORECLR" ] + }, + "dependencies": { + "NETStandard.Library": "1.6.0", + } + }, + "net451": { + "frameworkAssemblies": { + "System.Runtime": "", + "System.Xml": "", + "System.Data": "" + } + } + } +} diff --git a/test/fullclr/PowerShellGithubDev.Tests.ps1 b/test/fullclr/PowerShellGithubDev.Tests.ps1 index 2868d2b44..faab0a524 100644 --- a/test/fullclr/PowerShellGithubDev.Tests.ps1 +++ b/test/fullclr/PowerShellGithubDev.Tests.ps1 @@ -46,7 +46,7 @@ try } # this Describe makes sure we binplace all the files, like psd1, psm1, ps1xml and load usable modules from them - Describe 'Modules for the packge' { + Describe 'Modules for the package' { Context '$env:DEVPATH Modules loading' { It 'loads Microsoft.PowerShell.LocalAccounts' { try @@ -116,6 +116,8 @@ try { Import-Module CimCmdlets -ErrorAction Stop Get-CimClass -ClassName CIM_Error | Should Not Be $null + [Microsoft.Management.Infrastructure.CimCmdlets.AsyncResultType].Assembly.Location | Should Be ( + Join-Path $env:DEVPATH Microsoft.Management.Infrastructure.CimCmdlets.dll) } finally { @@ -123,6 +125,20 @@ try } } + It 'loads Microsoft.WSMan.Management' { + try + { + Import-Module Microsoft.WSMan.Management -ErrorAction Stop + Test-WSMan | Should Not Be $null + [Microsoft.WSMan.Management.TestWSManCommand].Assembly.Location | Should Be ( + Join-Path $env:DEVPATH Microsoft.WSMan.Management.dll) + } + finally + { + Remove-Module -ErrorAction SilentlyContinue Microsoft.WSMan.Management + } + } + It 'loads Microsoft.PowerShell.Diagnostics' { try {