繁体   English   中英

如何将 psm1 和 psd1 文件合并为一个 powershell 函数?

[英]How to merge a psm1 and a psd1 file into one powershell function?

我正在尝试在 Powershell (7+) 中实现一个旧的 Bash 函数来显示一些上次访问的目录的堆栈。 我从Pscx项目仓库中找到了这段代码 归根结底,我希望将其视为独立功能。

但是我遇到了几个问题:

  1. 所需的代码位于 2 个文件中: Pscx.CD.psm1Messages.psd1 如果可能的话,它们需要组合成一个函数。
  2. 即使命令仍在工作,也会出现一些不同的错误消息。 我不知道该怎么办。
Cannot index into a null array.
At D:\blah\blah\Pscx.CD.psm1:137 char:21
 +                 if ($Pscx:Preferences['CD_GetChildItem'])
 +                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
 + FullyQualifiedErrorId : NullArray
  1. 如果您当前位于堆栈中间的某个位置,并且要对新位置执行cd ,则所有后续堆栈项都将被覆盖,而不是添加到列表的末尾(最后一项)。 如何将cd <full path location>到堆栈的末尾而不覆盖以前的项目?

好的好的,这是合并的代码:

# From messages.psd1
ConvertFrom-StringData @'
    SettingLocationF1=Setting location to: '{0}'
    BackStackEmpty=The backward stack is empty.
    ForeStackEmpty=The foreward stack is empty.
    GoingToTheSameDir=Wherever you go, there you are!
    NumOutOfRangeF1={0} is out of range.
    '@



# From Messages.psd1

$backwardStack = new-object System.Collections.ArrayList
$forewardStack = new-object System.Collections.ArrayList

$ExecutionContext.SessionState.Module.OnRemove = {
    Set-Alias cd Set-Location -Scope Global -Option AllScope -Force
}.GetNewClosure()

# We are going to replace the PowerShell default "cd" alias with the CD function defined below.
Set-Alias cd Set-LocationEx -Force -Scope Global -Option AllScope -Description "PSCX alias"

function Set-LocationEx
{
    [CmdletBinding(DefaultParameterSetName='Path')]
    param(
        [Parameter(Position=0, ParameterSetName='Path', ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [string]
        $Path,

        [Parameter(Position=0, ParameterSetName='LiteralPath', ValueFromPipelineByPropertyName=$true)]
        [Alias("PSPath")]
        [string]
        $LiteralPath,

        [Parameter(ValueFromRemainingArguments=$true)]
        [string[]]
        $UnboundArguments,

        [Parameter()]
        [switch]
        $PassThru,

        [Parameter()]
        [switch]
        $UseTransaction
    )

    Begin
    {
        Set-StrictMode -Version Latest

        # String resources
        Import-LocalizedData -BindingVariable msgTbl -FileName Messages

        $ExtraArgs = @{}
        if (($PSVersionTable.PSVersion.Major -lt 6) -or ($PSVersionTable.PSEdition -eq 'Desktop'))
        {
            $ExtraArgs['UseTransaction'] = $UseTransaction
        }

        function SetLocationImpl($path, [switch]$IsLiteralPath)
        {
            if ($pscmdlet.ParameterSetName -eq 'LiteralPath' -or $IsLiteralPath)
            {
                Write-Debug "Setting location to literal path: '$path'"
                Set-Location -LiteralPath $path @ExtraArgs
            }
            else
            {
                Write-Debug "Setting location to path: '$path'"
                Set-Location $path @ExtraArgs
            }

            if ($PassThru)
            {
                Write-Output $ExecutionContext.SessionState.Path.CurrentLocation
            }
            else
            {
                # If not passing thru, then check for user options of other info to display.
                if ($Pscx:Preferences['CD_GetChildItem'])
                {
                    Get-ChildItem
                }
                elseif ($Pscx:Preferences['CD_EchoNewLocation'])
                {
                    Write-Host $ExecutionContext.SessionState.Path.CurrentLocation
                }
            }
        }
    }

    Process
    {
        if ($pscmdlet.ParameterSetName -eq 'Path')
        {
            Write-Debug "Path parameter received: '$Path'"
            $aPath = $Path
        }
        else
        {
            Write-Debug "LiteralPath parameter received: '$LiteralPath'"
            $aPath = $LiteralPath
        }

        if ($UnboundArguments -and $UnboundArguments.Count -gt 0)
        {
            $OFS=','
            Write-Debug "Appending unbound arguments to path: '$UnboundArguments'"
            $aPath = $aPath + " " + ($UnboundArguments -join ' ')
        }

        # If no input, dump contents of backward and foreward stacks
        if (!$aPath)
        {
            # Command to dump the backward & foreward stacks
            ""
            "     # Directory Stack:"
            "   --- ----------------"
            if ($backwardStack.Count -ge 0)
            {
                for ($i = 0; $i -lt $backwardStack.Count; $i++)
                {
                    "   {0,3} {1}" -f $i, $backwardStack[$i]
                }
            }

            "-> {0,3} {1}" -f $i++,$ExecutionContext.SessionState.Path.CurrentLocation

            if ($forewardStack.Count -ge 0)
            {
                $ndx = $i
                for ($i = 0; $i -lt $forewardStack.Count; $i++)
                {
                    "   {0,3} {1}" -f ($ndx+$i), $forewardStack[$i]
                }
            }
            ""
            return
        }

        Write-Debug "Processing arg: '$aPath'"

        $currentPathInfo = $ExecutionContext.SessionState.Path.CurrentLocation

        # Expand ..[.]+ out to ..\..[\..]+
        if ($aPath -like "*...*")
        {
            $regex = [regex]"\.\.\."
            while ($regex.IsMatch($aPath))
            {
                $aPath = $regex.Replace($aPath, "..$([System.IO.Path]::DirectorySeparatorChar)..")
            }
        }

        if ($aPath -eq "-")
        {
            if ($backwardStack.Count -eq 0)
            {
                Write-Warning $msgTbl.BackStackEmpty
            }
            else
            {
                $lastNdx = $backwardStack.Count - 1
                $prevPath = $backwardStack[$lastNdx]
                SetLocationImpl $prevPath -IsLiteralPath
                [void]$forewardStack.Insert(0, $currentPathInfo.Path)
                $backwardStack.RemoveAt($lastNdx)
            }
        }
        elseif ($aPath -eq "+")
        {
            if ($forewardStack.Count -eq 0)
            {
                Write-Warning $msgTbl.ForeStackEmpty
            }
            else
            {
                $nextPath = $forewardStack[0]
                SetLocationImpl $nextPath -IsLiteralPath
                [void]$backwardStack.Add($currentPathInfo.Path)
                $forewardStack.RemoveAt(0)
            }
        }
        elseif ($aPath -like "-[0-9]*")
        {
            [int]$num = $aPath.replace("-","")
            $backstackSize = $backwardStack.Count
            $forestackSize = $forewardStack.Count
            if ($num -eq $backstackSize)
            {
                Write-Host "`n$($msgTbl.GoingToTheSameDir)`n"
            }
            elseif ($num -lt $backstackSize)
            {
                $selectedPath = $backwardStack[$num]
                SetLocationImpl $selectedPath -IsLiteralPath
                [void]$forewardStack.Insert(0, $currentPathInfo.Path)
                $backwardStack.RemoveAt($num)

                [int]$ndx = $num
                [int]$count = $backwardStack.Count - $ndx
                if ($count -gt 0)
                {
                    $itemsToMove = $backwardStack.GetRange($ndx, $count)
                    $forewardStack.InsertRange(0, $itemsToMove)
                    $backwardStack.RemoveRange($ndx, $count)
                }
            }
            elseif (($num -gt $backstackSize) -and ($num -lt ($backstackSize + 1 + $forestackSize)))
            {
                [int]$ndx = $num - ($backstackSize + 1)
                $selectedPath = $forewardStack[$ndx]
                SetLocationImpl $selectedPath -IsLiteralPath
                [void]$backwardStack.Add($currentPathInfo.Path)
                $forewardStack.RemoveAt($ndx)

                [int]$count = $ndx
                if ($count -gt 0)
                {
                    $itemsToMove = $forewardStack.GetRange(0, $count)
                    $backwardStack.InsertRange(($backwardStack.Count), $itemsToMove)
                    $forewardStack.RemoveRange(0, $count)
                }
            }
            else
            {
                Write-Warning ($msgTbl.NumOutOfRangeF1 -f $num)
            }
        }
        else
        {
            $driveName = ''
            if ($ExecutionContext.SessionState.Path.IsPSAbsolute($aPath, [ref]$driveName) -and
                !(Test-Path -LiteralPath $aPath -PathType Container))
            {
                # File or a non-existant path - handle the case of "cd $profile" when the profile script doesn't exist
                $aPath = Split-Path $aPath -Parent
                Write-Debug "Path is not a container, attempting to set location to parent: '$aPath'"
            }

            SetLocationImpl $aPath

            $forewardStack.Clear()

            # Don't add the same path twice in a row
            if ($backwardStack.Count -gt 0)
            {
                $newPathInfo = $ExecutionContext.SessionState.Path.CurrentLocation
                if (($currentPathInfo.Provider     -eq $newPathInfo.Provider) -and
                    ($currentPathInfo.ProviderPath -eq $newPathInfo.ProviderPath))
                {
                    return
                }
            }
            [void]$backwardStack.Add($currentPathInfo.Path)
        }
    }
}


Messages.psd1的数据合并到函数定义中所需的唯一修改是在Begin块中的这一行:

        Import-LocalizedData -BindingVariable msgTbl -FileName Messages

此语句将在运行时从特定于语言环境的Messages.psd1文件导入资源并将它们分配给$msgTbl ,因此我们需要将其替换为静态值:

        $msgTbl = ConvertFrom-StringData @'
SettingLocationF1=Setting location to: '{0}'
BackStackEmpty=The backward stack is empty.
ForeStackEmpty=The foreward stack is empty.
GoingToTheSameDir=Wherever you go, there you are!
NumOutOfRangeF1={0} is out of range.
'@

您遇到的错误很容易修复 - 因为您只需要一个独立的功能,所以您无需担心特定于Pscx模块的配置选项,因此只需完全删除else语句:

else
{
    # If not passing thru, then check for user options of other info to display.
    if ($Pscx:Preferences['CD_GetChildItem'])
    {
        Get-ChildItem
    }
    elseif ($Pscx:Preferences['CD_EchoNewLocation'])
    {
        Write-Host $ExecutionContext.SessionState.Path.CurrentLocation
    }
}

恐怕我不明白最后一个问题。 如果您能展示如何重现所描述的行为,很高兴更新答案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM