Using wininet.dll to retrieve FTP command output - vb.net

I'm trying to find a simple way of checking user stats via FTP, wininet seems to be the best option.
How do I get the output from the command though?
Private Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal HINet As Integer) As Integer
Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" (ByVal sAgent As String, ByVal lAccessType As Integer, ByVal sProxyName As String, ByVal sProxyBypass As String, ByVal lFlags As Integer) As Integer
Private Declare Function InternetConnect Lib "wininet.dll" Alias "InternetConnectA" (ByVal hInternetSession As Integer, ByVal sServerName As String, ByVal nServerPort As Integer, ByVal sUsername As String, ByVal sPassword As String, ByVal lService As Integer, ByVal lFlags As Integer, ByVal lContext As Integer) As Integer
Public Declare Function ftpCommand Lib "wininet.dll" Alias "FtpCommandA" (ByVal hConnect As Integer, ByVal fExpectResponse As Boolean, ByVal dwFlags As Integer, ByVal lpszCommand As String, ByRef dwContext As Integer, ByRef phFtpCommand As Integer) As Boolean
Dim INet, INetConn As Integer
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
INet = InternetOpen("MyFTP", 1, vbNullString, vbNullString, 0)
INetConn = InternetConnect(INet, "192.168.1.6", 21, "user", "pwd", 1, 0, 0)
strCommand = "SITE SHOW SERVER 192.168.1.6.21"
Dim retv As Long
Dim Test = ftpCommand(INetConn, True, 2, strCommand, 0, retv)
Debug.Write(Test)
InternetCloseHandle(INetConn)
InternetCloseHandle(INet)
End Sub
The output I'm expecting is:
Response: 200- Server IP = "192.168.1.6"
Response: 200- Port = "21"
Response: 200- Start time = "10/02/2010 02:46:57 PM"
Response: 200- Download = "0.000 KB"
Response: 200- Upload = "0.000 KB"
Response: 200- Online Users = "0"
Response: 200-======================================
Response: 200 Site command OK
Thanks.

I think you may find use of InternetGetLastResponseInfo which is a link to the c++ definition
(found this by navigating the WinINet function list) but provides a useful hint
it says:
InternetGetLastResponseInfo Function
Retrieves the last error description or server response on the thread calling this function.
Consider this sample implementation
Private Function GetServerResponse() As String
Dim lError As Long
Dim strBuffer As String
Dim lBufferSize As Long
Dim retVal As Long
retVal = InternetGetLastResponseInfo(lError, strBuffer, lBufferSize)
strBuffer = New String("", lBufferSize + 1)
retVal = InternetGetLastResponseInfo(lError, strBuffer, lBufferSize)
GetServerResponse = strBuffer
End Function
Which calls the external function (here for copy paste access)
Declare Function InternetGetLastResponseInfo Lib "wininet" Alias "InternetGetLastResponseInfoA" (ByRef lpdwError As Long, ByVal lpszBuffer As String, ByRef lpdwBufferLength As Long) As Boolean
twice, once to get the buffer length and again to fill the buffer string then returns the filled buffer

Related

Writing text to console buffer

I am just learning programming, so please be understanding :)
I am writing an application that needs to send text data to another console program. I was successful with SendMessage(), but unfortunately with Wine (on linux) it is not supported for console applications.
So I found a function that is supported. This is WriteConsoleInput().
Here is my code, could someone indicate why it doesn't work?
Public Declare Function AttachConsole Lib "kernel32" (ByVal ProcessID As Long) As Boolean
Private Declare Function GetStdHandle Lib "kernel32.dll" (ByVal nStdHandle As Int32) As IntPtr
Declare Function WriteConsoleInputW Lib "kernel32" Alias "WriteConsoleInputW" (ByVal hConsoleInput As Integer, ByVal lpBuffer As String, ByVal nNumberOfCharsToWrite As Integer, ByRef lpNumberOfCharsWritten As Integer) As Integer
Declare Function WriteConsoleInputA Lib "kernel32" Alias "WriteConsoleInputA" (ByVal hConsoleInput As Integer, ByVal lpBuffer As String, ByVal nNumberOfCharsToWrite As Integer, ByRef lpNumberOfCharsWritten As Integer) As Integer
Declare Function SetConsoleTitle Lib "kernel32.dll" Alias "SetConsoleTitleA" (lpConsoleTitle As String) As Boolean
Private Const STD_OUTPUT_HANDLE As Long = -11&
Private Const STD_INPUT_HANDLE As Long = -10&
Private Const STD_ERROR_HANDLE As Long = -12&
Private Const INVALID_HANDLE_VALUE As Long = -1&
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim titleStr As String = "Test"
Dim textToWrite As Char() = CType("test", Char())
Dim stdIN As Integer
Dim stdOUT As Integer
Dim charwritten As Integer = 0
Dim ret As Integer
If ReturnCMDProcessID() = 0 Then
MessageBox.Show("CMD off")
Exit Sub
End If
AttachConsole(ReturnCMDProcessID())
stdIN = CInt(GetStdHandle(CInt(STD_INPUT_HANDLE)))
stdOUT = CInt(GetStdHandle(CInt(STD_OUTPUT_HANDLE)))
ret = WriteConsoleInputA(stdIN, textToWrite, textToWrite.Length, charwritten)
SetConsoleTitle(titleStr)
End Sub
Did you try the "built-in" way to do this?
System.Console:
https://learn.microsoft.com/en-us/dotnet/api/system.console?view=netframework-4.8
And in particular Console.In
https://learn.microsoft.com/en-us/dotnet/api/system.console.in?view=netframework-4.8
And Console.Out
https://learn.microsoft.com/en-us/dotnet/api/system.console.out?view=netframework-4.8
I also just noticed you are setting the title, that is as simple as Console.Title = "My Title"

How to resolve Error-487 during WNetAddConnection in VB.NET

I have been trying to connect remote PC with known Credentials but variable lon(refer below code) is showing Error-487.
Code:
Private Declare Function WNetAddConnection2 Lib "mpr.dll" Alias "WNetAddConnection2A" ( ByRef lpNetResource As NETRESOURCE, ByVal lpPassword As String, ByVal lpUserName As String, ByVal dwFlags As Integer) As Long
Private Declare Function WNetCancelConnection2 Lib "mpr.dll" Alias "WNetCancelConnection2A" (ByVal lpName As String, ByVal dwFlags As Long, ByVal fForce As Integer) As Long
Private Structure NETRESOURCE
Dim dwType As Long
Dim lpRemoteName As String
End Structure
Private Const RESOURCETYPE_DISK = &H1
Private Sub ConnectToPC()
Dim networkResource As New NETRESOURCE
Dim lon As Long
With networkResource
.dwType = RESOURCETYPE_DISK
.lpRemoteName = "\\192.168.1.1"
End With
lon = WNetAddConnection2(networkResource, "123", "ADMIN", 0)
msgbox(lon)
lon = WNetCancelConnection2("\\192.168.1.1", 0, 1)
msgbox(lon)
End Sub
Tried Below thing but it didn't serve my purpose
- Change type from Integer to Int32/Int64
I have been working on this issue for last two days but couldn't gain any success. Can anybody tell me what went wrong with code? Any help will be highly Appreciated

SFTP upload in VBA

Dode below doesn't return an error, or "success" or "fail" but it also doesn't work - information in the sub TestUpload that is CAPITALIZED is the only info that i changed to make this post - everything else is legit - thanks in advance.
Option Compare Database
Private Const FTP_TRANSFER_TYPE_UNKNOWN As Long = 0
Private Const INTERNET_FLAG_RELOAD As Long = &H80000000
Private Declare Function InternetOpenA Lib "wininet.dll" ( _
ByVal sAgent As String, _
ByVal lAccessType As Long, _
ByVal sProxyName As String, _
ByVal sProxyBypass As String, _
ByVal lFlags As Long) As Long
Private Declare Function InternetConnectA Lib "wininet.dll" ( _
ByVal hInternetSession As Long, _
ByVal sServerName As String, _
ByVal nServerPort As Long, _
ByVal sUsername As String, _
ByVal sPassword As String, _
ByVal lService As Long, _
ByVal lFlags As Long, _
ByVal lcontext As Long) As Long
Private Declare Function FtpPutFileA _
Lib "wininet.dll" _
_
(ByVal hFtpSession As Long, _
ByVal lpszLocalFile As String, _
ByVal lpszRemoteFile As String, _
ByVal dwFlags As Long, _
ByVal dwContext As Long) As Boolean
Private Declare Function InternetCloseHandle Lib "wininet" ( _
ByVal hInet As Long) As Long
Sub FtpUpload(ByVal strLocalFile As String, ByVal strRemoteFile As String, ByVal strHost As String, ByVal lngPort As Long, ByVal strUser As String, ByVal strPass As String)
Dim hOpen As Long
Dim hConn As Long
hOpen = InternetOpenA("FTPGET", 1, vbNullString, vbNullString, 1)
hConn = InternetConnectA(hOpen, strHost, lngPort, strUser, strPass, 1, 0, 2)
If FtpPutFileA(hConn, strLocalFile, strRemoteFile, FTP_TRANSFER_TYPE_UNKNOWN Or INTERNET_FLAG_RELOAD, 0) Then
Debug.Print "Success"
Else
Debug.Print "Fail"
End If
'Close connections
InternetCloseHandle hConn
InternetCloseHandle hOpen
End Sub
Sub TestUpload()
FtpUpload "C:\Users\FOLDER\UPLOAD FILE.csv", "/<root>/SFTPSITE FOLDER NAME/admin", _
"IP.ADDRESS.OF.SFTPSITE", "22", "SIGNIN#sftp.DOMAIN.com", "PASSWORD"
End Sub
WinINet functions do not support SFTP protocol (FTP protocol is completely different).
There's no native support for SFTP in VBA nor in Windows API. You have to use a 3rd party library or software.
See these questions for some examples:
Using WinSCP scripting: Using VBA to run WinSCP script
Using WinSCP .NET assembly: Getting "user defined type not defined" when trying to use WinSCP .NET assembly in VBA to upload file to SFTP
(I'm the author of WinSCP)

Ini-File reader with kernel32.dll do not read from file

I have the Problem that my script writes only the default value to the new Ini-File. It sould read the value from the BackupConfig. I do not see my error, yet. The output of the MessageBox should be the old URL but it prints google.
I hope you can help me, thank you.
My script looks like this
My.Computer.FileSystem.MoveFile(ConfigName, "backup.Config.ini", True)
Thread.Sleep(2000)
Dim Config As IniFile = New IniFile(ConfigName)
Dim BackupConfig As IniFile = New IniFile("backup.Config.ini")
MessageBox.Show(BackupConfig.GetString("Window08", "Url", "http://google.de"))
Config.WriteInteger("Setup", "Opacity", BackupConfig.GetInteger("Setup", "Opacity", 100))
This is my IniFile Class, i found it here on Stackoverflow an do not know which user posted it. (Sorry for that)
Public Class IniFile
' API functions
Private Declare Ansi Function GetPrivateProfileString _
Lib "kernel32.dll" Alias "GetPrivateProfileStringA" _
(ByVal lpApplicationName As String, _
ByVal lpKeyName As String, ByVal lpDefault As String, _
ByVal lpReturnedString As System.Text.StringBuilder, _
ByVal nSize As Integer, ByVal lpFileName As String) _
As Integer
Private Declare Ansi Function WritePrivateProfileString _
Lib "kernel32.dll" Alias "WritePrivateProfileStringA" _
(ByVal lpApplicationName As String, _
ByVal lpKeyName As String, ByVal lpString As String, _
ByVal lpFileName As String) As Integer
Private Declare Ansi Function GetPrivateProfileInt _
Lib "kernel32.dll" Alias "GetPrivateProfileIntA" _
(ByVal lpApplicationName As String, _
ByVal lpKeyName As String, ByVal nDefault As Integer, _
ByVal lpFileName As String) As Integer
Private Declare Ansi Function FlushPrivateProfileString _
Lib "kernel32.dll" Alias "WritePrivateProfileStringA" _
(ByVal lpApplicationName As Integer, _
ByVal lpKeyName As Integer, ByVal lpString As Integer, _
ByVal lpFileName As String) As Integer
Dim strFilename As String
' Constructor, accepting a filename
Public Sub New(ByVal Filename As String)
strFilename = Filename
End Sub
' Read-only filename property
ReadOnly Property FileName() As String
Get
Return strFilename
End Get
End Property
Public Function GetString(ByVal Section As String, _
ByVal Key As String, ByVal [Default] As String) As String
' Returns a string from your INI file
Dim intCharCount As Integer
Dim objResult As New System.Text.StringBuilder(256)
intCharCount = GetPrivateProfileString(Section, Key, _
[Default], objResult, objResult.Capacity, strFilename)
If intCharCount > 0 Then GetString = _
Left(objResult.ToString, intCharCount)
End Function
Public Function GetInteger(ByVal Section As String, _
ByVal Key As String, ByVal [Default] As Integer) As Integer
' Returns an integer from your INI file
Return GetPrivateProfileInt(Section, Key, _
[Default], strFilename)
End Function
Public Function GetBoolean(ByVal Section As String, _
ByVal Key As String, ByVal [Default] As Boolean) As Boolean
' Returns a boolean from your INI file
Return (GetPrivateProfileInt(Section, Key, _
CInt([Default]), strFilename) = 1)
End Function
Public Sub WriteString(ByVal Section As String, _
ByVal Key As String, ByVal Value As String)
' Writes a string to your INI file
WritePrivateProfileString(Section, Key, Value, strFilename)
Flush()
End Sub
Public Sub WriteInteger(ByVal Section As String, _
ByVal Key As String, ByVal Value As Integer)
' Writes an integer to your INI file
WriteString(Section, Key, CStr(Value))
Flush()
End Sub
Public Sub WriteBoolean(ByVal Section As String, _
ByVal Key As String, ByVal Value As Boolean)
' Writes a boolean to your INI file
WriteString(Section, Key, CStr(CInt(Value)))
Flush()
End Sub
Private Sub Flush()
' Stores all the cached changes to your INI file
FlushPrivateProfileString(0, 0, 0, strFilename)
End Sub
End Class

Mapping/unmapping drives failing

I need to first map and then later unmap 2x drives using VB.NET.
When mapping the drives, I also need to pass a username and password (as not all users have admin access).
However, not only is the below not working (failing to map, so in turn failing to unmap), but I notice that I only have the option to pass a password when mapping a drive, not a username.
Can anyone help me in fixing these problems? Thanks.
Private Declare Function WNetAddConnection Lib "mpr.dll" Alias "WNetAddConnectionA" (ByVal lpszNetPath As String,
ByVal lpszPassword As String,
ByVal lpszLocalName As String) As Long
Private Declare Function WNetCancelConnection Lib "mpr.dll" Alias "WNetCancelConnectionA" (ByVal lpszName As String,
ByVal bForce As Long) As Long
Public Function MapDrive(ByVal UNCPath As String, ByVal Password As String, ByVal DriveLetter As String) As Boolean
Dim MappedResult As Long = WNetAddConnection(UNCPath, Password, DriveLetter)
Return IIf(MappedResult = 0, True, False)
End Function
Public Function UnmapDrive(ByVal DriveLetter As String) As Boolean
Dim UnmappedResult As Long = WNetCancelConnection(DriveLetter, 0)
Return IIf(UnmappedResult = 0, True, False)
End Function
You should switch to using the WNetAddConnection2/WNetCancelConnection2 functions. The former allows you to specify a username in the call. Here are the PInvoke signatures I've used successfully in the past:
Private Declare Function WNetAddConnection2 Lib "mpr.dll" Alias "WNetAddConnection2A" _
(ByRef lpNetResource As NETRESOURCE, ByVal lpPassword As String, _
ByVal lpUserName As String, ByVal dwFlags As Integer) As Integer
Private Declare Function WNetCancelConnection2 Lib "mpr.dll" Alias "WNetCancelConnection2A" _
(ByVal lpName As String, ByVal dwFlags As Integer, ByVal fForce As Integer) As Integer
Private Declare Function WNetGetLastError Lib "mpr.dll" Alias "WNetGetLastErrorA" _
(ByRef nError As Integer, ByRef lpErrorBuf As String, ByVal nErrorBufSize As Integer, _
ByRef lpNamebuf As String, ByVal nNameBufSize As Integer) As Integer
<StructLayout(LayoutKind.Sequential)> _
Public Structure NETRESOURCE
Public dwScope As Integer
Public dwType As Integer
Public dwDisplayType As Integer
Public dwUsage As Integer
Public lpLocalName As String
Public lpRemoteName As String
Public lpComment As String
Public lpProvider As String
End Structure
Private Const ForceDisconnect As Integer = 1
Private Const RESOURCETYPE_DISK As Long = &H1
GetLastError is useful for figuring out why the mapping failed (bad password, etc).