PowerShell ps1 dosyasına komut satırı bağımsız değişkenleri nasıl iletilir


90

Yıllardır cmd/DOS/Windowskabuğu kullandım ve dosyaları toplu işlemek için komut satırı argümanlarını geçtim . Örneğin, bir dosya var, zuzu.batve içinde, ben erişim %1, %2vb Şimdi, ben bir çağırdığınızda aynı şeyi istiyoruz PowerShellsenaryoyu when I am in a Cmd.exe shell. Bir komut xuxu.ps1dosyam var (ve PATHEXT değişkenime ve PowerShell ile ilişkili PS1 dosyalarıma PS1 ekledim). Ama ne yaparsam yapayım $argsdeğişkenden hiçbir şey alamıyorum . Her zaman uzunluğu 0'dır.

PowerShellBunun yerine bir kabuğun içindeysem cmd.exeişe yarıyor (elbette). Ancak henüz tam zamanlı olarak PowerShell ortamında yaşayacak kadar rahat değilim. Ben yazın istemiyorum powershell.exe -command xuxu.ps1 p1 p2 p3 p4. Ben yazmak istediğiniz xuxu p1 p2 p3 p4.

Bu mümkün mü ve eğer mümkünse nasıl?

Çalışamadığım örnek önemsiz, foo.ps1:

Write-Host "Num Args:" $args.Length;
foreach ($arg in $args) {
    Write-Host "Arg: $arg";
}

Sonuçlar her zaman şu şekildedir:

C:\temp> foo
Num Args: 0
C:\temp> foo a b c d
Num Args: 0
c:\temp>

Yanıtlar:


34

Bu makale yardımcı olur. Özellikle bu bölüm:

-Dosya

Belirtilen komut dosyasını yerel kapsamda ("nokta kaynaklı") çalıştırır, böylece komut dosyasının oluşturduğu işlevler ve değişkenler geçerli oturumda kullanılabilir. Komut dosyası yolunu ve tüm parametreleri girin. Dosya, komuttaki son parametre olmalıdır, çünkü Dosya parametresi adından sonra yazılan tüm karakterler, komut dosyası yolu olarak yorumlanır ve ardından komut dosyası parametreleri gelir.

yani

powershell.exe -File "C:\myfile.ps1" arg1 arg2 arg3

myfile.ps1 dosyasını çalıştırın ve arg1 arg2 & arg3 PowerShell betiğinin parametreleridir.


1
Bu hala operasyonun ne istediğine yardımcı olmuyor ("Yazmak istiyorum xuxu p1 p2 p3 p4").
thdoan

19

PowerShell belgelerini inceledikten sonra, bu sorunla ilgili bazı yararlı bilgiler keşfettim. Dosyanızın başında 'yi $argskullandıysanız kullanamazsınız param(...); bunun yerine kullanmanız gerekecek $PSBoundParameters. Kodunuzu bir PowerShell betiğine kopyaladım / yapıştırdım ve PowerShell sürüm 2'de beklediğiniz gibi çalıştı (bu sorunla karşılaştığınızda hangi sürümü kullandığınızdan emin değilim).

Kullanıyorsanız $PSBoundParameters(ve bu YALNIZCA param(...)komut dosyanızın başında kullanıyorsanız çalışır ), o zaman bir dizi değil, bir karma tablodur, bu nedenle anahtar / değer çiftini kullanarak ona başvurmanız gerekir.

param($p1, $p2, $p3, $p4)
$Script:args=""
write-host "Num Args: " $PSBoundParameters.Keys.Count
foreach ($key in $PSBoundParameters.keys) {
    $Script:args+= "`$$key=" + $PSBoundParameters["$key"] + "  "
}
write-host $Script:args

Ve arandığında ...

PS> ./foo.ps1 a b c d

Sonuç ...

Num Args:  4
$p1=a  $p2=b  $p3=c  $p4=d

Bu, OP'nin komut satırını powershell.exe veya pwsh ile başlatmasını hesaba katmaz. OP bunu yaptığında davranış değişir.
Eric Hansen

1
@EricHansen Ne demek istediğini bilmiyorum, her iki şekilde de aynı sonucu alıyorum: `Powershell> powershell.exe. \ ParamTest.ps1 val1 val2 val3 val4 Num Args: 4 $ p1 = val1 $ p2 = val2 $ p3 = val3 $ p4 = val4 `
Randall Borck

@RandallBrock Argümanların davranışı benim için değişiyor. CMD / toplu iş içindeysem ve buna benzer bir şey yaparsam pwsh .\ParamTest.ps1 -arg1 val1 -listOfArgs val2 val3 val4, gerçekten bundan hoşlanmaz. Öte yandan, PowerShell'deysem ve yaparsam .\ParamTest.ps1 -arg1 val1 -listOfArgs val2 val3 val4, bu beklediğim gibi çalışır. "Güvenlik nedenleriyle" bu şekilde çalışması amaçlandığını duydum.
Eric Hansen

@EricHansen Bir versiyon şey mi merak ediyorum. Benim için pwsh 6.2.0'ı başlattı, ancak powershell.exe her ikisi de listelenen aynı sonuçları üreten 5.1.17134.858'i başlattı: Powershell>pwsh .\ParamTest.ps1 val1 val2 val3 val4verimler:Num Args: 4 $p1=val1 $p2=val2 $p3=val3 $p4=val4
Randall Borck

1
@Timo Tam olarak ne yaptığınızı bilmiyorum, ancak parambir dil yapısı, ancak dosyadaki ilk şey olmalı. Bir değişken veya ondan önce başka bir şey mi tanımladınız? Daha fazla bilgi burada: docs.microsoft.com/en-us/powershell/module/…
Randall Borck

18

Tamam, ilk önce bu PowerShell'de temel bir güvenlik özelliğini bozuyor. Bu anlayışla, işte bunu nasıl yapabileceğiniz:

  1. Bir Windows Gezgini penceresi açın
  2. Menü Araçları -> Klasör Seçenekleri -> Dosya Türleri sekmesi
  3. PS1 dosya türünü bulun ve gelişmiş düğmesine tıklayın
  4. Yeni düğmesini tıklayın
  5. Eylem için: Açık
  6. Uygulama için şunu koyun: "C: \ WINNT \ system32 \ WindowsPowerShell \ v1.0 \ powershell.exe" "-file" "% 1"% *

-NoProfileProfilinizin ne yaptığına bağlı olarak oraya da bir argüman koymak isteyebilirsiniz .


4
Sanırım anahtar, parametreleri powershell.exe'ye geçirdiğiniz 6. adımda. Daniel, PS1 dosyalarını PowerShell ile ilişkilendirdiğini, ancak bunun fazladan% 1% * özellikleri olmadan bağımsız değişkenleri iletmediğini söylüyor. Ayrıca -File parametresinin V1'de mevcut olmadığını unutmayın. V2 için yenidir.
Keith Tepesi

-File parametresiyle ilgili iyi yakaladım, bunu unutmuştum.
EBGreen

Önerinizi deneyebilmem için önce V2'yi yüklemem gerekecek. Teşekkürler. Bunun temel bir güvenlik özelliğini bozduğunu söylediğinizde, "bu" neyi kastediyorsunuz? Cmd.exe'den bir PowerShell komut dosyasını bir .com / .bat / .exe dosyasıymış gibi çağırmak mı? Komut dosyasına parametreler mi aktarıyorsunuz?
Daniel 'Dang' Griffith

1
Üzgünüm daha net olmalıydım. Açıkça powershell.exe'yi çağırmadan komut dosyasını çağırma. Kişisel olarak sizin için önemli bir güvenlik özelliği olduğunu ve her zaman hayran olmadığım belirsizlik yoluyla güvenlik olduğunu söylemiyorum.
EBGreen

6
EBGreen'in yorumuna eklemek için, PowerShell'in kaçınmaya çalıştığı temel güvenlik sorunu, e-postaya eklenmiş PS1 dosyalarına çift tıklamak ve komut dosyasını çalıştırmaktır. Bu nedenle PS1 dosyaları yalnızca varsayılan olarak bir düzenleyiciyle ilişkilendirilir. Microsoft, ILoveYou virüsünün PowerShell sürümünü gerçekten istemiyor, örneğin "LOVE-LETTER-FOR-YOU.TXT.ps1"
Keith Hill,

12

Parametrelerinizi dosyada belirtebilirsiniz, örneğin param:

[string]$para1
[string]$param2

Ve sonra PowerShell dosyasını böyle çağırın .\temp.ps1 para1 para2....para10, vb.


6

Belki PowerShell çağrısını şu şekilde bir .batdosyaya sarabilirsiniz :

rem ps.bat
@echo off
powershell.exe -command "%*"

Daha sonra bu dosyayı klasörünüzün altına yerleştirdiyseniz PATH, şu gibi PowerShell betiklerini çağırabilirsiniz:

ps foo 1 2 3

Yine de alıntı yapmak biraz dağınık olabilir:

ps write-host """hello from cmd!""" -foregroundcolor green

Üçlü tırnakları göstermek için +1. bu beni bir süre sıkıştı.
DeanOC

1

Göründüğü gibi "xuxu p1 p2 p3 p4" alamayabilirsiniz. Ancak PowerShell'deyken ve ayarladığınızda

PS > set-executionpolicy Unrestricted -scope currentuser

Bu komut dosyalarını şu şekilde çalıştırabilirsiniz:

./xuxu p1 p2 p3 p4

veya

.\xuxu p1 p2 p3 p4

veya

./xuxu.ps1 p1 p2 p3 p4

Umarım bu sizi PowerShell ile biraz daha rahat ettirir.


0

cmd'den ps1 komut dosyalarını çağırmak ve komut dosyasını çalıştırmadan argümanlar iletmek istiyorsanız

powershell.exe script.ps1 -c test
script -c test ( wont work )

aşağıdakileri yapabilirsin

setx PATHEXT "%PATHEXT%;.PS1;" /m
assoc .ps1=Microsoft.PowerShellScript.1
ftype Microsoft.PowerShellScript.1=powershell.exe "%1" %*

Bu, powershell.exe'nin yolunuzda olduğunu varsayıyor

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/ftype


Bunun cmd istemini Yönetici olarak çalıştırmayı gerektirdiğini belirtmek gerekir. Ayrıca, Windows 10 sürüm 1903 (18362.778) üzerinde gerçekten çalışmasını sağlamak için uğraşıyorum - tüm komutlar başarılı bir şekilde çalışıyor ancak argümanlar hala geçmiyor. Bence bir .bat dosyasıyla sarmalamanın en taşınabilir çözüm olduğunu düşünüyorum.
David Airapetyan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.