Czy istnieje sposób na pomijanie interaktywnych monitów w skrypcie PowerShell?

13

Pisząc skrypty PowerShell, zauważyłem, że gdy niektóre polecenia cmdlet napotykają problemy, pojawiają się interaktywne monity, których przykładem jest Usuń element z niepustego katalogu. Jest to zabójcze, gdy próbujesz zautomatyzować zadania, wolałbym, żeby akcja po prostu się nie powiodła i albo rzuciła wyjątek, albo zwróciła zły kod powrotu, aby cały skrypt nie był zamknięty, czekając na odpowiedź.

Czy jest jakiś sposób, aby zmusić PowerShell do automatycznego niepowodzenia w przeciwieństwie do proszenia użytkownika o działania?

Chuu
źródło
Myślę, że powinieneś zmienić nazwę swojego pytania na „Jak mogę Remove-Itemszybko zawieść?”
Jay Bazuzi
1
Nie chodzi konkretnie o Usuń element, to tylko przykładowy przykład. Istnieje wiele innych poleceń cmdlet, które będą blokować oczekiwanie na dane wejściowe użytkownika w odpowiednich warunkach.
Chuu

Odpowiedzi:

5

Rozwiązanie zaproponowane przez Eris skutecznie uruchamia kolejną instancję PowerShell. Alternatywnym sposobem na to, z prostszą składnią, jest skorzystanie z innej instancji programu powershell.exe.

powershell.exe -NonInteractive -Command "Remove-Item 'D:\Temp\t'"
Damian Powell
źródło
2
Naprawdę podoba mi się to rozwiązanie, ale przywraca koszmary pisania niezawodnych procedur przechowywanych w TSQL przed TRY / CATCH, które wymagały otaczania dosłownie każdego zapytania za pomocą wykrywacza błędów.
Chuu,
4

Zobacz Get-Help about_Preference_Variables:

$ ConfirmPreference
------------------
    Określa, czy Windows PowerShell automatycznie monituje o to
    potwierdzenie przed uruchomieniem polecenia cmdlet lub funkcji.

...

Brak: Windows PowerShell nie wyświetla monitów automatycznie.
                         Aby zażądać potwierdzenia określonego polecenia, użyj
                         parametr Potwierdź polecenie cmdlet lub funkcję.

Więc:

> $ConfirmPreference = 'None'
Jay Bazuzi
źródło
Odkryłem, że aby zobaczyć problem, który musiałem ustawić. $ ConfirmPreference = 'Low'
Guy Thomas
To nie wydaje się działać. Opcja Usuń element w katalogu nadal wyświetla monit po ustawieniu $ ConfirmPreference na „None” lub „Low”
Chuu
Działa dla Remove-ADUser(Serwer 2012R)
velkoon,
2

Ok, to jest naprawdę brzydkie, ale święta musztarda plami to „działa”.

Zagadnienia:

  • Nie wymyśliłem, jak kontynuować po pierwszym błędzie
  • W takim przypadku usuwa zwykłe pliki, a następnie zatrzymuje się w pierwszym folderze
  • Nie zastanawiałem się, jak uruchomić to polecenie cmdlet, jeśli dodam parametr UseTransaction
  • Będzie to działać tylko w przypadku Simple (polecenia, które nie robią wiele rzeczy w bieżącym środowisku). Nie testowałem niczego złożonego

    $MyPS = [Powershell]::Create()
    $MyPS.Commands.AddCommand("Remove-Item")
    $MyPS.Commands.AddParameter("Path", "D:\Temp\t")
    $MyPS.Invoke()

Wynik:

Commands                                                                                                                 
--------                                                                                                                 
{Remove-Item}                                                                                                            
{Remove-Item}                                                                                                            
Exception calling "Invoke" with "0" argument(s): "A command that prompts the user failed because the host program or the 
command type does not support user interaction. The host was attempting to request confirmation with the following 
message: The item at D:\Temp\t has children and the Recurse parameter was not specified. If you continue, all children 
will be removed with the item. Are you sure you want to continue?"
At line:19 char:1
+ $MyPS.Invoke()
+ ~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : CmdletInvocationException
Eris
źródło
Nie oznaczyłem tego jako rozwiązania, ponieważ nie znalazłem czasu na przetestowanie go. Czy ktoś oprócz tego wdrożył lub przetestował ten kod?
Chuu,
0

Wszystkie powyższe rozwiązania zawiodły dla mnie, gdy tworzyłem katalog, co oznaczało, że monitowałem o OK dla każdego katalogu, który utworzył mój skrypt - co było dużo. Dla mnie zadziałało | Out-null, aby przesłać wyniki do Out-Null

New-Item -ItemType Directory -Path $directory -Force:$true | Out-Null

Zauważ, że $ Directory jest ciągiem z pełną ścieżką do katalogu, który chcesz utworzyć. Mam nadzieję, że to komuś zaoszczędzi trochę czasu: P.

Chris Sprague
źródło
-1

Proponuję dwie techniki

a) Dołącz -force

b) Dołącz -errorAction silently continue

W ten sposób badam, które polecenia cmdlet obsługują dany parametr

Get-Command | where { $_.parameters.keys -contains "erroraction"}
Guy Thomas
źródło
Jednym z powodów, dla których zacząłem tą ścieżką jest to, że zwykle chcę zrobić coś przeciwnego do -force, tj. Coś w rodzaju -alwaysbackoff. Odkryłem, że większość poleceń obsługujących -force nie wydaje się mieć opcji wycofania się.
Chuu
1
Nawiasem mówiąc, wygodny skrót -errorAction SilentlyContinueto -ea 0.
Jay Bazuzi,