如何在不显示窗口的情况下运行 PowerShell 脚本?
Posted
技术标签:
【中文标题】如何在不显示窗口的情况下运行 PowerShell 脚本?【英文标题】:How to run a PowerShell script without displaying a window? 【发布时间】:2010-12-20 14:27:36 【问题描述】:如何在不向用户显示窗口或任何其他标志的情况下运行PowerShell 脚本?
换句话说,脚本应该在后台安静地运行,对用户没有任何迹象。
不使用第三方组件的答案的额外积分:)
【问题讨论】:
如果您有兴趣学习,请查看此问题:***.com/questions/573623/powershell-vs-unix-shells 此解决方案也适用于任务计划程序:***.com/a/51007810/571591 如果您需要绝对避免显示窗口,还有其他选项,例如 Windows 服务。 【参考方案1】:您可以使用PowerShell Community Extensions 并执行以下操作:
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/
Schedule Hidden PowerShell Tasks(互联网档案)
More fun with scheduled PowerShell(互联网档案)
(通过this forum thread。)
【讨论】:
是否有 NuGet 包,以便我可以从 Visual Studio 运行它?【参考方案2】:您可以像这样运行它(但这会显示一段时间的窗口):
PowerShell.exe -windowstyle hidden your script..
或者您使用我创建的帮助文件来避免执行该操作的名为 PsRun.exe 的窗口。您可以下载源代码和exe文件Run scheduled tasks with WinForm GUI in PowerShell。我将它用于计划任务。
已编辑:正如 Marco 所说,这个 -windowstyle 参数仅适用于 V2。
【讨论】:
我编译了PsRun,但是,如果我将它添加到计划任务中,它也会闪烁一个窗口...... 这里也一样,也不起作用,因为窗口仍然弹出来运行脚本。它会快速退出,但我们正在尝试在后台不间断地运行它。 是的,这就是为什么响应中有“但这会显示一段时间的窗口”。 -windowstyle hidden 并不完全有效。窗口至少会闪烁。【参考方案3】:我在从 c# 运行时遇到了这个问题,在 Windows 7 上,以 SYSTEM 帐户运行隐藏的 powershell 窗口时弹出“交互式服务检测”服务。
使用“CreateNoWindow”参数可防止 ISD 服务弹出它的警告。
process.StartInfo = new ProcessStartInfo("powershell.exe",
String.Format(@" -NoProfile -ExecutionPolicy unrestricted -encodedCommand ""0""",encodedCommand))
WorkingDirectory = executablePath,
UseShellExecute = false,
CreateNoWindow = true
;
【讨论】:
【参考方案4】:这是一种不需要命令行参数或单独的启动器的方法。它不是完全不可见的,因为在启动时会暂时显示一个窗口。但它很快就消失了。如果可以,我认为这是最简单的方法,如果您想通过在资源管理器中双击或通过“开始”菜单快捷方式(当然包括“启动”子菜单)来启动脚本。而且我喜欢它是脚本本身代码的一部分,而不是外部代码。
把它放在脚本的前面:
$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)
【讨论】:
谢谢,这很有帮助【参考方案5】:这是一个单行:
mshta vbscript:Execute("CreateObject(""Wscript.Shell"").Run ""powershell -NoLogo -Command """"& 'C:\Example Path That Has Spaces\My Script.ps1'"""""", 0 : window.close")
虽然这可能会非常短暂地闪烁窗口,但这应该很少发生。
【讨论】:
在大多数情况下,如果您使用 -windowstyle hidden,在登录的用户上下文中运行 Powershell.exe 将显示一个完整的窗口或短暂闪烁。要完全删除窗口,您可以执行以下两项操作之一: 1:在不同用户的上下文中运行,例如管理员帐户(不会向已登录的用户显示任何窗口)。或者 2:使用带有隐藏窗口标志的 objshell.run 的 vbscript 来启动 cmd.exe /c powershel.exe -file c:\script.ps1。当从 cmd 调用 powershell 时,它将在已被 wscript.exe //b /nologo c:\launcher.vbs 隐藏的现有 cmd 窗口中运行。 哇,突然。起初我什至没有注意到你的回答。我用一个非常相似的脚本回答。很高兴看到知识渊博的人给出真实的答案。 这应该是公认的答案,它是一种似乎适用于各种情况的方法(包括在任务调度程序内部,这是我的问题)。 警告:PowerShell 脚本的退出代码在这里丢失并且始终为 0。【参考方案6】:我认为在运行后台脚本时隐藏 PowerShell 控制台屏幕的最佳方法是 this code(“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" in his answer in this post.
【讨论】:
对我来说,控制台仍然显示大约一秒钟。 在 GPO 创建的计划任务中安排 powershell 时,这对我来说非常有用。为了踢球,我结合了“-windowstyle hidden”选项。根本没有弹出窗口。【参考方案7】:我遇到了同样的问题。我发现如果你去Task Scheduler中运行powershell.exe脚本的Task,你可以点击“Run无论用户是否登录”,并且在任务运行时永远不会显示powershell窗口。
【讨论】:
不依赖第三方扩展、可执行文件或包装脚本的最佳解决方案。 请注意,此选项要求用户具有“作为批处理作业登录”权限 这个解决方案使我的脚本not to run properly。 如果您的脚本涉及显示任何类型的 gui,则不是解决方案。 此解决方案将阻止您向当前用户显示通知。隐藏代码并不意味着它对现在工作的人完全有用。【参考方案8】:我创建了一个小工具,将调用传递给您想要启动无窗口的任何控制台工具到原始文件:
https://github.com/Vittel/RunHiddenConsole
编译后只需将可执行文件重命名为“
如果有人知道如何检查创建的进程是否正在等待输入,我很乐意提供您的解决方案:)
【讨论】:
如果您想在启动时使用MessageBox
运行powershell 脚本而没有任何 窗口闪烁(需要将EXE 编译为Winexe,而不是控制台应用程序,并要求将任务计划程序设置为“仅在用户登录时运行”,以便在当前桌面会话中显示对话框。)感谢您实现这一点,powershellw.exe 多年来一直在我的愿望清单上!
PS:我刚才已经包含了“等待输入”的解决方案(以及一些错误修复)!
@CarlWalsh 我假设你的意思是它不是一个控制台应用程序,而是一个赢取表单应用程序,这是正确的。只是它不包括任何窗口。但是项目类型应该在csproj文件中定义,用visual studio打开后不需要设置特定的输出类型【参考方案9】:
这是一个有趣的演示,用于控制控制台的各种状态,包括最小化和隐藏。
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"
【讨论】:
【参考方案10】:ps1 也隐藏在任务计划程序和快捷方式中
mshta vbscript:Execute("CreateObject(""WScript.Shell"").Run ""powershell -ExecutionPolicy Bypass & 'C:\PATH\NAME.ps1'"", 0:close")
【讨论】:
它也可以在链接中用作“目标:”。我希望这个答案在页面上更高,会为我节省很多时间。谢谢! 工作完美。正是我想要的【参考方案11】:这是 Windows 10 中不包含任何第三方组件的有效解决方案。它通过将 PowerShell 脚本包装到 VBScript 中来工作。
第 1 步:我们需要更改一些 windows 功能,以允许 VBScript 运行 PowerShell,并默认使用 PowerShell 打开 .ps1 文件。
-去运行并输入“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,当您的脚本在后台运行时,您应该看不到控制台窗口。
如果这对你有用,请务必投票!
【讨论】:
【参考方案12】:我真的厌倦了浏览答案却发现它没有按预期工作。
解决方案
制作一个 vbs 脚本来运行一个隐藏的批处理文件,该文件会启动 powershell 脚本。为这个任务制作 3 个文件似乎很愚蠢,但至少总大小小于 2KB,它可以从 tasker 或手动运行完美(你什么都看不到)。
scriptName.vbs
Set WinScriptHost = CreateObject("WScript.Shell")
WinScriptHost.Run Chr(34) & "C:\Users\leathan\Documents\scriptName.bat" & Chr(34), 0
Set WinScriptHost = Nothing
scriptName.bat
powershell.exe -ExecutionPolicy Bypass C:\Users\leathan\Documents\scriptName.ps1
scriptName.ps1
Your magical code here.
【讨论】:
为什么不能只在计划任务中使用.bat文件?为什么需要使用.vbs来调用.bat?我刚刚在计划任务中使用 .BAT 文件进行了测试,它工作正常,没有任何弹出窗口 我忘记了我不使用计划任务的原因,但是我能想到的原因有很多,但没有一个可以保证是正确的,因为我忘记了。我只记得发布我的解决方案,因为我最初尝试了其他解决方案,但它们没有用。我确实记得计划任务不是我想要的,但也许是因为它太动态了。事实上,答案可能是我使用了 vbs,因为我不能使用计划任务,无论如何它都无关紧要,如果它不在此处,只需提交你的作为另一个答案。 @shadowz1337 想通了,因为我需要再做一次。启动从调度程序隐藏的任务时会出现各种奇怪的情况,从而阻止 bat 文件实际被隐藏。这里的vbs专门解决了这个问题,这样你就可以以管理员用户身份运行隐藏的bat,否则你必须做系统,或者以任何用户身份运行。详细解释见superuser.com/questions/478052/…。 我只是使用 achedule 任务调用 nircmd exec hide 来运行 .bat 文件,然后它以管理员身份调用我的 Powershell 脚本,这从头到尾对用户完全隐藏。 我确定还有其他方法,但对我来说,如果我替换第一步它不会隐藏运行,可能是因为我没有登录用户我让脚本运行为?我不知道。【参考方案13】:c="powershell.exe -ExecutionPolicy Bypass (New-Object -ComObject Wscript.Shell).popup('Hello World.',0,'ОК',64)"
s=Left(CreateObject("Scriptlet.TypeLib").Guid,38)
GetObject("new:C08AFD90-F2A1-11D1-8455-00A0C91F3880").putProperty s,Me
WScript.CreateObject("WScript.Shell").Run c,0,false
【讨论】:
有趣的方法,但是如何在不使用临时文件的情况下将 PS (StdOut) 的输出捕获到变量中以在 vbs 脚本中使用? 我记得,这是我在其他评论中提出的一种极其简化的方法,它返回 StdOut 结果。你不应该从这个简单的代码中要求它不适合的东西。 我在您的其他评论中查看了较长的代码,它确实捕获了 StdOut,但它也在隐藏的控制台中重新启动了脚本,有效地隐藏了很多其他的东西,我只是在寻找一种方法只是隐藏脚本启动的 PS 窗口,但无论如何感谢您的重播,干杯。【参考方案14】:等到Powershell执行完毕,在vbs中得到结果
这是 Omegastripes 代码 Hide command prompt window when using Exec() 的改进版
将来自 cmd.exe 的混淆响应拆分为一个数组,而不是将所有内容都放入一个难以解析的字符串中。
此外,如果在执行 cmd.exe 期间发生错误,将在 vbs 中知道发生错误的消息。
Option Explicit
Sub RunCScriptHidden()
strSignature = Left(CreateObject("Scriptlet.TypeLib").Guid, 38)
GetObject("new:C08AFD90-F2A1-11D1-8455-00A0C91F3880").putProperty strSignature, Me
objShell.Run ("""" & Replace(LCase(WScript.FullName), "wscript", "cscript") & """ //nologo """ & WScript.ScriptFullName & """ ""/signature:" & strSignature & """"), 0, True
End Sub
Sub WshShellExecCmd()
For Each objWnd In CreateObject("Shell.Application").Windows
If IsObject(objWnd.getProperty(WScript.Arguments.Named("signature"))) Then Exit For
Next
Set objParent = objWnd.getProperty(WScript.Arguments.Named("signature"))
objWnd.Quit
'objParent.strRes = CreateObject("WScript.Shell").Exec(objParent.strCmd).StdOut.ReadAll() 'simple solution
Set exec = CreateObject("WScript.Shell").Exec(objParent.strCmd)
While exec.Status = WshRunning
WScript.Sleep 20
Wend
Dim err
If exec.ExitCode = WshFailed Then
err = exec.StdErr.ReadAll
Else
output = Split(exec.StdOut.ReadAll,Chr(10))
End If
If err="" Then
objParent.strRes = output(UBound(output)-1) 'array of results, you can: output(0) Join(output) - Usually needed is the last
Else
objParent.wowError = err
End If
WScript.Quit
End Sub
Const WshRunning = 0,WshFailed = 1:Dim i,name,objShell
Dim strCmd, strRes, objWnd, objParent, strSignature, wowError, output, exec
Set objShell = WScript.CreateObject("WScript.Shell"):wowError=False
strCmd = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass Write-Host Hello-World."
If WScript.Arguments.Named.Exists("signature") Then WshShellExecCmd
RunCScriptHidden
If wowError=False Then
objShell.popup(strRes)
Else
objShell.popup("Error=" & wowError)
End If
【讨论】:
【参考方案15】:当您计划任务时,只需在“常规”选项卡下选择“无论用户是否登录都运行”。
另一种方法是让任务以另一个用户身份运行。
【讨论】:
作品 +1。如果您需要海拔高度,用户也可以以用户“系统”身份运行。如果您需要您的用户,或者我的回答。【参考方案16】:powershell.exe -windowstyle hidden -noexit -ExecutionPolicy Bypass -File <path_to_file>
然后设置运行:最小化
应该可以按预期工作而无需添加隐藏窗口闪烁的代码 只是稍微延迟了执行。
【讨论】:
【参考方案17】:-WindowStyle Hidden
的答案很好,但窗口仍然会闪烁。
通过cmd /c start /min ""
调用它时,我从未见过窗口闪烁。
您的机器或设置可能不同,但对我来说效果很好。
1。调用文件
cmd /c start /min "" powershell -WindowStyle Hidden -ExecutionPolicy Bypass -File "C:\Users\username\Desktop\test.ps1"
2。调用带参数的文件
cmd /c start /min "" powershell -WindowStyle Hidden -ExecutionPolicy Bypass -Command ". 'C:\Users\username\Desktop\test me.ps1' -Arg1 'Hello' -Arg2 'World'"ps1'; -Arg1 'Hello' -Arg2 ' World'"
2 的 Powershell 内容。调用带参数的文件是:
Param
(
[Parameter(Mandatory = $true, HelpMessage = 'The 1st test string parameter.')]
[String]$Arg1,
[Parameter(Mandatory = $true, HelpMessage = 'The 2nd test string parameter.')]
[String]$Arg2
)
Write-Host $Arg1
Write-Host $Arg2
3。使用函数和参数调用文件
cmd /c start /min "" powershell -WindowStyle Hidden -ExecutionPolicy Bypass -Command ". 'C:\Users\username\Desktop\test me.ps1'; Get-Test -stringTest 'Hello World'"
3 的 Powershell 内容。使用函数和参数调用文件是:
function Get-Test()
[cmdletbinding()]
Param
(
[Parameter(Mandatory = $true, HelpMessage = 'The test string.')]
[String]$stringTest
)
Write-Host $stringTest
return
如果您需要在任务计划程序中运行它,则调用%comspec%
作为程序/脚本,然后调用上述文件的代码作为参数。
注意:当 PS1 文件的路径中有空格时,所有示例都有效。
【讨论】:
这很有趣,但我实际上发现你可以看到窗口。它只是比其他时间闪烁得快得多,但如果你密切注意,窗口仍然会弹出。如果你想看看我在说什么,然后打开一个窗口窗口(如资源管理器),你会看到它在短时间内失去焦点,因为另一个窗口获得焦点 这不是一个完美的解决方法,但它适用于我的所有用例,而且我从未见过它闪烁。它会失去文件资源管理器的焦点,不管它不会看到调用 PS 脚本会这样做吗? 只有在窗口前面弹出某些东西(无论多么简短)时,它才会失去对窗口的关注。当然,一旦焦点消失,焦点就会恢复,但重点仍然存在。我确实必须非常非常仔细地看才能看到闪光灯(它可能只出现了几帧),因为如果我不是在寻找它,我就看不到它,所以它比其他闪光灯(闪光) 方法。我最终使用了run-hidden
中的代码,它实际上是隐藏的(也没有失去焦点或任何东西),尽管我没有测试其他答案。至少你的回答肯定比其他闪光的侵入性更小
对于“调用带有参数的文件”,分号似乎是多余的,因为它会阻止脚本执行。
@Peter,感谢您指出这一点。为了清楚起见,我已经修复了这个问题并添加了 ps1 内容。【参考方案18】:
创建一个调用 PowerShell 脚本的快捷方式并将运行选项设置为最小化。这将防止窗口闪烁,尽管您仍会在任务栏上看到正在运行的脚本的瞬间。
【讨论】:
【参考方案19】:为了方便命令行使用,有一个简单的包装应用程序:
https://github.com/stax76/run-hidden
命令行示例:
run-hidden powershell -command calc.exe
【讨论】:
这实际上很有帮助,因为许多其他解决方案有点麻烦和/或不理想。这个很快。我也将其修改为以管理员身份运行模式,因为这就是我来这里的目的(没有闪烁的窗口+以管理员身份运行)。 github.com/cherryleafroad/run-hidden 当您在其中一个参数中使用“%USERPROFILE%”时,这似乎不起作用。 @jamie 我认为这是正常行为!我相信,Process 类不会扩展环境变量,并且像 run-hidden 这样的用户应用程序通常也不会这样做。 嗯,我明白了。谢谢你解释。【参考方案20】:在我尝试过的所有解决方案中,这是迄今为止最好且最容易设置的。从这里下载 hiddenw.exe - https://github.com/SeidChr/RunHiddenConsole/releases
假设您想在无控制台的情况下运行 Powershell v5。只需将 hiddenw.exe 重命名为 powershellw.exe。如果要对 cmd 执行此操作,请重命名为 cmdw.exe。如果要为 Powershell v7 (pwsh) 执行此操作,请重命名为 pwshw.exe。您可以创建 hiddenw.exe 的多个副本,然后将其重命名为实际进程并在末尾添加字母 w。然后,只需将该进程添加到您的系统环境 PATH 中,这样您就可以从任何地方调用它。或者直接复制到 C:\Windows。然后,就这样调用它:
powershellw .\example.ps1
【讨论】:
以上是关于如何在不显示窗口的情况下运行 PowerShell 脚本?的主要内容,如果未能解决你的问题,请参考以下文章
如何在不点击标记的情况下在 iOS 谷歌地图中显示信息窗口?
如何在不关闭 GUI 窗口的情况下停止运行 PyQt5 程序?
如何在不连接 Powershell 的情况下传递参数? [复制]