如何运行PowerShell脚本而不显示窗口?

如何在不向用户显示窗口或任何其他符号的情况下运行PowerShell脚本?

换句话说,脚本应该在后台安静地运行,而不向用户发出任何信号。

不使用第三方组件的答案额外加分:)

568329 次浏览

您可以使用PowerShell社区扩展并执行以下操作:

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

您也可以使用VBScript:__abc0来执行此操作

(通过这个论坛的主题。)

您可以像这样运行它(但这会显示一个窗口):

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

或者,您可以使用我创建的辅助文件来避免名为psrun.exe的窗口,该窗口正是这样做的。您可以从在PowerShell中使用WinForm GUI运行计划任务下载源代码和EXE文件。我用它来完成计划任务。

编辑:正如Marco所指出的,此-WindowStyle参数仅适用于V2及更高版本。

我在Windows 7上从C#运行时遇到了这个问题,当作为系统帐户运行隐藏的PowerShell窗口时,“交互式服务检测”服务弹出。

使用“ createNoWindow ”参数可防止ISD服务弹出警告。

process.StartInfo = new ProcessStartInfo("powershell.exe",
String.Format(@" -NoProfile -ExecutionPolicy unrestricted -encodedCommand ""{0}""",encodedCommand))
{
WorkingDirectory = executablePath,
UseShellExecute = false,
CreateNoWindow = true
};

这里有一种方法,它不需要命令行参数或单独的启动器。它不是完全看不见的,因为在启动时窗口会暂时显示。但它很快就消失了。我认为,如果您想通过双击资源管理器或通过“开始”菜单快捷方式(当然包括“启动”子菜单)来启动脚本,这是最简单的方法。我喜欢它是脚本本身代码的一部分,而不是外部的东西。

把这个放在你的脚本的前面:

$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)

这里有一行字:

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

虽然这可能会短暂地闪烁一个窗口,但这种情况应该很少发生。

我认为,当您运行后台脚本时,隐藏PowerShell控制台屏幕的最佳方法是这个代码(“蓝饼 ”答案)。

我在所有需要在后台运行的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

如果这个答案对你有帮助,请投票他在这篇文章中的回答是“蓝饼”。

我也有同样的问题。我发现,如果您转到正在运行PowerShell.exe脚本的任务计划程序中的任务,您可以单击“无论用户是否登录都运行 ”,但在任务运行时将永远不会显示PowerShell窗口。

我已经创建了一个小工具,将调用传递给您想要启动无窗口的任何控制台工具,直到原始文件:

https://github.com/vittel/runhiddenconsole.

编译

后,只需将可执行文件重命名为“<;targetExecutableName>;w.exe ”(附加一个“ w ”),并将其放在原始可执行文件的旁边。 然后,您可以使用常用参数调用例如PowerShellW.exe,它不会弹出一个窗口。

如果有人知道如何检查创建的进程是否正在等待输入,我很乐意提供您的解决方案:)

下面是一个控制控制台各种状态的有趣演示,包括最小化和隐藏。

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"

PS1也从任务计划程序和快捷方式中隐藏

    mshta vbscript:Execute("CreateObject(""WScript.Shell"").Run ""powershell -ExecutionPolicy Bypass & 'C:\PATH\NAME.ps1'"", 0:close")

这是Windows 10中的一个工作解决方案,它不包含任何第三方组件。它的工作原理是将PowerShell脚本包装到VBScript中。

步骤1:我们需要更改一些Windows功能,以允许VBScript运行PowerShell,并在默认情况下使用PowerShell打开.PS1文件。

-转到“运行”并键入";注册表编辑";。单击“确定”,然后允许其运行。

-粘贴此路径";HKEY_类_root\Microsoft.PowerShellScript.1\Shell";然后按Enter键。

-现在打开右侧的条目并将值更改为0。

-以管理员身份打开PowerShell并键入";Set-ExecutionPolicy-ExecutionPolicy RemoteSigned";,按Enter键并使用";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并按Enter键,再单击“确定”。

干得好!如果您现在打开.VBS,当您的脚本在后台运行时,您应该看不到控制台窗口。

我真的厌倦了浏览答案,却发现它并不像预期的那样有效。

解决方案

创建一个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

脚本名称.bat

powershell.exe -ExecutionPolicy Bypass C:\Users\leathan\Documents\scriptName.ps1

脚本名称.PS1

Your magical code here.
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

等待执行PowerShell并在VBS中获取结果

这是OmegaStripes代码使用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

当您计划任务时,只需选择";一般的";下的";无论用户是否登录都运行";选项卡。

另一种方法是让任务以另一个用户的身份运行。

powershell.exe -windowstyle hidden -noexit -ExecutionPolicy Bypass -File <path_to_file>

然后设置运行:最小化

在不添加隐藏窗口Flash的代码的情况下,

应按预期工作 只是稍微推迟了一下执行。

答案与-WindowStyle Hidden是伟大的,但窗口仍将闪烁。

我从未见过通过cmd /c start /min ""调用窗口时窗口会闪烁。

你的机器或设置可能不同,但它对我来说很好。

1.调用文件

cmd /c start /min "" powershell -WindowStyle Hidden -ExecutionPolicy Bypass -File "C:\Users\username\Desktop\test.ps1"

使用参数调用文件

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'"

使用参数调用文件的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

使用函数和参数调用文件

cmd /c start /min "" powershell -WindowStyle Hidden -ExecutionPolicy Bypass -Command ". 'C:\Users\username\Desktop\test me.ps1'; Get-Test -stringTest 'Hello World'"

使用函数和参数调用文件的PowerShell内容为:

function Get-Test() {
[cmdletbinding()]
Param
(
[Parameter(Mandatory = $true, HelpMessage = 'The test string.')]
[String]$stringTest
)
Write-Host $stringTest
return
}

如果您需要在任务计划程序中运行它,则调用%comspec%作为程序/脚本,然后调用上述文件的代码作为参数。

注意:当PS1文件的路径中有空格时,所有示例都有效。

enter image description here

创建调用PowerShell脚本的快捷方式,并将“运行”选项设置为“最小化”。这将防止窗口闪烁,尽管您仍然会看到任务栏上运行的脚本的瞬间光点。

为了方便命令行使用,有一个简单的包装应用程序:

https://github.com/stax76/run-hidden.

示例命令行:

run-hidden powershell -command calc.exe

在我尝试过的所有解决方案中,这是迄今为止最好、最容易设置的。从此处下载HiddenW.exe-https://github.com/seidchr/runhiddenconsole/releases

假设您想要运行PowerShell V5 Consoleless.只需将HiddenW.exe重命名为PowerShellW.exe.如果要对CMD执行此操作,则重命名为CMDW.exe.如果要对PowerShell V7(PWSH)执行此操作,则重命名为PWSHW.ex.您可以创建HiddenW.EXE的多个副本,并且只需重命名到以字母W结尾的实际进程。然后,只需将该进程添加到系统环境路径中,这样您就可以从任何地方调用它。或者直接复制到C:\Windows.然后,就像这样叫它:

PowerShellW.\example.PS1

我发现编译为EXE是实现这一点的最简单的方法。编译脚本的方法有很多,但您可以尝试使用ISE Steroids

打开";Windows PowerShell ISE";,安装并运行ISesteroids:

Install-Module -Name "ISESteroids" -Scope CurrentUser -Repository PSGallery -Force


Start-Steroids

然后转到工具->;将代码转换为EXE,选择“隐藏控制台窗口”,然后创建应用程序。 您可以直接从Task Scheduler运行它,而不需要包装器或第三方应用程序。

我所做的是将.PS1文件转换为一个不可见的.exe文件,使用一个名为PS1 to exe的很棒的应用程序,您可以在这里下载:https://www.majorgeeks.com/files/details/ps1_to_exe.html

也许这会有所帮助(尽管我希望12年后你已经找到了一个合适的解决方案……🙂)