I currently have a VBScript that allows me to call arbitrary powershell commands, which includes entire powershell scripts. When I call them I cannot set the execution policy due to registry restrictions. Meaning, powershell isn't running as administrator.
How can I change this?
I believe the following is the section of the VBScript that is calling powershell.exe
cmd = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -OutputFormat text -EncodedCommand " & b64 & " > " & logstd & " 2> " & logerr
There are various ways you can make a process run elevated but for this use case, I think you should just specify the execution policy in the command line:
cmd = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy unrestricted -OutputFormat text -EncodedCommand " & b64 & " > " & logstd & " 2> " & logerr
Related
I'm trying to pass a string array to powershell through vbscript.
I got the params in the file.ps1 script:
param (
[string[]]$target
)
I'm trying to call file.ps1 through vbscript.
I want $target = #('c:\dev','d:\lib') to be passed in.
I currently have in my vbscript :-
target1 = """c:\dev"", ""d:\lib"""
Set objShell = CreateObject("Wscript.Shell")
objShell.run("powershell.exe -noexit -ExecutionPolicy Unrestricted -file .\file.ps1 -target1 """ & target & """")
which returns:
c:\dev, d:\lib and which isn't the powershell string array format "c:\dev", "d:\lib"
Update - Thanks mklement0 and alex-dl for your answers!
alex-dl's helpful answer contains an effective solution, as long as the array's elements don't need quoting, but let me try to break it down conceptually in more detail:
The -File parameter of PowerShell's CLI, powershell.exe (pwsh in PowerShell (Core) 7+) fundamentally does not support passing arrays to PowerShell code, because all arguments are interpreted strictly as whitespace-separated, with verbatim content.
E.g., "c:\dev", "d:\lib" on the command line is parsed as two arguments:
c:\dev, (note the trailing ,, syntactic " quotes stripped)
d:\lib
You must use the -Command (-c) option in order to pass arrays.
-Command fundamentally changes how the arguments are parsed:
All arguments are stripped of syntactic (non \"-escaped) " quotes.
The resulting tokens are space-concatenated to form a single string.
The resulting string is then interpreted as PowerShell code, i.e. as if you had submitted it from inside a PowerShell session.
This therefore enables all of PowerShell's features, such as passing arrays with ,, '...' (single-quoting), ..., and notably also means that references to PowerShell variables (e.g. $HOME) are recognized (unlike with -File).
See this answer for more guidance on when to use -File vs. -Command (-c).
Therefore, the best approach in your case is:
target = "'c:\dev', 'd:\lib'" ' Note the embedded '...'-quoting
Set objShell = CreateObject("Wscript.Shell")
' Note the use of -c (-command) instead of -file
objShell.Run("powershell.exe -noexit -ExecutionPolicy Unrestricted -c .\file.ps1 -target " & target)
Using embedded '...'-quoting simplifies passing the array elements in a way that PowerShell sees them as individually quoted (with the values at hand, this isn't strictly necessary, but it may be in other cases).
Doing this with embedded "..."-quoting gets unwieldy, because each embedded " must then be escaped as \"" (sic):
"" to escape the " inside the VBScript string,
and \ to ensure that \" is ultimately passed on the command line, which PowerShell requires for escaping " on the command line[1] (whereas PowerShell-internally, it is `" or (alternatively, inside a double-quoted string) "").
target = "\""c:\dev\"", \""d:\lib\"""
Set objShell = CreateObject("Wscript.Shell")
objShell.Run("powershell.exe -noexit -ExecutionPolicy Unrestricted -c .\file.ps1 -target " & target)
[1] While in Windows PowerShell you can situationally get away with "" instead of \", it can break, especially if the overall -c argument is enclosed in "...".
This problem has been fixed in PowerShell (Core) 7+, where you can now use "" and \" interchangeably.
E.g., when invoked from cmd.exe,
powershell -c " ""ab c"".length " breaks, whereas
pwsh -c " ""ab c"".length " works.
You could use the following vbscript:
target1 = """c:\dev, d:\lib"""
Set objShell = CreateObject("Wscript.Shell")
objShell.run("powershell.exe -Command .\file.ps1 -target " & target1)
And this powershell script:
param (
[string[]]$target
)
foreach ($t in $target) {
write-output $t
}
Read-Host -Prompt "Press Enter to exit"
Without -Command the argument is always interpreted as a single string.
I have tried to run the script using command
cmd.exe /c Start /min powershell.exe -windowstyle hidden -file <file>.ps1
But getting a CMD window for a fraction of a second. I need it to run completely hidden.
Configure the scheduled task to run whether the user is logged on or not:
and reduce the commandline to this:
powershell.exe -File "C:\path\to\your.ps1"
This makes the task run in the background with no visible window.
I have had this issue and the only way I could fix it was to call the PowerShell script with a simple VBS wrapper:
https://github.com/gbuktenica/PsRun
http://blog.buktenica.com/run-a-powershell-task-silently/
' SYNOPSIS
' Run a PowerShell script in the user context without a script window
' EXAMPLE
' wscript.exe PsRun.vbs MyPsScript.ps1
' AUTHOR
' Glen Buktenica
Set objShell = CreateObject("Wscript.Shell")
Set args = Wscript.Arguments
For Each arg In args
Dim PSRun
PSRun = "powershell.exe -WindowStyle hidden -ExecutionPolicy bypass -NonInteractive -File " & arg
objShell.Run(PSRun),0
User JPBlanc and others have given a nice solution to such a problem with the solution:
Set Args = Wscript.Arguments
'MsgBox "Chemin LDAP: " & Args(0)
'MsgBox "Classe: " & Args(1)
Set objShell = CreateObject("Wscript.Shell")
objShell.Run "c:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -nologo -Noninteractive -file c:\SlxRH\RhModif.ps1 " & chr(34) & Args(0) & chr(34) , 0
I have tested such a solution out and it works fine. However, my problem concerns the situation when the file path identified as the argument for the "-file" option has white space in it; as example, if the code example above had a file path of:
c:\Slx RH\RhModif.PS1
Observe the white space in the file path. The question is this: how to escape the file path correctly. I haven't found a way to do this (to make it work).
I have searched on this site and the general "interweb" and have learned (I think) that there are two levels of script interpretation going on: VBscript and the Wscript. Another very good example appears here (link to the full page with this title):
Run scheduled tasks with WinForm GUI in PowerShell
Dim objShell
Set objShell=CreateObject("WScript.Shell")
strExpression="get-date | add-content c:\temp\test.txt"
strCMD="powershell -sta -noProfile -NonInteractive -nologo -command " & Chr(34) & "&{" & strExpression &"}" & Chr(34)
objShell.Run strCMD,0
I have tested this and it works for me. While not using the "-file" option, this example gives (what you would think) would be a generic method of putting a "-command" or "-file" input for the strCMD variable. However, when I use the following code, it does not work:
Dim objShell
Set objShell=CreateObject("WScript.Shell")
strExpression="C:\aP_RDB\Set Up\SimpleInsert.PS1"
strCMD="powershell -noprofile -executionpolicy Unrestricted -NonInteractive -file " & Chr(34) & "&{" & strExpression &"}" & Chr(34)
objShell.Run strCMD,0
In my example above, I essentially copied the code reference above (and from the link listed), replaced the PS command with my file path (which includes white space) for the variable strExpression, and updated the strCMD definition by replacing the "-command" argument with the "-file" argument. However, the error message points to an unrecognized argument "c:\aP_RDB\Set" that is, it does not see the whole path "C:\aP_RDB\Set Up\SimpleInsert.PS1". It appears that the escaping of the quotes (or something) is not working... better said, I am not doing it correctly.
Any thoughtful advice would be greatly appreciated. FYI: I have tried the -WindowStyle Hidden option in Powershell; I like many have found that not to be a consistent approach across Windows platforms (more specifically for me: I could not get it to work).
Thanks for the reference, here are two ways to start scripts with white space in the name :
1) using double " ("")
set Args = Wscript.Arguments
MsgBox "Chemin LDAP: " & Args(0)
'MsgBox "Classe: " & Args(1)
Set objShell = CreateObject("Wscript.Shell")
objShell.Run "c:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -nologo -Noninteractive -file ""c:\temp\test arg.ps1"" " & chr(34) & Args(0) & chr(34) , 0
2) Consist in writing your own PowerShell.exe with no console, as I explain at the end of this article ""PowerShell.exe" ne sait pas dĂ©marrer sans afficher une fenĂȘtre"(sorry in french)
The recommended way to run scripts is
powershell.exe -NonInteractive -Command " & some.ps1 "
However for example TeamCity PowerShell runner uses:
powershell.exe -NonInteractive -Command - < some.ps1
I do not have an idea what "- <" means and cannot find any information on subject. Any help?
Because powershell.exe is being invoked through the Windows shell, it is the same as if you were on a normal command prompt (cmd.exe). In that situation < pipes a file to the standard input (stdin) of the previous command. The help for powershell.exe states that if the value of -Command is simply -, the command text is read from standard input.
Here's a more self-documenting demonstration of < in cmd.exe:
processSomeFile.exe outputFileName.ext < intputFile.ext
If the value of Command is "-", the command text is read from
standard input.
< is just the stdout -> stdin redirection operator
I'd say that the recommaneded way to execute a script is with the -File parameter:
powershell.exe -NonInteractive -Command -File some.ps1
With regard to your question, the '<' character is reserved and cannot be used in PowerShell.
Using the I/O operators like > and < in a bash script means that you write output to an external file i.e. :
echo hello > hello.txt
or you get input from an external file i.e. :
psql -U test test < script.sql
the same logic is applied to the windows powershell, you can get more infos HERE
I needed to schedule a powershell script and before doing it, i needed to prep the environment by running some other powershell script.
Basically i wanted to run
PowerShell.exe -noexit " & ' C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\CONFIG\POWERSHELL\Registration\sharepoint.ps1' "
PowerShell.exe -command " & ' E:\PerfCounters\Powershell\RunPerf.ps1' "
The first statement will perp my environment and i want to execute my own script after that.
Issue is, if i use the -noexit command, the next script never gets executed. If i use -command instead of -noexit, the commands seems to be executed in different powershell instances so my second script is erroring out.
I am a newbee in powershell and i did my best tring to find a answer. Any help here would be really appreciated. thanks!
If you didn't solve this on your own, or if anyone else needs the syntax, here you go:
powershell -noprofile -command "& { & .\x.ps1; & .\z.ps1 }"