223

How is it possible to run a PowerShell script without displaying a window or any other sign to the user?

In other words, the script should run quietly in the background without any sign to the user.

Extra credit for an answer that does not use third party components :)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Thomas Bratt
  • 48,038
  • 36
  • 121
  • 139
  • Checkout this question if you are interested in learning: http://stackoverflow.com/questions/573623/powershell-vs-unix-shells – Thomas Bratt Nov 26 '09 at 12:21
  • This solution works for Task Scheduler as well: https://stackoverflow.com/a/51007810/571591 – Hilydrow May 15 '20 at 05:25
  • There are other options, such as a Windows service, if you need to absolutely avoid showing a window. – ryanwebjackson Jun 24 '21 at 02:22
  • For anyone interested, the window flashing even with `-WindowStyle hidden` is a known Windows limitation with CUI applications (it only works as expected with GUI ones -- hence the `pythonw.exe` / `javaw.exe`-type solutions implemented by other projects). It is being (rather) actively discussed [on GitHub](https://github.com/PowerShell/PowerShell/issues/3028), with several suggestions for potential workarounds / fixes at the PowerShell or OS level. So, it might get patched, "one day". – desseim May 10 '22 at 17:24

25 Answers25

200

You can either run it like this (but this shows a window for a while):

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

Or you use a helper file I created to avoid the window called PsRun.exe that does exactly that. You can download the source and exe file from Run scheduled tasks with WinForm GUI in PowerShell. I use it for scheduled tasks.

Edited: as Marco noted this -WindowStyle parameter is available only for V2 and above.

stej
  • 28,745
  • 11
  • 71
  • 104
  • 11
    I compiled the PsRun, however, if I add it to the scheduled task, it also flashes a window... – Ciantic Dec 12 '15 at 17:33
  • 5
    Same here, also does not work because the window still pops up to run the script. It exits quickly but we're trying to run this in the background without interruption. – Nathan McKaskle Aug 23 '16 at 15:30
  • 4
    Yes, that's why there is "but this shows a windows for a while" in the response. – stej Aug 24 '16 at 06:04
  • 46
    @ThomasBratt For scheduled tasks, I've found PowerShell scripts run silently without `-WindowStyle Hidden` if the task is set to `Run whether user is logged on or not` on the General tab under "Security Options" section. – adam Dec 02 '16 at 14:26
  • This is a nice option, but be aware that if you have a "wait for input" line at the end of your script, the window being hidden will make you unable to complete that wait line, causing the process to stay around forever. So if you know you're going to sometimes be adding the "wait for input" line after the tasks are done (for inspection/debugging), the other approaches (@AndyLowry @gavraham) are better as you can easily "re-show" the console window at that point. (just call `ShowWindow(..., 1)`) – Venryx Dec 08 '18 at 02:23
  • 2
    Using User Account to SYSTEM also avoids a window being displayed. – Jon Eldridge Dec 10 '18 at 16:43
  • 16
    -windowstyle hidden doesn't completely work. The window will at least flash. – js2010 Apr 20 '20 at 13:52
  • PowerShell.exe -windowstyle hidden -command yourscript.ps1 I use this as scheduled task to backup some folder on my machine so it does not jump into my face when it works – McVitas Jul 21 '20 at 15:02
  • 1
    For those interested: The powershell.exe executable has so far always been linked to use the character-mode (i.e. console) subsystem, so even if PowerShell was to hide its console window at the earliest possible time, a console window would always show from the start of the PowerShell process until it hides it. I only see two ways around that: either convince Microsoft to release, along with powershell.exe & powershell_ise.exe, an official, GUI-linked, and console-optional build (unlikely); or you/someone to fork the PowerShell open-source project and create a patch to make such build possible – johnwait Aug 19 '20 at 04:36
  • 1
    @johnwait: See [GitHub issue #3028](https://github.com/PowerShell/PowerShell/issues/3028). – mklement0 Nov 18 '20 at 23:30
  • 4
    You can at least get around the window flashing with calling cmd with `cmd /c start /min "" powershell -WindowStyle Hidden -ExecutionPolicy Bypass -File "C:\Users\username\Desktop\test.ps1"`. – Ste Apr 28 '21 at 12:03
  • Link is now dead. – user2924019 Jul 02 '21 at 12:06
77

I found out if you go to the Task in Task Scheduler that is running the powershell.exe script, you can click "Run whether user is logged on or not" and that will never show the powershell window when the task runs.


Drawbacks: the script can not interact with the screen of the logged on user (e.g. to display notifications or any GUI element).

Prerequisites: The user must have the "Log on as Batch Job" privilege.

ndemou
  • 4,691
  • 2
  • 30
  • 33
Yusha
  • 1,496
  • 2
  • 14
  • 30
26

You can use the PowerShell Community Extensions and do this:

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

You can also do this with VBScript: http://blog.sapien.com/index.php/2006/12/26/more-fun-with-scheduled-powershell/

(Via this forum thread.)

ax.
  • 58,560
  • 8
  • 81
  • 72
25

The answer with -WindowStyle Hidden is great but the windows will still flash.

I've never seen a window flash when calling it via cmd /c start /min "".

Your machine or setup may differ but it works well for me.

1. Call a file

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

2. Call a file with arguments

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

Powershell content for 2. Call a file with arguments is:

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. Call a file with a function and arguments

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

Powershell content for 3. Call a file with a function and arguments is:

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

In case you need to run this in Task Scheduler then call %comspec% as the Program/Script and then code for calling the file above as the argument.

Note: All examples work when the PS1 file has spaces in its path.

enter image description here

Community
  • 1
  • 1
Ste
  • 1,729
  • 1
  • 17
  • 27
  • 7
    This is interesting, but I actually discovered that you CAN see the window. It just flashes MUCH MUCH quicker than the other times, but if you're paying very close attention, the window still popped up. If you want to see what I'm talking about, then open a windowed window (like explorer) and you'll see it loses focus for a brief moment as the other window gains focus – Kobato Sep 10 '21 at 17:58
  • It's not a perfect workaround but it worked in all of my use cases and I've never seen it flash. It losing focus of File Explorer would happen regardless would it not seeing as calling a PS script would do that anyway? – Ste Sep 10 '21 at 21:21
  • It can only lose focus on a window if something popped up in front of it (no matter how brief). Of course the focus is restored once it disappears, but the point remains. I did have to look VERY VERY closely to see the flash (it may have only appeared for a few frames) as I couldn't see it if I wasn't looking for it, so it is less of a flash than other (flashy) methods. I ended up using the code from the `run-hidden` which was actually hidden (no lose focus or anything as well), although I haven't tested the other answers. Your answer was definitely less invasive than other flashes at least – Kobato Sep 10 '21 at 21:44
  • 1
    For the "Call a file with arguments" the semicolon seems to be extra as it prevents the script from executing. – Peter Jan 03 '22 at 04:38
  • @Peter, thanks for pointing that out. I've fixed that and added the ps1 content also for clarity. – Ste Jan 04 '22 at 20:41
  • @Ste maybe you have still left some stuff in there by mistake, or I am just not understanding what this part is supposed to do `ps1'; -Arg1 'Hello' -Arg2 ' World'"` – Peter Jan 04 '22 at 22:54
  • That has been removed in my edit for **Call a file with arguments**. In the **Call a file with a function and arguments** example the `;` is required after calling the file to call the function with those params. – Ste Jan 05 '22 at 00:14
17

Here's an approach that that doesn't require command line args or a separate launcher. It's not completely invisible because a window does show momentarily at startup. But it then quickly vanishes. Where that's OK, this is, I think, the easiest approach if you want to launch your script by double-clicking in explorer, or via a Start menu shortcut (including, of course the Startup submenu). And I like that it's part of the code of the script itself, not something external.

Put this at the front of your script:

$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)
Andy Lowry
  • 785
  • 7
  • 12
17

Here's a one-liner:

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

Although it's possible for this to flash a window very briefly, that should be a rare occurrence.

Adam Taylor
  • 4,691
  • 1
  • 37
  • 38
  • 1
    In most cases, running Powershell.exe in the logged on users context will either show a full window or flash briefly if you use -windowstyle hidden. To totally remove window you can do one of two things: 1: Run in a different user's context such as admin account (won't display any windows to the logged on user). Or 2: Use a vbscript with objshell.run with a hidden window flag to launch cmd.exe /c powershel.exe -file c:\script.ps1. When powershell is called from cmd it will run in the existing cmd window which is already hidden by wscript.exe //b /nologo c:\launcher.vbs. – Iconiu Mar 26 '19 at 21:59
  • wow, Suddenly. I did not even notice your answer at first. I answered with a very similar script. It's nice to see a knowledgeable person who gives a real answer. – Garric Dec 15 '19 at 16:16
  • 2
    This should be the accepted answer, it is the one method that seems to work in every situation (including inside the task scheduler, which was my problem). – Martin Argerami Jun 24 '20 at 20:40
  • 1
    Caveat: The exit code from the PowerShell script gets lost here and is always 0. – letmaik Nov 06 '20 at 21:17
15

ps1 hidden from the Task Scheduler and shortcut too

    mshta vbscript:Execute("CreateObject(""WScript.Shell"").Run ""powershell -ExecutionPolicy Bypass & 'C:\PATH\NAME.ps1'"", 0:close")
Garric
  • 591
  • 3
  • 10
  • 1
    It works as "Target:" in a link as well. I wish this answer was higher up on the page, would have saved me a lot of time. Thank you! – FHC Apr 24 '21 at 14:50
  • 1
    Worked Flawlessly. Just what i was looking for – Capgros Jul 19 '21 at 09:58
8

I think that the best way to hide the console screen of the PowerShell when your are running a background scripts is this code ("Bluecakes" answer).

I add this code in the beginning of all my PowerShell scripts that I need to run in background.

# .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

If this answer was help you, please vote to "Bluecakes" in his answer in this post.

gavraham
  • 129
  • 1
  • 3
  • 2
    For me the console still displays for about a second. – thdoan May 02 '20 at 03:19
  • This worked wonderfully for me when scheduling a powershell in a scheduled task created by a GPO. For kicks, I combined with the "-windowstyle hidden" option. No pop up window at all. – Chris Apr 01 '21 at 12:34
7

I was having this problem when running from c#, on Windows 7, the "Interactive Services Detection" service was popping up when running a hidden powershell window as the SYSTEM account.

Using the "CreateNoWindow" parameter prevented the ISD service popping up it's warning.

process.StartInfo = new ProcessStartInfo("powershell.exe",
    String.Format(@" -NoProfile -ExecutionPolicy unrestricted -encodedCommand ""{0}""",encodedCommand))
{
   WorkingDirectory = executablePath,
   UseShellExecute = false,
   CreateNoWindow = true
};
Vincent K
  • 1,326
  • 12
  • 19
jmc
  • 1,058
  • 1
  • 12
  • 20
6

When you scheduled task, just select "Run whether user is logged on or not" under the "General" tab.

Alternate way is to let the task run as another user.

Sandeep Verma
  • 61
  • 1
  • 1
5

Here's a fun demo of controlling the various states of the console, including minimize and hidden.

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"
js2010
  • 23,033
  • 6
  • 64
  • 66
5

Create a shortcut that calls the PowerShell script and set the Run option to Minimized. This will prevent a window from flashing although you will still get a momentary blip of the script running on the Task Bar.

4

I got really tired of going through answers only to find it did not work as expected.

Solution

Make a vbs script to run a hidden batch file which launches the powershell script. Seems silly to make 3 files for this task but atleast the total size is less than 2KB and it runs perfect from tasker or manually (you dont see anything).

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.
Leathan
  • 433
  • 4
  • 7
  • Why can't you just use the .bat file in scheduled task? Why do you need to use .vbs to call .bat? I just tested using the .BAT file in scheduled task and it works fine without any popups – shadowz1337 Apr 22 '21 at 22:29
  • I forgot the reason why I was not using scheduled task, but there are lots of reasons I could think of off the top of my head, none of which are guaranteed to be right as I forgot. I only remember posting my solution because I originally tried the others and they did not work. I do remember scheduled tasks was not what I wanted though maybe because it was too dynamic idk. In fact the answer might be I used the vbs because I could not use scheduled task, anyway its all irrelevant, just submit yours as another answer if its not on here. – Leathan Aug 24 '21 at 07:12
  • @shadowz1337 Figured it out since I needed to do it again. There are various oddities when starting a task hidden from the scheduler that prevent the bat file from actually being hidden. The vbs here specifically fixes this issue, with this you can run a hidden bat as your admin user, else ud have to do system, or run as any user. see https://superuser.com/questions/478052/windows-7-task-scheduler-hidden-setting-doesnt-work for detailed explanations. – Leathan Aug 28 '21 at 02:58
  • I just use achedule task to call nircmd exec hide to run the .bat file, which then invokes my Powershell script as admin and this is completely hidden to the user from start to end. – shadowz1337 Oct 26 '21 at 18:43
  • Im sure there are other ways, but for me, if I replace the first step it doesnt run hidden, maybe because im not signed on the user im having the script run as? I dont know. – Leathan Nov 08 '21 at 17:47
  • not sure what you mean by "doesn't run hidden if you replace the first step". Anyway, the way I do it is using Task Scheduler to call a .bat file with nircmd. Like this "nircmd exec hide D:\Test.bat". Nircmd is a tool from Nirsoft, just download it and put it into your C:\Windows folder, so that you can call it from anywhere. Then, in the .bat file, just call your Powershell script like this - powershell.exe -ExecutionPolicy ByPass -File "D:\Test.ps1". So basically, Task Scheduler uses Nircmd to call the .bat file, which then calls the Powershell script. Completely hidden, no popups. – shadowz1337 Nov 12 '21 at 01:10
  • And the reason why it is completely hidden is because Nircmd supports running commands without a console, by using the "exec hide" switch. The nice thing about this is I can still make my .bat or .ps1 scripts to show popups whenever I need it to. For example, if I have a script that shows a GUI to prompt the user to enter something, then that will still popup. The script itself is run in the background without disruption to the user, but I can still see the actual user input popup when required. – shadowz1337 Nov 12 '21 at 01:12
  • If you need to run Powershell elevated, just use this in your .bat file - CMD /C PowerShell "SL -PSPath '%CD%'; $Path = (GL).Path; SL ~; Start PowerShell -Verb RunAs -Args \"-ExecutionPolicy ByPass" SL -PSPath '"$Path"'; & '".\Test.ps1"'"\"" – shadowz1337 Nov 12 '21 at 01:13
  • Finally, I also use Autohotkey scripts, which I can run based on hotkey triggers. E.g. I can configure my Autohotkey script to do something when I press CTRL+SHIFT+O. I can invoke this hotkey trigger via a Powershell script. So again, nircmd calls .bat script, which calls Powershell script, which then invokes hotkey to trigger my Autohotkey script. I'll still get actual user prompt popups for Autohotkey. – shadowz1337 Nov 12 '21 at 01:17
  • In your Powershell script, you can use something like this to trigger the hotkeys: [void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') Add-Type -AssemblyName PresentationFramework Add-Type -AssemblyName Microsoft.VisualBasic [System.Windows.Forms.SendKeys]::SendWait("^{F16}"); – shadowz1337 Nov 12 '21 at 01:17
4

For easy command line usage, there is a simple wrapper app:

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

Example command line:

run-hidden powershell -command calc.exe
stax76
  • 416
  • 4
  • 12
  • This was actually very helpful, because so many of the other solutions are a bit cumbersome and/or not ideal. This one is FAST. I modified it to run-as admin mode as well since that's what I came here for (no flashing windows + run as admin). https://github.com/cherryleafroad/run-hidden – Kobato Sep 10 '21 at 20:02
  • This seems not to work when you use "%USERPROFILE%" in one of your arguments. – jamie Jan 24 '22 at 15:27
  • @jamie I think this is normal behavior! The Process class does not expand env vars and user applications like run-hidden typically don't do this either, I believe. – stax76 Jan 26 '22 at 15:59
  • Uh I see. Thanks for explaining that. – jamie Jan 31 '22 at 14:51
2

I have created a small tool passing the call to any console tool you want to start windowless through to the original file:

https://github.com/Vittel/RunHiddenConsole

After compiling just rename the executable to "<targetExecutableName>w.exe" (append a "w"), and put it next to the original executable. You can then call e.G. powershellw.exe with the usual parameters and it wont pop up a window.

If someone has an idea how to check whether the created process is waiting for input, ill be happy to include your solution :)

Chris
  • 527
  • 3
  • 15
  • 1
    This is the best answer if you want to run powershell scripts using `MessageBox` without **any** flash of the window on startup (requiring an EXE compiled as a Winexe, not a console app, and requiring Task Scheduler to be set to "Run only when user is logged on" so dialogs show in the current desktop session.) Thanks for implementing this, powershellw.exe has been on my wishlist for years! – Carl Walsh Jan 11 '19 at 16:48
  • PS: i have included the solution for "waiting for input" a while ago (as well as a couple of bugfixes)! – Chris Jul 12 '19 at 10:25
  • @CarlWalsh i assume you mean that its not an console app, but a win forms app instead, which is correct. just it doesnt include any windows. but the project type should be defined in the csproj file and you should not need to set a specific output type after opening it with visual studio – Chris Jul 12 '19 at 10:28
1

Here is a working solution in windows 10 that does not include any third-party components. It works by wrapping the PowerShell script into VBScript.

Step 1: we need to change some windows features to allow VBScript to run PowerShell and to open .ps1 files with PowerShell by default.

-go to run and type "regedit". Click on ok and then allow it to run.

-paste this path "HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell" and press enter.

-now open the entry on the right and change the value to 0.

-open PowerShell as an administrator and type "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned", press enter and confirm the change with "y" and then enter.

Step 2: Now we can start wrapping our script.

-save your Powershell script as a .ps1 file.

-create a new text document and paste this script.

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

-now change the file path to the location of your .ps1 script and save the text document.

-Now right-click on the file and go to rename. Then change the filename extension to .vbs and press enter and then click ok.

DONE! If you now open the .vbs you should see no console window while your script is running in the background.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
neobihli
  • 11
  • 1
1

Wait until Powershell is executed and get the result in vbs

This is an improved version of the Omegastripes code Hide command prompt window when using Exec()

Splits the confused responses from cmd.exe into an array instead of putting everything into a hard-to-parse string.

In addition, if an error occurs during the execution of cmd.exe, a message about its occurrence will become known in 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
Garric
  • 591
  • 3
  • 10
1
powershell.exe -windowstyle hidden -noexit -ExecutionPolicy Bypass -File <path_to_file>

then set the run: Minimized

should work as expected without added code for hidden window flash just slightly more delayed execution.

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Jehson
  • 11
  • 1
1

A single vbs file solution. You first have to convert your ps script to base64 string, place it in a variable in the template shown below and save it as I vbs file. Runs without powershell popppring up.

dim EncodedCommand
EncodedCommand = "COMMAND"

pSCmd = "powershell.exe -noexit -windowstyle Hidden -executionpolicy bypass -encodedcommand " & EncodedCommand

CreateObject("WScript.Shell").Run pSCmd, 0, True
Nawad-sama
  • 151
  • 2
  • 12
0
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
Garric
  • 591
  • 3
  • 10
  • Interesting method, but how can you capture the output from PS (StdOut) into a variable to use in the vbs script without using a temporary file? – Safwan Mar 13 '21 at 10:59
  • As I recall, This is my an extremely simplified method presented here in my other comment, which returns StdOut result. You should not demand from this simple code that for which it is not intended. – Garric Mar 14 '21 at 15:30
  • I went through the longer code in your other comment, it does capture StdOut but it also relaunches the script in a hidden console, effectively hiding a lot of other things, I was simply looking for a way to just hide the PS window that is started by the script, but thanks anyway for your replay, cheers. – Safwan Mar 15 '21 at 19:05
0

Out of all the solutions I've tried, this is by far the best and easiest to set up. Download hiddenw.exe from here - https://github.com/SeidChr/RunHiddenConsole/releases

Let's say you want to run Powershell v5 consoleless. Simply rename hiddenw.exe to powershellw.exe. If you want to do this for cmd, then rename to cmdw.exe. If you want to do it for Powershell v7 (pwsh), then rename to pwshw.exe. You can create multiple copies of hiddenw.exe and just rename to the actual process with the letter w at the end. Then, simply add the process to your system environmental PATH, so you can call it from anywhere. Or just copy to C:\Windows. Then, just call it, like this:

powershellw .\example.ps1

shadowz1337
  • 710
  • 1
  • 8
  • 21
0

I found compiling to exe was the easiest way to achieve this. Theres a number of ways to compile a script, but you can try ISE Steroids

Open "Windows PowerShell ISE", install and run ISESteroids:

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

Start-Steroids

Then go to Tools->Turn code into EXE, select 'Hide Console Window', and then create the application. You can run this directly from task scheduler without the need for wrappers or 3rd party apps.

JMax
  • 647
  • 6
  • 8
0

What I do is transform the .ps1 file into an invisible .exe file using an awesome app called Ps1 To Exe which you can download here : https://www.majorgeeks.com/files/details/ps1_to_exe.html

Maybe this helps (although I hope after 12 years you have found a suitable solution... )

Silloky
  • 147
  • 13
0

In other words, the script should run quietly in the background without any sign to the user.
Extra credit for an answer that does not use third party components :)

I found a way to do this by compiling a PowerShell script to a Windows executable. Third party modules are required to build the executable but not to run it. My end goal was to compile a one line PowerShell script that ejects a DVD on my system:

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

My target system is running Windows 7. The specific WMF update needed varies based on Windows version:

Download and install the WMF 5.1 package

The required PowerShell modules should be applicable to any Windows version. Here are the exact commands I used to install the necessary modules and compile the exe. You'll need to tweak the drive, directory and filename details for your system:

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
James
  • 41
  • 4
0

I am lazy so I use these powershell commands to create scheduled tasks that incorporate Adam Taylor's solution above. You can edit the created task later (e.g. to change from running daily to something else):

#---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
ndemou
  • 4,691
  • 2
  • 30
  • 33