none
Powershell verläuft sich in Batch RRS feed

  • Frage

  • powershell -noprofile -command $Profilepath="\\AS_Server\Bu.txt" powershell -noprofile -command "Get-Content $Profilepath | Foreach-Object {(Get-Content $_) | Out-String | Foreach-Object {$_.Replace('Status=OFF','Status=OFF')} | Set-Content $_}"


    Get-Content : Cannot bind argument to parameter 'Path' because it is null.
    At line:1 char:12+ Get-Content <<<<  $Profilepath | Foreach-Object {(Get-Content $_) | Out-String | Foreach-Object {$_.Replace('Status=OFF','Status=OFF')} | Set-Content $_}    + CategoryInfo          : InvalidData: (:) [Get-Content], ParameterBindingValidationException    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.GetContentCommand

    Das war der erste versuch, der andere sah so aus:

    Code:
    1. powershell -noprofile -command "Get-ChildItem –path “\\AS_Server\Bu.txt” | Foreach-Object {(Get-Content $_) | Out-String | Foreach-Object {$_.Replace('Status=ON','Status=OFF')} | Set-Content $_}"

    lasse ich das über batch laufen kommt das:
    Code:
    1. Get-ChildItem : Cannot find path 'D:\Tasks\ûpath' because it does not exist.
    2. At line:1 char:14
    3. + Get-ChildItem <<<< ûpath ô\\AS_Server\Bu.txtö | Forea
    4. ch-Object {(Get-Content $_) | Out-String | Foreach-Object {$_.Replace('Status=ON','Status=OFF')} | Set-Content $_}
    5. + CategoryInfo : ObjectNotFound: (D:\Tasks\ûpath:String) [Get-ChildItem], ItemNotFoundException
    6. + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
    in der ps console geht es wenn ich "powershell -noprofile -command " weglasse. was ist läuft da schief?

    Freitag, 24. Januar 2014 15:46

Antworten

  • Hallo,

    das sieht alles ein wenig durcheinander aus, zumindest fuer mich.

    In deinem 1. Versuch arbeitest Du mit der Variable $Profilepath, die in einer "normalen" PowerShell Session auf das verwendetet Profile zeigt, was eine PS1 Datei ist, bei dir aber eine Textdatei, die du mit Get-Content lesen willst und dann fuer jeder Zeile in der Datei nochmal ein Get-Content gemacht wird, was nur Sinn machen wuerde, wenn in der Bu.txt Pfade mit Dateinamen stehen wuerden usw. und so fort.
     
    powershell -noprofile -command $Profilepath="\\AS_Server\Bu.txt"

    >> Es wird eine PowerShell Session geoeffnet, die Variable $Profilepath des Typs [string] mit Inhalt "\\AS_Server\Bu.txt" gebaut und direkt danach wird die Session schon wieder beendet. Was beduetet, das die Variable eine Lebenszeit von max. ein paar Millisekunden hat.

    >> Mit der naechsten Zeile wird dann eine neue PowerShell Session gestartet, die somit die Variable $Profilepath nicht kennen kann, und somit Get-Content $Profilepath gegen die Wand laeuft usw.

    Hier koennte der Parameter -NoExit helfen

    Ich vermute mal Du willst einfach nur in einer Textdatei, hier Bu.txt, Text aendern.

    Das kannst Du z.B.: so machen.

    Move-Item Bu.txt Bu-Temp.txt
    Get-Content Bu-Temp.txt | ForEach-Object {$_ -replace 'Status=ON', 'Status=OFF'} | Set-Content Bu.txt



    Wenn ich mit meinem Tipp falsch liege beschreibe bitte genau, was du machen willst, wie die Datei, die Dateien aussehen usw.

    Beste Gruesse
    brima

    • Als Antwort vorgeschlagen Alex Pitulice Donnerstag, 30. Januar 2014 10:20
    • Als Antwort markiert Alex Pitulice Montag, 3. Februar 2014 15:30
    Freitag, 24. Januar 2014 19:12
  • Wie Brima schon beschrieben hat, startest du in deinem 1. Versuch 2 PowerShell Prozesse.
    Jeder Prozess ist ein völlig eigenständiges Programm, die voneinander von Windows getrennt verwaltet werden. Prozesse sind voneinander aus Sicherheitsgründe abgeschottet. Prozesse können sich nicht gegenseitig verändern oder einem anderen Prozess in die Karten sehen.

    Das heißt der 2. Prozess kann die Variable $Profilepath von dem 1. Prozess nicht sehen.
    Wie Brima schon sagte wird der 1. PowerShell Prozess gleich nach dem Start wieder beendet da er nur die Variable verändert und sonst nichts tut.

    Die Variable $Profilepath ist eine Variable, die von PowerShell schon mitgeliefert wird und diese sollte möglichst nicht angefasst werden! Denk dir da einen eigenen, noch nicht benutzten, Variablen Namen aus!

    In deinem 2. Versuchst gehst du mit den Anführungszeichen falsch um.
    Anführungszeichen sind ähnlich wie Klammern zu sehen! Nur das es dort keine öffnenden und schließenden Anführungszeichen gibt.

    Aus Sicht von PowerShell hört dein Kommando nach dem 2. Anführungszeichen auf, da dies das Erste Anführungszeichen schließt!

    PowerShell -noprofile -command "Get-ChildItem –path " <--- schließendes Anführungszeichen!

    PowerShell kann mit einfachen Anführungszeichen  UND den doppelten umgehen..
    Du Startest das in einer DOS Batch DOS, kann nur mit den Doppelten Anführungszeichen umgehen.
    Das heißt, du musst ganz außen die Doppelten Anführungszeichen nehmen und innen drinne die einfachen.
    So etwa:

    PowerShell -noprofile -command "Get-ChildItem –path '\\AS_Server\Bu.txt' | Foreach-Object {(Get-Content $_) | Out-String | Foreach-Object {$_.Replace('Status=ON','Status=OFF')} | Set-Content $_}"

    Aber auch hier wird dein Kommando nichts bringen, weil der PowerShell Code völliger murks ist.
    Kauf die ein gutes PowerShell Buch oder mach einen PowerShell Kurs!

    Get-ChildItem ist dafür gedacht mehrere Dateien zu holen, du holst hier nur eine Datei.
    Wenn du nur eine Datei holen willst, kann das Get-Content machen.
    Get-Content liest eine Datei Zeile für Zeile ein und jede Zeile wird einzeln an die Pipeline an das nächste Cmdlet übergeben.
    Out-String ist hier völlig überflüssig, da Get-Content schon Strings liefert!

    Dort kannst du deine Textersetzung machen.
    So etwa ist es richtig:

    PowerShell -noprofile -command "(Get-Content -Path '\\AS_Server\Bu.txt') | Foreach-Object {$_.Replace('Status=ON','Status=OFF')} | Set-Content '\\AS_Server\Bu.txt'"
     

    Das Get-Content habe ich in Klammern gesetzt, damit die gesamte Datei eingelesen wird und nicht mehr vom Prozess Blockiert wird (File lock).
    So kann ich die Datei am Ende der Pipeline wieder verändert an Ihren alten Platz zurückschreiben.

    oder so:

    # alle Dateien mit der endung .txt verarbeiten 
    Get-ChildItem -Path '\\AS_Server\Sharename\Verzeichnisname' -Filter '*.txt' | ForEach-Object {(Get-Content -Path $_.Fullname )} | Foreach-Object {$_.Replace('Status=ON','Status=OFF')} | Set-Content '\\AS_Server\Bu.txt'



    PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
    auf der deutschsprachigen PowerShell Community

    Mein 21 Teiliger PowerShell Video Grundlehrgang
    Deutsche PowerShell Videos auf Youtube
    Folge mir auf:
    Twitter | Facebook | Google+



    • Bearbeitet Peter Kriegel Montag, 27. Januar 2014 07:31
    • Als Antwort vorgeschlagen Alex Pitulice Donnerstag, 30. Januar 2014 10:20
    • Als Antwort markiert Alex Pitulice Montag, 3. Februar 2014 15:29
    Montag, 27. Januar 2014 07:21

Alle Antworten

  • Hallo,

    das sieht alles ein wenig durcheinander aus, zumindest fuer mich.

    In deinem 1. Versuch arbeitest Du mit der Variable $Profilepath, die in einer "normalen" PowerShell Session auf das verwendetet Profile zeigt, was eine PS1 Datei ist, bei dir aber eine Textdatei, die du mit Get-Content lesen willst und dann fuer jeder Zeile in der Datei nochmal ein Get-Content gemacht wird, was nur Sinn machen wuerde, wenn in der Bu.txt Pfade mit Dateinamen stehen wuerden usw. und so fort.
     
    powershell -noprofile -command $Profilepath="\\AS_Server\Bu.txt"

    >> Es wird eine PowerShell Session geoeffnet, die Variable $Profilepath des Typs [string] mit Inhalt "\\AS_Server\Bu.txt" gebaut und direkt danach wird die Session schon wieder beendet. Was beduetet, das die Variable eine Lebenszeit von max. ein paar Millisekunden hat.

    >> Mit der naechsten Zeile wird dann eine neue PowerShell Session gestartet, die somit die Variable $Profilepath nicht kennen kann, und somit Get-Content $Profilepath gegen die Wand laeuft usw.

    Hier koennte der Parameter -NoExit helfen

    Ich vermute mal Du willst einfach nur in einer Textdatei, hier Bu.txt, Text aendern.

    Das kannst Du z.B.: so machen.

    Move-Item Bu.txt Bu-Temp.txt
    Get-Content Bu-Temp.txt | ForEach-Object {$_ -replace 'Status=ON', 'Status=OFF'} | Set-Content Bu.txt



    Wenn ich mit meinem Tipp falsch liege beschreibe bitte genau, was du machen willst, wie die Datei, die Dateien aussehen usw.

    Beste Gruesse
    brima

    • Als Antwort vorgeschlagen Alex Pitulice Donnerstag, 30. Januar 2014 10:20
    • Als Antwort markiert Alex Pitulice Montag, 3. Februar 2014 15:30
    Freitag, 24. Januar 2014 19:12
  • Wie Brima schon beschrieben hat, startest du in deinem 1. Versuch 2 PowerShell Prozesse.
    Jeder Prozess ist ein völlig eigenständiges Programm, die voneinander von Windows getrennt verwaltet werden. Prozesse sind voneinander aus Sicherheitsgründe abgeschottet. Prozesse können sich nicht gegenseitig verändern oder einem anderen Prozess in die Karten sehen.

    Das heißt der 2. Prozess kann die Variable $Profilepath von dem 1. Prozess nicht sehen.
    Wie Brima schon sagte wird der 1. PowerShell Prozess gleich nach dem Start wieder beendet da er nur die Variable verändert und sonst nichts tut.

    Die Variable $Profilepath ist eine Variable, die von PowerShell schon mitgeliefert wird und diese sollte möglichst nicht angefasst werden! Denk dir da einen eigenen, noch nicht benutzten, Variablen Namen aus!

    In deinem 2. Versuchst gehst du mit den Anführungszeichen falsch um.
    Anführungszeichen sind ähnlich wie Klammern zu sehen! Nur das es dort keine öffnenden und schließenden Anführungszeichen gibt.

    Aus Sicht von PowerShell hört dein Kommando nach dem 2. Anführungszeichen auf, da dies das Erste Anführungszeichen schließt!

    PowerShell -noprofile -command "Get-ChildItem –path " <--- schließendes Anführungszeichen!

    PowerShell kann mit einfachen Anführungszeichen  UND den doppelten umgehen..
    Du Startest das in einer DOS Batch DOS, kann nur mit den Doppelten Anführungszeichen umgehen.
    Das heißt, du musst ganz außen die Doppelten Anführungszeichen nehmen und innen drinne die einfachen.
    So etwa:

    PowerShell -noprofile -command "Get-ChildItem –path '\\AS_Server\Bu.txt' | Foreach-Object {(Get-Content $_) | Out-String | Foreach-Object {$_.Replace('Status=ON','Status=OFF')} | Set-Content $_}"

    Aber auch hier wird dein Kommando nichts bringen, weil der PowerShell Code völliger murks ist.
    Kauf die ein gutes PowerShell Buch oder mach einen PowerShell Kurs!

    Get-ChildItem ist dafür gedacht mehrere Dateien zu holen, du holst hier nur eine Datei.
    Wenn du nur eine Datei holen willst, kann das Get-Content machen.
    Get-Content liest eine Datei Zeile für Zeile ein und jede Zeile wird einzeln an die Pipeline an das nächste Cmdlet übergeben.
    Out-String ist hier völlig überflüssig, da Get-Content schon Strings liefert!

    Dort kannst du deine Textersetzung machen.
    So etwa ist es richtig:

    PowerShell -noprofile -command "(Get-Content -Path '\\AS_Server\Bu.txt') | Foreach-Object {$_.Replace('Status=ON','Status=OFF')} | Set-Content '\\AS_Server\Bu.txt'"
     

    Das Get-Content habe ich in Klammern gesetzt, damit die gesamte Datei eingelesen wird und nicht mehr vom Prozess Blockiert wird (File lock).
    So kann ich die Datei am Ende der Pipeline wieder verändert an Ihren alten Platz zurückschreiben.

    oder so:

    # alle Dateien mit der endung .txt verarbeiten 
    Get-ChildItem -Path '\\AS_Server\Sharename\Verzeichnisname' -Filter '*.txt' | ForEach-Object {(Get-Content -Path $_.Fullname )} | Foreach-Object {$_.Replace('Status=ON','Status=OFF')} | Set-Content '\\AS_Server\Bu.txt'



    PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
    auf der deutschsprachigen PowerShell Community

    Mein 21 Teiliger PowerShell Video Grundlehrgang
    Deutsche PowerShell Videos auf Youtube
    Folge mir auf:
    Twitter | Facebook | Google+



    • Bearbeitet Peter Kriegel Montag, 27. Januar 2014 07:31
    • Als Antwort vorgeschlagen Alex Pitulice Donnerstag, 30. Januar 2014 10:20
    • Als Antwort markiert Alex Pitulice Montag, 3. Februar 2014 15:29
    Montag, 27. Januar 2014 07:21