如何在不向用户显示窗口或任何其他标志的情况下运行PowerShell脚本?
换句话说,脚本应该在后台安静地运行,而不需要向用户发出任何信号。
不使用第三方组件的答案的额外功劳:)
您可以像这样运行它(但这会显示一段时间的窗口):
PowerShell.exe -windowstyle hidden { your script.. }
或者您使用我创建的帮助文件来避免执行该操作的名为 PsRun.exe 的窗口。您可以下载源文件和 exe 文件在 PowerShell 中使用 WinForm GUI 运行计划任务。我将它用于计划任务。
已编辑:正如 Marco 所指出的,此 -windowstyle 参数仅适用于 V2。
我遇到了同样的问题。我发现如果您转到正在运行powershell.exe脚本的任务计划程序中的任务,您可以单击“无论用户是否登录都运行”,并且在任务运行时永远不会显示 powershell 窗口。
您可以使用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/
安排隐藏的 PowerShell 任务(Internet 存档)
使用预定的 PowerShell(Internet 存档)更有趣
(通过此论坛主题。)
这是一种不需要命令行参数或单独的启动器的方法。它不是完全不可见的,因为在启动时会暂时显示一个窗口。但它很快就消失了。没关系,我认为,如果您想通过在资源管理器中双击或通过“开始”菜单快捷方式(当然包括“启动”子菜单)来启动脚本,这是最简单的方法。而且我喜欢它是脚本本身代码的一部分,而不是外部代码。
将其放在脚本的前面:
$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")
尽管这可能会非常短暂地闪烁窗口,但这应该很少发生。
答案-WindowStyle Hidden
很好,但窗口仍然会闪烁。
通过调用它时,我从未见过窗口闪烁cmd /c start /min ""
。
您的机器或设置可能会有所不同,但对我来说效果很好。
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'"
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
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 文件的路径中有空格时,所有示例都有效。
ps1 也隐藏在任务计划程序和快捷方式中
mshta vbscript:Execute("CreateObject(""WScript.Shell"").Run ""powershell -ExecutionPolicy Bypass & 'C:\PATH\NAME.ps1'"", 0:close")
我认为当您运行后台脚本时隐藏 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”。
从 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
};
这是一个有趣的演示,用于控制控制台的各种状态,包括最小化和隐藏。
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"
创建一个调用 PowerShell 脚本的快捷方式并将运行选项设置为最小化。这将防止窗口闪烁,尽管您仍然会在任务栏上看到正在运行的脚本的瞬间。
为了方便命令行使用,有一个简单的包装应用程序:
https://github.com/stax76/run-hidden
示例命令行:
run-hidden powershell -command calc.exe
我真的厌倦了通过答案才发现它没有按预期工作。
解决方案
制作一个 vbs 脚本来运行一个隐藏的批处理文件,该文件会启动 powershell 脚本。为这个任务制作 3 个文件似乎很愚蠢,但至少总大小小于 2KB,它可以从 tasker 或手动运行完美(你什么都看不到)。
脚本名.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.
我创建了一个小工具,将调用传递给您想要通过原始文件启动无窗口的任何控制台工具:
https://github.com/Vittel/RunHiddenConsole
编译后只需将可执行文件重命名为“<targetExecutableName>w.exe”(附加一个“w”),并将其放在原始可执行文件旁边。然后您可以使用通常的参数调用 eG powershellw.exe,它不会弹出窗口。
如果有人知道如何检查创建的进程是否正在等待输入,我很乐意提供您的解决方案:)
这是 Windows 10 中不包含任何第三方组件的有效解决方案。它通过将 PowerShell 脚本包装到 VBScript 中来工作。
第 1 步:我们需要更改一些 Windows 功能以允许 VBScript 运行 PowerShell,并默认使用 PowerShell 打开 .ps1 文件。
- 运行并输入“regedit”。单击确定,然后允许它运行。
- 粘贴此路径“HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell”,然后按 Enter。
- 现在打开右侧的条目并将值更改为 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 并按 Enter 键,然后单击确定。
完毕!如果您现在打开 .vbs,当您的脚本在后台运行时,您应该看不到控制台窗口。
如果这对您有用,请务必投票!
当您计划任务时,只需在“常规”选项卡下选择“无论用户是否登录都运行”。
另一种方法是让任务以另一个用户身份运行。
等到Powershell执行完毕,在vbs中得到结果
这是使用 Exec() 时Omegastripes 代码隐藏命令提示符窗口的改进版本
将来自 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
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.exe -windowstyle hidden -noexit -ExecutionPolicy Bypass -File <path_to_file>
然后设置运行:最小化
应该可以按预期工作,而无需添加隐藏窗口闪烁的代码,只是稍微延迟了执行。
在我尝试过的所有解决方案中,这是迄今为止最好和最容易设置的。从这里下载 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