Использование PowerShell в качестве двоичного файла CGI в IIS Express

1

Я пытаюсь использовать PowerShell в качестве бинарного CGI из IIS Express. Я получил его на работу, но с глупой работой, которая мне не особенно нравится. Я хотел бы понять, почему это необходимо.

Вот простой файл 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://localhost:8080/hello.cgi, я получаю сообщение об ошибке:

Ошибка HTTP 502.2 - Bad Gateway
Указанное приложение CGI плохо себя ведет, не возвращая полный набор заголовков HTTP. Заголовки, которые он вернул, - это "".

Я посмотрел с Process Monitor, и powershell.exe действительно запускает правильные аргументы. Файлы журнала трассировки IIS Express показывают код выхода 0, но ничего в выходном потоке. Странно, что при запуске из IIS Express файл powershell.exe даже не читает мой файл ps1; Я могу видеть, что файл читается, если я вручную использую ту же командную строку при захвате событий с помощью Process Monitor.

Затем я попытался проверить, может ли простой скрипт cmd.exe использоваться в качестве скрипта CGI. Это прекрасно работает; вот простой cgi.cmd, который я использовал:

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

Хм... Что делать, если я запускаю powershell.exe из скрипта cgi.cmd? Это тоже не сработало - весь вывод из сценария cmd возвращается в IIS Express; выход PowerShell все еще где-то потерян.

Однако интересно то, что когда я это делал (вызывается PowerShell из сценария cmd), появляется окно PowerShell, которое мигает при каждом обновлении страницы. Таким образом, похоже, что PowerShell выполняет мой скрипт только в новом окне, поэтому stdin/stdout не подключен к CGI в IIS.

Что делать, если я использую start/b powershell.exe... в сценарии cmd? Это не изменило ситуацию.

Что делать, если я устанавливаю system.webServer/cgi/createCGIWithNewConsole = true в конфигурации IIS Express? Это тоже не сработало, но с каждым запросом это вызвало появление консоли 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" />

Мой вопрос: зачем нужно это глупое обходное решение? Моя программа просто выполняет powershell.exe с теми же аргументами, тем же stdio, тем же stdout и тем же stderr, который он получает. Я подозреваю, что это может быть связано с флагом CreateNoWindow; но не start/b делать то же самое? Почему моя маленькая программа-обертка может перенаправлять ввод и вывод из файла powershell.exe просто отлично, но модуль CGI в IIS Express не может?

Сводный вопрос: как я могу использовать powershell.exe как двоичный код CGI, без каких-либо взломов, чтобы заставить его работать? Я хотел бы видеть, что это работает так же, как это делает cmd.exe.

Теги:
powershell
cgi
iis
iis-express

1 ответ

1

Если кто-то заинтересован, у меня была такая же проблема и я смог решить его с помощью следующей конфигурации в 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>

Ещё вопросы

Сообщество Overcoder
Наверх
Меню