简体   繁体   English

在 PS 脚本中将 powershell 变量传递给 C# 代码

[英]passing powershell variables to C# code within PS script

I read a lot about passing vars from C# to powershell script but i am interesten in the other way around.我阅读了很多关于将变量从 C# 传递到 powershell 脚本的内容,但我对其他方式感兴趣。

here I have this code to create a Type in my powershell script:在这里,我有这段代码可以在我的 powershell 脚本中创建一个类型:

Add-Type @'

public class Node
{

    public string Type;
    public string VM_Name;
    public string VM_IP;
    public string Hostname;

}
'@

$vm1 = New-Object Node
$vm2 = New-Object Node
$vm3 = New-Object Node
$vm4 = New-Object Node

After this code I have C# code:在这段代码之后,我有 C# 代码:

$sourceCode = @'


public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void InitializeComponent()
    {
    }
}

'@

How I might be able to access $vm1,2,3,4 in the C# code above ?我如何才能在上面的 C# 代码中访问 $vm1,2,3,4 ?

You could either pass the variables into the type via a method in your C# class that would accept the variables as parameters eg:您可以通过 C# 类中的方法将变量传递到类型中,该方法将接受变量作为参数,例如:

$form = new-object Form1
$form.SetVariables($vm1, $vm2, $vm3, $vm4)

I recommend that approach.我推荐这种方法。

Another option (heavier weight and not tested) is to try accessing the current runspace from the C# code eg:另一种选择(较重且未经测试)是尝试从 C# 代码访问当前运行空间,例如:

var defRunspace = System.Management.Automation.Runspaces.Runspace.DefaultRunspace;
var pipeline = defRunspace.CreateNestedPipeline();
pipeline.Commands.AddScript("$vm1,$vm2,$vm3,$vm4");
var results = pipeline.Invoke();
var vm1 = results[0];
var vm2 = results[1];
...

I haven't tried this from C# code (only from within PowerShell) so I'm not 100% sure it will work.我还没有从 C# 代码(仅在 PowerShell 中)尝试过这个,所以我不能 100% 确定它会起作用。

A way to pass variables to C# scripts running inside Powershell is to use an HttpListener (monitoring a localhost port) that harvests the Content-Type.将变量传递给在 Powershell 内运行的 C# 脚本的一种方法是使用 HttpListener(监视本地主机端口)来收集内容类型。 The Content-Type field can take up to 16,000 characters, and I used it to prevent colleagues on your machine using a browser to create spurious input. Content-Type 字段最多可以包含 16,000 个字符,我用它来防止您机器上的同事使用浏览器创建虚假输入。

The listener shown here is in a stand-alone Powershell script:此处显示的侦听器位于独立的 Powershell 脚本中:

Add-Type -TypeDefinition @'

using System;
using System.Threading.Tasks;
using System.Net;
using System.Windows.Forms;

namespace LocalHostListener
{
    public class Program
    {
        HttpListener listener = new HttpListener();

            public static void Main(string[] args)
            {
                    Program program = new Program();
                    program.Start(args[0]);
            }

            public void Start(string url_)
            {
                    listener.Prefixes.Add(url_);
                    listener.Start();
                    listener.BeginGetContext(new AsyncCallback(GetContextCallback), null);
                    Console.ReadLine();
                    listener.Stop();
            }

            public void GetContextCallback(IAsyncResult result)
            {
            HttpListenerContext context = listener.EndGetContext(result);
            HttpListenerRequest request = context.Request;
            HttpListenerResponse response = context.Response;

            Task.Factory.StartNew(() => 
            {
                // KICK OFF YOUR UPDATE ACTIONS HERE (THE LENGTH FILTER EXCLUDES BROWSER CALLS)
                if(request.ContentType.Length>0) yourAction(request.ContentType);
            });

                // SEND A RESPONSE TO KEEP POWERSHELL Invoke-WebRequest,
                // BROWSERS AND VBS MSXML2.XMLHTTP.6.0 HAPPY
                // (C# HttpWebRequest DOESN'T CARE)
                    response.ContentLength64 = 1;
            response.OutputStream.WriteByte(Convert.ToByte('!'));

                    listener.BeginGetContext(new AsyncCallback(GetContextCallback), null);
            }

        public void yourAction(string update)
        {
            Console.WriteLine(update); 
            MessageBox.Show(new Form(), update,"Message from localhost feed",
             MessageBoxButtons.OK,MessageBoxIcon.None,
               MessageBoxDefaultButton.Button1,(MessageBoxOptions)0x40000);
        }
    }
}

'@ -Language CSharp -ReferencedAssemblies System.Windows.Forms

$Host.UI.RawUI.WindowTitle='Monitoring "Content-Type" on http://localhost:1959'
[LocalHostListener.Program]::Main('http://localhost:1959/')

You can then update the listener using the Powershell WebRequest:然后,您可以使用 Powershell WebRequest 更新侦听器:

Invoke-WebRequest -ContentType 'Your message here' -URI http://localhost:1959

Updates can also be sent to the listener using a C# sender that sets the Content-Type with your variables (again, shown here in a stand-alone Powershell script):还可以使用 C# 发送器将更新发送到侦听器,该发送器使用您的变量设置 Content-Type(同样,此处显示为独立 Powershell 脚本):

Add-Type -TypeDefinition @'

using System;
using System.Net;

namespace LocalHostSender
{
    public class Program
    {
        public static void Main(string[] args)
        {
            try{
                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:1959");
                    request.ContentType = args[0];
                    request.Timeout = 200;
                    request.GetResponse();          
            }catch{}
        }
    }
}

'@ -Language CSharp -ReferencedAssemblies System.Net

[LocalHostSender.Program]::Main("Your message here")

The response section of the listener script can be removed if only the C# sender is used.如果仅使用 C# 发送器,则可以删除侦听器脚本的响应部分。

Another advantage with this method is that VBS scripts can also update the Content-Type:这种方法的另一个优点是 VBS 脚本还可以更新 Content-Type:

text_ = "Your message here"

Randomize
Set req = CreateObject("MSXML2.XMLHTTP.6.0")
req.open "GET", "http://localhost:1959/" & rnd, False
req.setRequestHeader "Content-Type", text_
req.send
'req.responseText

The random addition to the page request is required if you want to loop multiple requests, as MSXML2.XMLHTTP.6.0 doesn't send Content-Type information on identical page requests.如果您想循环多个请求,则需要对页面请求进行随机添加,因为 MSXML2.XMLHTTP.6.0 不会在相同的页面请求上发送 Content-Type 信息。

If you actually wanted browser/HTML access you could harvest the page requests in the listener using:如果您确实想要浏览器/HTML 访问,您可以使用以下方法在侦听器中收集页面请求:

string simplePageRequest_ = request.Url;
//Parsing "favicon.ico" and "http://localhost:1959/"

string pageQuery_ = request.QueryString["q"];

updating via the browser page requests, or again using the Powershell WebRequest:通过浏览器页面请求更新,或再次使用 Powershell WebRequest:

Invoke-WebRequest 'http://localhost:1959/Your message here'
Invoke-WebRequest 'http://localhost:1959/?q=Your message here'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM