Running Perl scripts through cmd on VB with asynchronous output to VB - vb.net

I'm quite new to VB.
I'm attempting to run a Perl script within perl through cmd, while streaming output from the perl script asynchronously.
Here's a part of my code:
Dim command as string = "perl perlscriptname.pl"
Dim proc As ProcessStartInfo = New ProcessStartInfo("cmd", "/c " & command)
proc.RedirectStandardOutput = True
proc.UseShellExecute = False
proc.CreateNoWindow = True
Dim process As Process = Process.Start(proc)
Dim stream As StreamReader = process.StandardOutput
While Not process.HasExited
tb.AppendText(Await stream.ReadLineAsync & vbNewLine)
End While
This allow me to run different cmd commands from VB, and I will mainly be only running Perl scripts from VB.
With this code, I'm able to get asynchronous output while executing some functions such as pinging, but when I attempt to run a Perl script, I'm unable to get a "live"/asynchronous output from the Perl script to VB.
Hope guys can help or advice me on how to proceed cus i'm stuck at this for quite some time.
Thanks in advance!

Related

Import-Module not working from within WinForms Application

I have a VB.net app where I invoke Import-Module on a PowerShell from within my vb.net Window Application but the error says it could not find the module. Error as below.
Import-Module : The specified module 'MSOnline' was not loaded because no valid module file was found in any module directory.
When I load the same Module by launching the PowerShell externally in the usual way it works fine. Image as below.
The VB script is as below
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim procStartInfo As New ProcessStartInfo
Dim procExecuting As New Process
With procStartInfo
.UseShellExecute = True
.FileName = "powershell.exe"
.WindowStyle = ProcessWindowStyle.Normal
.Verb = "runas" 'add this to prompt for elevation
Dim psscript As String = My.Resources.mymsolPS
procStartInfo.Arguments = psscript
procExecuting = Process.Start(procStartInfo)
End With
End Sub
My PowerShell Script is saved in my.resource as a txt file. My PowerShell Script is as below.
Import-Module Msonline
Connect-msolService
I replaced the PowerShell script to Get-Help and that works only it dosnt work when I use Import-Module Msonline.
One more information that can be shared is the module is stored in the below location.
C:\Windows\System32\WindowsPowerShell\v1.0\Modules\MSOnline\MSOnline.psd1
Any Help is greatly appreciated.
Thanks in Advance
Update 2:
More fiddling with it found some thing which i am not sure if is relevant.
If I launch the powershell from within my VB.net and run the below command I cant see the MSOnline module.
PS C:\windows\system32>> cd $env:WINDIR\System32\WindowsPowerShell\v1.0\Modules\
PS C:\windows\System32\WindowsPowerShell\v1.0\Modules>> dir
If I run the PowerShell directly from my system and run the above script I can see the Module
d----- 11/22/2017 2:59 PM MSOnline
Still a mystery for me which I cant crack. :(
A difference I notice is when launching from your app, or locally, the directory is either your user, or system.. so maybe the way PS is being loaded it can't find the module.
What about if you provide a full path to the module?
I've had much better luck using RunSpace - I use it to pass any powershell commands - here are a snippet from one of the sites and some examples to look at:
'Create the runspace.
Using R As System.Management.Automation.Runspaces.Runspace = _
System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace()
'Create the pipeline
Using P As System.Management.Automation.Runspaces.Pipeline = R.CreatePipeline()
'Open the runspace.
R.Open()
'Create each command (in this case just one)...
Dim Cmd As New System.Management.Automation.Runspaces.Command("C:\script.ps1", True)
'...and add it to the pipeline.
P.Commands.Add(Cmd)
'Execute the commands and get the response.
Dim Result As System.Collections.ObjectModel.Collection(Of _
System.Management.Automation.PSObject) = P.Invoke()
'Close the runspace.
R.Close()
'Display the result in the console window.
For Each O As System.Management.Automation.PSObject In Result
Console.WriteLine(O.ToString())
Next
End Using
End Using
http://www.winsoft.se/2009/08/execute-a-cmdlet-or-ps1-script-from-visual-basic/
https://social.msdn.microsoft.com/Forums/vstudio/en-US/5d2279c8-e02c-45eb-a631-951c56067bb5/run-powershell-script-from-vbnet?forum=vbgeneral
https://code.msdn.microsoft.com/windowsdesktop/VBPowerShell-6b4f83ea
The last one provides a pretty solid breakdown of what it's doing. Let me know if you can't get it to work, I can try to see if this import works on an app.
I actually found the solution after hours of pain. This is pretty silly solution.
Went I went to my application Properties I found that the Preferred run was set to 32 bit hence when my PowerShell was launched from within it was looking for the module under SYSWOW where its suppose to look it under System32. I unchecked the "Preferred 32 BIT" and not it imports the module from system 32.
Thought I should share this silly miss so that others should not suffer the same.

VB.NET wait for command line input before continuing

I'm writing a program to interface with an inspection machine. The machine has the ability to output command lines during its program run.
The machine has an interface application which allows the passing and automatic start of programs into the machine. I can get this to work with a single instance, however I would like to be able to select several programs for it to run back to back.
Below is the code to pass a single program to the machine:
im ProgramName As String = cbProgram.Text
Dim ProgURL = GetXMLNode(1, ProgramName)
Dim exeDir As New IO.FileInfo(Reflection.Assembly.GetExecutingAssembly.FullName)
Dim EXEPath = IO.Path.Combine(exeDir.DirectoryName, "iscmd.exe")
' New ProcessStartInfo created
Dim p As New ProcessStartInfo
' Specify the location of the binary
p.FileName = EXEPath
' Use these arguments for the process
p.Arguments = " /run""" & ProgURL & """ /nowait"
' Use a hidden window
p.WindowStyle = ProcessWindowStyle.Hidden
' Start the process
Dim ISCMD As Process = Process.Start(p)
ISCMD.WaitForExit()
MsgBox("PING!")
The PING will show immediately after the program has been passed to the machine (but not completed). What I want to be able to do is build an array of programs and launch this process once each time a program has completed. Is it possible to use a command line from the machine to signal to my software that the next program can be started? Below is a screenshot the machines command line.

Is calling CMD from vb.net sandboxed?

I've been trying to call cmd in order to run a command and get the output from it - specifically the "query user /server:servername" command, and have found lots of posts discussing how to run it. When I run it though, it seems to work for most commands (ipconfig, ping, tracert) but not my query user command. Interestingly, the code below seems to be ok for most commands but not this one.
Process.Start("cmd", "/c query user /server:PCNAME")
I also tried creating a batch file and running that.
Dim currentdir As String = Directory.GetCurrentDirectory
Dim server As String = txt_target_server.Text
Dim cmdline As String = "query user /server:" & server & " > tmpidlvw.txt"
IO.File.WriteAllText("tempbat.bat", "#echo off" & vbNewLine & cmdline)
Process.Start("tempbat.bat")
Dim currentreader As StreamReader
Dim currentfile As String = currentdir & "\tmpidlvw.txt"
If System.IO.File.Exists(currentfile) Then
currentreader = New StreamReader(currentfile)
Dim usercount As Integer = 0
Dim userarray(100) As String
Do While Not currentreader.EndOfStream
Dim tempstring As String = currentreader.ReadLine
MsgBox(tempstring)
userarray(usercount) = tempstring
usercount += 1
Loop
currentreader.Close()
For count As Integer = 1 To usercount
MsgBox(userarray(count))
Next
Else
MsgBox(currentfile)
End If
This also fails. I found that the batch file it creates works fine if I run it normally (the code generates it ok). I've isolated it to that the process.start(cmd.exe) doesn't seem to run the same as normal cmd.
for Example, if i run process.start(cmd.exe) and then do the following
cd c:\windows\system32
dir | findstr query
I get the following
14/07/09 02:14 AM 66,048 driverquery.exe
14/07/09 02:15 AM 395,776 dsquery.dll
08/07/15 10:48 PM 1,549,312 tquery.dll
If I run the exact same command from a normal command prompt, the output is below.
14/07/09 02:39 AM 96,256 driverquery.exe
14/07/09 02:40 AM 429,056 dsquery.dll
21/11/10 04:24 AM 16,384 query.exe
08/07/15 10:48 PM 2,315,776 tquery.dll
I believe this is why it fails - the cmd called does not "see" the same directory as a normal command prompt and cannot see the query.exe file.
Does anyone know what I can do to get this to work? I've verified this happens if I run my code on another machine, and have turned off vmware debugging, antivirus, autosandbox etc.

Multiple commands to run using Visual Basic

I am developing a tool on Visual Studio 2010 which has a button which executes a powershell program. But before this execution we need to change the path on cmd prompt.
cd Try & powershell C:\Users\Medha\Try\out.ps1
, this statement works fine on cmd prompt but in my VB code, both the commands are taken together and executed at once, which needs to be one by one.
I have tried this
> Shell("cmd.exe /k" + "cd Try & powershell C:\Users\Medha\Try\out.ps1")
Please suggest changes to make it work.
Why don't you use WorkingDirectory property
Dim myProcess As New System.Diagnostics.Process
//if it's in system directory use Environment.SystemDirectory
myProcess.StartInfo.WorkingDirectory = "your\working\directory"
myProcess.StartInfo.FileName = "powershell.exe"
myProcess.StartInfo.UseShellExecute = True
myProcess.Start

How to pass command line arguments to the .exe file (e.g silent mode) using process.start

I have an vb.net windows application in this application i want run another exe file in silent mode,for this first i have run this exe file in command line it is working.But i don't know how to pass the these arguments through vb.coding process.start .
through command line i have pass like this.
D:\myapps>sample.exe /s /v/qn (working fine)
but through coding i have pass like this
Directory.SetCurrentDirectory(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))
Dim info As New System.Diagnostics.ProcessStartInfo
info.FileName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\sample.exe"
info.Arguments = "/s /v/qn"
Dim process As New System.Diagnostics.Process
process.StartInfo = info
process.Start()
MessageBox.Show(info.Arguments.ToString())
process.Close()
this is not working what is wrong with this code please help me..
Process.Start("D:\myapps\sample.exe", "/s /v/qn")