Using VB, is there a way to capture the FTP results from a CMD window? - vb.net

I'm using Visual studio 2012 and writing in VB. I want to find a way to launch a batch file for an FTP download or upload, have the progress show in the CMD window and record the results of the transfer times to a textbox.
Any help is appreciated.
FTP batch Scripts are as follows:
Filename: FTP_1M_Download.bat:
#Echo off
cd (Folder name here)
ftp -s:FTP_1M_Download_s.bat
Filename: FTP_1M_Download_s.bat:
open (FTP Address here)
username
password
hash
bin
be
get down_1M.zip

Here is some un-edited utility code I use to run RoboCopy using ProcessStartInfo. It captures the output stream (the code doesn't do anything with it in this case.)
I use the Kellerman SFTP library - works great, not expensive.
Sub RunRobo(ByVal SD As String, ByVal DD As String, ByVal Job As String, ByRef Out As String, ByRef Err As String)
' runs RoboCopy and returns log text
' typical job: "*.* /V /NDL /S /E /COPY:DAT /PURGE /NP /R:0 /W:0 "
Try
Application.DoEvents()
Dim sParams As String = SD & " " & DD & " " & Job
'If Not ShowHeadFoot Then sParams &= " /NJH /NJS"
' Set start information.
Dim start_info As New ProcessStartInfo("RoboCopy", sParams)
start_info.UseShellExecute = False
start_info.CreateNoWindow = True
start_info.RedirectStandardOutput = True
start_info.RedirectStandardError = True
' Make the process and set its start information.
Dim proc As New Process()
proc.StartInfo = start_info
' Start the process.
proc.Start()
' Attach to stdout and stderr.
Dim std_out As System.IO.StreamReader = proc.StandardOutput()
Dim std_err As System.IO.StreamReader = proc.StandardError()
' Display the results.
Out = std_out.ReadToEnd()
Err = std_err.ReadToEnd()
'Dim aLines() As String = sOut.Split(vbCrLf) ' if no header/footer creates array of file info
' more generic would be to return via params
'txtStreetsErr.Text = sErr
'txtStreetsOut.Text = sOut
Try
std_out.Close()
std_err.Close()
Catch ex As Exception
End Try
Try
proc.Close()
Catch ex As Exception
End Try
Catch ex As Exception
MsgBox(ex.Message, , "Error during RoboCopy")
Finally
'Cursor = Cursors.Default
End Try
End Sub

Related

Using SSIS Script Task to download files from FTP

I am trying to download files from FTP using SSIS script task, I have written some code to download files from FTP using the ftpWebRequest class which is working. But I also need to take in to account that we might be asked to download it from a sFTP. Since many are suggesting that WinSCP assemblies are the best way to download sFTP files, can some provide me with some examples to download files using a SSIS script with the WinSCP classes.
PS: I am new to Vb.net
Yes, as people have said the only option is to use a library like WinSCP.
Take a look at the examples here on the WinSCP website - http://winscp.net/eng/docs/script_vbnet_robust_example
Here is the source code from the example
Imports System
Imports System.IO
Imports System.Diagnostics
Imports System.Xml
Imports System.Xml.XPath
Imports System.Configuration.ConfigurationManager
Public Class SFTP
' SFTP support, built on WinSCP
Public Shared Function PutSFTP(ByRef filename As String, ByRef remotehost As String, ByRef username As String, ByRef password As String, _
Optional ByVal outfilename As String = Nothing, Optional ByVal output As String = Nothing,
Optional ByRef errmsg As String = Nothing) As Boolean
' Run hidden WinSCP process
Dim winscp As Process = New Process()
Dim logname As String = Path.ChangeExtension(Path.GetTempFileName, "xml")
With winscp.StartInfo
' SFTPExecutable needs to be defined in app.config to point to winscp.com
Try
.FileName = AppSettings("SFTPExecutable")
If .FileName Is Nothing OrElse .FileName.Length = 0 Then Throw (New Exception("from PutSFTP: SFTPExecutable not set in config file."))
Catch ex As Exception
errmsg = ex.Message
Return False
End Try
.Arguments = "/xmllog=" + logname
.UseShellExecute = False
.RedirectStandardInput = True
.RedirectStandardOutput = True
.CreateNoWindow = True
End With
Try
winscp.Start()
Catch ex As Exception
errmsg = "from PutSFTP: Could not run the WinSCP executable " & winscp.StartInfo.FileName & Environment.NewLine & ex.Message
Return False
End Try
' Feed in the scripting commands
With winscp.StandardInput
.WriteLine("option batch abort")
.WriteLine("option confirm off")
.WriteLine("open sftp://" & username & ":" & password & "#" & remotehost & "/")
If outfilename Is Nothing Then .WriteLine("put " & filename) Else .WriteLine("put " & filename & " """ & outfilename & """")
.Close()
End With
If output IsNot Nothing Then output = winscp.StandardOutput.ReadToEnd()
' Wait until WinSCP finishes
winscp.WaitForExit()
' Parse and interpret the XML log
' (Note that in case of fatal failure the log file may not exist at all)
If Not File.Exists(logname) Then
errmsg = "from PutSFTP: The WinSCP executable appears to have crashed."
Return False
End If
Dim log As XPathDocument = New XPathDocument(logname)
Dim ns As XmlNamespaceManager = New XmlNamespaceManager(New NameTable())
ns.AddNamespace("w", "http://winscp.net/schema/session/1.0")
Dim nav As XPathNavigator = log.CreateNavigator()
' Success (0) or error?
Dim status As Boolean = (winscp.ExitCode = 0)
If Not status Then
errmsg = "from PutSFTP: There was an error transferring " & filename & "."
' See if there are any messages associated with the error
For Each message As XPathNavigator In nav.Select("//w:message", ns)
errmsg &= Environment.NewLine & message.Value
Next message
End If
Try
My.Computer.FileSystem.DeleteFile(logname)
Catch ex As Exception
' at least we tried to clean up
End Try
Return status
End Function
End Class

Displaying the output of Process.Start

I have a Process.Start command that I would like to see the output of, but the new window is opening and closing too quickly for me to see anything. Here is the code I have so far that I'm working with:
System.Diagnostics.Process.Start(Environment.GetEnvironmentVariable("VS110COMNTOOLS") & "..\Ide\MSTEST.EXE", "/Testsettings: """ & rwSettings & "" & " /Testcontainer: """ & rwContainer & "" & " /Resultsfile: """ & rwResults & "")
Unfortunately as I try to debug this if I allow this to run it flashes up the window but doesn't let me see what the error is, or if it's running successfully at all. I'm using VS2012 so I might just not be looking at the right view when I'm debugging.
Here is some code taen out of the middle of some logic, so it is not standalone. You can use ProcessStartInfo() and Process() to have more control:
Dim start_info As New ProcessStartInfo("sqlcmd", cmd)
start_info.UseShellExecute = False
start_info.CreateNoWindow = True
start_info.RedirectStandardOutput = True
start_info.RedirectStandardError = True
' Make the process and set its start information.
Dim proc As New Process()
proc.StartInfo = start_info
Dim dt As Date = Now()
' Start the process.
proc.Start()
' Attach to stdout and stderr.
Dim std_out As StreamReader = proc.StandardOutput() ' will not continue until process stops
Dim std_err As StreamReader = proc.StandardError()
' Retrive the results.
Dim sOut As String = std_out.ReadToEnd()
Dim sErr As String = std_err.ReadToEnd()

Get data from Text file Print to Label

Just to keep this short I am working on a simple game to be played with anyone in the world who be interested in it, and because I am creating said game I decided to work on a simple launcher for the game one that pings the website for a version, checks that version with a stored text file with the game already installed and see if its a difference in version. If its a difference in version the launcher downloads the game. If the person does not already have the game installed it downloads the game for them.
Now for my problem why I am posting here, I am trying to get the text file already stored on the computer from the AppData directory to be read by the launcher and use it as an comparison with the version on the website. This is what I have for the on launch:
On Launch:
Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim wc As New Net.WebClient
Text = wc.DownloadString("https://dl.dropboxusercontent.com/u/47132467/version.txt")
If My.Computer.FileSystem.FileExists("C:\Program Files\SC\SC.exe") Then
StartBtn.Enabled = True
StartBtn.Visible = True
Else
StartBtn.Enabled = False
StartBtn.Visible = False
End If
If My.Computer.FileSystem.FileExists("C:\Program Files\SC\Readme.txt") Then
ReadMeBtn.Visible = True
Else
ReadMeBtn.Visible = False
End If
End Sub
In short I am trying to figure out how to make a text file from the computer itself stored in AppData under Environ("AppData") & "\SC\version.txt" Been trying to figure out how to get the program to Read the local stored text file and put it as a variable where the program will compare it with the text file online. Thanks in Advanced! Sorry if I confuse anyone my brain is in derp mode trying to figure this out for a while now.
Here are 2 Functions Read & Write:
Public Function GetFileContents(ByVal FullPath As String, _
Optional ByRef ErrInfo As String = "") As String
Dim strContents As String
Dim objReader As StreamReader
Try
objReader = New StreamReader(FullPath)
strContents = objReader.ReadToEnd()
objReader.Close()
Return strContents
Catch Ex As Exception
ErrInfo = Ex.Message
End Try
End Function
Public Function SaveTextToFile(ByVal strData As String, _
ByVal FullPath As String, _
Optional ByVal ErrInfo As String = "") As Boolean
Dim Contents As String
Dim bAns As Boolean = False
Dim objReader As StreamWriter
Try
objReader = New StreamWriter(FullPath)
objReader.Write(strData)
objReader.Close()
bAns = True
Catch Ex As Exception
ErrInfo = Ex.Message
End Try
Return bAns
End Function
Call:
Dim File_Path as string = Environ("AppData") & "\SC\version.txt"
Dim versionStr as String = GetFileContents("File_Path")
Label1.text = versionStr
Label1.text.refresh ''// Sometimes this may be required depending on what you are doing!
if you want to read the version directly, rather than a text file, have a look at this code:
If My.Computer.FileSystem.FileExists(fn) Then
Dim fv As FileVersionInfo = FileVersionInfo.GetVersionInfo(fn)
If fv Is Nothing Then Return -1 'file has no version info
Return fv.FileMajorPart * 100000 + fv.FileMinorPart * 1000 + fv.FileBuildPart
Else
Return 0 'file does not exist
End If

VB.NET - Problems trying to write a textfile

I have problems when trying to delete/create/write to this file.
The error:
The process cannot access the file 'C:\Users\Administrador\AppData\Local\Temp\PlayList_temp.txt' because it is being used by another process.
The highlighted lines by debugger:
If System.IO.File.Exists(Temp_file) = True Then System.IO.File.Delete(Temp_file)
System.IO.File.Create(Temp_file)
(Any of two, if I delete one line, the other line takes the same error id)
The sub:
Public Sub C1Button2_Click(sender As Object, e As EventArgs) Handles Button1.Click
If Not playerargs = Nothing Then
Dim Str As String
Dim Pattern As String = ControlChars.Quote
Dim ArgsArray() As String
Dim Temp_file As String = System.IO.Path.GetTempPath & "\PlayList_temp.txt"
Dim objWriter As New System.IO.StreamWriter(Temp_file)
Str = Replace(playerargs, " " & ControlChars.Quote, "")
ArgsArray = Split(Str, Pattern)
If System.IO.File.Exists(Temp_file) = True Then System.IO.File.Delete(Temp_file)
System.IO.File.Create(Temp_file)
For Each folder In ArgsArray
If Not folder = Nothing Then
Dim di As New IO.DirectoryInfo(folder)
Dim files As IO.FileInfo() = di.GetFiles("*")
Dim file As IO.FileInfo
For Each file In files
' command to writleline
'Console.WriteLine("File Name: {0}", file.Name)
'Console.WriteLine("File Full Name: {0}", file.FullName)
objWriter.Write(file.FullName)
objWriter.Close()
Next
End If
Next
If randomize.Checked = True Then
RandomiseFile(Temp_file)
End If
Process.Start(userSelectedPlayerFilePath, playerargs)
If autoclose.Checked = True Then
Me.Close()
End If
Else
MessageBox.Show("You must select at least one folder...", My.Settings.APPName)
End If
End Sub
First, File.Create creates or overwrite the file specified, so you don't need to Delete it before.
Second, initializing a StreamWriter as you do, blocks the file and therefore you can't recreate it after.
So, simply move the StreamWriter intialization after the File.Create, or better, remove altogether the File.Create and use the StreamWriter overload that overwrites the file
....
If Not playerargs = Nothing Then
....
Dim Temp_file As String = System.IO.Path.GetTempPath & "\PlayList_temp.txt"
Using objWriter As New System.IO.StreamWriter(Temp_file, false)
For Each folder In ArgsArray
If Not folder = Nothing Then
Dim di As New IO.DirectoryInfo(folder)
Dim files As IO.FileInfo() = di.GetFiles("*")
Dim file As IO.FileInfo
For Each file In files
' command to writleline
'Console.WriteLine("File Name: {0}", file.Name)
'Console.WriteLine("File Full Name: {0}", file.FullName)
objWriter.Write(file.FullName)
' objWriter.Close()
Next
End If
Next
End Using ' Flush, close and dispose the objWriter
....
Noticed also that you close the writer while still inside the loop, use the Using statement to close correctly the writer after the work is done.
The process cannot access the file 'C:\Users\Administrador\AppData\Local\Temp\PlayList_temp.txt' because it is being used by another process.
That means the file is opened or been used by another process.
Open your task manager and check if the file is there, then close it or simplex end the process.
I have had the same issue but I got it solved by closing the file.
Hope this helps!
From your details it seems that you are willing to delete if file exists and creates a new one.
I would suggest to remove this line:
System.IO.File.Create(Temp_file)
and move this line just over the streamwriter line:
If System.IO.File.Exists(Temp_file) = True Then System.IO.File.Delete(Temp_file)
Something like this would help you:
Partial code:
Dim Temp_file As String = System.IO.Path.GetTempPath & "\PlayList_temp.txt"
' Delete file if exists
If System.IO.File.Exists(Temp_file) = True Then System.IO.File.Delete(Temp_file)
' Create file for write.
Dim objWriter As New System.IO.StreamWriter(Temp_file)
Str = Replace(playerargs, " " & ControlChars.Quote, "")
ArgsArray = Split(Str, Pattern)
...
...
...

Reading Console Output to write out an error log VB

I am running some commands on computers and I would like to have them output a seperate text file if the command cannot run.
For Each strUserName As String In strLines
Dim ReplaceCommand As String = sCommand.Replace("*", strUserName).Replace("$$$", saveFileDialog3.FileName & ".txt").Replace("###", exeSearch)
Shell("cmd.exe /c" & ReplaceCommand, AppWinStyle.Hide, True, )
' If Command Cannot Execute, List Why and Move onto Next Command
Using swrr As New StreamWriter(File.Open(ErrorLog, FileMode.OpenOrCreate))
If Console.Readline = "blahblah" Then swrr.WriteLine("FAIL") Else swrr.WriteLine("PASS")
End Using
Next
Am I on the right track? I am getting an output to a text file but its just one line ans always says PASS.
Several things: you're creating a new StreamWriter every time you want to write a line to it, instead of creating one then just writing to it when you need to. You're still using shell which is really basic, and not really suited for what you need. You should really be using a process for this.
I've written a function for you to use to execute the process instead of using the shell, which will return the output from the command execution to the ConsoleOutput variable, which you can then check for output strings.
Lastly, you should be using String.Format instead of replace to create the correct string for the command to run. For example:
Dim FirstName As String = "Jay"
Dim Age As String = "twenty"
Dim Greeting As String = String.Format("Hello {0}, I know you're {1} years old", FirstName, Age)
' Greetings value would be "Hello Jay, I know you're twenty years old"
So tweak the below to suit, specifically the Args variable, USING THE STRING.FORMAT function :)
Sub DoWork()
Dim ConsoleOutput As String = String.Empty
Using swrr As New StreamWriter(ErrorLog, True)
For Each strUserName As String In StrLines
ConsoleOutput = GetCMDOuput(strUserName, saveFileDialog3.FileName, exeSearch)
' If Command Cannot Execute, List Why and Move onto Next Command
If ConsoleOutput = "blahblah" Then swrr.WriteLine("FAIL") Else swrr.WriteLine("PASS")
Next
End Using
End Sub
Function GetCMDOuput(ByVal strUserName As String, ByVal strFileName As String, ByVal strExeSearch As String) As String
Dim Args As String = String.Format("/c -paramzero {0} -paramone {1} -paramtwo {2}", strUserName, strFileName, strExeSearch)
Dim CMD As New Process
CMD.StartInfo.FileName = "cmd.exe"
CMD.StartInfo.Arguments = Args
CMD.StartInfo.UseShellExecute = False
CMD.StartInfo.RedirectStandardInput = True
CMD.StartInfo.RedirectStandardOutput = True
CMD.StartInfo.CreateNoWindow = True
CMD.Start()
Dim retval As String = CMD.StandardOutput.ReadToEnd
CMD.WaitForExit()
Return retval
End Function