예제 #1
0
        /// <summary>
        /// Proxy method for substitution of executing Initialize/Reset methods in adapter interface.
        /// </summary>
        /// <param name="mcall">The IMethodCallMessage containing method invoking data.</param>
        /// <param name="helpMessage">The help message from the attribute</param>
        /// <returns>Always void.</returns>
        private IMessage InvokeCompact(IMethodCallMessage mcall, string helpMessage)
        {
            string path = LookupScript(mcall.MethodName);

            if (path != null)
            {
                TestSite.Log.Add(LogEntryKind.EnterAdapter,
                                 "Power Shell adapter: {0}, method: {1}",
                                 ProxyType.Name,
                                 mcall.MethodName);

                try
                {
                    PSParameterBuilder builder = InvokeScript(path, null, helpMessage);
                    //should always return null
                    TestSite.Assert.IsNull(builder, "Compact mode should always return null");
                }
                catch (Exception ex)
                {
                    TestSite.Log.Add(LogEntryKind.Debug, ex.ToString());
                    throw;
                }
                finally
                {
                    TestSite.Log.Add(LogEntryKind.ExitAdapter,
                                     "Power Shell adapter: {0}, method: {1}",
                                     ProxyType.Name,
                                     mcall.MethodName);
                }
            }
            else
            {
                TestSite.Log.Add(LogEntryKind.Debug,
                                 "Power Shell adapter: {0}, method: {1} not found, skipped.",
                                 ProxyType.Name,
                                 mcall.MethodName);
            }
            ReturnMessage mret = new ReturnMessage(
                null,
                null,
                0,
                mcall.LogicalCallContext,
                mcall);

            return(mret);
        }
예제 #2
0
        private PSParameterBuilder SetPSVariables(
            IMethodCallMessage methodCall,
            Type sessionStateProxy,
            object proxyInstance,
            string helpMessage)
        {
            //get "SetVariable" method which will set all param as variable.
            MethodInfo methodSetVariable = sessionStateProxy.GetMethod(
                "SetVariable",
                BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod,
                null,
                new Type[] { typeof(string), typeof(object) },
                null
                );

            if (methodSetVariable == null)
            {
                throw new InvalidOperationException("Cannot get 'SetVariable' method from SessionStateProxy.");
            }

            //set all properties and help message as variable
            //which can be used in PowerShell script.
            //set help message as variable
            methodSetVariable.Invoke(proxyInstance, new object[] { "PtfHelpMessage", helpMessage });
            //set all properties as variables
            foreach (string key in this.TestSite.Properties.AllKeys)
            {
                string propName = "PTFProp" + key;
                methodSetVariable.Invoke(
                    proxyInstance,
                    new object[] { propName, this.TestSite.Properties[key] }
                    );
            }

            if (methodCall != null)
            {
                //set all parameters as variables which can be used
                //by users directly in the PowerShell script
                PSParameterBuilder builder = new PSParameterBuilder(methodCall);
                builder.SetAllParametersAsVariables(methodSetVariable, proxyInstance);

                return(builder);
            }

            return(null);
        }
        /// <summary>
        /// Proxy method for substitution of executing Initialize/Reset methods in adapter interface.
        /// </summary>
        /// <param name="targetMethod">The method the caller invoked.</param>
        /// <param name="helpMessage">The help message from the attribute</param>
        /// <returns>Always null.</returns>
        private object ExecuteMethodCompact(MethodInfo targetMethod, string helpMessage)
        {
            string path = LookupScript(targetMethod.Name);

            if (path != null)
            {
                TestSite.Log.Add(LogEntryKind.EnterAdapter,
                                 "PowerShell adapter: {0}, method: {1}",
                                 ProxyType.Name,
                                 targetMethod.Name);

                try
                {
                    PSParameterBuilder builder = InvokeScript(path, targetMethod, null, helpMessage);
                    //should always return null
                    TestSite.Assert.IsNull(builder, "Compact mode should always return null");
                }
                catch (Exception ex)
                {
                    TestSite.Log.Add(LogEntryKind.Debug, ex.ToString());
                    throw;
                }
                finally
                {
                    TestSite.Log.Add(LogEntryKind.ExitAdapter,
                                     "Power Shell adapter: {0}, method: {1}",
                                     ProxyType.Name,
                                     targetMethod.Name);
                }
            }
            else
            {
                TestSite.Log.Add(LogEntryKind.Debug,
                                 "Power Shell adapter: {0}, method: {1} not found, skipped.",
                                 ProxyType.Name,
                                 targetMethod.Name);
            }

            return(null);
        }
        /// <summary>
        /// Proxy method for substitution of executing methods in adapter interface.
        /// </summary>
        /// <param name="targetMethod">The method the caller invoked.</param>
        /// <param name="args">The arguments the caller passed to the method.</param>
        /// <returns>The return value of the ExecuteMethod implementation.</returns>
        protected override object ExecuteMethod(MethodInfo targetMethod, object[] args)
        {
            //get help message from attribute
            string methodhelp = AdapterProxyHelpers.GetHelpMessage(targetMethod);

            bool compactMode = ((targetMethod.Name == "Initialize" || targetMethod.Name == "Reset") &&
                                AdapterType.IsAdapterTypeFullName(targetMethod.DeclaringType.FullName)
                                );

            if (compactMode)
            {
                return(ExecuteMethodCompact(targetMethod, methodhelp));
            }

            object retVal = null;

            object[] outArgs = args;

            // Check if this is a method from IAdapter. Any IAdapter methods should be ignored.
            if (!AdapterType.IsAdapterTypeFullName(targetMethod.DeclaringType.FullName) &&
                (targetMethod.DeclaringType.FullName != typeof(IDisposable).FullName)
                )
            {
                TestSite.Log.Add(LogEntryKind.EnterAdapter,
                                 "PowerShell adapter: {0}, method: {1}",
                                 ProxyType.Name,
                                 targetMethod.Name);

                try
                {
                    string path = LookupScript(targetMethod.Name);
                    if (path == null)
                    {
                        TestSite.Assume.Fail(
                            "PowerShell script file ({0}.ps1) can not be found.",
                            targetMethod.Name);
                    }
                    else
                    {
                        PSParameterBuilder builder = InvokeScript(path, targetMethod, args, methodhelp);
                        if (builder != null)
                        {
                            retVal = builder.RetValue;

                            if (builder.OutArguments != null)
                            {
                                int argsIndex    = 0;
                                int outArgsIndex = 0;
                                foreach (ParameterInfo pi in targetMethod.GetParameters())
                                {
                                    if (pi.ParameterType.IsByRef)
                                    {
                                        outArgs[argsIndex] = builder.OutArguments[outArgsIndex++];
                                    }
                                    argsIndex++;
                                }
                            }

                            //clear builder
                            builder = null;
                        }
                    }
                }
                catch (Exception ex)
                {
                    TestSite.Log.Add(LogEntryKind.Debug, ex.ToString());
                    throw;
                }
                finally
                {
                    TestSite.Log.Add(LogEntryKind.ExitAdapter,
                                     "PowerShell adapter: {0}, method: {1}",
                                     ProxyType.Name,
                                     targetMethod.Name);
                }
            }

            return(retVal);
        }
        /// <summary>
        /// Invokde script by given file path and arguments.
        /// </summary>
        /// <param name="path">The file path to the cmd script.</param>
        /// <param name="targetMethod">The method the caller invoked.</param>
        /// <param name="args">The argument to be passed to the script.</param>
        /// <param name="helpMessage">The help message from the attribute.</param>
        /// <returns>The return value of script executation.</returns>
        private PSParameterBuilder InvokeScript(string path, MethodInfo targetMethod, object[] args, string helpMessage)
        {
            //the patameter builder to handle all parameters
            PSParameterBuilder builder = null;

            //use the Dot operation in PowerShell to make all variables can be accessed in whole runspace.
            string scriptContent = string.Format(". \"{0}\"", Path.GetFullPath(path));

            //call static method, and create the instance of runspace type
            Runspace runspace = RunspaceFactory.CreateRunspace();

            //open run space
            runspace.Open();

            //call runspace.CreatePipeline to create an instance of Pipeline
            Pipeline pipeline = runspace.CreatePipeline();

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                //set execution policy for Windows in order to load and run local script files
                pipeline.Commands.AddScript("Set-ExecutionPolicy -Scope Process RemoteSigned");
            }

            pipeline.Commands.AddScript(scriptContent);

            SessionStateProxy sessionStateProxy = runspace.SessionStateProxy;

            //set current location to the folder containing the script
            sessionStateProxy.Path.SetLocation(Path.GetDirectoryName(path));
            //set variables which can be used in PowerShell script
            SetPTFVariables(sessionStateProxy);

            //set all parameters as variables which can be used
            //by users directly in the PowerShell script
            builder = new PSParameterBuilder(targetMethod);
            builder.SetAllParametersAsVariables(sessionStateProxy, args, helpMessage);

            try
            {
                if (builder != null)
                {
                    //invoke script and get the return value and out/ref parameters
                    if (builder.HasRetValue)
                    {
                        Collection <PSObject> returnValueCollection = pipeline.Invoke();

                        //get return value object
                        KeyValuePair <string, object> retValue = GetRetValueFromCollection(returnValueCollection);

                        if (retValue.Value != null)
                        {
                            if (builder.RetType.IsInstanceOfType(retValue.Value))
                            {
                                builder.RetValue = retValue.Value;
                            }
                            else
                            {
                                throw new InvalidOperationException("The returned type is mismatched");
                            }
                        }
                        else
                        {
                            builder.RetValue = null;
                        }
                    }
                    else
                    {
                        pipeline.Invoke();
                    }

                    //get out parameters values
                    builder.GetAllOutParameterValues(
                        sessionStateProxy,
                        targetMethod.GetParameters().Length);
                }
                else
                {
                    pipeline.Invoke();
                }

                //check errors in the error pipeline
                CheckErrorsInPipeline(pipeline);
            }
            catch (RuntimeException ex)
            {
                string errorMessage        = ex.Message;
                string traceInfo           = ex.ErrorRecord.InvocationInfo.PositionMessage;
                string ptfAdFailureMessage = string.Format(
                    "Exception thrown in PowerShell Adapter: {0} {1}", errorMessage, traceInfo);
                throw new InvalidOperationException(ptfAdFailureMessage);
            }

            //close runspace and release resources
            runspace.Close();

            return(builder);
        }
예제 #6
0
        //use reflection to invoke PowerShell script via APIs in System.Management.Automation.dll
        private PSParameterBuilder InvokeScript(string path, IMethodCallMessage methodCall, string helpMessage)
        {
            //the patameter builder to handle all parameters
            PSParameterBuilder builder             = null;
            Assembly           sysMgmtAutoAssembly = null;

            try
            {
                sysMgmtAutoAssembly = Assembly.Load(PSConstant.SystemManagementAutomationAssemblyNameV3);
            }
            catch { }
            // If loading System.Management.Automation, Version=3.0.0.0 failed, try Version=1.0.0.0
            if (sysMgmtAutoAssembly == null)
            {
                try
                {
                    sysMgmtAutoAssembly = Assembly.Load(PSConstant.SystemManagementAutomationAssemblyNameV1);
                }
                catch
                {
                    throw new InvalidOperationException("Can not find system management automation assembly from GAC." +
                                                        "Please make sure your PowerShell installation is valid." +
                                                        "Or you need to reinstall PowerShell.");
                }
            }

            if (sysMgmtAutoAssembly != null)
            {
                //use the Dot operation in PowerShell to make all variables can be accessed in whole runspace.
                string scriptContent = string.Format(". \"{0}\"", Path.GetFullPath(path));

                BindingFlags flag = BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod;

                //call static method, and create the instance of runspace type
                Type runspaceFactory =
                    GetPSType(sysMgmtAutoAssembly, "System.Management.Automation.Runspaces.RunspaceFactory");

                object runspaceInstance = runspaceFactory.InvokeMember(
                    "CreateRunspace", BindingFlags.InvokeMethod, null, null, null);

                //open run space
                Type runspace =
                    GetPSType(sysMgmtAutoAssembly, "System.Management.Automation.Runspaces.Runspace");

                runspace.InvokeMember("Open", flag, null, runspaceInstance, null);

                //call runspace.CreatePipeline to create an instance of Pipeline
                Type pipeline =
                    GetPSType(sysMgmtAutoAssembly, "System.Management.Automation.Runspaces.Pipeline");

                object pipelineInstance = runspace.InvokeMember(
                    "CreatePipeline", flag, null, runspaceInstance, null);

                //get the Commands property of the pipeline instance
                object commandsInstance = pipeline.InvokeMember(
                    "Commands", BindingFlags.GetProperty, null, pipelineInstance, null);

                //add commands to invoke script
                Type commands =
                    GetPSType(sysMgmtAutoAssembly, "System.Management.Automation.Runspaces.CommandCollection");

                commands.InvokeMember(
                    "AddScript", flag, null, commandsInstance, new object[] { scriptContent });

                //get "SessionStateProxy" instance from runspace
                Type sessionStateProxy =
                    GetPSType(sysMgmtAutoAssembly, "System.Management.Automation.Runspaces.SessionStateProxy");

                object proxyInstance = runspace.InvokeMember(
                    "SessionStateProxy",
                    BindingFlags.GetProperty,
                    null,
                    runspaceInstance,
                    null);

                //set variables which can be used in PowerShell script
                builder = SetPSVariables(methodCall, sessionStateProxy, proxyInstance, helpMessage);

                try
                {
                    if (builder != null)
                    {
                        //invoke script and get the return value and out/ref parameters
                        if (builder.HasRetValue)
                        {
                            object returnValueCollection =
                                pipeline.InvokeMember("Invoke", flag, null, pipelineInstance, null);
                            Type psObject =
                                GetPSType(sysMgmtAutoAssembly, "System.Management.Automation.PSObject");

                            //get return value object
                            KeyValuePair <string, object> retValue =
                                this.GetRetValueFromCollection(returnValueCollection, psObject);

                            if (retValue.Value != null)
                            {
                                if (builder.RetType.IsInstanceOfType(retValue.Value))
                                {
                                    builder.RetValue = retValue.Value;
                                }
                                else
                                {
                                    throw new InvalidOperationException("The returned type is mismatched");
                                }
                            }
                            else
                            {
                                builder.RetValue = null;
                            }
                        }
                        else
                        {
                            pipeline.InvokeMember("Invoke", flag, null, pipelineInstance, null);
                        }

                        //get out parameters values
                        builder.GetAllOutParameterValues(
                            sysMgmtAutoAssembly,
                            sessionStateProxy,
                            proxyInstance,
                            methodCall.MethodBase.GetParameters().Length);
                    }
                    else
                    {
                        pipeline.InvokeMember("Invoke", flag, null, pipelineInstance, null);
                    }

                    //check errors in the error pipeline
                    CheckErrorsInPipeline(sysMgmtAutoAssembly, pipeline, pipelineInstance);
                }
                catch (TargetInvocationException ex)
                {
                    string    innerException = string.Empty;
                    string    traceInfo      = string.Empty;
                    Exception e = ex as Exception;
                    if (null != e.InnerException)
                    {
                        innerException = e.InnerException.Message;
                        traceInfo      = GetPSScriptPositionMessage(sysMgmtAutoAssembly, e.InnerException);
                    }
                    string ptfAdFailureMessage = string.Format(
                        "Exception thrown. InnerException: {0} {1}", innerException, traceInfo);
                    throw new InvalidOperationException(ptfAdFailureMessage);
                }

                //close runspace and release resources
                runspace.InvokeMember("Close", flag, null, runspaceInstance, null);
            }
            else
            {
                throw new InvalidOperationException("Can not find system management automation assembly from GAC." +
                                                    "Please make sure your PowerShell installation is valid." +
                                                    "Or you need to reinstall PowerShell.");
            }

            return(builder);
        }
예제 #7
0
        protected override IMessage Invoke(IMethodCallMessage methodCall)
        {
            //get help message from attribute
            string methodhelp = AdapterProxyHelpers.GetHelpMessage(methodCall);

            bool compactMode = ((methodCall.MethodName == "Initialize" || methodCall.MethodName == "Reset") &&
                                AdapterType.IsAdapterTypeFullName(methodCall.MethodBase.DeclaringType.FullName)
                                );

            if (compactMode)
            {
                return(InvokeCompact(methodCall, methodhelp));
            }

            object retVal = null;

            object[] outArgs = methodCall.Args;

            // Check if this is a method from IAdapter. Any IAdapter methods should be ignored.
            if (!AdapterType.IsAdapterTypeFullName(methodCall.MethodBase.DeclaringType.FullName) &&
                (methodCall.MethodBase.DeclaringType.FullName != typeof(IDisposable).FullName)
                )
            {
                TestSite.Log.Add(LogEntryKind.EnterAdapter,
                                 "Power Shell adapter: {0}, method: {1}",
                                 ProxyType.Name,
                                 methodCall.MethodName);

                try
                {
                    string path = LookupScript(methodCall.MethodName);
                    if (path == null)
                    {
                        TestSite.Assume.Fail(
                            "PowerShell script file ({0}.ps1) can not be found.",
                            methodCall.MethodName);
                    }
                    else
                    {
                        PSParameterBuilder builder = InvokeScript(path, methodCall, methodhelp);
                        if (builder != null)
                        {
                            retVal = builder.RetValue;

                            if (builder.OutArguments != null)
                            {
                                int argsIndex    = 0;
                                int outArgsIndex = 0;
                                foreach (ParameterInfo pi in methodCall.MethodBase.GetParameters())
                                {
                                    if (pi.ParameterType.IsByRef)
                                    {
                                        outArgs[argsIndex] = builder.OutArguments[outArgsIndex++];
                                    }
                                    argsIndex++;
                                }
                            }

                            //clear builder
                            builder = null;
                        }
                    }
                }
                catch (Exception ex)
                {
                    TestSite.Log.Add(LogEntryKind.Debug, ex.ToString());
                    throw;
                }
                finally
                {
                    TestSite.Log.Add(LogEntryKind.ExitAdapter,
                                     "Power Shell adapter: {0}, method: {1}",
                                     ProxyType.Name,
                                     methodCall.MethodName);
                }
            }

            ReturnMessage mret = new ReturnMessage(
                retVal,
                (outArgs != null && outArgs.Length > 0) ? outArgs : null,
                (outArgs != null) ? outArgs.Length : 0,
                methodCall.LogicalCallContext,
                methodCall);

            return(mret);
        }
        private PSParameterBuilder SetPSVariables(
            IMethodCallMessage methodCall,
            Type sessionStateProxy,
            object proxyInstance,
            string helpMessage)
        {
            //get "SetVariable" method which will set all param as variable.
            MethodInfo methodSetVariable = sessionStateProxy.GetMethod(
                "SetVariable",
                BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod,
                null,
                new Type[] { typeof(string), typeof(object) },
                null
                );

            if (methodSetVariable == null)
            {
                throw new InvalidOperationException("Cannot get 'SetVariable' method from SessionStateProxy.");
            }

            //set all properties and help message as variable
            //which can be used in PowerShell script.
            //set help message as variable
            methodSetVariable.Invoke(proxyInstance, new object[] { "PtfHelpMessage", helpMessage });
            //set all properties as variables
            foreach (string key in this.TestSite.Properties.AllKeys)
            {
                string propName = "PTFProp" + key;
                methodSetVariable.Invoke(
                    proxyInstance,
                    new object[] { propName, this.TestSite.Properties[key] }
                    );
            }

            if (methodCall != null)
            {
                //set all parameters as variables which can be used
                //by users directly in the PowerShell script
                PSParameterBuilder builder = new PSParameterBuilder(methodCall);
                builder.SetAllParametersAsVariables(methodSetVariable, proxyInstance);

                return builder;
            }

            return null;
        }
        /// <summary>
        /// Proxy method for substitution of executing methods in adapter interface.
        /// </summary>
        /// <param name="targetMethod">The method the caller invoked.</param>
        /// <param name="args">The arguments the caller passed to the method.</param>
        /// <returns>The return value of the ExecuteMethod implementation.</returns>
        protected override object ExecuteMethod(MethodInfo targetMethod, object[] args)
        {
            //get help message from attribute
            string methodhelp = AdapterProxyHelpers.GetHelpMessage(targetMethod);

            bool compactMode = ((targetMethod.Name == "Initialize" || targetMethod.Name == "Reset") &&
                                AdapterType.IsAdapterTypeFullName(targetMethod.DeclaringType.FullName)
                                );

            if (compactMode)
            {
                return(ExecuteMethodCompact(targetMethod, methodhelp));
            }

            object retVal = null;

            object[] outArgs = args;

            // Check if this is a method from IAdapter. Any IAdapter methods should be ignored.
            if (!AdapterType.IsAdapterTypeFullName(targetMethod.DeclaringType.FullName) &&
                (targetMethod.DeclaringType.FullName != typeof(IDisposable).FullName)
                )
            {
                TestSite.Log.Add(LogEntryKind.EnterAdapter,
                                 "PowerShell adapter: {0}, method: {1}",
                                 ProxyType.Name,
                                 targetMethod.Name);

                try
                {
                    string path = LookupScript(targetMethod.Name);
                    if (path == null)
                    {
                        TestSite.Assume.Fail(
                            "PowerShell script file ({0}.ps1) can not be found.",
                            targetMethod.Name);
                    }
                    else
                    {
                        int timeout = AdapterProxyHelpers.GetTimeout(targetMethod, int.Parse(TestSite.Properties["AdapterInvokeTimeout"]));
                        Task <PSParameterBuilder> invokeTask = Task.Run <PSParameterBuilder>(() =>
                        {
                            TestSite.Log.Add(LogEntryKind.Debug, $"Start to invoke Script {targetMethod.Name}.ps1, timeout: {timeout}");
                            var invokeResult = InvokeScript(path, targetMethod, args, methodhelp);
                            TestSite.Log.Add(LogEntryKind.Debug, $"Complete execute Script {targetMethod.Name}.ps1");
                            return(invokeResult);
                        });

                        TimeSpan waiter = TimeSpan.FromMinutes(timeout);

                        if (invokeTask.Wait(waiter))
                        {
                            PSParameterBuilder resultBuilder = invokeTask.Result;
                            if (resultBuilder != null)
                            {
                                retVal = resultBuilder.RetValue;

                                if (resultBuilder.OutArguments != null)
                                {
                                    int argsIndex    = 0;
                                    int outArgsIndex = 0;
                                    foreach (ParameterInfo pi in targetMethod.GetParameters())
                                    {
                                        if (pi.ParameterType.IsByRef)
                                        {
                                            outArgs[argsIndex] = resultBuilder.OutArguments[outArgsIndex++];
                                        }
                                        argsIndex++;
                                    }
                                }

                                //clear builder
                                resultBuilder = null;
                            }
                        }
                        else
                        {
                            throw new TimeoutException($"Invoke adapater method timeout after wait {timeout} minutes.");
                        }
                    }
                }
                catch (Exception ex)
                {
                    TestSite.Log.Add(LogEntryKind.Debug, ex.ToString());
                    throw;
                }
                finally
                {
                    TestSite.Log.Add(LogEntryKind.ExitAdapter,
                                     "PowerShell adapter: {0}, method: {1}",
                                     ProxyType.Name,
                                     targetMethod.Name);
                }
            }

            return(retVal);
        }