2017-05-09 16 views
2

Ich stieß auf ein seltsames Problem, das ich nicht erklären kann. Ich hoffe, jemand könnte etwas Licht für mich werfen.Piping-Parameter Problem mit Powershell

Ich möchte eine Funktion erstellen, die einen Parameter eines Arrays nimmt, sagen wir $ Skriptnamen und Benutzer haben eine Option, es aus früheren Ergebnissen zu leiten, wenn sie bevorzugen. Ich entfernte die nicht verwandten Sachen, um meine Verwirrung besser zu illustrieren.

In dem Prozess des Moduls, ich lese jedes Element aus dem Array und nur das Element drucken.

Meine Funktion:

function Get-Test 
{ 
[CmdletBinding()] 
param 
(
[parameter(mandatory=$true, 
      ValueFromPipeline=$True, 
      ValueFromPipelineByPropertyName=$true)] 
    [string[]]$scriptNames 
) 
    BEGIN 
    { 
    } 
    PROCESS 
    { 
    foreach ($scriptName in $scriptNames) 
    { 
     Write-Verbose "Executing: $scriptname" 
    }  
    } 
    END{} 

Hier war es, was mich verwirrt:

Szenario 1:

ich diesen Befehl verwendet, um die Liste der Datei in meinem Verzeichnis zu erhalten:

get-childitem | Select-Object {$_.BaseName} 

Die Liste der Datei war ohne Erweiterung korrekt zurück:

enter image description here

Allerdings, wenn ich die Ergebnisse meiner Funktion geleitet, habe ich diesen Ausdruck:

enter image description here

Beachten Sie die unerwünschte $ _.BaseName = Literal wurde hinzugefügt.

Szenario 2:

Wenn ich jedoch gebe diesen Befehl aus:

get-childitem | Select-Object $_.BaseName 

Die Ergebnisse

enter image description here

nur die Basisnamen herauszufiltern nicht wirklich, aber wenn Rohrleitungen zu meiner Funktion:

get-childitem | Select-Object $_.BaseName| 
Get-Test -Verbose 

die $ _basename wörtlichen war nicht inbegriffen:

enter image description here

der Basisname jedoch die Erweiterung enthalten, das verwirrt mich wirklich.

Kann jemand etwas sehen, das bei Ihnen aufflackert? und warum passierten die folgenden Dinge:

1) Warum wurde $ _. BaseName literal im Ausdruck in Szenario 1 markiert, nach dem ich nicht gefragt habe?

2) Warum schien die Auswahl in Szenario 2 nicht zu funktionieren, aber der Ausdruck hatte nicht $ _. BaseName mit genau demselben Skript?

3) Was muss ich in meinem Skript korrigieren, um den Dateinamen nur ohne die Erweiterung und ohne das Literal $ _ auszudrucken.

+0

'Select-Object {$ _ Basename.}' -> 'ForEach-Object {$ _. Basename}' – PetSerAl

Antwort

3

Wenn Sie Select-Object BaseName umfassen, Ihr ein Array von Objekten mit 1 Eigentum Rückkehr BaseName. Wechseln Sie zu Select-Object -ExpandProperty BaseName, um das zu tun, was Sie suchen, oder Sie können (Get-ChildItem).BaseName verwenden, um das gleiche Ergebnis zu erzielen.

Immer wenn Sie etwas erwartet als Zeichenfolge (d. H. Filename) sehen, die stattdessen als ein Objekt/Hashtable (d. H. @{$_.BaseName=Filename}) zurückgegeben wird. Wenn Sie möchten, dass die Erweiterung ebenfalls zurückgegeben wird, verwenden Sie Name anstelle von BaseName. Wenn Sie den vollständigen Pfad zur Datei wünschen, verwenden Sie in diesem Fall FullName.

Um Ihre Szenario Fragen zu beantworten ...

  1. Das wie erwartet verhalten hat, wie Sie nur eine einzige Eigenschaft angegeben von den Objekten zurückgeführt werden, sind aber nach wie vor Objekte zurück. Die Objekteigenschaft hat den Namen $_.BaseName, weil Sie sie so definiert haben, wie Sie sie aufgerufen haben (normalerweise müssten Sie nur den Eigenschaftsnamen angeben, ohne die $_. vor dem Pipelineobjekt anzugeben, d. H. Select-Object BaseName). Es funktioniert auch wegen der umgebenden geschweiften Klammern in Szenario 1

  2. Der ausführliche Text scheint die Eigenschaft Name standardmäßig zu sein, obwohl Sie vollständige Objekte an es übergeben. Das erste Beispiel in Szenario 2 gibt das vollständige Objekt zurück, da Sie Select-Object falsch aufrufen.

  3. Meine erste Antwort sollte die Lösung abdecken, denke ich

+0

Super! Das erklärt es!! Vielen Dank! – user1205746

0

Sie nicht angeben, wie Sie Ihre Funktion aufrufen, so sagen kann, nicht wirklich, was mit # 1 falsch ist, scheint es, wie Sie ein Array statt String

# 2 ist einfach zurückkehren. Sie sollten einfach geschrieben haben

anstelle von $ _. Basisname.

# 3 Wahrscheinlich bis 2. Zusammenhang

Auch nicht Select-Object verwenden, wenn Sie versuchen, erhalten Basename zu und wollen nicht den Header. Sie können stattdessen tun:

(get-childitem).basename | whatever 

Hier ist, wie es mit der Beispielfunktion druckt Sie oben

versehen
PS C:\> (gci).basename |get-test -ver 
VERBOSE: Executing: batch 
VERBOSE: Executing: DB 
VERBOSE: Executing: Modules 
VERBOSE: Executing: nix 
VERBOSE: Executing: py 
VERBOSE: Executing: utils 
VERBOSE: Executing: Microsoft.PowerShellISE_profile 
VERBOSE: Executing: Microsoft.PowerShell_profile 
VERBOSE: Executing: PowerShellTranscripts 

Oh Sie sollten wirklich Mandatory entfernen, wenn Sie Rohr Zeug, um es erwarten oder werden Sie erhält einen verbindlichen Fehler:

Get-Test : Cannot bind argument to parameter 'scriptNames' because it is an empty string 
+0

ich es erstellt als ein Modul, setze es an die Stelle, wo das Modul von PS platziert und erkannt werden soll, dann benutze ich Import-Module um das Modul zu laden. Ich habe auch versucht, es zu laden. . \ myFunction.ps1 und es hat immer noch das gleiche Verhalten. Ich denke, das Problem könnte in dem Skript liegen und nicht, wie das Skript geladen wurde.Aber ich bin PS neu, also könnte ich etwas tun, was ich nicht tun soll. – user1205746

+0

Ich habe versucht mit basename anstelle von $ _. Basename und es macht immer noch das gleiche ... seltsam .. – user1205746

+0

Ich denke, du hast missverstanden. Ich bezog mich auf die "Linie", wo Sie Sie Funktion nennen. Was ist das für eine Linie? Select-Objekt {$ _. Basisname} | Ihre_func? In jedem Fall sollten Sie nicht {$ _. Baseline} oder $ _. Baseline verwenden. Benutze die letzte Zeile, die ich erwähnt habe, und setze deinen Funktionsnamen stattdessen auf "was auch immer". Sehen Sie, wenn das mit dem Fehler hilft –