Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > PowerShell передача параметров


Автор: RastaDja 4.8.2011, 13:32
   Доброго времени суток уважаемые форумчане.
   Долго думал - в какой раздел написать, решил сюда.
   Собственно проблема:
   Есть у меня класс в проекте WPF, который загружает элементы управления из файла (XML). Из этого же файла он загружает скрипты на PowerShell. Эти скрипты я записываю в Runspace своего PowerShell.
   У меня стоит задача, в скрипте получить доступ к данным элементов формы (например, прочитать текст из TextBox-ов), для этого я загружаю свои элементы на форму, создаю Runspace, в который загружаю свой скрипт, и в этот же Runspace передаю все контролы по именам - в качестве переменных.
   Вот псевдокод (без использования файла, только идея)
Код

using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace WpfApplication5
{
    public partial class TaskWnd : Window
    {
        readonly Runspace runspace;
                
        public TaskWnd( String path )
        {
            InitializeComponent();
            runspace = RunspaceFactory.CreateRunspace();
            runspace.RunspaceConfiguration.Scripts.Reset();
            // чтение файла конфигурации
            LoadConfig( path );
        }

        private void LoadConfig( String path )
        {
            String XAMLCode = "<Grid xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" \nxmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"><StackPanel><TextBox Name=\"textBox1\">Hello</TextBox><Button Content=\"button1\" Name=\"button1\"></Button><Button Content=\"button2\" Name=\"button2\"></Button></StackPanel></Grid>";
            //  добавляем элементы на форму
            UIElement rootElement;
            rootElement = (UIElement)XamlReader.Load(new XmlTextReader(new StringReader(XAMLCode)));
            this.UIContent.Children.Clear();
            this.UIContent.Children.Add(rootElement);

            // заполнение функциями 
            ScriptConfigurationEntry script = new ScriptConfigurationEntry("button2_Click", "$textBox1.Text");   //скрипт для обработки нажатия на кнопку
            runspace.RunspaceConfiguration.Scripts.Append(script);
            runspace.Open();

            //  Подключаем эти элементы к событиям
            ConnectObjectsToEvent(this);
           //  Добавляем эти элементы в Runspace PowerShell
            AddObjectsToRunspace(this);
        }

        private void AddObjectsToRunspace(FrameworkElement node)
        {
            System.Collections.IEnumerable allObj = LogicalTreeHelper.GetChildren(node);
            foreach (Object obj in allObj)
            {
                if (obj.GetType().ToString() == "System.Windows.Controls.Button")
                {
                    Button RefButton = (Button)obj;
                    runspace.SessionStateProxy.SetVariable(RefButton.Name, RefButton);
                }
                if (obj.GetType().ToString() == "System.Windows.Controls.TextBox")
                {
                    TextBox RefText = (TextBox)obj;
                    runspace.SessionStateProxy.SetVariable(RefText.Name, RefText);
                }
                try
                {
                    AddObjectsToRunspace((FrameworkElement)obj);
                }
                catch   //  исключение, если обьект не есть контейнером
                {
                }
            }
        }

        private void ConnectObjectsToEvent(DependencyObject node)
        {
            System.Collections.IEnumerable allObj = LogicalTreeHelper.GetChildren(node);
            foreach (Object obj in allObj)
            {
                if (obj.GetType().ToString() == "System.Windows.Controls.Button")
                {
                    Button RefButton = (Button)obj;
                    RefButton.Click += new RoutedEventHandler(all_Buttons_Click);
                }
                try
                {
                    ConnectObjectsToEvent((DependencyObject)obj);
                }
                catch   //  исключение, если обьект не есть контейнером
                {
                }
            }
        }

        //  общий обработчик для всех кнопок
        private void all_Buttons_Click(object sender, RoutedEventArgs e)
        {
            Button refButton = (Button)sender;
            string sFuncName = String.Format("{0}_{1}", refButton.Name, "Click");
            Pipeline pl = runspace.CreatePipeline(sFuncName);
            try
            {
                Collection<PSObject> objs = pl.Invoke();    //   <-----------  вот тут
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
}

   В коде стрелочкой обозначено, где я хочу получить данные из TextBox, но почему-то получаю Null, хотя точно знаю что поле не пустое. Также возникает исключение - cross thread - если я в скрипте пропишу что-то такое $button1.Content=\"hello\".
   Подскажите, что в коде не так? Правильно ли я передал переменные в Runspace. И как обойти проблемы с работой в разных потоках.
   Спасибо.

Автор: RastaDja 5.8.2011, 09:26
Ну подскажите. Может кто знает, почему я не могу обратится к объекту в скрипте? Как правильно работать?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)