running powershell script with parameters with vb.net - vb.net

i have a powershell script that i want to kick off with vb.net code, however when it gets to the part where i invoke the pipeline i get the error "Cannot process command because of one or more missing mandatory parameters: District County FMS."
the powershell script is very simple, it takes 3 parameters and write-host's the param values back to the shell. pretty much my question is, how do i make it work? thank you everyone for you time.
vb.net(the other professionals i work with have boiled the error down to 'get-process' not being the right command for my scriptParams variable, but we're not sure which command to use)
Sub Main()
Console.WriteLine(RunScript(LoadScript(Directory.GetCurrentDirectory() + "/CreateProject.ps1 ")))
Console.ReadLine()
End Sub
Private Function RunScript(ByVal scriptText As String) As String
' create Powershell runspace
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")
'[ay]create a command object by bassing the command to the constructor
Dim scriptParams As New Command("get-process")
'[ay]pass parameters to the command
scriptParams.Parameters.Add("District", "D1")
scriptParams.Parameters.Add("County", "Lee")
scriptParams.Parameters.Add("FMS", "101000")
MyPipeline.Commands.Add(scriptParams)
' 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()
End Function
Private Function LoadScript(ByVal filename As String) As String
Try
' Create an instance of StreamReader to read from our file.
' The using statement also closes the StreamReader.
Dim sr As New StreamReader(filename)
' use a string builder to get all our lines from the file
Dim fileContents As New StringBuilder()
' string to hold the current line
Dim curLine As String = ""
' loop through our file and read each line into our
' stringbuilder as we go along
Do
' read each line and MAKE SURE YOU ADD BACK THE
' LINEFEED THAT IT THE ReadLine() METHOD STRIPS OFF
curLine = sr.ReadLine()
fileContents.Append(curLine + vbCrLf)
Loop Until curLine Is Nothing
' close our reader now that we are done
sr.Close()
' call RunScript and pass in our file contents
' converted to a string
Return fileContents.ToString()
Catch e As Exception
' Let the user know what went wrong.
Dim errorText As String = "The file could not be read:"
errorText += e.Message + "\n"
Return errorText
End Try
End Function
PowerShell
[CmdletBinding()]
Param(
[Parameter(Mandatory = $True)]
[string]$District,
[Parameter(Mandatory = $True)]
[string]$County,
[Parameter(Mandatory = $True)]
[string]$FMS
)
Write-Host "District: $Dsistrict"
Write-Host "County: $County"
Write-Host "FMS: $FMS"

These examples are in C#, but it's the same API.
https://blogs.msdn.microsoft.com/kebab/2014/04/28/executing-powershell-scripts-from-c/
More C# examples, but these are using the RunspaceFactory API you already have in your pipeline.
Execute PowerShell Script from C# with Commandline Arguments

I'm new to PowerShell but may this help you
in your code
scriptParams.Parameters.Add("District", "D1")
scriptParams.Parameters.Add("County", "Lee")
scriptParams.Parameters.Add("FMS", "101000")
MyPipeline.Commands.Add(scriptParams)
I think this ADD new params to your script so value for already exit params not set
You need to pass param values to your script not add new param

I know this is an old question but there was no good answer and I just spent too long getting this to work to not share my knowledge.
In the VB code, you'd remove the following:
MyPipeline.Commands.AddScript(scriptText)
MyPipeline.Commands.Add("Out-String")
Then, in place of the Out-String addition, add:
Dim myCommand As Command = New Command(scriptText, True)
' Add your parameters here.
' Obviously you can add variables instead of static strings if needed.
myCommand.Parameters.Add("District", "D1")
myCommand.Parameters.Add("County", "Lee")
myCommand.Parameters.Add("FMS", "101000")
' You can add switches in this manner as well. For example, a switch "I"
' You need to include the - with switches
myCommand.Parameters.Add("-i")
' Finally, apply your command object to the pipeline and proceed as normal
MyPipeline.Commands.Add(myCommand)

Related

Process.Start arguments not working

I am trying to start a process with two parameters that will run from a cmd prompt window just fine. The problem comes when I try to launch it via process.start.
In the cmd window, it looks like this.
D:\Projects\MyProg.exe "D:\Projects\MyScript.txt" "D:\Projects\MyInputData.txt"
When I try to build the arguments in .NET it puts double quotes around the entire string and it looks like this. The program doesn't interpret it as two parameters and just stops. If I add double quotes around each argument it still misinterprets it.
I know it is the MyProg.exe issue (vendor program that I can't change) but is there a way to send this command so it will work?
myProcess.StartInfo.Arguments = "D:\Projects\MyScript.txt D:\Projects\MyInputData.txt"
When I add double quotes it sort of works, the program starts but then has a problem and just stops.
myProcess.StartInfo.Arguments = """D:\Projects\MyScript.txt"" ""D:\Projects\MyInputData.txt"""
I'm not quite sure what D:\Projects\MyProg.exe is doing but following sample is working for. Two variable strings are declared. The two strings indicate two argument parameters I want to use with the executable.
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'// Set first file parameter to the executable
Dim sourceFileName As String = "source.txt"
'// Set second file parameter to the executable
Dim targetFileName As String = "target.txt"
'// Create a new ProcessStartInfo
Dim p As New ProcessStartInfo
'// Specify the location of the binary
p.FileName = "D:\_working\ConsoleApplication3.exe"
'// Use these arguments for the process
p.Arguments = " """ & sourceFileName & """ """ & targetFileName & """ -optionalPara"
' Use a hidden window
'p.WindowStyle = ProcessWindowStyle.Hidden
' Start the process
Process.Start(p)
End Sub
End Class
See resulting screenshot:

Visual Basic Powershell query Server Pending Reboot status

I am new to VB.net & Powershell.
Never the less I am programming an application which querys the PendingReboot status of our Win2012 Servers.
There is this wonderful script which I implemented into my programm which does exactly that:
https://gallery.technet.microsoft.com/scriptcenter/Get-PendingReboot-Query-bdb79542
This is the code I use from Zainnab, to get access from VB2010.net to Powershell an return the result as a string.
'Takes script text as input and runs it, then converts
'the results to a string to return to the user
Private Function RunScript(ByVal scriptText As String) As String
'create Powershell runspace
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()
End Function
#
Try
‘ Create an instance of StreamReader to read from our file.
‘ The using statement also closes the StreamReader.
Dim sr As New StreamReader(filename)
‘ use a string builder to get all our lines from the file
Dim fileContents As New StringBuilder()
‘ string to hold the current line
Dim curLine As String = ""
‘ loop through our file and read each line into our
‘ stringbuilder as we go along
Do
‘ read each line and MAKE SURE YOU ADD BACK THE
‘ LINEFEED THAT IT THE ReadLine() METHOD STRIPS OFF
curLine = sr.ReadLine()
fileContents.Append(curLine + vbCrLf)
Loop Until curLine Is Nothing
‘ close our reader now that we are done
sr.Close()
‘ call RunScript and pass in our file contents
‘ converted to a string
Return fileContents.ToString()
Catch e As Exception
‘ Let the user know what went wrong.
Dim errorText As String = "The file could not be read:"
errorText += e.Message + "\n"
Return errorText
End Try
End Function
......
Dim ausgabe2 As String
ausgabe2 = RunScript(LoadScript("c:\FHServerStat\PS_PR.stat\60.2.ps1"))
------
I managed to get it partially working.
How ever the problem which I encounter is, by executing the script in powershell the rusult is correct.
By executing the script through visual basic, SOME returned values are incorrect, but see for yourself:
enter image description here
Please help me out on this
Regards
Okun

VB.NET Communicating with console app and sending parameters

I'm creating myself a GUI for a program that can be used in CMD, a CLI.
The program has the following input:
Ex: extractor.exe filename.rar newfilename.zip -c <password for achive>
filename.rar = the original file
newfilename.zip = the file to be created with new format
-c a command meaning key
<password...> - here comes the archive password.
It's great on CMD, but I would like to make a GUI.
I do it in VB and so:
For filename.rar I have one textbox that goes filled with a path specified by user using OpenFileDialog1.
For newfilename.zip I use a savefiledialog and a textbox: The textbox gets the path specified by user
Another textbox3 for the password and a button to call extractor.exe:
How can I pass these arguments to extractor?
I have tried with
argument = textbox1.text + textbox2.text + "-c" + textbox3.text
The program starts but simply closes as it simply doesn't get the parameters.
I have also tried this:
Dim psi As ProcessStartInfo
Dim procname = "extractor.exe"
Dim filename = TextBox1.Text
Dim newfile = TextBox3.Text
Dim key = TextBox2.Text
Dim args = ("extract" + filename + newfile + "-k" + key)
psi = New ProcessStartInfo(procname, args)
Dim proc As New Process()
proc.StartInfo = psi
proc.Start()
No luck. I'm able to send 1 parameter if I do like
argument = "extract" but i have multiple arguments that needs to be fetched from textboxes....is there a way?
Thanks!

How can I append a string that contains "" to an existing string in VB .NET?

I am working on a utility that will take the contents of a .ps1 script (Powershell), and run it in the context of a VB.NET Winform. Basically it does this by referencing some Powershell DLLs, opening the .ps1 file, reading a line of text and feeding it into an internal string that will run on a button click event.
Here's the full code I have so far:
Private Function RunScript(ByVal scriptText As String) As String
' create Powershell runspace
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()
End Function
' helper method that takes your script path, loads up the script
' into a variable, and passes the variable to the RunScript method
' that will then execute the contents
Private Function LoadScript(ByVal filename As String) As String
Try
' Create an instance of StreamReader to read from our file.
' The using statement also closes the StreamReader.
Dim sr As New StreamReader(filename)
' use a string builder to get all our lines from the file
Dim fileContents As New StringBuilder()
' string to hold the current line
Dim curLine As String = ""
' loop through our file and read each line into our
' stringbuilder as we go along
Do
' read each line and MAKE SURE YOU ADD BACK THE
' LINEFEED THAT IT THE ReadLine() METHOD STRIPS OFF
curLine = sr.ReadLine()
If curLine.Contains("") Then
fileContents.AppendLine("$Folder=tbpath.selectedpath")
Else
fileContents.Append(curLine + vbCrLf)
If curLine.Contains ($Folder="") Then
Loop Until curLine Is Nothing
' close our reader now that we are done
sr.Close()
' call RunScript and pass in our file contents
' converted to a string
Return fileContents.ToString()
Sorry for the lengthy stuff, but the lines I am curious about are the curLine.Contains part. What I'm trying to do is have the parser detect whether or not the line is a specific one (which reads $Folder = "") and replace the empty quotes with a folder path that is stored in a text box (tbpath.selectedtext). Unfortunately, since the Powershell script requires quotes around the path string (in case there are spaces) I am having trouble figuring out how to do what I want it to do.
What should I do there? Should I build what I want into a new variable (maybe vbPath = tbpath.selectedtext) and put it into the new line? Are there any "best practices"?
Double up the quotes
Dim s As String = "$Folder = """""
s =
$Folder = ""
In your code
If curLine.Contains("$Folder = """"") Then
End If
Do you want curLine.Contains() to check for a literal string $Folder=""? If so, you need to put the whole string in double quotes and escape the inner ones. Double quotes are escaped by doubling them. Also, if you want to insert a variable, you need to concatenate it with the string literals, so the command should probably look like this:
If curLine.Contains ("$Folder = """"") Then
fileContents.Append("$Folder = """ & tbpath.selectedpath & """")
End If

unable to run Exchange Powershell through vb.net application

So I'm going round in circles trying to get this to work, I've been trying for two days and I just can't figure it out.
I have the following vb function that takes a created powershell script, and should run it in powershell. Everything works fine, until the point at which the command pipeline is invoked. At this point, no commands run.
As you can see, I have tried to add the Microsoft.Exchange.Management.PowerShell.E2010 snapin to the runspace, it didn't like that at all stating something along the lines of the snapin didnt exist (which it does), and also when I run the code as shown, no commands are recognised as valid. I even added the specific command "Add-PSSnapin" to try and load any Exchange snapins, but it states that "Add-PSSnapin" is not recognised as a valid command.
If I pause the program just before the commands are involked, I can see every command within the pipeline, in the correct format. If I copy and paste the command text in the pipeline directly into a powershell window, it runs fine.
My code is below, any suggestions welcome.
edit: I have also tried adding the line "Add-PSSnapin Ex" (with an asterisk each side of Ex - I cant figure the formatting out on this, sorry)
to try and load the Exchange PS Snapins as the first thing the script would run (opposed to setting this up in the runspace) but no luck
Private Function scriptRunner(ByVal scripttorun As String) As String
Dim initial As InitialSessionState = InitialSessionState.CreateDefault()
Dim result As String = ""
Dim lineFromScript As String = ""
Dim reader As New StreamReader(tempScript)
Dim rsConfig As RunspaceConfiguration = RunspaceConfiguration.Create()
Dim snapInException As New PSSnapInException
Dim strUserName As String = "DOMAIN\USER"
Dim strPassword As String = "PASSWORD"
Dim SecuredPSWD As New System.Security.SecureString()
For Each character As Char In strPassword
SecuredPSWD.AppendChar(character)
Next
Dim wsmConnectionInfo As WSManConnectionInfo
Dim strSystemURI As String = "http://SERVER.DOMAIN/powershell?serializationLevel=Full"
Dim strShellURI As String = "http://schemas.microsoft.com/powershell/Microsoft.Exchange"
Dim powerShellCredentials As PSCredential = New PSCredential(strUserName, SecuredPSWD)
wsmConnectionInfo = New WSManConnectionInfo(New Uri(strSystemURI), strShellURI, powerShellCredentials)
Dim runspace As Runspace = RunspaceFactory.CreateRunspace(wsmConnectionInfo)
Runspace.Open()
' runspace.RunspaceConfiguration.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.E2010", snapInException)
Dim pipeLine As Pipeline = runspace.CreatePipeline()
Dim command As Command = New Command("")
' TEST >> pipeLine.Commands.Add("Add-PSSnapin *Ex*")
Do While reader.Peek() <> -1
lineFromScript = Nothing
lineFromScript = reader.ReadLine()
pipeLine.Commands.Add(lineFromScript)
'command.Parameters.Add(lineFromScript)
'pipeLine.Commands.Add(command)
Loop
'' Run the contents of the pipeline
Dim psObjCollection As Collection(Of PSObject) = pipeLine.Invoke()
runspace.Close()
runspace.Dispose()
Return ""
End Function
I ended up working around the problem rather than fixing it.
I moved the script code into the vb.net application, and wrote each line to a file, i.e.
writer.WriteLine("Add-PSSnapin *Ex*")
Then I loaded the script through PowerShell as an application;
Dim exeStartInfo As System.Diagnostics.ProcessStartInfo
Dim exeStart As New System.Diagnostics.Process
exeStartInfo = New System.Diagnostics.ProcessStartInfo("C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe")
exeStartInfo.Arguments = ("-command work\scriptbuilder.ps1")
exeStartInfo.WorkingDirectory = "C:\ExchangeManager\"
exeStartInfo.UseShellExecute = False
exeStart.StartInfo = exeStartInfo
exeStart.Start()
exeStart.Close()
Not ideal but it got the job done.