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 Sub
Onneksi 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 Sub
Heippa 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 Sub
Moi,
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.