How to run a PowerShell script without displaying a window?
Asked Answered
Q

27

238

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

Quilting answered 26/11, 2009 at 7:45 Comment(5)
Checkout this question if you are interested in learning: https://mcmap.net/q/86671/-is-powershell-ready-to-replace-my-cygwin-shell-on-windows-closedQuilting
This solution works for Task Scheduler as well: https://mcmap.net/q/119447/-powershell-in-task-manager-shows-windowFeune
There are other options, such as a Windows service, if you need to absolutely avoid showing a window.Methodist
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, with several suggestions for potential workarounds / fixes at the PowerShell or OS level. So, it might get patched, "one day".Saraisaraiya
Note that a powershell login script in group policy will have a hidden window.Casino
S
209

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.

Statehood answered 26/11, 2009 at 10:22 Comment(10)
I compiled the PsRun, however, if I add it to the scheduled task, it also flashes a window...Daunt
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.Tyronetyrosinase
Yes, that's why there is "but this shows a windows for a while" in the response.Statehood
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))Yandell
Using User Account to SYSTEM also avoids a window being displayed.Saire
-windowstyle hidden doesn't completely work. The window will at least flash.Casino
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 worksOperon
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 possibleRepresent
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".Nursling
cmd /c start /min "" still flashes Powershell in the taskbarTobias
F
82

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.

Fence answered 31/5, 2018 at 18:35 Comment(6)
Best solution without depending on a third-party extension, executable, or wrapper script.Beal
Note that this option requires the user to have the "Log on as Batch Job" privilegeCalycine
This solution makes my script not to run properly.Whodunit
Not a solution if your script involves displaying any kind of gui.Galloping
This solution will prevent you from displaying notifications to the current user. Hiding the code does not mean that it will be useful at all for the person who is working now.Thermopylae
Also, if your script starts any other background programs, they will not have windows either.Gyrate
N
40

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

Nursling answered 28/4, 2021 at 12:21 Comment(9)
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 focusEpidaurus
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?Nursling
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 leastEpidaurus
For the "Call a file with arguments" the semicolon seems to be extra as it prevents the script from executing.Vinaya
@Peter, thanks for pointing that out. I've fixed that and added the ps1 content also for clarity.Nursling
@Nursling 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'"Vinaya
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.Nursling
cmd /c start /min "" still flashes Powershell in the taskbarTobias
I found setting the task to Hidden solves the toolbar flash for me.Finkelstein
B
25

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

Backstairs answered 26/11, 2009 at 7:58 Comment(1)
Is there a NuGet paclage for this so I can run it from Visual Studio?Dinnerware
L
18

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.

Lauderdale answered 3/8, 2017 at 2:46 Comment(4)
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.Backspin
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.Thermopylae
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).Whodunit
Caveat: The exit code from the PowerShell script gets lost here and is always 0.Galloping
G
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)
Gnathonic answered 16/1, 2015 at 20:40 Comment(1)
Thanks, this was helpfulSelfexpression
T
16

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")
Thermopylae answered 15/12, 2019 at 16:9 Comment(2)
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!Hanger
Worked Flawlessly. Just what i was looking forCommute
F
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.

Florescence answered 25/9, 2017 at 21:8 Comment(2)
For me the console still displays for about a second.Mathildamathilde
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.Parachronism
T
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
};
Thetos answered 29/1, 2014 at 6:47 Comment(0)
T
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.

Tudor answered 6/1, 2021 at 7:27 Comment(2)
Works +1. Also user run as user "system" works if you need the elevation. Or my answer if you need your user.Hitandmiss
Good job soldier !Urien
C
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"
Casino answered 1/9, 2019 at 16:42 Comment(0)
P
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.

Plunger answered 24/6, 2021 at 1:25 Comment(0)
I
5

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
Isosceles answered 22/7, 2021 at 9:29 Comment(4)
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). github.com/cherryleafroad/run-hiddenEpidaurus
This seems not to work when you use "%USERPROFILE%" in one of your arguments.Boffa
@Boffa 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.Isosceles
Uh I see. Thanks for explaining that.Boffa
H
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.
Hitandmiss answered 6/12, 2020 at 22:58 Comment(10)
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 popupsFrancie
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.Hitandmiss
@Francie 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 superuser.com/questions/478052/… for detailed explanations.Hitandmiss
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.Francie
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.Hitandmiss
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.Francie
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.Francie
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"'"\""Francie
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.Francie
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}");Francie
P
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 :)

Parachronism answered 17/11, 2018 at 19:56 Comment(3)
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!Glossitis
PS: i have included the solution for "waiting for input" a while ago (as well as a couple of bugfixes)!Parachronism
@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 studioParachronism
E
2

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
Encephalo answered 23/2, 2023 at 9:47 Comment(1)
How do you capture the text output from the command?Burgle
P
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.

Philippic answered 2/6, 2020 at 9:18 Comment(0)
T
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
Thermopylae answered 21/12, 2020 at 8:51 Comment(0)
A
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.

Advocate answered 17/3, 2021 at 5:57 Comment(0)
V
1

If your looking for a version that doesn't require any command line parameters, just code in your powershell script and works with the new windows Terminal.

I found this solution here

$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."
  }
}
Vilmavim answered 4/10, 2023 at 22:43 Comment(0)
T
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
Thermopylae answered 21/12, 2020 at 8:41 Comment(3)
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?Quixotic
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.Thermopylae
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.Quixotic
F
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

Francie answered 28/1, 2022 at 0:47 Comment(0)
S
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.

Stoddard answered 15/7, 2022 at 9:10 Comment(0)
M
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... 🙂)

Magical answered 6/11, 2022 at 8:20 Comment(0)
C
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
Compline answered 6/2, 2023 at 17:21 Comment(0)
V
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
Vulcanology answered 25/8, 2023 at 11:53 Comment(0)
C
0

on top of your commands just write the below script:

echo off
Cariole answered 22/1 at 2:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.