在 IIS Express 中使用 PowerShell 作为 CGI 二进制文件

问题描述 投票:0回答:2

我正在尝试使用 PowerShell 作为 IIS Express 中的 CGI 二进制文件。我让它工作了,但是有一个我不太喜欢的愚蠢的解决方法。我想了解为什么需要这种解决方法。

这是一个简单的

cgi.ps1
文件,我用它来尝试一下:

"HTTP/1.1 200 OK`r`nContent-Type: text/plain`r`n`r`n"

Get-ChildItem env:

连同这个

web.config
文件:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <handlers>
            <add name="PowerShell CGI" path="*.cgi" verb="GET,HEAD,POST" modules="CgiModule" scriptProcessor="&quot;%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe&quot; -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -File C:\Users\Nikhil\Documents\GitHub\PowerShellCGI\App\cgi.ps1"/>
        </handlers>
    </system.webServer>
</configuration>

然后,在该目录中启动 IIS Express 并导航到

http://localhost:8080/hello.cgi
后,出现错误:

HTTP 错误 502.2 - 错误网关
指定的CGI应用程序 未返回完整的 HTTP 标头集而导致行为不当。这 它返回的标头是“”。

我查看了Process Monitor,事实上,powershell.exe 确实以正确的参数启动。 IIS Express 跟踪日志文件显示退出代码为 0,但输出流中没有任何内容。奇怪的是,当从 IIS Express 启动时,powershell.exe 甚至从未读取我的 ps1 文件;如果我在使用进程监视器捕获事件时手动使用相同的命令行,我可以看到正在读取的文件。

接下来,我尝试看看是否可以将普通的 cmd.exe 批处理脚本用作 CGI 脚本。效果很好;这是我使用的简单 cgi.cmd:

@echo off
echo HTTP/1.1 200 OK
echo Content-Type: text/plain
echo.
echo Hello, World!

嗯...如果我从 cgi.cmd 脚本中启动 powershell.exe 会怎么样?这也不起作用——cmd 脚本的所有输出都返回到 IIS Express; PowerShell 输出仍然在某处丢失。

但是,有趣的是,当我这样做时(从cmd脚本调用PowerShell),每次页面刷新时都会有一个PowerShell窗口闪烁。 看起来 PowerShell 确实执行了我的脚本,只是在一个新窗口中,所以 stdin/stdout 没有连接到 IIS 中的 CGI。

如果我在cmd脚本中使用

start /b powershell.exe ...
会怎样?这没有什么区别。

如果我在 IIS Express 配置中设置

system.webServer/cgi/createCGIWithNewConsole = true
会怎么样?这也不起作用,但它确实具有每次请求都会弹出 PowerShell 控制台的效果。

解决方法

我认为问题是 powershell.exe 想要一个自己的控制台,当它启动一个新控制台时,输入和输出重定向不再连接到新控制台。

这就是我最终让它工作的方法:我编写了一个薄包装器,它启动 powershell.exe,并重定向 stdio、stdout 和 stderr。这是完整的 Program.cs:

using System;
using System.Diagnostics;

namespace PowerShell_CGI
{
    class Program
    {
        static void Main(string[] args)
        {
            var process = new Process();
            process.StartInfo = new ProcessStartInfo
            {
                FileName = "powershell.exe",
                Arguments = String.Join(" ", args),
                UseShellExecute = false,
                RedirectStandardInput = true,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                CreateNoWindow = true
            };

            process.OutputDataReceived += (sender, e) =>
            {
                Console.WriteLine(e.Data);
            };

            process.ErrorDataReceived += (sender, e) =>
            {
                Console.Error.WriteLine(e.Data);
            };

            process.Start();
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();

            process.StandardInput.Write(Console.In.ReadToEnd());

            process.WaitForExit();
        }
    }
}

现在,有了我的

web.config
中的这一行,一切都工作正常:

<add name="PowerShell-CGI" path="*" verb="GET,HEAD,POST" modules="CgiModule" scriptProcessor="C:\Users\Nikhil\Documents\GitHub\PowerShellCGI\App\PowerShell-CGI.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -File C:\Users\Nikhil\Documents\GitHub\PowerShellCGI\App\cgi.ps1" />

我的问题是:为什么需要这种愚蠢的解决方法?我的程序只是使用相同的参数、相同的 stdio、相同的 stdout 和相同的 stderr 来执行 powershell.exe。我怀疑这可能与

CreateNoWindow
标志有关;但
start /b
不是在做同样的事情吗?为什么我的小包装程序可以很好地重定向 powershell.exe 的输入和输出,但 IIS Express 中的 CGI 模块却不能?

推论问题:如何使用 powershell.exe 作为 CGI 二进制文件,而不需要任何修改来使其工作?我希望看到它像 cmd.exe 一样简单地工作。

c# powershell iis cgi iis-express
2个回答
4
投票

如果有人感兴趣,我也遇到了同样的问题,并且能够在 IIS 8.5 上使用以下配置解决它。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <handlers>
            <add name="PowerShell CGI" path="*.ps1" verb="GET,POST,HEAD" modules="CgiModule" scriptProcessor="C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile -NonInteractive -File &quot;%s&quot; %s" resourceType="File" requireAccess="Script" />
        </handlers>
    </system.webServer>
</configuration>

0
投票

您可以在 IIS CGI 设置中启用 “每次调用都使用新控制台”为 True,然后单击 应用

© www.soinside.com 2019 - 2024. All rights reserved.