I have a VBscript file. I run this VBscript using CScript on windows 2012 server. The VBscript runs fine on the server.
But I need to call this VBScript file from Powershell. This is what I did.
For simplicity, this is what I have in my VBscript file
echo.vbs
Msgbox("hello world")
I wrote the test.ps1
$acommand = "C:\Windows\System32\Cscript.exe C:\deleteit\echo.vbs"
Invoke-Expression $acommand
It is the right way to run an external application and you can use the same technique if you are using command line exe's or VBS scripts.
Personally, I would be looking to add the functionality to a PowerShell script rather then calling an external VBS script, but that's just my 2 cents worth :)
Aside from simply running
Cscript.exe C:\deleteit\echo.vbs //nologo
There's a com object that can embed vbscript right into powershell, but it's 32-bit only. There's a way to run jobs as 32 bit. In powershell 7 you have to use the 32-bit version.
start-job {
$sc = New-Object -ComObject MSScriptControl.ScriptControl.1
$sc.Language = 'VBScript'
$sc.AddCode('
Function MyFunction(byval x)
MyFunction = 2 * x
End Function
')
$sc.codeobject.MyFunction(1)
$sc.codeobject.MyFunction(2)
} -runas32 | wait-job | receive-job
Output:
2
4
Related
Im trying to use this code to get a list of Actions in the SCCM pushed into python, but all I get in retun is an empty bytes string.
count = r"""
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{
$arguments = "& '" +$myinvocation.mycommand.definition + "'"
Start-Process powershell -Verb runAs -ArgumentList $arguments
Break
}
$CMGR = New-Object -ComObject CPApplet.CPAppletMgr
$ClientActions = Out-String ($CMGR.GetClientActions() | Select Name).count
$ClientActions
"""
def runPS(command):
import subprocess
process=subprocess.run(["powershell", "-ExecutionPolicy", "Bypass", command],stdout=subprocess.PIPE);
print(process.stdout)
All this outputs is b''
What am I doing wrong???
EDIT: I figured part of it out. Its because it's tecnically running another powershell within this one (Python >> Powershell >> Admin Powershell), and the second one doesn't return its value to the first. (Python <> Powershell >> Admin Powershell)
I would suggest using check_output() instead of run() here. That allows you to detect a non-zero exit code from the child process. More information here. The Powershell might be failing for some reason, but you're not capturing stderr or checking the return code.
Something like this might be more robust:
def runPS(command):
import subprocess
output = subprocess.check_output(["powershell", "-ExecutionPolicy", "Bypass", command])
return output
EDIT: I figured part of it out. Its because it's tecnically running another powershell within this one (Python >> Powershell >> Admin Powershell), and the second one doesn't return its value to the first. (Python <> Powershell >> Admin Powershell)
Hmm. Sorry, I don't know powershell, so I can't help you with that half of it.
I am trying to get a local powershell script to trigger a VBS script inside a citrix instance. The events should be this:
Citrix Instance opening Windows Explorer ----> Network Path of script typed into the windows explorer session
I'm using the WfIcaLib.dll (ICOSDK) that came with the Citrix receiver install. Documentation PDF for the Citrix ICOSDK is available here
So this is the code I'm using, which works PERFECTLY in Powershell command line, but when I use the 32-bit ISE, it does nothing other than telling me the DLL has been loaded. I get no errors, but the Citrix Client never actually opens like it does when I run the same exact commands through Powershell command line.
#load Citrix ICA Client SDK
[System.Reflection.Assembly]::LoadFile("C:\Program Files (x86)\Citrix\ICA Client\WfIcaLib.dll")
$ICA = New-Object WFICALib.ICAClientClass
$ICA.Address = "***.***.***.***:****"
$ICA.Application = "Windows ExplorerFED6"
$ICA.Username = "******"
$ICA.Domain = "**"
$ICA.Launch = $true
$ICA.Outputmode = [WfIcaLib.OutputMode]::OutputModeNormal
$ICA.SetProp("Password", "*********")
$ICA.TWIMode=$true
$ICA.Connect()
Any ideas?
EDIT: SOLVED - after reopening under 32-bit ISE and getting code to work, I could not run the .ps1 file since it kept defaulting to 64-bit (even if using Open With on 32-bit powershell version). Running the script via command prompt or 32-bit powershell console both worked.
Using any method suggested by Mike Garuccio worked just fine. I will most likely end up using a Task Scheduler to run the script.
It looks like the problem is a versioning one, which you can deal with using start-job (was originally going to do this with a runspace but that's a lot more code for no real benefit). This will start a job to run your code under 32-bit powershell, it should still place any GUI elements or popups on screen but if you need to get any data out from the script later you'll need to receive the job. code would look something like below.
$SB = {
[System.Reflection.Assembly]::LoadFile("C:\Program Files (x86)\Citrix\ICA Client\WfIcaLib.dll")
$ICA = New-Object WFICALib.ICAClientClass
$ICA.Address = "***.***.***.***:****"
$ICA.Application = "Windows ExplorerFED6"
$ICA.Username = "******"
$ICA.Domain = "**"
$ICA.Launch = $true
$ICA.Outputmode = [WfIcaLib.OutputMode]::OutputModeNormal
$ICA.SetProp("Password", "*********")
$ICA.TWIMode=$true
$ICA.Connect()
}
Start-Job -ScriptBlock $SB -RunAs32
get-job | Receive-Job
Alternatively, you could also use a simple .bat file as a launcher with something like C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -file yourscript.ps1
or if you need everything to be wrapped in powershell and the job does not work you can use the solution Here that basically does the same thing but from within powershell (drop the if statement they use tho, just use the stuff contained inside it like below, with any changes you need to make wrt the profile and interactive settings.)
&"$env:windir\syswow64\windowspowershell\v1.0\powershell.exe" -noninteractive -noprofile -file "C:\Path o\script.ps1" -executionpolicy bypass
hope one of those works for you!
I created a small aws.bat script and then in PowerShell I navigated to the script directory.
But when I type aws then I get an error message and it does not execute the script. Is there a special thing I should be doing?
Here's what I have tried:
PS C:\G> .\aws.bat
C:\G>$BucketName = "ab-user"
'$BucketName' is not recognized as an internal or external command,
operable program or batch file.
The very first and every othre command has a similar message.
You can't just enter the name on its own, with or without file extension, you first have to tell powershell what to do with it.
You can call it as follows:
& .\aws.bat
If you need the LastExitCode returned in powershell to check if the bat file worked (0 usually means it worked, anything else usually means it didn't), use Start-Process as follows:
$batch = Start-Process -FilePath .\aws.bat -Wait -passthru;$batch.ExitCode
And if you want the batch file to be hidden when it is run by powershell do this:
$batch = Start-Process -FilePath .\aws.bat -Wait -passthru -WindowStyle Hidden;$batch.ExitCode
I am very new to powershell and sometimes this question may be so simple
Can please anybody please tell me what is the equivalent to the following(vbscript) in PowerShell
set obj = wscript.createobject( wscript.shell )
Obj.Run $smCmnd
What is the use of wscript.shell.
After a bit of search I found first line can be presented as;
$obj = New-Object -ComObject WScript.Shell
But have have no idea how to call Run method ($obj.run(...)???)
If I run cmd.exe with some commands as the smCmnd, How can I keep cmd.exe without close and to run another command later in same console??
EDIT
I am writing PS script and it will be call from another application. Basically it will do some folder creations and file coping etc. I would like to open CMD.exe and show all the commands running on that. How to use same cmd prompt through out my whole script.
Is smCmnd a string of shell commands? If so, you can call them directly from PowerShell, without trying to get a wscript.shell COM object to run them against like you'd need to do in VBScript.
VBScript wasn't a shell. Powershell is. You can write shell commands directly in .ps1 or .ps2 files, just like in a batch file.
I'm not a powershell expert here, but try doing
& $smCmnd
Try running $smCmnd directly. If that fails, use Invoke-Expression $smCmnd.
If you do need to use CMD.EXE (possibly because you want to run pre-existing BAT file), and you want all of the output in a single CMD window you can pipe all the input into cmd at once like this:
# Powershell script to execute existing BAT file
cmd.exe /k "cd c:\batchfiles & firstone.bat & second.bat & echo that's all folks"
# CMD will remain open (/k). User will have to type exit to return to powershell
# Or if you want user just to hit any key to leave CMD prompt:
cmd.exe /c "c:\batchfiles\mybatchfile.bat & pause"
# /C means CMD should close after is has executed the commands on the command line
However if you want to have something execute in CMD, then make a decision in your Powershell script about what to execute next in CMD then do something similar to the answer at the following link which pipes input and output between a powershell script and CMD.exe.
How to run interactive commands in another application window from powershell
The script i've created uses componets which are only available with the 32 bit version of powershell.
By default windows excutes the script with powershell x64 and it causes several errors.
Is the a way to set an value at the beginning of a script to force windows to use powershellx86 instead of x64?
Example:
using powershell(x86).exe
scriptblock
Thank you
Couldn't you just start the "powershell(x86).exe" file?
%SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe
/Fredrik
There is no straightforward way to do it, but there is a way to invoke another instance of Powershell host in x64 host, and that instance may as well be x86. $env:PROCESSOR_ARCHITECTURE will tell you what version of Powershell host you are running.
Just a sketch, use chisel and sand paper to finish.
function Execute-Scriptx86
{
param(
[Parameter(Mandatory=$True,Position=1)]
[string]$ScriptFile
)
if($env:PROCESSOR_ARCHITECTURE -eq "AMD64")
{
$powershellx86 = $env:SystemRoot + "\syswow64\WindowsPowerShell\v1.0\powershell.exe"
& $powershellx86 -File $ScriptFile
}
else
{
& $ScriptFile
}
}