Нет вывода консоли во время вызова WSL / WSL2 команды в Powershell из C # - PullRequest
0 голосов
/ 27 июня 2019

У меня есть Pengwin (Linux дистрибутив, оптимизированный для работы с WSL - наверняка, все знают) с установленным github-лингвистом, настроенным в руководстве по https://github.com/github/linguist/blob/master/README.md. Даже я использовал свой экземпляр Windows Insider, изменил версию WSL на предстоящие 2, но все осталось как прежде.

В Pengwin и Powershell cmd все в порядке:

wsl bash -c "github-linguist '/mnt/d/Documents/Visual Studio 2017/Projects/LearnCss/LearnCss/Program.cs'"

Но при вызове в C # выводится пустой (любая другая команда, например, dir работает):

static PowershellBuilder builder = new PowershellBuilder();

/// <summary>
/// Tested, working
/// For every command return at least one entry in result
/// </summary>
/// <param name="commands"></param>
/// <returns></returns>
public async static Task<List< List<string>>> InvokeAsync(IEnumerable<string> commands)
{
    List<List<string>> returnList = new List<List<string>>();
    PowerShell ps = null;
    //  After leaving using is closed pipeline, must watch for complete or 
    using (ps = PowerShell.Create())
    {
        foreach (var item in commands)
        {
            ps.AddScript(item);

            var async = ps.BeginInvoke();
            // Return for SleepWithRandomOutputConsole zero outputs
            var psObjects = ps.EndInvoke(async);

            returnList.Add(ProcessPSObjects(psObjects));
        }
    }

    return returnList;
}

/// <summary>
/// Tested, working
/// For every command return at least one entry in result
/// </summary>
/// <param name="commands"></param>
/// <returns></returns>
public static List<List<string>> Invoke(IEnumerable<string> commands)
{
    var result = InvokeAsync(commands);
    result.Wait();
    return result.Result;
}

private static List<string> ProcessPSObjects(ICollection<PSObject> pso)
{
    List<string> output = new List<string>();

    foreach (var item in pso)
    {
        if (item != null)
        {
            output.Add(item.ToString());
        }
    }

    return output;
}

public static List<string> InvokeSingle(string command)
{
    return Invoke(CA.ToListString(command))[0];
}

Но при звонке с Process.Start все работает как шарм:

/// <summary>
/// If in A1 will be full path specified = 'The system cannot find the file specified'
/// A1 if dont contains extension, append exe
/// </summary>
/// <param name="exeFileNameWithoutPath"></param>
/// <param name="arguments"></param>
/// <returns></returns>
public static List<string> InvokeProcess(string exeFileNameWithoutPath, string arguments)
{
    FS.AddExtensionIfDontHave(exeFileNameWithoutPath, AllExtensions.exe);

    //Create process
    System.Diagnostics.Process pProcess = new System.Diagnostics.Process();

    // Must contains only filename, not full path
    pProcess.StartInfo.FileName = exeFileNameWithoutPath;

    //strCommandParameters are parameters to pass to program
    pProcess.StartInfo.Arguments = arguments;

    pProcess.StartInfo.UseShellExecute = false;

    //Set output of program to be written to process output stream
    pProcess.StartInfo.RedirectStandardOutput = true;

    //Optional, recommended do not enter, then old value is not deleted and both paths is combined
    //pProcess.StartInfo.WorkingDirectory = ;

    //Start the process
    pProcess.Start();
    W32.EnableWow64FSRedirection(true);

    //Get program output
    string strOutput = pProcess.StandardOutput.ReadToEnd();

    //Wait for process to finish
    pProcess.WaitForExit();

    var result = SH.GetLines(strOutput);
    return result;
}

Телефонный код:

const string lang = "language:";

public static string DetectLanguageForFileGithubLinguist(string windowsPath)
{
    string command = null;
    string arguments = null;

    // With WSL or WSL 2 not working. In both cases Powershell returns right values but in c# everything empty. Asked on StackOverflow
    StringBuilder linuxPath = new StringBuilder();
    linuxPath.Append("/mnt/");
    linuxPath.Append(windowsPath[0].ToString().ToLower());
    var parts = SH.Split(windowsPath, AllStrings.bs);
    for (int i = 1; i < parts.Count; i++)
    {
        linuxPath.Append("/" + parts[i]);
    }

    command = "wsl";
    arguments = " bash -c \"github-linguist '" + linuxPath + "'\"";

    W32.EnableWow64FSRedirection(false);

    // empty
    var pc = PowershellRunner.InvokeSingle("cmd /c bash -c 'ruby -v'");
    // empty
    var pc2 = PowershellRunner.InvokeSingle("wsl bash -c whoami");
    // with content
    var pc3 = PowershellRunner.InvokeSingle("dir");

    //command = @"c:\Windows\System32\wsl.exe";
    //arguments = " -- github-linguist \"/mnt/d/Documents/Visual Studio 2017/Projects/LearnCss/LearnCss/Program.cs\"";

    // empty
    var pc4 = PowershellRunner.InvokeSingle(command + arguments);

    PowershellRunner.InvokeProcess(command + ".exe", arguments);


    var lines = PowershellRunner.InvokeSingle(command);
    var line = CA.ReturnWhichContains(lines, lang).FirstOrNull();
    if (line == null)
    {
        return null;
    }
    var result = line.ToString().Replace(lang, string.Empty).Trim();
    return result;
}

Почему вызов с PowerShell классом не работает?

...