I'm trying to call a powershell script in-between one of my project steps in Visual Build.
I've created a new script within visual build and having that call my powershell script.
I selected vbscript and this is the code within the script:
Dim paths, source1
paths = "C:\Dev\"
source1 = "\\10.156.3.14\win"
sCmd = "powershell.exe -noexit -ExecutionPolicy Unrestricted -file C:\Dev\downloadfiles.ps1 -target """ & paths & """ -source """ & source1 & """"
Set xShell = CreateObject("Wscript.Shell")
rReturn = xShell.Run(sCmd, 0, true)
The script timeouts my build.
The powershell script works fine when ran through the console.
Is there something I'm missing?
download.files.ps1 paramaters:
param (
[string[]]$target,
[string[]]$source
)
Additionally is there any way I could see the console output whilst it's running. Even with "-noexit" I'm seeing nothing.
Update --
The first part of the script runs and returns some of the relevant files.
Although the part that takes in the parameters are not functioning.
This seems to be the better alternative as the script is now taking in parameters :
Set objShell = CreateObject("Wscript.Shell")
objShell.run("powershell.exe -noexit -ExecutionPolicy Unrestricted -file .\downloadfiles.ps1 -target """ & paths & """ -source """ & source1 & """")
Follow up question. How would I go about passing in a string arrray through the vbscript call?
e.g
$target = #('c:\dev','d:\lib')
When using -File, I'm afraid all array elements in $target will be forwarded to the PowerShell script as a single string.
Try
VbScript
Option Explicit
'I hate writing """something""" or Chr(34) & "something" & Chr(34)
'all the time, so I use this little helper function
Private Function Quote(text)
Quote = Chr(34) & text & Chr(34)
End Function
Dim paths, source1, script, sCmd, objShell
'join the quoted path elements with a semi-colon
paths = Join(Array(Quote("C:\Dev"), Quote("D:\lib")), ";")
source1 = Quote("\\10.156.3.14\win")
script = Quote("D:\Test\downloadfiles.ps1")
sCmd = "powershell.exe -NoExit -NoLogo -ExecutionPolicy Unrestricted -File " & script & " -target " & paths & " -source " & source1
Set objShell = CreateObject("Wscript.Shell")
objShell.run(sCmd)
Test with PowerShell
downloadfiles.ps1
param (
[string[]]$target,
[string[]]$source
)
$target = $target | ForEach-Object { $_ -split ';' }
$source = $source | ForEach-Object { $_ -split ';' }
Write-Host "Elements in target: $($target.Count)"
Write-Host "Elements in source: $($source.Count)"
Write-Host
for ($i = 0; $i -lt $target.Count; $i++) {
'$target[{0}]: {1}' -f $i, $target[$i]
}
Write-Host
for ($i = 0; $i -lt $source.Count; $i++) {
'$source[{0}]: {1}' -f $i, $source[$i]
}
Output in PowerShell console:
Elements in target: 2
Elements in source: 1
$target[0]: C:\Dev
$target[1]: D:\lib
$source[0]: \\10.156.3.14\win
Related
i want to run some conditional looping code along with other task like running a .bat file in one .ps1 file. I dont have sound knowledge in poweershell but i am trying to do this.
i tried to run the file but only batch file is executing successfully but not the code that needs to perform a different tasks in the process.
i tried using this command to run .batch file
cmd.exe /k ""c:\Users\ADM_SPANCHADULA\Desktop\status_check\status.bat" & powershell"
which is executing fine. but the remaining part
cd C:\Users\ADM_SPANCHADULA\Desktop\status_check
cmd.exe /c "c:\Users\ADM_SPANCHADULA\Desktop\status_check\status.bat"
"hello world " | Out-Host
$a=0
Do {
$output1 = Compare-Object (get-content "Job_status.txt") (get-content "done.txt")
$output2 = Compare-Object (get-content "Job_status.txt") (get-content "warn.txt")
if ( $output1 = "" ) {
$a = 1
$a|Out-Host
} elseif ( $output2 = "" ) {
$a = 1
$a|Out-Host
} else {
echo "looping "
}
} while ( $a -gt 0 )
is not executing .
can someone please help me out.
I wanted to know if it is possible to pass arguments to powershell via VBscript.
Here is my code and my investigation on this topic so far.
VBscript:
Dim pathvalue (pathvalue will dynamic path, which may have spaces in it. lets say path is "\\Server\search\File in some folder\Stack Overflow\")
sCmd = "powershell.exe -ExecutionPolicy ByPass -noexit -File \\server\Support\abhishek\Automation\SearchUtility.ps1 -Inputs " & PathValue
Set oShell = CreateObject("Wscript.Shell")
iResult = oShell.Run(sCmd, 1, true)
PS1.
Param([String] $Inputs)
$FolderPath = $Inputs;
echo "$FolderPath";
Expected result :
\\Server\search\File in some folder\Stack Overflow\
Actual Result :
\\Server\search\File
I tried different methods to pass the arguments ex. by putting it in single quotes, by putting 3 double Quotes but still it is not working.
Here is a code example:
sCmd = "powershell.exe -ExecutionPolicy ByPass -noexit -File \\server\Support\abhishek\Automation\SearchUtility.ps1 -Inputs " &"'" & PathValue & "'"
I got stuck for days and I haven't found a way to get this done. I need some help here. (I am new to Powershell)
Thanks in advance.
Try this. You don't need to build it in steps like this. I just did it this way to make it more readable. The last line is the critical part.
sCmd = "powershell.exe -ExecutionPolicy ByPass -noexit "
sCmd = sCmd & "-File \\server\Support\abhishek\Automation\SearchUtility.ps1 "
sCmd = sCmd & "-Inputs " & Chr(34) & PathValue & Chr(34)
I appreciate you taking the time to read this.
My issue is as follows: I'm trying to create a program that uses powershell to do the following:
Take a table generated outside of powershell
Loop calls to a powershell script with the parameters from the table
The powershell script calls a special type of .cmd file and then runs commands on it that are located in a different shared location.
Now my problem is with the 3rd point.
I'm currently using the following to call my script (and the arguements are just hard coded to get it working, they'll be generated by the calls from step 2 later on):
powershell.exe -ExecutionPolicy Bypass -Command {invoke-command -file \\sharedlocation\test5.ps1 -computername server1121 -argumentlist 7058,Jason}
The inside of test5.ps1 is currently:
param(
[Parameter(Mandatory=$true)]
[string] $Var1,
[Parameter(Mandatory=$true)]
[string] $Var2
)
$CommandsPath = "\\sharedlocation\testcommands.cmd"
$path = "C:\"+$Var1+"\TOOLS\"+$Var2+"launchtool.cmd"
$scriptPath = [scriptblock]::Create($path)
$out | invoke-command {PARAM($MyArg) $scriptPath } -ArgumentList $CommandsPath
I've also tried using
$CommandsPath = "\\sharedlocation\testcommands.cmd"
$path = "C:\"+$Var1+"\TOOLS\"+$Var2+"\launchtool.cmd & " + $CommandsPath
$scriptPath = [scriptblock]::Create($path)
$out | invoke-command {$scriptPath }
I've also tried to call with hardcoded testcommands instead of them being in a file.
Now my problem is in both cases, it DOES run launchtool.cmd, but it doesn't pass the testcommands.cmd file.
However when on the machine i run
C:\7058\TOOLS\Jason\launchtool.cmd & \\sharedlocation\testcommands.cmd
It works fine.
Any ideas what I'm doing wrong?
Try, invoke-expression "cmd.exe /c C:\7058\TOOLS\Jason\launchtool.cmd & \sharedlocation\testcommands.cmd"
cmd.exe /c is my best way to ensure consistency between cmd and powershell
Is the UNC Path accessible from powershell? Copy the testcommands.cmd to a local path and try if it works!
$CommandsPath = "\\sharedlocation\testcommands.cmd"
if(Test-Path $CommandsPath)
{
$path = "C:\"+$Var1+"\TOOLS\"+$Var2+"\launchtool.cmd & " + $CommandsPath
$scriptPath = [scriptblock]::Create($path)
$out | invoke-command {$scriptPath }
}
If have created a VBS script that watches for new created processes like notepad.exe or calc.exe. When a new notepad or calc proces is found i like to do something in powershell with the found procesname.
The VBS script i created works fine when I manually edit the procesname in the VBS file, but when i try to use/pass the procesname form vbs (strName) to powershell I expect to see the procesname (notepad.exe), but instead the powershell window shows "strName".
I've been all over the internet to find a solution, without result.
My VBS file [start.vbs]
source: http://blogs.technet.com/b/heyscriptingguy/archive/2009/11/02/hey-scripting-guy-november-1-2009.aspx
arrProcesses = Array("calc.exe","notepad.exe")
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
i = 0
Set colMonitoredProcesses = objWMIService. ExecNotificationQuery _
("Select * From __InstanceCreationEvent Within 5 Where TargetInstance ISA 'Win32_Process'")
Do While i = 0
Set objLatestProcess = colMonitoredProcesses.NextEvent
strProcess = LCase(objLatestProcess.TargetInstance.Name)
For Each strName in arrProcesses
If strName = strProcess Then
''Run Powershell file
'source: https://stackoverflow.com/questions/19156178/passing-arguments-to-powershell
Set WshShell = CreateObject("WScript.Shell")
''this works great
WshShell.Run ("Powershell.exe -file .\GetParamFromVBS.ps1 ""notepad.exe"" ")
'this doesnt
WshShell.Run ("Powershell.exe -file .\GetParamFromVBS.ps1 ""strName"" ")
'OR
'Trying to work arround it, with no result :(
RUNPSVAR="(" + """" +"Powershell.exe -file .\GetParamFromVBS.ps1 & """"" +strName +"""""" +""& " " +"""" +")"
wscript.Echo RUNPSVAR
WshShell.Run ("Powershell.exe -file .\GetParamFromVBS.ps1 ""RUNPSVAR"" ")
End If
Next
Loop
My Powershell File [GetParamFromVBS.ps1]
source: How to pass command-line arguments to a PowerShell ps1 file
param($p1, $p2, $p3, $p4)
$Script:args=""
write-host "Num Args: " $PSBoundParameters.Keys.Count
foreach ($key in $PSBoundParameters.keys) {
$Script:args+= "`$$key=" + $PSBoundParameters["$key"] + " "
}
write-host $Script:args
pause
Anyone any ideas?
Change:
WshShell.Run("Powershell.exe -file .\GetParamFromVBS.ps1 ""strName"" ")
To:
WshShell.Run("Powershell.exe -file .\GetParamFromVBS.ps1 '" & strName & "'")
Variables aren't string literals.
So something like this
a = "a string literal" & aVariableContainingAString
If I have an instance of PowerShell ISE running and I install something that modifies the PATH or I modify it in any way outside of PowerShell then I need to restart PowerShell for it to see the updated PATH variable.
Is there a way to reload the path from within PowerShell without restarting it?
Just to bring Rob's comment to light:
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
Try getting the machine path and assigning it to the session's path.
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine")
Easiest way, use Chocolatey (freeware). It works for both CMD and PowerShell. Then you will be able to reload PATH (with variable expansion) with a simple command:
refreshenv
Installation from cmd (requires administrator rights):
#"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
Example usage:
> SET JAVA_HOME=c:/java/jdk6
> SET PATH=%JAVA_HOME%/bin
> ECHO %PATH%
c:/java/jdk6/bin
> SET JAVA_HOME=c:/java/jdk8
> refreshenv
Refreshing environment variables from registry for cmd.exe. Please wait...Finished..
> echo %PATH%
c:/java/jdk8/bin
Based on mpen's answer, here is a PowerShell function:
function refresh-path {
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") +
";" +
[System.Environment]::GetEnvironmentVariable("Path","User")
}
Then just call refresh-path.
Just to add to other answers, you can make sure you don't add superfluous joins by filtering in case the user has an empty path.
$env:Path=(
[System.Environment]::GetEnvironmentVariable("Path","Machine"),
[System.Environment]::GetEnvironmentVariable("Path","User")
) -match '.' -join ';'
Or, more usefully, if you're running a script that adds to a different or multiple environment variables, use a function to reset them all
function resetEnv {
Set-Item `
-Path (('Env:', $args[0]) -join '') `
-Value ((
[System.Environment]::GetEnvironmentVariable($args[0], "Machine"),
[System.Environment]::GetEnvironmentVariable($args[0], "User")
) -match '.' -join ';')
}
resetEnv Path
resetEnv AppPath
If your path contains environment variables that weren't defined at the start of the session, you'll want to expand those too:
$env:Path = [System.Environment]::ExpandEnvironmentVariables([System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User"))
For me this was useful after installing NVM which defines and adds %NVM_HOME% to the path.
To take this to its logical conclusion you could use this recursive function to expand instead:
function Expand-EnvironmentVariablesRecursively($unexpanded) {
$previous = ''
$expanded = $unexpanded
while($previous -ne $expanded) {
$previous = $expanded
$expanded = [System.Environment]::ExpandEnvironmentVariables($previous)
}
return $expanded
}
And then use:
$env:Path = Expand-EnvironmentVariablesRecursively([System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User"))
I've opened an issue to add this solution into refreshenv from Chocolatey.