Running PowerShell code inside VBS with many nested quotes, in one line - powershell

I'm starting to see double here from staring at this so long. I am trying to use an environment variable inside a script path that I'm going to launch from PowerShell, all initiated from a single line inside an mshta command run from a scheduled task on logon.
In case you were wondering, MSHTA can execute HTML/VBS/JS as if a local GUI app.
mshta vbscript:Execute("CreateObject(""Wscript.Shell"").Run ""powershell -NoLogo -Command """"& '\\$env:USERDNSDOMAIN\FOLDER1\FOLDER with Spaces\Folder3\Script-To-Run.ps1'"""""", 0 : window.close")
Premise: I have to do it this way to prevent momentary popups that flash onscreen when running from a scheduled task in user context. I cannot run this script in the System context.
I know that putting anything inside two single quotes gives me a string literal but if I try double quotes it seems to then use the space in the path. I've tried separating the two and concatenating them in all sorts of ways to no avail.
VBS equivalent of $env:USERDNSDOMAIN is
CreateObject("Wscript.Shell").ExpandEnvironmentStrings( "%USERDNSDOMAIN%" )

If the goal/purpose is to execute a PowerShell script without displaying the powershell.exe console window, you can do this by running it from a VBScript script executed by wscript.exe (not cscript.exe).
Example VBScript script:
Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run "%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -File """d:\path name\whatever.ps1"" [parameter [...]]", 0, False
The second parameter of the WshShell object's Run method is 0, so powershell.exe executes from a hidden window.
(Hint: The -File parameter to powershell.exe is generally easier to use than -Command. It must be the last parameter on the powershell.exe command line.)
End result: VBScript script runs the PowerShell script from a hidden window. Also, the VBScript itself has no console window, because you executed it using wscript.exe (the GUI host).

Related

How to run a PowerShell Script in the background (no window) from Windows Explorer? [duplicate]

The shortcut below executes powershell.exe and passes it the script vscode.ps1. It works except that for all my attempts, it still displays a terminal window briefly when running. You can see I've passed parameters which is supposed to prevent this, but I still see the window. What do I have to do to execute a PS script from a shortcut without the terminal window being displayed?
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -nologo -NoProfile -WindowStyle Hidden -file C:\Users\bernie\OneDrive\PowerShell\vscode.ps1 C:\Users\bernie\OneDrive\Documents\windows.txt
It's a known issue, see https://github.com/PowerShell/PowerShell/issues/3028#issuecomment-583834582
As #Ciantic mentioned, the best way to work around this issue is by using a VB script:
In, say ps-run.vbs put
Set objShell = CreateObject("Wscript.Shell")
Set args = Wscript.Arguments
For Each arg In args
objShell.Run("powershell -windowstyle hidden -executionpolicy bypass -noninteractive ""&"" ""'" & arg & "'"""),0
Next
Then use it to run the command you want, e.g.
wscript "C:\Path\To\ps-run.vbs" "C:\Other\Path\To\your-script.ps1"
I use something like this to run a task frequently without seeing any flashing windows.
Yes, Powershell can't completely do this. But VBScript can do this. Also I use Hidden Start which can start any program hidden or bypass UAC.

How to run PowerShell script without terminal window?

The shortcut below executes powershell.exe and passes it the script vscode.ps1. It works except that for all my attempts, it still displays a terminal window briefly when running. You can see I've passed parameters which is supposed to prevent this, but I still see the window. What do I have to do to execute a PS script from a shortcut without the terminal window being displayed?
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -nologo -NoProfile -WindowStyle Hidden -file C:\Users\bernie\OneDrive\PowerShell\vscode.ps1 C:\Users\bernie\OneDrive\Documents\windows.txt
It's a known issue, see https://github.com/PowerShell/PowerShell/issues/3028#issuecomment-583834582
As #Ciantic mentioned, the best way to work around this issue is by using a VB script:
In, say ps-run.vbs put
Set objShell = CreateObject("Wscript.Shell")
Set args = Wscript.Arguments
For Each arg In args
objShell.Run("powershell -windowstyle hidden -executionpolicy bypass -noninteractive ""&"" ""'" & arg & "'"""),0
Next
Then use it to run the command you want, e.g.
wscript "C:\Path\To\ps-run.vbs" "C:\Other\Path\To\your-script.ps1"
I use something like this to run a task frequently without seeing any flashing windows.
Yes, Powershell can't completely do this. But VBScript can do this. Also I use Hidden Start which can start any program hidden or bypass UAC.

PowerShell in Task Manager Shows Window

I am trying to make Task Schedule Task so it is completely invisible that a PowerShell script is running so I created a Task on my Win10 machine configured as follows:
Program/Script:
powershell.exe
Add arguments (optional):
-WindowStyle Hidden -command "& {Out-File 'C:\temp\somefile.txt'}" -NonInteractive -NoLogo -NoProfile
When I run this task the powershell command windows pops up for a split second which I don't want.
You can get around this with an 'Application Host' type wrapper. This is a known issue with powershell as a console-based host.
The most convenient way to do this I've found, is to use WScript.exe and run a VBS script that will invoke the process "invisibly", with no console or task bar flicker.
VBS Code:
On Error Resume Next
ReDim args(WScript.Arguments.Count-1)
For i = 0 To WScript.Arguments.Count-1
If InStr(WScript.Arguments(i), " ") > 0 Then
args(i) = Chr(34) & WScript.Arguments(i) & Chr(34)
Else
args(i) = WScript.Arguments(i)
End If
Next
CreateObject("WScript.Shell").Run Join(args, " "), 0, False
Save the above code in a file with extension '.vbs', and place it somewhere it can be run by the client running the task. This may be in a protected fileshare on the network (if you expect the script it invokes to only run while connected to the network), or locally on the client.
Now when you invoke your console-based script (PowerShell, BAT, CScript, etc.), you invoke this VBS script with WScript explicitly WScript.exe. It also pays to throw on the 'Batch Mode' parameter //B which will suppress script errors & prompts - such as if the wrapper file itself can't be found.
At this point, all you need to do is pass powershell & the command you want powershell to run to this launch sequence:
WScript.exe //B "\\Path\To\Launcher.VBS" powershell.exe -ExecutionPolicy ByPass -file "\\Powershell\Script\To\Run"
I had the same problem, it was resolved at the simple way.
When you create a Task on Windows, just set this configuration:
Open Properties dialog;
Then you check Run whether user is logged on or not;
You can check Do not store password to avoid asking for PC password on Task execution;
In Add arguments (optional): just:
-File 'C:\temp\somefile.txt
This spcript will run without popup the prompt.
Solved in this link below:
https://stackoverflow.com/a/50630717/19926325

How do I write this in Powershell script?

I am very new to Powershell script.
I am trying to run a powershell script from a cmd
powershell.exe Set-ExecutionPolicy Unrestricted
powershell.exe .\startup.ps1
I need two lines within powershell script.
%WINDIR%\system32\inetsrv\appcmd.exe add apppool /name:"VCPool" /managedRuntimeVersion:"v4.0" /managedPipelineMode:"Integrated"
%WINDIR%\system32\inetsrv\appcmd.exe set app "WebRole_IN_0_VC/" /applicationPool:"VCPool"
Can I simply write it like this within the ps1 file?
& %WINDIR%\system32\inetsrv\appcmd.exe add apppool /name:"VCPool" /managedRuntimeVersion:"v4.0" /managedPipelineMode:"Integrated"
Many Thanks
Short answer, including a question: Why the hell does that need to be a PowerShell script?
You can simply create a batch file containing
%WINDIR%\system32\inetsrv\appcmd.exe add apppool /name:"VCPool" /managedRuntimeVersion:"v4.0" /managedPipelineMode:"Integrated"
%WINDIR%\system32\inetsrv\appcmd.exe set app "WebRole_IN_0_VC/" /applicationPool:"VCPool"
and run that directly instead of trying to figure out execution policies, etc.
Furthermore, appcmd should probably be in your PATH, so you can run it directly without needing to specify the full path to the program.
Longer answer, actually using PowerShell: There are two problems here.
You want to run a PowerShell script without having the appropriate execution policy set. This can be done with
powershell -ExecutionPolicy Unrestricted -File myscript.ps1
You need to adjust environment variable usage within PowerShell scripts, as % is not used to expand environment variables there. So you actually need
& $Env:WinDir\system32\inetsrv\appcmd.exe add apppool /name:VCPool /managedRuntimeVersion:v4.0 /managedPipelineMode:Integrated
& $Env:WinDir\system32\inetsrv\appcmd.exe set app WebRole_IN_0_VC/ /applicationPool:VCPool
Note also that you need an ampersand (&) before each line as a variable name in the beginning of a line switches into expression mode while you want to run a command, therefore needing command mode.
Furthermore quoted arguments can be a bit of a pain in PowerShell. PowerShell tries quoting arguments when necessary and it's not always obvious when things go wrong what actually comes out on the other end. In this case the easiest way is to not quote the arguments in any way whcih ensures that they come out correctly:
PS Home:\> args add apppool /name:VCPool /managedRuntimeVersion:v4.0 /managedPipelineMode:Integrated
argv[1] = add
argv[2] = apppool
argv[3] = /name:VCPool
argv[4] = /managedRuntimeVersion:v4.0
argv[5] = /managedPipelineMode:Integrated
PS Home:\> args set app WebRole_IN_0_VC/ /applicationPool:VCPool
argv[1] = set
argv[2] = app
argv[3] = WebRole_IN_0_VC/
argv[4] = /applicationPool:VCPool
However, if appcmd actually needs the quotes around the argument after a colon, then you need to quote the whole argument with single quotes and add the double quotes back in:
& $Env:WinDir\system32\inetsrv\appcmd.exe set app WebRole_IN_0_VC/ '/applicationPool:"VCPool"'
You might like to know you can combine the two launch statements into a single call within your CMD file:
powershell.exe -noprofile -executionpolicy unrestricted -file .\startup.ps1
The only slightly strange thing about calling appcmd.exe from PowerShell is you must surround the parameter in quotes, even if it contains no spaces. You have already done this, so yes it should work.

Set up PowerShell Script for Automatic Execution

I have a few lines of PowerShell code that I would like to use as an automated script. The way I would like it to be able to work is to be able to call it using one of the following options:
One command line that opens PowerShell, executes script and closes PowerShell (this would be used for a global build-routine)
A file that I can double-click to run the above (I would use this method when manually testing components of my build process)
I have been going through PowerShell documentation online, and although I can find lots of scripts, I have been unable to find instructions on how to do what I need. Thanks for the help.
From http://blogs.msdn.com/b/jaybaz_ms/archive/2007/04/26/powershell-polyglot.aspx
If you're willing to sully your beautiful PowerShell script with a little CMD, you can use a PowerShell-CMD polyglot trick. Save your PowerShell script as a .CMD file, and put this line at the top:
#PowerShell -ExecutionPolicy Bypass -Command Invoke-Expression $('$args=#(^&{$args} %*);'+[String]::Join(';',(Get-Content '%~f0') -notmatch '^^#PowerShell.*EOF$')) & goto :EOF
If you need to support quoted arguments, there's a longer version, which also allows comments. (note the unusual CMD commenting trick of double #).
##:: This prolog allows a PowerShell script to be embedded in a .CMD file.
##:: Any non-PowerShell content must be preceeded by "##"
##setlocal
##set POWERSHELL_BAT_ARGS=%*
##if defined POWERSHELL_BAT_ARGS set POWERSHELL_BAT_ARGS=%POWERSHELL_BAT_ARGS:"=\"%
##PowerShell -ExecutionPolicy Bypass -Command Invoke-Expression $('$args=#(^&{$args} %POWERSHELL_BAT_ARGS%);'+[String]::Join(';',$((Get-Content '%~f0') -notmatch '^^##'))) & goto :EOF
Save your script as a .ps1 file and launch it using powershell.exe, like this:
powershell.exe .\foo.ps1
Make sure you specify the full path to the script, and make sure you have set your execution policy level to at least "RemoteSigned" so that unsigned local scripts can be run.
Run Script Automatically From Another Script (e.g. Batch File)
As Matt Hamilton suggested, simply create your PowerShell .ps1 script and call it using:
PowerShell C:\Path\To\YourPowerShellScript.ps1
or if your batch file's working directory is the same directory that the PowerShell script is in, you can use a relative path:
PowerShell .\YourPowerShellScript.ps1
And before this will work you will need to set the PC's Execution Policy, which I show how to do down below.
Run Script Manually Method 1
You can see my blog post for more information, but essentially create your PowerShell .ps1 script file to do what you want, and then create a .cmd batch file in the same directory and use the following for the file's contents:
#ECHO OFF
SET ThisScriptsDirectory=%~dp0
SET PowerShellScriptPath=%ThisScriptsDirectory%MyPowerShellScript.ps1
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '%PowerShellScriptPath%'"
Replacing MyPowerShellScript.ps1 on the 3rd line with the file name of your PowerShell script.
This will allow you to simply double click the batch file to run your PowerShell script, and will avoid you having to change your PowerShell Execution Policy.
My blog post also shows how to run the PowerShell script as an admin if that is something you need to do.
Run Script Manually Method 2
Alternatively, if you don't want to create a batch file for each of your PowerShell scripts, you can change the default PowerShell script behavior from Edit to Run, allowing you to double-click your .ps1 files to run them.
There is an additional registry setting that you will want to modify so that you can run scripts whose file path contains spaces. I show how to do both of these things on this blog post.
With this method however, you will first need to set your execution policy to allow scripts to be ran. You only need to do this once per PC and it can be done by running this line in a PowerShell command prompt.
Start-Process PowerShell -ArgumentList 'Set-ExecutionPolicy RemoteSigned -Force' -Verb RunAs
Set-ExecutionPolicy RemoteSigned -Force is the command that actually changes the execution policy; this sets it to RemoteSigned, so you can change that to something else if you need. Also, this line will automatically run PowerShell as an admin for you, which is required in order to change the execution policy.
Source for Matt's answer.
I can get it to run by double-clicking a file by creating a batch file with the following in it:
C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe LocationOfPS1File
you can use this command :
powershell.exe -argument c:\scriptPath\Script.ps1