// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#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;
}
///
/// namespace
///
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
}
}