问题标签 [powershell-hosting]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
278 浏览

powershell - 从 C# 异常调用的 PowerShell AddCommand

我正在尝试构建一个 C# 控制台应用程序,该应用程序执行一系列针对 Azure 订阅运行的 PowerShell 命令。

我以为它会呈现一个交互式登录框,然后继续运行。相反,这是抛出:

System.Management.Automation.dll 中出现“System.Management.Automation.CommandNotFoundException”类型的未处理异常附加信息:术语“$cred = Get-Credential”未被识别为 cmdlet、函数、脚本文件的名称, 或可操作...

如果我从 CMD 启动 PowerShell,然后键入

$cred = 获取凭据

我看到了默认的交互式登录框,用户可以输入凭据,它们被捕获到 $cred 并且我可以继续。

什么是在 C# 中使其工作的正确命令集?

谢谢。

0 投票
1 回答
742 浏览

powershell - 通过 PSSessionConfiguration 文件获取 Enter-PSHostProcess 行为

场景:其中嵌入了 Powershell 主机的 Windows 服务。单个运行空间在启动时分配。多dll解决方案。

要求:需要访问正在运行的服务中的 .NET 类。从本地 Powershell 实例使用

...因为我可以访问 .NET 类,所以正是我想要的。

问题:如何使用 Enter-PSSession 将这种 Powershell 行为提供给远程端点到自定义端点?从 Register-PSSessionConfiguration 我们可以指定一个 dll,但这会产生一个进程并且不会连接到正在运行的实例。对通过 HTTPS 或命名管道编写代理不感兴趣,但使用 Powershell 中提供的本机功能来支持 .NET。

是否可以通过 PSSessions 扩展它?还是我们只需要先执行 Enter-PSSession 或 Invoke-Command?

0 投票
1 回答
354 浏览

powershell - 如何确定 Write-Host 是否适用于当前主机

在可以针对任何合理的主机实现运行的脚本中,是否有任何理智、可靠的合同规定是否Write-Host在给定的 PowerShell 主机实现中受支持?

(假设我理解Write-Hostand Write-Output/之间的区别,并且Write-Verbose我肯定想要Write-Host语义,如果支持的话,对于这个特定的人类可读文本。)

我想过尝试询问$Host变量,或者$Host.UI/$Host.UI.RawUI但我发现的唯一相关差异是:

  • $Host.Name

    • Windows powershell.exe 命令行有$Host.Name = 'ConsoleHost'
    • 伊势有$Host.Name = 'Windows PowerShell ISE Host'
    • SQL Server 代理作业步骤有$Host.Name = 'Default Host'
    • 我没有安装任何非 Windows 版本,但我希望它们有所不同
  • $Host.UI.RawUI

    • Windows powershell.exe 命令行返回所有属性的值$Host.UI.RawUI
    • ISE$null对 的某些属性不返回任何值(或 )$Host.UI.RawUI,例如$Host.UI.RawUI.CursorSize
    • SQL Server 代理作业步骤不返回任何值$Host.UI.RawUI
    • 同样,我无法签入任何其他平台

维护$Host.Name支持的值列表Write-Host似乎有点负担,尤其是现在 PowerShell 是跨平台的。我会合理地希望脚本能够从任何主机调用并且只是做正确的事情

背景

我编写了一个脚本,可以从 PowerShell 命令提示符、ISE 或 SQL Server 代理作业中合理运行。该脚本的输出完全是文本的,供人类阅读。从命令提示符或 ISE 运行时,输出使用Write-Host.

SQL Server 作业可以通过两种不同的方式设置,并且都支持将输出捕获到 SQL Server 代理日志查看器中:

  1. 通过 CmdExec 步骤,这是简单的命令行执行,其中 Job Step 命令文本是可执行文件及其参数,因此您调用 powershell.exe 可执行文件。捕获的输出是过程的标准输出/标准输出:

    /li>
  2. 通过 PowerShell 步骤,其中 Job Step 命令文本是由其自己的嵌入式 PowerShell 主机实现解释的原始 PS 脚本。捕获的输出是通过Write-Outputor写入的任何内容Write-Error

    /li>

由于 SQL Server 主机实现的其他一些弱点,我发现您可以使用Write-Output或发出输出Write-Error,但不能同时使用。如果作业步骤失败(即如果您throwWrite-Error 'foo' -EA 'Stop'),您只会在日志中获得错误流,如果成功,您只会在日志中获得输出流。

此外,嵌入式 PS 实现不支持Write-Host. 至少到 SQL Server 2016,Write-Host抛出一个System.Management.Automation.Host.HostException带有消息A command that prompt the user failed because the host program or the command type does not support user interaction

为了支持我所有的用例,到目前为止,我开始使用一个自定义函数Write-Message,该函数基本上设置为(简化):

从 SQL Server 2019(可能更早)开始,它似乎Write-Host不再在嵌入式 SQL Server 代理 PS 主机中引发异常,而是一个不向输出或错误流发出任何内容的空操作。由于没有例外,我的脚本Write-Message函数无法再可靠地检测它是否应该使用Write-HostStringBuilder.AppendLine

SQL Server 代理作业的基本解决方法是使用更成熟的 CmdExec 步骤类型(其中Write-OutputWrite-Host两者都被捕获为标准输出),但我更喜欢 PowerShell 步骤类型,因为(除其他原因外)它能够可靠地拆分命令多行,所以我很想看看是否有更全面的、基于 PowerShell 的方法来解决是否Write-Host对我所在的主机有用的问题。

0 投票
0 回答
179 浏览

c# - 在 C# 中,使用脚本将命令添加到 PowerShell InitialSessionState 并使其可从 C# 中发现

有没有办法找到使用 ImportPSModule() 导入到 InitialSessionState 中的函数?

我有这个围绕 PowerShell 的包装器来运行由我的应用程序自托管的脚本(为简洁起见,删除了注释和错误检查)

当我使用 engine.AddCommand() 添加类型时,它们会按预期显示在 engine.ListCommands() 中。我现在想让用户拥有一组他们预先定义的自定义函数,我将通过 ImportPSModule() 导入这些函数。最后,我希望能够将 UI 中的这些命令列为可用命令。

我创建了一个非常简单的模块(init.psm1)

并测试导入它,但功能不显示为可用命令。(尽管用户脚本可以很好地使用它们。)

我根据这个问题查看了 System.Management.Automation.Language.Parser.ParseFile并且可以在 {function} 之后检查令牌,但这似乎是一种迂回的方法。(目前,这是我最好的选择。)

我考虑过使用 运行一个小脚本Get-ChildItem function:,但使用时 Get-ChildItem 不可用InitialSessionState.CreateDefault()(我不想使用 InitialSessionState.Create()。我的场景需要引擎比这更锁定。)

我可以使用其他选项来获取用户定义的函数列表吗?只要用户可以将它们作为 powershell 代码提供,以另一种方式导入它们是可以接受的。

谢谢!

编辑 重新阅读文档,似乎我错过了这一非常重要的行:

所以我将把这个问题稍微更新为“有没有办法从可以添加到 initialSessionState.Commands 的脚本文件中创建 SessionStateCommandEntry()?”

0 投票
1 回答
42 浏览

c# - 使用 C# 中的 PowerShell 主机如何获取输出?

具有以下 NET 5 控制台应用程序:

调用似乎没有错误地执行,但是输出去哪里了?我已经尝试了AddCommandand AddStatement,并且还检查了ps调试器中的变量,没有输出迹象。我确实发现了,ps.Streams.Information但它是空的。

0 投票
0 回答
56 浏览

c# - C# 在调用 Invoke() 后将命令添加到长时间运行的托管 PowerShell 会话

我正在尝试(最终)为长时间运行的 .exe 应用程序(例如加密节点或游戏服务器)编写 C# 服务包装器。到目前为止,我已经编写了一个输出 .exe 输出的小型 PowerShell 主机(当前输出到控制台,最终它将转到其他地方)和一个每秒输出时间的小型示例应用程序,并Console.ReadLine()正在寻找“停止”以停止执行。目前我能够托管示例应用程序并将输出正确定向(到控制台),但我需要知道如何在PowerShell.Invoke()调用后添加命令。

游戏服务器之类的程序通常具有可用的命令,例如“保存”或“退出”来控制服务器。程序在托管的 PowerShell 会话中运行后,我想添加一个“停止”命令来停止示例应用程序,但我不知道如何。

我的目标.NET 5.0和使用Microsoft.PowerShell.SDK

下面是我的代码

托管程序

注意这里第 15 行, Console.WriteLine("Started");, 将执行,但以下语句(包括和 after Console.WriteLine("Attempting stop");)不会执行,或者至少不会进入控制台。

示例应用程序

这个小应用程序的目标是模拟一个长时间运行的程序(如游戏服务器)并且需要一些输入(如“停止”)才能正确退出程序。这主要是为了完整性

Invoke()由于示例程序需要读取“停止”才能正确停止,因此在托管 PowerShell 对象上已经调用之后,如何以编程方式发送它?本质上是为了复制坐在控制台前的用户,但不是用户,而是一个程序。