Eli miten lähteä ratkaisemaan ongelmaa. Yritän käyttää VB6:lla cmd:tä saan ensimmäisen käskyn menemään läpi, mutta kaikki cmd:ssä tapahtuva ei onnistu aina hetkessä, joten pitää hetki odotella, ennenkuin voidaan antaa uusi käsky. Eli yksinkertaisetettuna..
Annan VB:llä käskyn:
n = Shell("cmd.exe /c ftp")Ja kaikki toimii, mutta kuinka voin antaa seuraavan käskyn, kun tuo ftp ohjelma on auki. Esimerkiksi "open 192.x.x.x" Ja sitten perään vaikkapa "send a.txt a.txt"
-Viljami-
Suosittelen tekemään ennemmin vaikka VB.Netillä. Sillä on huomattavasti helpompaa avata prosessi jonka kanssa voi keskustella. Toki VB6:llakin onnistuu WinAPIa käyttäen, mutta mitään järkeä ei ole tehdä uusia ohjelmia kielellä, jonka tuki on loppunut yli kaksi vuotta sitten.
Tiedetään... Ja harmittaa, kun en ole juurikaan kerennyt tuohon nettiin perehtyä ja tarttis tässä tehdä suurinpiirtein nopealla tahdilla käyttöliittymä missä tarvii pyöräyttää kolme cmd ohjelmaa läpi joista yksi on tämä ftp...
Taidan sitten siirtyä toiseksi vahvimman kielen pariin ja tehdä C++ cmd ohjelman jossa sitten kutsutaan näitä loppuja ohjelmia, mahtaa olla helpompi sitä kautta...
Ei mahda C++:lla olla yhtään sen helpompaa, päinvastoin.
Yksi helppo ratkaisu on kirjoittaa komennot bat-tiedostoon ja ajaa se. Ohjelmien syötteet voi myös tallentaa tiedostoihin ja syöttää ohjelmille näin:
ftp < ftpkomennot.txt
Jos ohjelman ei tarvitse tehdä muuta kuin ajaa muutama muu ohjelma, voisi olla viisasta toteuttaa se kokonaan bat-tiedostona ilman mitään VB:tä tms.
Se on muissakin kielissä, esimerkiksi Pythonissa, että jos annat jonkin command line-käskyn ja ohjelma jää pyörimään niin et voi suorittaa seuraavaa ennen kuin ohjelma on sulkeutunut.
Eihän tässä edes haluttu suorittaa seuraavaa, vaan antaa ohjeita tuolle käynnistetylle.
Olen kyllä tehnyt taannoin tuon kysytyn koodin vb6:lla mutta tuntuisi hieman väärältä julkaista se, koska se vaan kannustaisi jatkamaan tuhoon tuomitulla tiellä.
Moikka viljami!
tässä toimiva systeemi VB6/VBA ympäristöön...
Private Declare Function ShellExecute Lib "Shell32.dll" _
Alias "ShellExecuteA" (ByVal hwnd As Long, _
ByVal lpOperation As String, ByVal lpFile As String, _
ByVal lpParameters As String, _
ByVal lpDirectory As String, ByVal nshowcmd As Long) As Long
Sub FtpTransfer(ByVal localPath As String)
If Dir(localPath) = "" Then
MsgBox "Tiedostoa " & localPath & " ei löydy!"
Exit Sub
End If
Dim batchPath As String
Dim remoteFile As String
batchPath = "C:\ftpKomento.dat"
If InStr(localPath, "\") > 0 Then
Dim strArray() As String
strArray = Split(localPath, "\")
remoteFile = strArray(UBound(strArray))
Erase strArray
Else
remoteFile = localPath
End If
On Error Resume Next
Kill batchPath
If Err <> 0 Then
Err.Clear
On Error GoTo 0
End If
Open batchPath For Output As #1
Print #1, "Open"
Print #1, "ftp-palvelin"
Print #1, "käyttäjätunnus"
Print #1, "salasana"
Print #1, "put " & localPath _
& " " & remoteFile & vbCrLf
Print #1, "Quit": Close #1
Do While Dir(batchPath) = "": Loop
z& = ShellExecute(Me.hwnd, vbNullString, _
"ftp.exe", "-s:" + batchPath, "C:\", 2)
'(VBA:ssa - Application.hwnd)
End SubOnneksi muilla ei näytä olevan eettistä ongelmaa asiassa :D (tosin tuo ratkaisu ei ole ihan se mitä ajattelin - joskin toiminee FTP:n kanssa jos ei tulle ylläreitä)
Suurin ongelmahan tuossa on, ettei siinä ole minkäänlaista hallintaa ongelmien varalta. Mitä jos FTP ei yhdisty tai jos yhteys katkeaa kesken kaiken? Jos ohjelma tulee jonkun toisen käyttöön, niin sieltä tulee hyvä bugiraportti: "se ei toimi".
Näiden virhetilanteiden hallitsemista varten on oikeastaan pakko käyttää jonkinlaista FTP-luokkaa tai -kontrollia (tai sitten valmista ActiveX-kontrollia tai DLL-kirjastoa). Tämä linkittämäni versio on simppelihkö, toteuttaa itsensä kontrollina ja sorsan näkee, jolloin sitä voi myös muuttaa, esim. tehdä oman version luokkana.
Nean esimerkin ongelmana on vielä se, että se tallentaa C-aseman juureen Windowsin tallennuskäytäntöjen vastaisesti. Koodi ei taida edes toimia Vistalla ja Seiskalla, XP toki hyrrää kitkatta kun sillä ei ole niin paljon käyttöoikeuksiin tehtyjä rajoituksia.
Heippa taas!
tässä vielä systeemi joka antaa palautetta...
Private Sub Command1_Click()
'Testi esimerkki...
Dim localPath As String
Environ("HOMEDRIVE")
localPath = Environ("HOMEDRIVE") & "\polku\tiedosto.ext"
If Dir(localPath) = "" Then
MsgBox "Tiedostoa " & localPath & " ei löydy!"
Exit Sub
End If
Dim remoteFile As String
If InStr(localPath, "\") > 0 Then
Dim strArray() As String
strArray = Split(localPath, "\")
remoteFile = strArray(UBound(strArray))
Erase strArray
Else
remoteFile = localPath
End If
Dim cmdstr As string
cmdstr = "put " & localPath & " " & remoteFile & vbCrLf
MsgBox FtpTransfer("server", "user", "password", cmdstr)
End Sub
Function FtpTransfer(ByVal server As String, _
ByVal user As String, ByVal password As String,
ByVal cmdstr As String) As String
Dim basePath As String
basePath = Environ("APPDATA") & "\ftpStuff"
If Dir(basePath, vbDirectory) = "" Then
MkDir basePath
End If
Dim cmdPath As String, resPath As String
cmdPath = basePath & "\ftpCommand.dat"
resPath = basePath & "\ftpResult.txt"
KillFile cmdPath: KillFile resPath
Open cmdPath For Output As #1
Print #1, "Open"
Print #1, server
Print #1, user
Print #1, password
Print #1, cmdstr
Print #1, "Quit": Close #1
Do While Dir(cmdPath) = "": Loop
Shell "cmd.exe /c ftp.exe -s:" _
& cmdPath & " >" & resPath
Do While Dir(resPath) = "": Loop
Open resPath For Input As #1
FtpTransfer = Input$(LOF(1), 1): Close #1
KillFile cmdPath: KillFile resPath
End Function
Sub KillFile(ByVal fullPath As String)
On Error Resume Next
Kill fullPath
If Err <> 0 Then
Err.Clear
On Error GoTo 0
End If
End SubHeippa taas!
heitin ton edellisen testaamatta suoraan hatusta, mutta tämä toimii...
Private Sub CommandButton1_Click()
Dim localPath As String
localPath = Environ("HOMEDRIVE") & "\folderpath\filename.ext"
If Dir(localPath) = "" Then
MsgBox "Tiedostoa " & localPath & " ei löydy!"
Exit Sub
End If
Dim remoteFile As String
If InStr(localPath, "\") > 0 Then
Dim strArray() As String
strArray = Split(localPath, "\")
remoteFile = strArray(UBound(strArray))
Erase strArray
Else
remoteFile = localPath
End If
Dim cmdstr As String
cmdstr = "put " & localPath & " " & remoteFile & vbCrLf
MsgBox FtpAction("ServerAddress", "YourUserName", "YourPassword", cmdstr)
End Sub
Function FtpAction(ByVal server As String, _
ByVal user As String, ByVal password As String, _
ByVal cmdstr As String) As String
Dim basePath As String
basePath = Environ("HOMEDRIVE") & "\ftpStuff"
If Dir(basePath, vbDirectory) = "" Then
MkDir basePath
Do While Dir(basePath, vbDirectory) = "": Loop
End If
Dim cmdPath As String, resPath As String
cmdPath = basePath & "\ftpCommand.dat"
resPath = basePath & "\ftpResult.txt"
KillFile cmdPath: KillFile resPath
Open cmdPath For Output As #1
Print #1, "Open"
Print #1, server
Print #1, user
Print #1, password
Print #1, cmdstr
Print #1, "Quit": Close #1
Do While Dir(cmdPath) = "": Loop
Shell "cmd.exe /c ftp.exe -s:" _
& cmdPath & " >" & Chr(34) & resPath & Chr(34)
JumpBack:
'ohjelma vaatii referenssin:
'Microsoft WMI Scripting V1.2 Library
'(C:\Windows\System32\wbem\wbemdisp.tlb)
Set MyProcesses = GetObject _
("winmgmts:{impersonationLevel=impersonate}") _
.InstancesOf("Win32_Process")
For Each MyProcess In MyProcesses
With MyProcess
If LCase(.Name) = "cmd.exe" Then
GoTo JumpBack
End If
End With
Next
Set MyProcesses = Nothing
Do While Dir(resPath) = "": Loop
Open resPath For Input As #1
FtpAction = Input$(LOF(1), 1): Close #1
KillFile cmdPath: KillFile resPath
End Function
Sub KillFile(ByVal fullPath As String)
On Error Resume Next
Kill fullPath
If Err <> 0 Then
Err.Clear
On Error GoTo 0
End If
End SubMoi,
Kiitos eritoten Nealle, sekä myös muille. Eilen illalla istahdin koneelle, ja kirjoitin batin googlen avulla, jolla ajan nuo kolme exeä läpi. Käytännössä minulla on tiedosto, joka ensin parseroidaan yhdellä exellä, sitten käännetään toisella exellä ja lopuksi siirretään serverille käyttäen FTP:tä.
Tällä saatiin nyt tehtyä ne asiat, joita pitikin saada. Tosin tekemättä on edelleen graaffinen käyttöliittymä, joten tässä hyvää mallia, siihen kuinka tuo tehdään.
Kiitos vielä oikein kovasti!
Aihe on jo aika vanha, joten et voi enää vastata siihen.