Привязка вывода из сценария powershell к gridview в asp. net c# - PullRequest
2 голосов
/ 27 февраля 2020

Я очень новичок в c#, и я ожидаю, что я пытаюсь сделать это довольно просто - я sh, но я не могу найти или следовать другим примерам, где вывод из массива powershell заполняет gridview для дальнейшей манипуляции / выполнения другого скрипта. Процесс загрузки страницы заключается в запуске сценария powershell, который создает массив деталей сеанса, которые заполняют сетку. Затем может быть запущен второй сценарий для взаимодействия с этим сеансом (например, принудительное завершение сеанса) путем выбора строки сетки.

Используя другие примеры, мне удалось инициировать первое выполнение powershell, которое выбрасывает данные в форму через:

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="PowerShellExecution.Default" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
     <div>
           <h1>PowerShell Harness<asp:Label ID="Label1" runat="server" Text="Label" Visible="False"></asp:Label>
           </h1>
           <asp:TextBox ID="ResultBox" TextMode="MultiLine" Width="1000px" Height="400px" runat="server"></asp:TextBox>
    </div>
</asp:Content>

CodeBehind

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Management.Automation;
using System.Text;

namespace PowerShellExecution
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
          // Gets the name if authenticated.
                if (User.Identity.IsAuthenticated)
                    Label1.Text = User.Identity.Name;
                else
                    Label1.Text = "No user identity available.";

            // Clean the Result TextBox
            ResultBox.Text = string.Empty;

            // Initialize PowerShell engine
            var shell = PowerShell.Create();

            // Add the script to the PowerShell object
            // shell.Commands.AddScript(Input.Text);
            // shell.Commands.AddScript("D:\\Local_Scripts\\sessioncall.ps1");
            shell.Commands.AddCommand("c:\\Local_Scripts\\sessioncall.ps1");

            // Add Params
            // shell.Commands.AddParameter(null,User.Identity.Name);
            // shell.Commands.AddParameter("Username", Label1.Text);
            shell.Commands.AddArgument(User.Identity.Name);

            // Execute the script
            var results = shell.Invoke();

            // display results, with BaseObject converted to string
            // Note : use |out-string for console-like output
            if (results.Count > 0)
            {
                // We use a string builder ton create our result text
                var builder = new StringBuilder();

                foreach (var psObject in results)
                {
                    // Convert the Base Object to a string and append it to the string builder.
                    // Add \r\n for line breaks
                    builder.Append(psObject.BaseObject.ToString() + "\r\n");
                }

                // Encode the string in HTML (prevent security issue with 'dangerous' caracters like < >
                ResultBox.Text = Server.HtmlEncode(builder.ToString());
            }

        }
    }
}

Sessioncall.ps1

$SessionUser = "$($args[0])"
set-brokersite -AdminAddress UKSite 
$a = @(Get-BrokerSession -BrokeringUserName $SessionUser | Select-Object UserFullName, BrokeringTime, ClientName,DesktopGroupName, sessionstate, uid, machinename,@{Name='ENV';Expression={'UK'}})
#Pull US Sessions into array
Set-brokersite -AdminAddress USSite
$a += @(Get-BrokerSession -BrokeringUserName $SessionUser | Select-Object UserFullName, BrokeringTime, ClientName,DesktopGroupName, sessionstate, uid, machinename,@{Name='ENV';Expression={'US'}})

If ($a -ne $null){
    Write-Output $a | out-string
}
Else {
    Write-Output "No User session! Username was $SessionUser"
}

В настоящее время выходные данные выбрасываются в текстовое поле в виде строки. Я изо всех сил пытаюсь понять, как начать привязку данных к выводу массива в виде строк в виде сетки. Просто нужно немного руки, чтобы начать это!

Заранее спасибо! Пол.

Ответы [ 2 ]

0 голосов
/ 28 февраля 2020

Большое спасибо за руководство. Gridview теперь заполняется.

    protected void Page_Load(object sender, EventArgs e)
    {
      // Gets the name if authenticated.
            if (User.Identity.IsAuthenticated)
                Label1.Text = User.Identity.Name;
            else
                Label1.Text = "No user identity available.";

        // Clean the Result TextBox

        // Initialize PowerShell engine
        var shell = PowerShell.Create();

        // Add the script to the PowerShell object
        // shell.Commands.AddScript(Input.Text);
        // shell.Commands.AddScript("D:\\Local_Scripts\\sessioncall.ps1");
        shell.Commands.AddCommand("c:\\Local_Scripts\\sessioncall.ps1");

        // Add Params
        // shell.Commands.AddParameter(null,User.Identity.Name);
        // shell.Commands.AddParameter("Username", Label1.Text);
        shell.Commands.AddArgument(User.Identity.Name);

        // Execute the script
        var results = shell.Invoke();

        // display results, with BaseObject converted to string
        // Note : use |out-string for console-like output
        if (results.Count > 0)
        {
            // We use a string builder ton create our result text
            var results2 = shell.Invoke();
            foreach (var psObject in results)
            {
                // Convert the Base Object to a string and append it to the string builder.
                // Add \r\n for line breaks
                var UserFullName = (psObject.Members["UserFullName"]);
                var BrokeringTime = (psObject.Members["BrokeringTime"]);
                var ClientName = (psObject.Members["ClientName"]);
                var DesktopGroupName = (psObject.Members["DesktopGroupName"]);
                var SessionState = (psObject.Members["SessionState"]);
                var Uid = (psObject.Members["Uid"]);
                var MachineName = (psObject.Members["MachineName"]);
                var ENV = (psObject.Members["ENV"]);
                // builder.Append(psObject.BaseObject.ToString() + "\r\n");
            }

            this.ResultGrid.DataSource = results2;
            this.ResultGrid.DataBind();
        }

        }

Возвращает [! [Введите описание изображения здесь] [1]] [1]

Однако этот метод выдает ошибку исключения, когда вы затем определяете имя ключа данных.

<asp:GridView ID="ResultGrid" runat="server" DataKeyNames="uid" AutoGenerateColumns="False" OnSelectedIndexChanged="ResultGrid_SelectedIndexChanged">
                <Columns>
                     <asp:buttonfield buttontype="Button" 
                 commandname="Select"
                 headertext="View" 
                 text="View"/>
                    <asp:BoundField DataField="UserFullName" HeaderText="UserFullName" />
                    <asp:BoundField DataField="BrokeringTime" HeaderText="BrokeringTime"  />
                    <asp:BoundField DataField="ClientName" HeaderText="ClientName"  />
                    <asp:BoundField DataField="DesktopGroupName" HeaderText="DesktopGroupName" />
                    <asp:BoundField DataField="SessionState" HeaderText="SessionState"  />
                    <asp:BoundField DataField="Uid" HeaderText="Uid"  />
                    <asp:BoundField DataField="MachineName" HeaderText="MachineName"  />
                    <asp:BoundField DataField="ENV" HeaderText="ENV"  />
                </Columns>
            </asp:GridView>

код позади

 protected void ResultGrid_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Determine the RowIndex of the Row whose Button was clicked.
            //int rowIndex = ((sender as Button).NamingContainer as GridViewRow).RowIndex;
            String key = ResultGrid.SelectedDataKey.Value.ToString();
            //Get the value of column from the DataKeys using the RowIndex.
            //int id = Convert.ToInt32(ResultGrid.DataKeys[rowIndex].Values[01]);
            //  Response.Write("IM_RAA_657x_Date.aspx?Day=" + ResultGrid.SelectedDataKey.Value(0) + "&BusinessCategory=" + ResultGrid.SelectedDataKey.Values(1).ToString())
        }

Это приводит к ошибке исключения в

this.ResultGrid.DataBind ();

"System.Web. HttpException: 'DataBinding:' System.Management.Automation.PSObject 'не содержит свойство с именем' uid '.' "

Мне не ясно, является ли метод в настоящее время проблемой или что-то вне который. Я в замешательстве, так как он должен видеть внутри PSObjects правильно, чтобы переменные были определены и заполнить gridview ?! Хм.

Ух ты; ХОРОШО; Я только что понял, что весь этот раздел игнорируется! Дело в точке; это можно закомментировать! Так что четко отрегулируйте вывод скрипта powershell!

 foreach (var psObject in results)
                {
                    // Convert the Base Object to a string and append it to the string builder.
                    // Add \r\n for line breaks
                    //var UserFullName = (psObject.Members["UserFullName"]);
                    //var BrokeringTime = (psObject.Members["BrokeringTime"]);
                    //var ClientName = (psObject.Members["ClientName"]);
                    //var DesktopGroupName = (psObject.Members["DesktopGroupName"]);
                    //var SessionState = (psObject.Members["SessionState"]);
                    //var Uid = (psObject.Members["Uid"]);
                    //var MachineName = (psObject.Members["MachineName"]);
                    //var ENV = (psObject.Members["ENV"]);
                    // builder.Append(psObject.BaseObject.ToString() + "\r\n");
                }

Простите, но я почти у цели!

r => new MyClass
                        {
                            UserFullName = (string)r.Properties["UserFullName"].Value,
                            BrokeringTime = (DateTime)r.Properties["BrokeringTime"].Value,
                            ClientName = (string)r.Properties["ClientName"].Value,
                            DesktopGroupName = (string)r.Properties["DesktopGroupName"].Value,
                            //SessionState = (string)r.Properties["SessionState"].Value,
                            Uid = (Int64)r.Properties["Uid"].Value,
                            //MachineName = (string)r.Properties["MachineName"].Value,
                            //ENV = (string)r.Properties["ENV"].Value,
                        }
                    );
                this.ResultGrid.DataSource = objects;
                this.ResultGrid.DataBind();
            }

            }

        protected void ResultGrid_SelectedIndexChanged(object sender, EventArgs e)
        {

            Response.Write(ResultGrid.SelectedValue.ToString());

        }
    }

    internal class MyClass
    {
        public string UserFullName { get; set; }
        public DateTime BrokeringTime { get; set; }
        public string ClientName { get; set; }
        public string DesktopGroupName { get; set; }
        public String SessionState { get; set; }
        public Int64 Uid { get; set; }
        public string MachineName { get; set; }
        public string ENV { get; set; }
    }

Итак, теперь я правильно заполняю gridview; Некоторые столбцы по-прежнему проблематичны c и не обрабатываются как строки, НО я почти там!

Похоже на тип Get-member:

BrokeringTime    NoteProperty datetime BrokeringTime=28/02/2020 06:56:39 
ClientName       NoteProperty string ClientName=clientname           
DesktopGroupName NoteProperty string DesktopGroupName=desktopgroupname
ENV              NoteProperty System.String ENV=UK                       
MachineName      NoteProperty string MachineName=machinename  
SessionState     NoteProperty SessionState SessionState=Active           
Uid              NoteProperty long Uid=12345678                           
UserFullName     NoteProperty string UserFullName=username  

C# Кажется нравится system.string.

0 голосов
/ 28 февраля 2020

Прошло много времени с тех пор, как я баловался с WebForms, но я нашел способ сделать то, что вам нужно ...

Прежде всего, давайте немного изменим ваш скрипт PowerShell. Вместо того, чтобы возвращать строку (что делает | out-string), мы можем просто вернуть объекты. Метод shell.Invoke() в коде C# знает, как извлечь полноценные объекты из выходных данных сценария, поэтому нам не нужно сериализовать строку в сценарии PowerShell, а затем попытаться снова десериализовать ее обратно в объекты. внутри нашего C# кода.

Не обращая внимания на логику вашей бизнес-сферы c на минуту, мой скрипт просто возвращает массив PSCustomObjects и выглядит так:

MyScript.ps1

write-output @(
    (new-object PSCustomObject -Property ([ordered] @{
         "MyProperty1" = "MyValue1.1"
         "MyProperty2" = "MyValue2.1"
         "MyProperty3" = "MyValue3.1"
    })),
    (new-object PSCustomObject -Property ([ordered] @{
          "MyProperty1" = "MyValue1.2"
          "MyProperty2" = "MyValue2.2"
          "MyProperty3" = "MyValue3.2"
    }))
);

Теперь мой метод C# Page_Load делает это:

Default.aspx.cs

protected void Page_Load(object sender, EventArgs e)
{

    // Initialize PowerShell engine
    var powershell = PowerShell.Create();

    // Add the script to the PowerShell object
    var script = "c:\\temp\\MyScript.ps1";
    powershell.Commands.AddCommand(script);

    // Execute the script
    var results = powershell.Invoke();

    ...

и results содержит System.Collections.ObjectModel.Collection<PSObject>. Мы не можем связать это напрямую с GridView, потому что свойства спрятаны в парах ключ-значение в Properties элементе каждого PSObject, но если мы создадим новый класс, довольно легко извлечь значения в нечто, что мы может привязка данных:

MyClass.cs

public class MyClass
{
    public string MyProperty1 { get; set; }
    public string MyProperty2 { get; set; }
    public string MyProperty3 { get; set; }
}

и наш Page_Load может преобразовывать объекты PSObject в экземпляры этого класса:

Default.aspx.cs

    ...

    var objects = results.Select(
        r => new MyClass
        {
            MyProperty1 = (string)r.Properties["MyProperty1"].Value,
            MyProperty2 = (string)r.Properties["MyProperty2"].Value,
            MyProperty3 = (string)r.Properties["MyProperty3"].Value,
        }
    );

    this.ResultGrid.DataSource = objects;
    this.ResultGrid.DataBind();

}

Затем для отображения данных вам просто необходим GridView, добавленный в ваш Default.aspx с любыми столбцами и форматированием, которые вы хотите определить:

Default.aspx

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
     <div>
           <h1>PowerShell Harness<asp:Label ID="Label1" runat="server" Text="Label" Visible="False"></asp:Label></h1>
            <asp:GridView ID="ResultGrid" runat="server" AutoGenerateColumns="false">
                <Columns>
                    <asp:BoundField DataField="MyProperty1" HeaderText="My Property 1" />
                    <asp:BoundField DataField="MyProperty2" HeaderText="My Property 2"  />
                    <asp:BoundField DataField="MyProperty3" HeaderText="My Property 3"  />
                </Columns>
            </asp:GridView>
    </div>
</asp:Content>

Запустите это, и вы должны увидеть что-то подобное на странице:

ASP.Net page with GridView bound from a PowerShell script

Примечание

Возможно, ваш командлет Get-BrokerSession возвращает коллекцию объекта определенного типа c уже, а не PSCustomObject, и в этом случае вы могли бы пропустите шаг преобразования и привязайте данные непосредственно к объекту results, чтобы вы возможно, придется поиграть с этим, чтобы увидеть. Надеюсь, что приведенное выше даст вам несколько советов, если есть какие-либо различия.

Надеюсь, это поможет.

...