Membuat alias secara dinamis di PowerShell

3

Saya ingin membuat beberapa alias secara dinamis tetapi saya tidak dapat membuat kode saya berfungsi. Ini kodenya:

# Drives
$drives = ("a","b","c","d","e")
foreach ($drive in $drives) {
    New-Item -Path alias:\ -Name $drive -Value GoToDrive($drive) #.GetNewClosure()
}

function GoToDrive($drive) {
    $formatted = "$($drive):\"
    if (Test-Path $formatted) {
        Set-Location $formatted
    } else {
        Write-Host "`"$formatted`" does not exist."
    }
}

Ketika saya mengetik "a", atau "b", atau salah satu huruf dalam $ drive, itu harus mengubah direktori kerja saya ke huruf drive itu (misalnya: A :).

Kesalahan yang saya dapatkan sekarang adalah ini:

New-Item : A positional parameter cannot be found that accepts argument 'a'.
At C:\Users\prubi\OneDrive\Documentos\WindowsPowerShell\Microsoft.PowerShell_profile.ps1:17 char:5
+     New-Item -Path alias:\ -Name $drive -Value GoToDrive($drive) #.Ge ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [New-Item], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.NewItemCommand

New-Item : A positional parameter cannot be found that accepts argument 'b'.
At C:\Users\prubi\OneDrive\Documentos\WindowsPowerShell\Microsoft.PowerShell_profile.ps1:17 char:5
+     New-Item -Path alias:\ -Name $drive -Value GoToDrive($drive) #.Ge ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [New-Item], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.NewItemCommand

New-Item : A positional parameter cannot be found that accepts argument 'c'.
At C:\Users\prubi\OneDrive\Documentos\WindowsPowerShell\Microsoft.PowerShell_profile.ps1:17 char:5
+     New-Item -Path alias:\ -Name $drive -Value GoToDrive($drive) #.Ge ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [New-Item], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.NewItemCommand

New-Item : A positional parameter cannot be found that accepts argument 'd'.
At C:\Users\prubi\OneDrive\Documentos\WindowsPowerShell\Microsoft.PowerShell_profile.ps1:17 char:5
+     New-Item -Path alias:\ -Name $drive -Value GoToDrive($drive) #.Ge ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [New-Item], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.NewItemCommand

New-Item : A positional parameter cannot be found that accepts argument 'e'.
At C:\Users\prubi\OneDrive\Documentos\WindowsPowerShell\Microsoft.PowerShell_profile.ps1:17 char:5
+     New-Item -Path alias:\ -Name $drive -Value GoToDrive($drive) #.Ge ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [New-Item], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.NewItemCommand

Adakah yang bisa membantu saya menyelesaikan pekerjaan ini?

prubini87
sumber

Jawaban:

3

Masalah langsungnya adalah bahwa PowerShell menafsirkan -Value GoToDrive($drive)sebagai menentukan saklar -Value 'GoToDrive'dan juga parameter posisi $drive. (Ini aneh dan tidak intuitif, ya.) Menutup GoToDrive($drive)tanda kurung akan mencoba untuk memanggil fungsi as-yet-nonexistent GoToDrivedan kemudian menggunakan hasilnya sebagai argumen untuk -Value, yang bukan apa yang Anda cari walaupun GoToDrivetelah didefinisikan sebelumnya. Masalah lain adalah alias tidak bisa memberikan argumen ke perintah yang mereka panggil; mereka hanya nama alternatif untuk perintah.

Anda perlu secara dinamis menjalankan perintah yang membuat fungsi pintasan:

# This is the exact same GoToDrive function you've been using
function GoToDrive($drive) {
    $formatted = "$($drive):\"
    if (Test-Path $formatted) {
        Set-Location $formatted
    } else {
        Write-Host "`"$formatted`" does not exist."
    }
}

# This does the magic
'a', 'b', 'c', 'd', 'e' | % {iex "function $_ {GoToDrive '$_'}"}

Invoke-Expression, atau iexsingkatnya, jalankan argumen yang ditentukan saat runtime seolah-olah Anda sendiri yang mengetiknya di baris perintah. Sehingga baris terakhir dieksekusi function a {GoToDrive 'a'}, lalu function b {GoToDrive 'b'}, dan seterusnya.

Ben N
sumber
Terima kasih banyak atas klarifikasi dan kode kerjanya! Saya menerima jawaban Anda sebagai jawaban yang tepat.
prubini87