You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在二进制PowerShell模块的参数补全器中获取当前工作目录

解决PowerShell二进制Cmdlet中相对路径解析的参数补全问题

问题背景

基于.NET 6维护已有的二进制PowerShell模块,需为ReaderCmdlet新增带参数补全功能的ConfigurationName参数。现有Cmdlet定义:

public class ReaderCmdlet : Cmdlet
{
    [Parameter]
    public string ProjectFolder { get; set; }
    // 其他成员
}

新增参数及补全器定义:

[Parameter]
[ArgumentCompleter(typeof(ConfigurationCompleter))]
public string ConfigurationName { get; set; }
public class ConfigurationCompleter : IArgumentCompleter
{
    public IEnumerable<CompletionResult> CompleteArgument(
        string commandName,
        string parameterName,
        string wordToComplete,
        CommandAst commandAst,
        IDictionary fakeBoundParameters)
    {
        // 补全逻辑
    }
}

遇到的问题:ConfigurationName的补全结果依赖ProjectFolder指定的项目路径。当用户输入绝对路径时,可通过fakeBoundParameters正常处理;但输入相对路径时,需要结合PowerShell当前工作目录解析,而IArgumentCompleter没有Cmdlet上下文,无法直接通过SessionState.Path获取当前目录。尝试通过Runspace.DefaultRunspace.SessionStateProxy.Path访问时,因补全管道运行状态抛出异常。

解决方案

方案1:改用ICmdletArgumentCompleter接口(推荐)

PowerShell 5.1及以上版本提供了ICmdletArgumentCompleter接口,它的CompleteArgument方法会直接传入当前Cmdlet实例,让你可以直接访问Cmdlet的SessionState,完美解决路径解析问题。

修改补全器实现:

using System.Collections.Generic;
using System.Management.Automation;

public class ConfigurationCompleter : ICmdletArgumentCompleter
{
    public IEnumerable<CompletionResult> CompleteArgument(
        Cmdlet cmdlet,
        string parameterName,
        string wordToComplete,
        CommandAst commandAst,
        IDictionary fakeBoundParameters)
    {
        if (fakeBoundParameters.TryGetValue("ProjectFolder", out var projectFolderObj) && 
            projectFolderObj is string projectFolder)
        {
            // 利用Cmdlet的SessionState解析路径,自动处理绝对/相对路径
            string resolvedProjectPath = cmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath(projectFolder);
            
            // 这里根据resolvedProjectPath获取配置名称列表,示例逻辑
            var configNames = GetConfigurationNamesFromProject(resolvedProjectPath);
            
            foreach (var name in configNames)
            {
                yield return new CompletionResult(name);
            }
        }
    }

    // 示例方法:从项目路径获取配置名称
    private IEnumerable<string> GetConfigurationNamesFromProject(string projectPath)
    {
        // 实际逻辑:读取项目目录下的配置文件或配置项
        return new List<string> { "Debug", "Release", "Staging" };
    }
}

更新参数的ArgumentCompleter属性指向该补全器即可。

方案2:通过Runspace获取当前工作目录(兼容旧版本)

如果需要兼容PowerShell 5.1以下版本,可通过Runspace.DefaultRunspace获取当前会话的PWD变量(PowerShell当前工作目录),手动解析相对路径:

using System.Collections.Generic;
using System.IO;
using System.Management.Automation;
using System.Management.Automation.Language;

public class ConfigurationCompleter : IArgumentCompleter
{
    public IEnumerable<CompletionResult> CompleteArgument(
        string commandName,
        string parameterName,
        string wordToComplete,
        CommandAst commandAst,
        IDictionary fakeBoundParameters)
    {
        if (fakeBoundParameters.TryGetValue("ProjectFolder", out var projectFolderObj) && 
            projectFolderObj is string projectFolder)
        {
            string resolvedProjectPath;
            if (Path.IsPathRooted(projectFolder))
            {
                resolvedProjectPath = projectFolder;
            }
            else
            {
                // 获取PowerShell当前工作目录
                var pwd = Runspace.DefaultRunspace.SessionStateProxy.GetVariable("PWD") as PathInfo;
                string currentDir = pwd?.Path ?? Directory.GetCurrentDirectory();
                resolvedProjectPath = Path.Combine(currentDir, projectFolder);
            }
            
            // 后续逻辑同方案1
            var configNames = GetConfigurationNamesFromProject(resolvedProjectPath);
            foreach (var name in configNames)
            {
                yield return new CompletionResult(name);
            }
        }
        yield break;
    }

    private IEnumerable<string> GetConfigurationNamesFromProject(string projectPath)
    {
        return new List<string> { "Debug", "Release", "Staging" };
    }
}

注意:这种方式要确保在补全线程中访问Runspace.DefaultRunspace的安全性,常规场景下可正常工作。

内容的提问来源于stack exchange,提问作者Hemisphera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 10:13:28