I need to run a powershell script from vb.net. I wrote it and tried it in powershell ISE and the powershell console and it's working properly.
But when I try to use it in my vb.net code, nothing happens.
The script put into text file citrix session from some user.
here is my powershell script :
$username = 'domain\myusername'
$password = 'mypassword'
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword
Start-Process C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Credential $credential -NoNewWindow -ArgumentList "add-pssnapin citrix*`nGet-BrokerSession -AdminAddress 'ipadresshere' | Out-File -FilePath C:\inetpub\wwwroot\gestusers\ajax\data\arrays.txt"
and here's my vb.net code :
Dim MyRunSpace As Runspace = RunspaceFactory.CreateRunspace()
' open it
MyRunSpace.Open()
' create a pipeline and feed it the script text
Dim MyPipeline As Pipeline = MyRunSpace.CreatePipeline()
MyPipeline.Commands.AddScript(scriptText)
' add an extra command to transform the script output objects into nicely formatted strings
' remove this line to get the actual objects that the script returns. For example, the script
' "Get-Process" returns a collection of System.Diagnostics.Process instances.
MyPipeline.Commands.Add("Out-String")
' execute the script
Dim results As Collection(Of PSObject) = MyPipeline.Invoke()
' close the runspace
MyRunSpace.Close()
' convert the script result into a single string
Dim MyStringBuilder As New StringBuilder()
For Each obj As PSObject In results
MyStringBuilder.AppendLine(obj.ToString())
Next
' return the results of the script that has
' now been converted to text
Return MyStringBuilder.ToString()
When I try to use a smaller script like :
$test = "blablabla"
$test | Out-File -filepath "C:\inetpub\wwwroot\gestusers\ajax\data\arrays.txt"
it works so I don't really understand why the first script is not working .. if you have some suggestion I would be thankful
I finaly found a solution to my problem.
I am running my web app on a IIS server and when I was launching my script it was the default user "IIS default/application_pool" which was lauching it although I specified a specific user to run it, it was like my script doesn't work.
So I choosed to go in my IIS server params and I just made an other app_pool with my specific user. I put my app under this pool and now it works perfectly.
Here's how to make a specific pool on IIS Server : https://www.developer.com/net/asp/article.php/2245511/IIS-and-ASPNET-The-Application-Pool.htm
cya
Related
I am trying to run a pwershell script from excel, which i can do and it works, but the powershell window does not show the information from the write-host comands in the script. If i run the file from the cmd prompt i get all the write-host texts appearing in the console window, like below.
Powershell run from command prompt
[]
However if i use this code from excel.
Sub RunAndGetCmd()
strCommand = "Powershell -File ""C:\PSFiles\TestOutput.ps1"""
Set WshShell = CreateObject("WScript.Shell")
Set WshShellExec = WshShell.Exec(strCommand)
End Sub
I get no texts shown in the console window, just the a flashing cursor like the following
Same Powershell ran from excel
I know the script runs and dooes everything, but i would like to output the texts as the script runs so i can see how far it has gotten.
Any ideas greatly appreciated.
The WScript.Shell Exec command redirects the stdin, stdout and stderr streams so you can access them from your application. As a result, anything written to stdout by the external application (e.g. using write-host in PowerShell) gets redirected instead of being displayed in the external application's window.
If you want the output displayed in the application's window you can use the Run method instead - e.g.
Option Explicit
Sub RunAndGetCmd()
Dim strCommand As String
Dim WshShell As Object
strCommand = "Powershell -File ""C:\PSFiles\TestOutput.ps1"""
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run strCommand
End Sub
but if you're doing that, you might as well just use the built-in VBA Shell function:
Option Explicit
Sub RunAndGetCmd()
Dim strCommand As String
strCommand = "Powershell -File ""C:\PSFiles\TestOutput.ps1"""
VBA.Shell strCommand
End Sub
Note also that you might want an -ExecutionPolicy RemoteSigned in your command in case the machine has it set to Restricted:
strCommand = "Powershell -ExecutionPolicy RemoteSigned -File ""C:\PSFiles\TestOutput.ps1"""
everyone.
When I issue the Invoke-RestMethod command, via the PS shell (version 7), the expected output is saved into a variable.
However, when I put the same commands into a PS script, then calling said script using VBA, the same output is not saved into a variable (or into a file). Why, and what am I missing?
VBA code (snippet):
strCommand = "pwsh -NoLogo -NonInteractive -ExecutionPolicy Bypass -File C:\Users\....\tpCancelOrder.ps1 " & sCW & " " & sDON & ""
Set WshShell = CreateObject("WScript.Shell")
WshShellexec = WshShell.Run(strCommand)
PS code (snippet from tpCancelOrder.ps1):
$response = Invoke-RestMethod #params -SkipCertificateCheck
Pausing the PS script to see what's being outputted / returned
So, (from the screenshot) we can see that there is (actually, the same expected) output.
However, the next PS commmands
Write-Output $response.ToString | Set-Content "C:\Users\....\tpCancelOrder.log"
$response | ConvertTo-Json
return NULL.
I've tried various combinations of write-host, write-debug... redirection, out-file, tee-object.... but all to no avail.
From a PS shell, no issues——$response stores/contains the expected output.
Thanks in advance.
I need to run a powershell script with a parameter from a word macros. For now even the attempts to simply run a script from VBA are not sucessful. I do the following:
Sub Powershell_Run()
sCmd = "powershell -file ""C:\Users\i351063\Desktop\Scripts\NewAttempt.ps1"""
Set xShell = CreateObject("Wscript.Shell")
Set xShellExec = xShell.Run(sCmd)
rReturn = xShellExec.Run("C:\Users\i351063\Desktop\Scripts\NewAttempt.ps1")
End Sub
The execution of this code returns an error: "Run-time error '70': Permission denied" on the line Set xShellExec = xShell.Run(sCmd). What do I do wrong? How to fix the error?
Thanks a lot in advance!
UPD: Powershell code (I want to pass the filename as a parameter from VBA to PS, for now it's initialized right in the code)
Param([string]$filename)
$filename = "HT.docm"
Add-Type -AssemblyName "Microsoft.Office.Interop.Word"
$word = [Runtime.Interopservices.Marshal]::GetActiveObject('Word.Application')
$wshell = New-Object -ComObject Wscript.Shell
$doc = $word.Documents | Where-Object {$_.Name -eq "$filename"}
If (!$doc)
{
$form.Close()
[void] $wshell.Popup("Failed to find an opened report",0,"Report not found",0x1)
$word.ScreenUpdating = $true
Break
}
Else {...}
This script works in a PowerShell terminal (32 bit host to a 64 bit target) :
PS C:\Users\Administrateur> $username=login
PS C:\Users\Administrateur> $pass=ConvertTo-SecureString -AsPlainText password -Force
PS C:\Users\Administrateur> $cred= New-Object System.Management.Automation.PSCredential
-ArgumentList $username,$pass
PS C:\Users\Administrateur> set-item WSMan:\localhost\Client\TrustedHosts
TARGETHOST -Force
PS C:\Users\Administrateur> Invoke-Command -ComputerName TARGETHOST
-ScriptBlock { icacls "F:\WWW\file.txt" /grant GROUP:F }
-Authentication Negotiate -credential $cred
I need to set Authentication to Negociate to be able to log as a local remote user (TARGETHOST\Administrator).
I'm trying to reproduce it in VB.NET :
Imports System.Management.Automation
Imports System.Security
Imports System.Management.Automation.Runspaces
Public Class RemoteRightsManager
' Credential is already set up here '
' [...] '
Public Function setRemoteRights(ByVal path As String,
ByVal icaclsEntry As String) As Boolean
Dim icaclsCommand As String = "icacls """ + path + """ /grant """ & icaclsEntry & """"
setRemoteRights = True
Dim psi As PowerShell
Dim initial As InitialSessionState = InitialSessionState.CreateDefault()
Dim runspace As Runspace = RunspaceFactory.CreateRunspace(initial)
runspace.Open()
psi = PowerShell.Create
psi.Runspace = runspace
psi.AddCommand("Set-Variable")
psi.AddParameter("Name", "credential")
psi.AddParameter("Value", Me.credential)
psi.AddCommand("Set-Item")
psi.AddArgument("wsman:\localhost\client\trustedhosts")
psi.AddArgument(Me.host)
psi.AddParameter("Force")
psi.AddCommand("Invoke-Command")
psi.AddParameter("ComputerName", Me.host)
Dim block As ScriptBlock = ScriptBlock.Create(icaclsCommand )
psi.AddParameter("ScriptBlock", block)
psi.AddParameter("Authentication", "Negotiate")
psi.AddParameter("Credential", credential)
For Each item As PSObject In psi.Invoke()
Console.WriteLine(item)
Next
End Function
End Class
I don't understand why, but psi.Invoke() seems to do absolutly nothing ; the execution never enters in the For Each loop, except if I comment most psi lines except the ScriptBlock one, and even, I don't catch the console output (seems to be another issue though).
I'm needing to run scripts from within a vb.net windows app.
I've got the scripts running in the background fine;
Using MyRunSpace As Runspace = RunspaceFactory.CreateRunspace()
MyRunSpace.Open()
Using MyPipeline As Pipeline = MyRunSpace.CreatePipeline()
MyPipeline.Commands.AddScript("import-module -name " & moduleName &
vbCrLf &
"(get-module -name " & moduleName & ").version")
Dim results = MyPipeline.Invoke()
'Do something with the results
End Using
MyRunSpace.Close()
End Using
However, i now need to be able to have the powershell run (not in the background) eg. When prompts occur;
Set-ExecutionPolicy unrestricted
I'm currently looking into the Microsoft.PowerShell.ConsoleHost namespace to see if i can use something like;
Dim config = RunspaceConfiguration.Create
ConsoleShell.Start(config, "Windows PowerShell", "", New String() {""})
Can anyone advise me please???
EDIT: I've fudged it a bit with this;
Public Function RunPowershellViaShell(ByVal scriptText As String) As Integer
Dim execProcess As New System.Diagnostics.Process
Dim psScriptTextArg = "-NoExit -Command ""& get-module -list"""
'Dim psScriptTextArg = "-NoExit -Command ""& set-executionPolicy unrestricted"""
'Dim psScriptTextArg = ""-NoExit -Command """ & scriptText & """"
execProcess.StartInfo.WorkingDirectory = Environment.SystemDirectory & "\WindowsPowershell\v1.0\"
execProcess.StartInfo.FileName = "powershell.exe"
execProcess.StartInfo.Arguments = psScriptTextArg
execProcess.StartInfo.UseShellExecute = True
Return execProcess.Start
End Function
But there's gotta be a better way??
There is a distinction between the PowerShell engine and its host. What you're wanting is to run the engine within your application but then fire up a separate host (which also is hosting the PowerShell engine) to handle prompts. You might want to look into modifying your application to act as a host itself. You could then react to prompts (read-host) and pop dialog boxes or whatever. Take a look at this relevant PowerShell namespace. Also check out this blog post on creating a simple PSHost.