如何运行PowerShell脚本而不向用户显示窗口或任何其他符号?

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

不使用第三方组件的答案可获得额外分数:)


当前回答

我发现编译成exe是实现这一目标最简单的方法。有许多方法来编译一个脚本,但你可以尝试ISE类固醇

打开“Windows PowerShell ISE”,安装并运行ISESteroids:

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

Start-Steroids

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

其他回答

我也有同样的问题。我发现如果你去任务调度器的任务,正在运行powershell.exe脚本,你可以点击“运行无论用户是否登录”,这将永远不会显示powershell窗口时,任务运行。

等待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

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

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

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

换句话说,脚本应该在后台安静地运行,而不需要向用户发出任何信号。 不使用第三方组件的答案可获得额外分数:)

我找到了一种方法,通过将PowerShell脚本编译为Windows可执行文件来实现这一点。需要第三方模块来构建可执行文件,但不需要运行它。我的最终目标是编译一行PowerShell脚本,在我的系统上弹出DVD:

(New-Object -com "WMPlayer.OCX.7").cdromcollection.item(0).eject()

我的目标系统是Windows 7。具体的WMF更新需要根据Windows版本有所不同:

下载并安装WMF 5.1包

所需的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

您可以使用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 Archive) 更多的乐趣与计划的PowerShell(互联网档案)

(通过这个论坛。)