Hei,
Onko parempaa tapaa muuntaa teksti "VB-koodiksi" kuin alla oleva koodini tekee? Eli esim "moi" olisi "Chr(109) & Chr(111) & Chr(105)"
Jos teksti on pitkä, huomaa kuinka ohjelma hidastuu sitä mukaa kun se etenee. Ja se johtuu tuosta kohdasta jossa returnTxt:ksi asetetaan muunnetun tekstin lisäksi oma itsenä koko ajan uudelleen ja sehän kasvaa koko ajan.. Olen usein törmännyt vastaavaan ongelmaan.
Pitäisikö tuo muunnos tehdä suuremmissa osissa vai miten ihmeessä?
Private Sub Command1_Click() Dim returnText As String On Error GoTo err Command1.Enabled = False txtToChr Text1, returnText Text2 = returnText GoTo bye err: MsgBox "Error: " & Error bye: Command1.Enabled = True End Sub Sub txtToChr(Txt As String, ByRef returnTxt As String) On Error GoTo err Dim n As Long, txtLen As Long Dim titleBckUp As String titleBckUp = Me.Caption 'Laitetaan tuo nyt tässä erikseen, ettei tarvitse laskea koko ajan uudelleen tuolla loopissa txtLen = Len(Txt) For n = 1 To txtLen returnTxt = returnTxt + "Chr(" & Asc(Mid(Txt, n, 1)) & ") & " 'Näytetään eteneminen ohjelman otsikossa Me.Caption = Round(n / txtLen, 2) * 100 & " %" 'Että ohjelmalla voisi tehdä jotain muutakin samaan aikaan DoEvents Next n 'Ylimääräiset pois -.- returnTxt = Mid(returnTxt, 1, Len(returnTxt) - 3) GoTo bye err: MsgBox "txtToChr error: " & Error, vbCritical bye: Me.Caption = titleBckUp End Sub
Koodisi hitaus johtuu luultavasti ensisijaisesti siitä, että joka merkin jälkeen päivität otsikon ja käsittelet tapahtumat. Jos otat nuo kaksi riviä silmukasta pois, pitkäkin teksti luultavasti muuttuu varsin nopeasti.
Jotta koodistasi saisi jotain selvää, kannattaisi sisentää se kunnolla.
Hei,
Otsikkohommeli on väliaikainen, että näen miten se edistyy. DoEvents on pakollinen, että ohjelmalla voisi tehdä jotain muutakin samaan aikaan.
Kyllähän ne hidastaa reilusti, mutta tasainen hitaus ei ole nyt se ongelma vaan hidasTUMINEN koko ajan enemmän, jos teksti on pitkä.
Pitäisikö teksti pilkkoa osiin ja käsitellä ne erikseen ja lopuksi lisätä yhteen?
DoEventsiä ei missään tapauksessa kannata ajaa joka kierroksella, vaan voit ajaa sen vaikka sadan tai tuhannen merkin välein (sen mukaan, miten nopeasti algoritmi toimii).
Luultavasti &-operaatio aina varaa uuden tekstin ja kopioi aiemmat sinne, ja =-operaatio kopioi lopuksi uuden tekstin vanhan päälle. Algoritmia voisi siis tehostaa varaamalla valmiiksi tarpeeksi pitkän tekstin ja muokkaamalla sitä suoraan (käsittääkseni Mid-lauseella).
Olettaisin että VB käsittelee merkkijonoja samaan tapaan kuin Java, eli aina kun lisäät merkkijonon perään jotain, niin se luo joka kerta uuden merkkijonon, joka luonnollisesti hidastaa ohjelmaa merkittävästi jos tätä joudutaan tekemään jatkuvasti.
Hyviä hakusanoja googleen voisi olla esimerkiksi "vb6 string builder" tai "vb6 string buffer".
Midillä (http://msdn.microsoft.com/en-us/library/05e63829(VS.80).aspx) ei taida pystyä muokkaamaan suoraan, mutta katsotaan mitä löydän Samin hakusanoila.
Kyllä tällä toisella Midillä voi muokata. En tiedä VB6:n tilanteesta, mutta uskoisin, että sama pätee.
Edit: Toteutin ehdotukseni (FreeBASICilla):
' Vanha tapa: Function A(teksti As String) As String Dim koodi As String = "" Dim i As Integer For i = 1 To Len(teksti) koodi = koodi & "Chr(" & Asc(Mid(teksti, i, 1)) & ") & " Next A = Left(koodi, Len(koodi) - 3) End Function ' Uusi tapa: Function B(teksti As String) As String Dim koodi As String = Space(Len(teksti) * 11) Dim i As Integer For i = 1 To Len(teksti) Mid(koodi, 1 + 11 * (i - 1)) = "Chr(" & Asc(Mid(teksti, i, 1)) & ") & " Next B = Left(koodi, InStrRev(koodi, "&") - 2) End Function ' Testaus Dim x As String Dim teksti As String = "abcdefg" Dim i As Integer For i = 0 To 11 teksti = teksti & teksti Next i Dim t As Double t = Timer x = A(teksti) Print Timer - t ' 6,88 sekuntia t = Timer x = B(teksti) Print Timer - t ' 0,04 sekuntia
Tein Midillä ja tuli aika nopea, mutta mistäköhän johtuu bugi, että tekstin perään tulee eri määrä tuota "ylimääräistä" riippuen siitä mitä Txt sisältää (eli ilmeisesti rplLenin käytössä on jotai pielessä)?
Sub txtToChr(Txt As String, ByRef returnTxt As String) Dim n As Long, n2 As Long Dim replaCement As String, rplLen As Integer n2 = 1 returnTxt = Space(Len(Txt) * 11) For n = 1 To Len(Txt) replaCement = "Chr(" & Asc(Mid(Txt, n, 1)) & ") & " rplLen = Len(replaCement) Mid(returnTxt, n2, rplLen) = replaCement n2 = n2 + rplLen Next n 'Ylimääräiset pois -.- returnTxt = Mid(returnTxt, 1, Len(returnTxt) - 3) End Sub
EDIT: Kiitos metabolix, kokeilen tuotakin
Vika on koodisi lopussa. Tulosta Len(Txt)*11, Len(returnTxt) ja n2, niin näet ongelman.
Juu kiitoksia. Päädyin kuitenkin käyttämään sun funktiota, paitsi ettei ainakaan VBA:ssa ollut Leftiä ollenkaan.
Function txtToChr(Txt As String) As String Dim vbCode As String vbCode = Space(Len(Txt) * 11) Dim i As Integer For i = 1 To Len(Txt) Mid(vbCode, 1 + 11 * (i - 1)) = "Chr(" & Asc(Mid(Txt, i, 1)) & ") & " Next txtToChr = Mid(vbCode, 1, InStrRev(vbCode, "&") - 2) End Function
Tota voi muun muassa käyttää esim. siihen, ettei ihan aloittelija pysty muuttamaan ohjelman sisäisiä tekstejä. Eli pieni anti-crack systeemi.
Esimerkiksi jos halutaan, että ohjelman otsikko on "Program made by Jussi", niin seuraava koodi tarkistaa, ettei sitä ole muutettu esim vbDeFormerilla:
'Seuraava koodi Form_Loadiin: If Not StrReverse(Me.Caption) = StrReverse(Chr(80) & Chr(114) & Chr(111) & Chr(103) & Chr(114) & Chr(97) & Chr(109) & Chr(32) & Chr(109) & Chr(97) & Chr(100) & Chr(101) & Chr(32) & Chr(98) & Chr(121) & Chr(32) & Chr(74) & Chr(117) & Chr(115) & Chr(115) & Chr(105)) Then End
Ja jos tuota tarkistusta haluaa muuttaa, niin kyllä se varmaan vähän päänvaivaa aiheuttaa, kun katsotaan jollain decompilerilla :D
Itse käytän tuota vastaavaan tarkoitukseen.
..Niin tai sitten, jos haluaa edes vähän piilottaa jostain keyloggerista ftp-tunnuksiansa tms. Tosin ne näkee packet snifferillä ja joillain palomuureillakin. Itse laittaisin ohjelman lähettämään tiedot jonkin ilmaisella hostilla olevan php-sivun kautta tietokantaan tai mihin haluaa..
Meni vähän offtopic, mutta kahvi sekotti mun pään. Aika iso pulssi btw.
Harhautat nyt luultavasti eniten itseäsi. Tuollaisen tarkistuksen voi kiertää ottamalla Not-sanan pois eli vaihtamalla vain hyppykäskyn käänteiseksi, mikä onnistuisi debuggerin ja heksaeditorin avulla parissa minuutissa. Sitä paitsi järkevän kääntäjän pitäisi osata optimoida tuollainen tyhmystely muotoon If Me.Caption <> "...", jolloin muokkaaminen onnistuisi heksaeditorilla ilmankin assemblyn tuntemista. (VB-kääntäjä tosin ei välttämättä ole järkevä.) Jos haluat tarkistaa jotain, laske tarkistussumma (vaikka MD5) tai käytä jotain edes hieman salausalgoritmin tapaista. (Tosin nämäkin voi yleensä kiertää samanlaisella menetelmällä, mutta ainakin koodista tulee kryptisempi.)
Jooh.. Enpä pahemmin ajatellut. Yksi VB encrypter vaan tekee noin, eli sillä ei taida tehdä mitään.
Tämmönen löyty myös.
http://www.xtremevbtalk.com/showthread.php?t=155206
Tuohan tekee käytännössä aivan saman asian. Tilaa vain varataan aina tasamäärä megatavuja, kun taas oma koodi osaa laskea paljon tarkemman arvauksen ja on erityisesti pienillä teksteillä kätevämpi. :)
Aihe on jo aika vanha, joten et voi enää vastata siihen.