在我尝试的所有解决方案中,这是迄今为止最好且最容易设置的。从这里下载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 脚本编译为 Windows 可执行文件来实现。构建可执行文件需要使用第三方模块,但是运行可执行文件时不需要这些模块。我的最终目标是编译一个一行 PowerShell 脚本,用于弹出我的系统上的 DVD:
(New-Object -com "WMPlayer.OCX.7").cdromcollection.item(0).eject()
我的目标系统正在运行 Windows 7。所需的 WMF 更新因 Windows 版本而异:
所需的 PowerShell 模块适用于任何 Windows 版本。以下是我用于安装必要模块和编译 exe 的确切命令。您需要根据自己的系统调整驱动器、目录和文件名等详细信息:
mkdir i:\tmp\wmf
cd i:\tmp\wmf
pkunzip ..\Win7AndW2K8R2-KB3191566-x64.zip
c:\windows\system32\windowspowershell\v1.0\powershell.exe
Set-ExecutionPolicy RemoteSigned
.\Install-WMF5.1.ps1
<click> "Restart Now"
c:\Windows\System32\WindowsPowerShell\v1.0\powershell -version 3.0
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Install-Module -Name ps2exe -RequiredVersion 1.0.5
ps2exe i:\utils\scripts\ejectDVD.ps1 -noConsole
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 命令来创建包含Adam Taylor上面解决方案的定期任务。您可以稍后编辑创建的任务(例如,更改从每天运行为其他方式):
#---adjust this part---
$script = "C:\Users\user\some-script.ps1"
$time = '5:15 AM'
$user = 'user'
$title = "Some title"
#-----------------------------------
$arguments = @'
vbscript:Execute("CreateObject(""Wscript.Shell"").Run ""powershell -NoProfile -ExecutionPolicy bypass -NoLogo -Command """"& '{script}'"""""", 0 : window.close")
'@
$arguments = $arguments -replace "{script}",$script
$actions = (New-ScheduledTaskAction -Execute "mshta" -Argument $arguments)
$trigger = New-ScheduledTaskTrigger -Daily -At $time
$principal = New-ScheduledTaskPrincipal -UserId $user
$settings = New-ScheduledTaskSettingsSet -RunOnlyIfNetworkAvailable
$task = New-ScheduledTask -Action $actions -Principal $principal -Trigger $trigger -Settings $settings
Register-ScheduledTask $title -InputObject $task
$ShowWindowAsyncCode = '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);'
$ShowWindowAsync = Add-Type -MemberDefinition $ShowWindowAsyncCode -name Win32ShowWindowAsync -namespace Win32Functions -PassThru
$hwnd = (Get-Process -PID $pid).MainWindowHandle
if ($hwnd -ne [System.IntPtr]::Zero) {
# When you got HWND of the console window:
# (It would appear that Windows Console Host is the default terminal application)
$ShowWindowAsync::ShowWindowAsync($hwnd, 0)
} else {
# When you failed to get HWND of the console window:
# (It would appear that Windows Terminal is the default terminal application)
# Mark the current console window with a unique string.
$UniqueWindowTitle = New-Guid
$Host.UI.RawUI.WindowTitle = $UniqueWindowTitle
$StringBuilder = New-Object System.Text.StringBuilder 1024
# Search the process that has the window title generated above.
$TerminalProcess = (Get-Process | Where-Object { $_.MainWindowTitle -eq $UniqueWindowTitle })
# Get the window handle of the terminal process.
# Note that GetConsoleWindow() in Win32 API returns the HWND of
# powershell.exe itself rather than the terminal process.
# When you call ShowWindowAsync(HWND, 0) with the HWND from GetConsoleWindow(),
# the Windows Terminal window will be just minimized rather than hidden.
$hwnd = $TerminalProcess.MainWindowHandle
if ($hwnd -ne [System.IntPtr]::Zero) {
$ShowWindowAsync::ShowWindowAsync($hwnd, 0)
} else {
Write-Host "Failed to hide the console window."
}
}
pythonw.exe
/javaw.exe
类型的解决方案)。 它正在GitHub上被(相当)积极地讨论,有几个关于在PowerShell或操作系统级别进行潜在解决方法/修复的建议。 因此,它可能会在“某一天”得到修补。 - desseim