Как запустить сценарий PowerShell без отображения окна?

127

Как можно запустить сценарий PowerShell, не отображая окно или какой-либо другой знак для пользователя?

Другими словами, сценарий должен работать в фоновом режиме без каких-либо сигналов для пользователя.

Дополнительный балл за ответ, который не использует сторонние компоненты :)

Томас Братт
источник
Проверьте этот вопрос, если вы заинтересованы в обучении: stackoverflow.com/questions/573623/powershell-vs-unix-shells
Thomas Bratt
Это решение также работает для планировщика задач: stackoverflow.com/a/51007810/571591
Hilydrow

Ответы:

128

Вы можете запустить его так (но на какое-то время отображаются окна):

PowerShell.exe -windowstyle hidden { your script.. }

Или вы используете вспомогательный файл, который я создал, чтобы избежать окна PsRun.exe, которое делает именно это. Вы можете скачать исходный код и exe-файл Запускать запланированные задачи с помощью графического интерфейса WinForm в PowerShell. . Использую для плановых задач.

Отредактировано: как заметил Марко, этот параметр -windowstyle доступен только для V2.

stej
источник
6
Я скомпилировал PsRun, однако, если я добавлю его к запланированной задаче, он также
высветит
2
То же самое и здесь, тоже не работает, потому что все равно всплывает окно для запуска скрипта. Он быстро завершается, но мы пытаемся запустить его в фоновом режиме без перерыва.
Натан МакКаскл,
1
Да, поэтому в ответе есть «но это показывает окна на время».
Stej
21
@ThomasBratt Для запланированных задач я обнаружил, что сценарии PowerShell запускаются без вывода сообщений, -WindowStyle Hiddenесли задача не установлена Run whether user is logged on or notна вкладке «Общие» в разделе «Параметры безопасности».
Адам
1
Использование учетной записи пользователя для SYSTEM также позволяет избежать отображения окна.
Джон Элдридж
27

У меня была такая же проблема. Я узнал, что если вы перейдете к задаче в планировщике задач , в которой запущен сценарий powershell.exe , вы можете щелкнуть « Запускать независимо от того, вошел ли пользователь в систему или нет », и это никогда не отобразит окно PowerShell при выполнении задачи.

Yusha
источник
3
Лучшее решение, не зависящее от стороннего расширения, исполняемого файла или сценария-оболочки.
инвертировать
1
Обратите внимание, что эта опция требует, чтобы у пользователя была привилегия «Вход в систему как
пакетное задание
Это решение делает мой скрипт некорректным .
Мартин Аргерами,
18

Вы можете использовать расширения сообщества PowerShell и сделать следующее:

start-process PowerShell.exe -arg $pwd\foo.ps1 -WindowStyle Hidden

Вы также можете сделать это с помощью VBScript: http://blog.sapien.com/index.php/2006/12/26/more-fun-with-scheduled-powershell/

(Через эту ветку форума .)

Топор.
источник
Есть ли для этого пакет NuGet, чтобы я мог запускать его из Visual Studio?
Петр Кула
13

Вот подход, который не требует аргументов командной строки или отдельной программы запуска. Это не совсем невидимо, потому что окно на мгновение отображается при запуске. Но затем он быстро исчезает. Если все в порядке, это, я думаю, самый простой подход, если вы хотите запустить свой скрипт двойным щелчком в проводнике или с помощью ярлыка меню «Пуск» (включая, конечно, подменю «Запуск»). И мне нравится, что это часть кода самого скрипта, а не что-то внешнее.

Поместите это в начало вашего скрипта:

$t = '[DllImport("user32.dll")] public static extern bool ShowWindow(int handle, int state);'
add-type -name win -member $t -namespace native
[native.win]::ShowWindow(([System.Diagnostics.Process]::GetCurrentProcess() | Get-Process).MainWindowHandle, 0)
Энди Лоури
источник
10

Вот однострочник:

mshta vbscript:Execute("CreateObject(""Wscript.Shell"").Run ""powershell -NoLogo -Command """"& 'C:\Example Path That Has Spaces\My Script.ps1'"""""", 0 : window.close")

Хотя при этом возможно очень короткое мигание окна, это должно быть редкостью.

Адам Тейлор
источник
В большинстве случаев при запуске Powershell.exe в контексте вошедшего в систему пользователя отображается либо полное окно, либо кратковременное мигание, если вы используете -windowstyle hidden. Чтобы полностью удалить окно, вы можете сделать одно из двух: 1: Запускать в контексте другого пользователя, такого как учетная запись администратора (не будут отображать окна для вошедшего в систему пользователя). Или 2: используйте vbscript с objshell.run с флагом скрытого окна для запуска cmd.exe / c powershel.exe -file c: \ script.ps1. Когда powershell вызывается из cmd, он запускается в существующем окне cmd, которое уже скрыто wscript.exe // b / nologo c: \ launcher.vbs.
Iconiu
вау, Вдруг. Я сначала даже не заметил вашего ответа. Я ответил очень похожим сценарием. Приятно видеть знающего человека, который дает реальный ответ.
Гоша
Это должен быть принятый ответ, это единственный метод, который, кажется, работает в любой ситуации (в том числе в планировщике задач, что было моей проблемой).
Мартин Аргерами,
6

У меня возникла эта проблема при запуске из C #, в Windows 7 служба «Обнаружение интерактивных служб» выскакивала при запуске скрытого окна PowerShell в качестве учетной записи SYSTEM.

Использование параметра CreateNoWindow предотвратило появление предупреждения службы ISD.

process.StartInfo = new ProcessStartInfo("powershell.exe",
    String.Format(@" -NoProfile -ExecutionPolicy unrestricted -encodedCommand ""{0}""",encodedCommand))
{
   WorkingDirectory = executablePath,
   UseShellExecute = false,
   CreateNoWindow = true
};
JMC
источник
5

Я думаю, что лучший способ скрыть экран консоли PowerShell, когда вы запускаете фоновые скрипты, - это этот кодBluecakes ответ ").

Я добавляю этот код в начало всех моих сценариев PowerShell, которые мне нужно запускать в фоновом режиме.

# .Net methods for hiding/showing the console in the background
Add-Type -Name Window -Namespace Console -MemberDefinition '
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();

[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'
function Hide-Console
{
    $consolePtr = [Console.Window]::GetConsoleWindow()
    #0 hide
    [Console.Window]::ShowWindow($consolePtr, 0)
}
Hide-Console

Если этот ответ помог вам, проголосуйте за "Bluecakes" за его ответ в этом посте.

gavraham
источник
Для меня консоль все еще отображается около секунды.
thdoan
3

ps1 скрыт от планировщика заданий и ярлыка тоже

    mshta vbscript:Execute("CreateObject(""WScript.Shell"").Run ""powershell -ExecutionPolicy Bypass & 'C:\PATH\NAME.ps1'"", 0:close")
Гоша
источник
2

Я создал небольшой инструмент, передающий вызов любому консольному инструменту, который вы хотите запустить без окон, через исходный файл:

https://github.com/Vittel/RunHiddenConsole

После компиляции просто переименуйте исполняемый файл в «<targetExecutableName> w.exe» (добавьте «w») и поместите его рядом с исходным исполняемым файлом. Затем вы можете вызвать eG powershellw.exe с обычными параметрами, и окно не появится.

Если у кого-то есть идея, как проверить, ожидает ли созданный процесс ввода, я буду рад включить ваше решение :)

Крис
источник
1
Это лучший ответ, если вы хотите запускать сценарии powershell, используя MessageBoxбез какой-либо вспышки окна при запуске (требуется EXE, скомпилированный как Winexe, а не консольное приложение, и требуется, чтобы планировщик заданий был установлен на «Запускать только тогда, когда пользователь вошел в систему. on ", чтобы диалоговые окна отображались в текущем сеансе рабочего стола.) Спасибо за реализацию, powershellw.exe уже много лет находится в моем списке желаний!
Карл Уолш
PS: я недавно включил решение для "ожидания ввода" (а также пару исправлений)!
Крис
@CarlWalsh, я полагаю, вы имеете в виду, что это не консольное приложение, а приложение winforms, что правильно. просто в нем нет окон. но тип проекта должен быть определен в файле csproj, и вам не нужно устанавливать конкретный тип вывода после его открытия в Visual Studio
Крис
2

Вот рабочее решение в Windows 10, которое не включает сторонних компонентов. Он работает, заключая сценарий PowerShell в VBScript.

Шаг 1: нам нужно изменить некоторые функции Windows, чтобы VBScript мог запускать PowerShell и открывать файлы .ps1 с помощью PowerShell по умолчанию.

-перейдите к запуску и введите "regedit". Нажмите ОК, а затем дайте ему поработать.

-вставьте этот путь «HKEY_CLASSES_ROOT \ Microsoft.PowerShellScript.1 \ Shell» и нажмите ввод.

-Теперь откройте запись справа и измените значение на 0.

-открыть PowerShell от имени администратора и ввести «Set-ExecutionPolicy -ExecutionPolicy RemoteSigned», нажать клавишу ВВОД и подтвердить изменение с помощью «y», а затем введите.

Шаг 2: Теперь мы можем начать упаковывать наш скрипт.

-сохраните ваш скрипт Powershell как файл .ps1.

-создайте новый текстовый документ и вставьте этот скрипт.

Dim objShell,objFSO,objFile

Set objShell=CreateObject("WScript.Shell")
Set objFSO=CreateObject("Scripting.FileSystemObject")

'enter the path for your PowerShell Script
 strPath="c:\your script path\script.ps1"

'verify file exists
 If objFSO.FileExists(strPath) Then
   'return short path name
   set objFile=objFSO.GetFile(strPath)
   strCMD="powershell -nologo -command " & Chr(34) & "&{" &_
    objFile.ShortPath & "}" & Chr(34)
   'Uncomment next line for debugging
   'WScript.Echo strCMD

  'use 0 to hide window
   objShell.Run strCMD,0

Else

  'Display error message
   WScript.Echo "Failed to find " & strPath
   WScript.Quit

End If

-Теперь измените путь к файлу на местоположение вашего сценария .ps1 и сохраните текстовый документ.

-Теперь щелкните файл правой кнопкой мыши и перейдите к переименованию. Затем измените расширение имени файла на .vbs и нажмите клавишу ВВОД, а затем нажмите ОК.

СДЕЛАНО! Если вы сейчас откроете .vbs, вы не увидите консольного окна, пока ваш скрипт работает в фоновом режиме.

не забудьте проголосовать, если это сработало для вас!

neobihli
источник
1

Вот забавная демонстрация управления различными состояниями консоли, включая свертывание и скрытие.

Add-Type -Name ConsoleUtils -Namespace WPIA -MemberDefinition @'
   [DllImport("Kernel32.dll")]
   public static extern IntPtr GetConsoleWindow();
   [DllImport("user32.dll")]
   public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'@

$ConsoleMode = @{
 HIDDEN = 0;
 NORMAL = 1;
 MINIMIZED = 2;
 MAXIMIZED = 3;
 SHOW = 5
 RESTORE = 9
 }

$hWnd = [WPIA.ConsoleUtils]::GetConsoleWindow()

$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.MAXIMIZED)
"maximized $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.NORMAL)
"normal $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.MINIMIZED)
"minimized $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.RESTORE)
"restore $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.HIDDEN)
"hidden $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.SHOW)
"show $a"
js2010
источник