The Kandie Man Posted October 16, 2006 Posted October 16, 2006 I have been working on an autoit patcher. You compare two executables, the old version, and the new version. Once it gets the difference between the two, it then writes the byte differences to the old version to make it the new version. The only problem is that it seems that autoit doesn't have a native binary read or write method. It has been writing in binary, but it hasn't written any null values(Hexidecimal 00?). Everything else seems to get written ok, but it doesn't write the null values. I am not sure what i am doing wrong or if autoit can even do what i am trying to get it to do.http://www.thekandieman.com/applications/P...er/download.phpThere is the source and two executables that it compares and patches. "So man has sown the wind and reaped the world. Perhaps in the next few hours there will no remembrance of the past and no hope for the future that might have been." & _"All the works of man will be consumed in the great fire after which he was created." & _"And if there is a future for man, insensitive as he is, proud and defiant in his pursuit of power, let him resolve to live it lovingly, for he knows well how to do so." & _"Then he may say once more, 'Truly the light is sweet, and what a pleasant thing it is for the eyes to see the sun.'" - The Day the Earth Caught Fire
Moderators SmOke_N Posted October 16, 2006 Moderators Posted October 16, 2006 Figured it out TKC ... I'll either work up the entire interface later while your in school, or send you what I did, and you can take care of it. 2 functions 35 lines total ... Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.
The Kandie Man Posted October 17, 2006 Author Posted October 17, 2006 (edited) I think you SmOke_N. He helped me with it and was able to make a working version. Unfortunately it isn't very fast at patching large files and cannot create a portable database that is smaller than the file to be patched itself. Any help from any senior programmers would be most appreciated. I can PM you my latest updates of my source code if you would like me to, simply PM me or reply to this thread. Any help would be appreciated, whenever i write to file it seems to write a string of ASCII binary characters to the file instead of actual binary. :S -The Kandie Man Edited October 17, 2006 by The Kandie Man "So man has sown the wind and reaped the world. Perhaps in the next few hours there will no remembrance of the past and no hope for the future that might have been." & _"All the works of man will be consumed in the great fire after which he was created." & _"And if there is a future for man, insensitive as he is, proud and defiant in his pursuit of power, let him resolve to live it lovingly, for he knows well how to do so." & _"Then he may say once more, 'Truly the light is sweet, and what a pleasant thing it is for the eyes to see the sun.'" - The Day the Earth Caught Fire
Moderators SmOke_N Posted October 17, 2006 Moderators Posted October 17, 2006 (edited) I think you SmOke_N. He helped me with it and was able to make a working version. Unfortunately it isn't very fast at patching large files and cannot create a portable database that is smaller than the file to be patched itself. Any help from any senior programmers would be most appreciated. I can PM you my latest updates of my source code if you would like me to, simply PM me or reply to this thread. Any help would be appreciated, whenever i write to file it seems to write a string of ASCII binary characters to the file instead of actual binary. :S -The Kandie ManI tried to IM you, guess you are going torrent crazy again. This is what I did to speed it up 10x's as fast. But, there's an issue in my logic, or I'm just not seeing something. It reads the Old to be patched exe and the new exe and compares their binary. Writes the Chr Number / Chr / and remaining difference of chrs if the new file is greater than the old in String Length each to their seperate file. Then it outputs a GUI with the function to patch the old exe on the end-users computer, using FileInstall to install the 3 files for this and outputs them to the pre-destined name and temp file and then reads them to an array. I was initially, as you know, using StringLeft()/StringTrimLeft() for the changing of the file, but it proved for large changes to be quite tedious. It now reads the end-users exe into an array, and changes only the necessary items, this sped it up alot, and then it re-writes all the info back to a temp var, and then writes that temp var to a file and FileMoves to the old exe with the old exe name. Anyone that uses this, should make a folder, put the .au3 of this in that folder, then make an OldExe SubFolder.. Put the OldExe in it, and a NewExe SubFolder and put the new exe in it. If anyone wants to play with it feel free, I kind of gave up on it because the output was genrally more in size then just replacing the actual exe itself. CODEGlobal $hNewExe, $hOldExe, $aExeArray $GUIMain = GUICreate("AutoPatchIt: AutoIt Exe Patch Creator", 355, 150) GUICtrlCreateLabel("New Release:", 110, 10, 110, 22) GUICtrlSetFont(-1, 8, 800, 0, "Verdana") $B1 = GUICtrlCreateButton("www", 192, 2, 30, 25, 0) GUICtrlSetFont(-1, 8, 800, 0, "Wingdings") GUICtrlCreateLabel("Old Release:", 115, 60, 110, 22) GUICtrlSetFont(-1, 8, 800, 0, "Verdana") $B2 = GUICtrlCreateButton("www", 192, 52, 30, 25, 0) GUICtrlSetFont(-1, 8, 800, 0, "Wingdings") $B3 = GUICtrlCreateButton("Create Patch", 120, 115, 115, 25, 0) GUICtrlSetFont(-1, 8, 800, 0, "Verdana") $I1 = GUICtrlCreateEdit("", 10, 30, 340, 20, BitOR(0x0800, 0x0080)) $I2 = GUICtrlCreateEdit("", 10, 80, 340, 20, BitOR(0x0800, 0x0080)) GUISetState() While 1 Switch GUIGetMsg() Case - 3 Exit Case $B1 $hNewExe = FileOpenDialog('New Release', @ScriptDir, 'Exe (*.exe)') If Not @error Then GUICtrlSetData($I1, '') GUICtrlSetData($I1, $hNewExe) EndIf Case $B2 $hOldExe = FileOpenDialog('Old Release', @ScriptDir, 'Exe (*.exe)') If Not @error Then GUICtrlSetData($I2, '') GUICtrlSetData($I2, $hOldExe) EndIf Case $B3 If $hOldExe <> $hNewExe Then $aExeArray = _CompareExe2Exe($hNewExe, $hOldExe) MsgBox(64, 'Info', 'Finished!' & @CR & _ 'Your Patch .Au3 file is here: ' & @CR & _ _CreatePatchAu3($hOldExe, $aExeArray)) $hOldExe = '' $hNewExe = '' EndIf EndSwitch WEnd Func _CompareExe2Exe($hNew, $hOld) Local $sOld = String(FileRead($hOld)), $aOld = StringSplit($sOld, '') Local $sNew = String(FileRead($hNew)), $aNew = StringSplit($sNew, '') Local $iUBOld = UBound($aOld) - 1, $iUBNew = UBound($aNew) - 1, $iUBound = $iUBOld If $iUBNew < $iUBOld Then $iUBound = $iUBNew Local $aOutNC[$iUBound + 1][5], $iAdd = 1, $nNCC, $nXCC ProgressOn("Comparing Both Exe's", "", "", -1, -1, 18) For $iCC = 1 To $iUBound Step 5 If $aNew[$iCC] <> $aOld[$iCC] Then $iAdd += 1 $aOutNC[$iAdd - 1][0] = $iCC $aOutNC[$iAdd - 1][1] = $aNew[$iCC] EndIf If $iCC < $iUBound - 1 And $aNew[$iCC + 1] <> $aOld[$iCC + 1] Then $iAdd += 1 $aOutNC[$iAdd - 1][0] = $iCC $aOutNC[$iAdd - 1][1] = $aNew[$iCC] EndIf If $iCC < $iUBound - 2 And $aNew[$iCC + 2] <> $aOld[$iCC + 2] Then $iAdd += 1 $aOutNC[$iAdd - 1][0] = $iCC $aOutNC[$iAdd - 1][1] = $aNew[$iCC] EndIf If $iCC < $iUBound - 3 And $aNew[$iCC + 3] <> $aOld[$iCC + 3] Then $iAdd += 1 $aOutNC[$iAdd - 1][0] = $iCC $aOutNC[$iAdd - 1][1] = $aNew[$iCC] EndIf If $iCC < $iUBound - 4 And $aNew[$iCC + 4] <> $aOld[$iCC + 4] Then $iAdd += 1 $aOutNC[$iAdd - 1][0] = $iCC $aOutNC[$iAdd - 1][1] = $aNew[$iCC] EndIf $nNCC = (($iCC + 4) / $iUBound) * 100 If Int($nNCC) <> $nXCC Then ProgressSet($nNCC , (100 - Int($nNCC)) & ' % To Go', Int($nNCC) & '% Finshed Comparing') $nXCC = Int($nNCC) EndIf Next ProgressOff() ReDim $aOutNC[$iAdd][5] $aOutNC[0][2] = '' If $iUBNew > $iUBOld Then $aOutNC[0][2] = StringRight($sNew, $iUBNew - $iUBOld) EndIf $aOutNC[0][3] = $iUBNew $aOutNC[0][4] = $iUBOld Return $aOutNC EndFunc ;==>_CompareExe2Exe Func _CreatePatchAu3($hExe, $aOutNC) Local $hF1 = _GetTempFileName(), $hF2 = _GetTempFileName(), $hF3 = _GetTempFileName() Local $hOutFile = StringLeft(@ScriptFullPath, StringInStr(@ScriptFullPath, '.', 0, -1) - 1) & '_Patcher.au3' Local $hTempNum = @ScriptDir & '\TempNum.tmp', $hTempChr = @ScriptDir & '\TempChr.tmp' Local $hTempEx = @ScriptDir & '\TempExt.tmp', $sWNum, $sWChr FileClose(FileOpen($hTempNum, 2)) FileClose(FileOpen($hTempChr, 2)) FileClose(FileOpen($hTempEx, 2)) FileClose(FileOpen($hOutFile, 2)) Local $sWrite = 'Global $hOldExe' & @CRLF & _ 'FileInstall("' & $hTempNum & '", "' & $hF1 & '")' & @CRLF & _ 'FileInstall("' & $hTempChr & '", "' & $hF2 & '")' & @CRLF & _ 'FileInstall("' & $hTempEx & '", "' & $hF3 & '")' & @CRLF & _ '$GUIMain = GUICreate("", 355, 95);Fill in a title' & @CRLF & _ 'GUICtrlCreateLabel("", 85, 8, 110, 17);Fill in the label' & @CRLF & _ 'GUICtrlSetFont(-1, 8, 800, 0, "Verdana")' & @CRLF & _ '$B1 = GUICtrlCreateButton("www", 192, 7, 27, 17, 0)' & @CRLF & _ 'GUICtrlSetFont(-1, 8, 800, 0, "Wingdings")' & @CRLF & _ '$B2 = GUICtrlCreateButton("Patch It", 121, 60, 113, 25, 0)' & @CRLF & _ 'GUICtrlSetFont(-1, 8, 800, 0, "Verdana")' & @CRLF & _ '$I1 = GUICtrlCreateEdit("", 10, 28, 337, 21, BitOR(0x0800, 0x0080))' & @CRLF & _ 'GUISetState()' & @CRLF & _ 'While 1' & @CRLF & _ ' Switch GUIGetMsg()' & @CRLF & _ ' Case -3' & @CRLF & _ ' Exit' & @CRLF & _ ' Case $B1' & @CRLF & _ ' $hOldExe = FileOpenDialog("Find Exe", @WorkingDir, "Exe (*.exe)")' & @CRLF & _ ' If Not @error Then' & @CRLF & _ ' GUICtrlSetData($I1, "")' & @CRLF & _ ' GUICtrlSetData($I1, $hOldExe)' & @CRLF & _ ' EndIf' & @CRLF & _ ' Case $B2' & @CRLF & _ ' _WritePatch($hOldExe)' & @CRLF & _ ' EndSwitch' & @CRLF & _ 'WEnd' & @CRLF & _ 'Func _WritePatch($hExe)' & @CRLF & _ ' Local $iNewTotal = ' & $aOutNC[0][3] & ', ' & '$iOldTotal = ' & $aOutNC[0][4] & @CRLF & _ ' Local $sExe = String(FileRead($hExe)), $sTemp = ""' & @CRLF & _ ' If $iNewTotal < $iOldTotal Then $sExe = StringTrimRight($sExe, $iOldTotal - $iNewTotal)' & @CRLF & _ ' Local $nNum = StringSplit(FileRead("' & $hF1 & '"), Chr(1))' & @CRLF & _ ' Local $sChr = StringSplit(FileRead("' & $hF2 & '"), Chr(1))' & @CRLF & _ ' $sExe = StringSplit($sExe, "")' & @CRLF & _ ' Local $nNCC, $nXCC, $iUBound = UBound($nNum) - 1, $iUBound2 = UBound($sExe) - 1' & @CRLF & _ ' ProgressOn("Setting Enviroment...", "", "", -1, -1, 16)' & @CRLF & _ ' For $xCC = 1 To $iUBound Step 5' & @CRLF & _ ' $sExe[$nNum[$xCC]] = $sChr[$xCC]' & @CRLF & _ ' If $xCC < $iUBound - 1 Then $sExe[$nNum[$xCC + 1]] = $sChr[$xCC + 1]' & @CRLF & _ ' If $xCC < $iUBound - 2 Then $sExe[$nNum[$xCC + 2]] = $sChr[$xCC + 2]' & @CRLF & _ ' If $xCC < $iUBound - 3 Then $sExe[$nNum[$xCC + 3]] = $sChr[$xCC + 3]' & @CRLF & _ ' If $xCC < $iUBound - 4 Then $sExe[$nNum[$xCC + 4]] = $sChr[$xCC + 4]' & @CRLF & _ ' $nNCC = (($xCC + 4) / $iUBound) * 100' & @CRLF & _ ' If Int($nNCC) <> $nXCC Then' & @CRLF & _ ' ProgressSet($nNCC , (100 - Int($nNCC)) & " % To Go", Int($nNCC) & "% Finshed Patching")' & @CRLF & _ ' $nXCC = Int($nNCC)' & @CRLF & _ ' EndIf' & @CRLF & _ ' Next' & @CRLF & _ ' ProgressOff()' & @CRLF & _ ' ProgressOn("Patching...", "", "", -1, -1, 16)' & @CRLF & _ ' For $iCC = 1 To $iUBound2 Step 5' & @CRLF & _ ' $sTemp &= $sExe[$iCC]' & @CRLF & _ ' If $iCC < $iUBound2 - 1 Then $sTemp &= $sExe[$iCC + 1]' & @CRLF & _ ' If $iCC < $iUBound2 - 2 Then $sTemp &= $sExe[$iCC + 2]' & @CRLF & _ ' If $iCC < $iUBound2 - 3 Then $sTemp &= $sExe[$iCC + 3]' & @CRLF & _ ' If $iCC < $iUBound2 - 4 Then $sTemp &= $sExe[$iCC + 4]' & @CRLF & _ ' $nNCC = (($iCC + 4) / $iUBound2) * 100' & @CRLF & _ ' If Int($nNCC) <> $nXCC Then' & @CRLF & _ ' ProgressSet($nNCC , (100 - Int($nNCC)) & " % To Go", Int($nNCC) & "% Finshed Patching")' & @CRLF & _ ' $nXCC = Int($nNCC)' & @CRLF & _ ' EndIf' & @CRLF & _ ' Next' & @CRLF & _ ' ProgressOff()' & @CRLF & _ ' $sTemp &= FileRead("' & $hF3 & '")' & @CRLF & _ ' $hNewOut = StringLeft($hExe, StringInStr($hExe, ".", 0, -1)) & ".patched"' & @CRLF & _ ' FileClose(FileOpen($hNewOut, 2))' & @CRLF & _ ' FileWrite($hNewOut, BinaryString($sTemp))' & @CRLF & _ ' FileMove($hNewOut, $hExe, 1)' & @CRLF & _ ' FileDelete("' & $hF1 & '")' & @CRLF & _ ' FileDelete("' & $hF2 & '")' & @CRLF & _ ' FileDelete("' & $hF3 & '")' & @CRLF & _ ' Return 1' & @CRLF & _ 'EndFunc' For $xCC = 1 To UBound($aOutNC) - 1 $sWNum &= $aOutNC[$xCC][0] & Chr(1) $sWChr &= $aOutNC[$xCC][1] & Chr(1) Next $sWNum = StringTrimRight($sWNum, 1) $sWChr = StringTrimRight($sWChr, 1) FileWrite($hTempNum, $sWNum) FileWrite($hTempChr, $sWChr) FileWrite($hTempEx, $aOutNC[0][2]) FileWrite($hOutFile, $sWrite) Return $hOutFile EndFunc ;==>_CreatePatchAu3 Func _GetTempFileName() Local $oFSO = ObjCreate("Scripting.FileSystemObject"), $sTFolder $sTFolder = $oFSO.GetSpecialFolder (2) Return @TempDir & "\" & $oFSO.GetTempName EndFunc ;==>_GetTempFileName P.S. Before anyone asks why I didn't just transfer all the info over into array form, I originally did that, but the file was 3 x's as huge as the file I wanted to patch. Since this needs the autoit exe to be passed with it to interpret, this didn't / doesn't seem to be a good approach with all the free patch programs out there (I tried a few today), they seem to be MUCH faster for obvious reasons anyway. But it was fun all the same, maybe someone can pick up where I left off. Edit: Changed to codebox Edit2: Now that I look at as a public post... maybe it would have been smarter to go through like 1000 chrs at a time, and Just changed that. Edited October 17, 2006 by SmOke_N Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.
The Kandie Man Posted October 17, 2006 Author Posted October 17, 2006 Allright, i got it to work, but not. The problem is that i get it to output in binary, but for some reason every single null character (Hex 00) is gone. I don't know why the null character is missing. Do the string functions removed null characters. Particularly StringSplit? "So man has sown the wind and reaped the world. Perhaps in the next few hours there will no remembrance of the past and no hope for the future that might have been." & _"All the works of man will be consumed in the great fire after which he was created." & _"And if there is a future for man, insensitive as he is, proud and defiant in his pursuit of power, let him resolve to live it lovingly, for he knows well how to do so." & _"Then he may say once more, 'Truly the light is sweet, and what a pleasant thing it is for the eyes to see the sun.'" - The Day the Earth Caught Fire
The Kandie Man Posted October 17, 2006 Author Posted October 17, 2006 (edited) Yeah, i am using it to create a char[] array like in c++. It works fine except for the fact that it seems to want to truncate all null characters. I am missing all 6,257 occurances of null characters in my final output exe file. EDIT I am looking and i can't find any other efficient function for converting a string into a char array. Anyone here know of an efficient way to convert a string of binary to a char[] array where each element has only one byte of data? Edited October 17, 2006 by The Kandie Man "So man has sown the wind and reaped the world. Perhaps in the next few hours there will no remembrance of the past and no hope for the future that might have been." & _"All the works of man will be consumed in the great fire after which he was created." & _"And if there is a future for man, insensitive as he is, proud and defiant in his pursuit of power, let him resolve to live it lovingly, for he knows well how to do so." & _"Then he may say once more, 'Truly the light is sweet, and what a pleasant thing it is for the eyes to see the sun.'" - The Day the Earth Caught Fire
spyrorocks Posted October 17, 2006 Posted October 17, 2006 if your deal;ing with binary stuff you should talk to Joke758. He seems very good at that kind of stuff. [center] My Projects: Online AutoIt Compiler - AutoForum - AutoGuestbook - AutoIt Web-based Auto Installer - Pure AutoIt Zipping Functions - ConfuseGen - MindReader - P2PChat[/center]
Moderators SmOke_N Posted October 17, 2006 Moderators Posted October 17, 2006 This came out much more realistic.expandcollapse popupGlobal $hNewExe, $hOldExe, $aExeArray $GUIMain = GUICreate("AutoPatchIt: AutoIt Exe Patch Creator", 355, 150) GUICtrlCreateLabel("New Release:", 110, 10, 110, 22) GUICtrlSetFont(-1, 8, 800, 0, "Verdana") $B1 = GUICtrlCreateButton("www", 192, 2, 30, 25, 0) GUICtrlSetFont(-1, 8, 800, 0, "Wingdings") GUICtrlCreateLabel("Old Release:", 115, 60, 110, 22) GUICtrlSetFont(-1, 8, 800, 0, "Verdana") $B2 = GUICtrlCreateButton("www", 192, 52, 30, 25, 0) GUICtrlSetFont(-1, 8, 800, 0, "Wingdings") $B3 = GUICtrlCreateButton("Create Patch", 120, 115, 115, 25, 0) GUICtrlSetFont(-1, 8, 800, 0, "Verdana") $I1 = GUICtrlCreateEdit("", 10, 30, 340, 20, BitOR(0x0800, 0x0080)) $I2 = GUICtrlCreateEdit("", 10, 80, 340, 20, BitOR(0x0800, 0x0080)) GUISetState() While 1 Switch GUIGetMsg() Case - 3 Exit Case $B1 $hNewExe = FileOpenDialog('New Release', @ScriptDir, 'Exe (*.exe)') If Not @error Then GUICtrlSetData($I1, '') GUICtrlSetData($I1, $hNewExe) EndIf Case $B2 $hOldExe = FileOpenDialog('Old Release', @ScriptDir, 'Exe (*.exe)') If Not @error Then GUICtrlSetData($I2, '') GUICtrlSetData($I2, $hOldExe) EndIf Case $B3 If $hOldExe <> $hNewExe Then $aExeArray = _CompareExe2Exe($hNewExe, $hOldExe) MsgBox(64, 'Info', 'Finished!' & @CR & _ 'Your Patch .Au3 file is here: ' & @CR & _ _CreatePatchAu3($hOldExe, $aExeArray)) $hOldExe = '' $hNewExe = '' EndIf EndSwitch WEnd Func _CompareExe2Exe($hNew, $hOld) Local $sOld = FileRead($hOld) Local $sNew = FileRead($hNew) Local $nNewLen = StringLen($sNew), $nOldLen = StringLen($sOld) Local $nUBLen = Int($nNewLen) / 2050 Local $aOutNC[$nUBLen + 1][4], $iAdd = 1, $nNCC, $nXCC ProgressOn("Comparing Both Exe's", "", "", -1, -1, 18) For $iCC = 1 To $nNewLen Step 2050 $sMidNew = StringMid($sNew, $iCC, 2050) $sMidOld = StringMid($sOld, $iCC, 2050) If $sMidNew <> $sMidOld Then $iAdd += 1 $aOutNC[$iAdd - 1][0] = $iCC $aOutNC[$iAdd - 1][1] = $sMidNew EndIf $nNCC = ($iCC / $nNewLen) * 100 If Int($nNCC) <> $nXCC Then ProgressSet($nNCC , (100 - Int($nNCC)) & " % To Go", Int($nNCC) & "% Done Comparing.") $nXCC = Int($nNCC) EndIf Next ProgressOff() ReDim $aOutNC[$iAdd][4] $aOutNC[0][2] = $nNewLen $aOutNC[0][3] = $nOldLen Return $aOutNC EndFunc ;==>_CompareExe2Exe Func _CreatePatchAu3($hExe, $aOutNC) Local $hF1 = _GetTempFileName(), $hF2 = _GetTempFileName() Local $hOutFile = StringLeft(@ScriptFullPath, StringInStr(@ScriptFullPath, '.', 0, -1) - 1) & '_Patcher.au3' Local $hTempNum = @ScriptDir & '\TempNum.tmp', $hTempChr = @ScriptDir & '\TempChr.tmp', $sWNum, $sWChr FileClose(FileOpen($hTempNum, 2)) FileClose(FileOpen($hTempChr, 2)) FileClose(FileOpen($hOutFile, 2)) Local $sWrite = 'Global $hOldExe' & @CRLF & _ 'FileInstall("' & $hTempNum & '", "' & $hF1 & '")' & @CRLF & _ 'FileInstall("' & $hTempChr & '", "' & $hF2 & '")' & @CRLF & _ '$GUIMain = GUICreate("", 355, 95);Fill in a title' & @CRLF & _ 'GUICtrlCreateLabel("", 85, 8, 110, 17);Fill in the label' & @CRLF & _ 'GUICtrlSetFont(-1, 8, 800, 0, "Verdana")' & @CRLF & _ '$B1 = GUICtrlCreateButton("www", 192, 7, 27, 17, 0)' & @CRLF & _ 'GUICtrlSetFont(-1, 8, 800, 0, "Wingdings")' & @CRLF & _ '$B2 = GUICtrlCreateButton("Patch It", 121, 60, 113, 25, 0)' & @CRLF & _ 'GUICtrlSetFont(-1, 8, 800, 0, "Verdana")' & @CRLF & _ '$I1 = GUICtrlCreateEdit("", 10, 28, 337, 21, BitOR(0x0800, 0x0080))' & @CRLF & _ 'GUISetState()' & @CRLF & _ 'While 1' & @CRLF & _ ' Switch GUIGetMsg()' & @CRLF & _ ' Case -3' & @CRLF & _ ' Exit' & @CRLF & _ ' Case $B1' & @CRLF & _ ' $hOldExe = FileOpenDialog("Find Exe", @WorkingDir, "Exe (*.exe)")' & @CRLF & _ ' If Not @error Then' & @CRLF & _ ' GUICtrlSetData($I1, "")' & @CRLF & _ ' GUICtrlSetData($I1, $hOldExe)' & @CRLF & _ ' EndIf' & @CRLF & _ ' Case $B2' & @CRLF & _ ' _WritePatch($hOldExe)' & @CRLF & _ ' EndSwitch' & @CRLF & _ 'WEnd' & @CRLF & _ 'Func _WritePatch($hExe)' & @CRLF & _ ' Local $iNewTotal = ' & $aOutNC[0][2] & ', ' & '$iOldTotal = ' & $aOutNC[0][3] & @CRLF & _ ' Local $sExe = FileRead($hExe), $sTemp = $sExe' & @CRLF & _ ' If $iNewTotal < $iOldTotal Then $sExe = StringTrimRight($sExe, $iOldTotal - $iNewTotal)' & @CRLF & _ ' Local $nNum = StringSplit(FileRead("' & $hF1 & '"), Chr(1))' & @CRLF & _ ' Local $sChr = StringSplit(FileRead("' & $hF2 & '"), Chr(1)&Chr(1)&Chr(1), 1)' & @CRLF & _ ' Local $nNCC, $nXCC, $iUBound = UBound($nNum) - 1' & @CRLF & _ ' ProgressOn("Patching...", "", "", -1, -1, 16)' & @CRLF & _ ' For $xCC = 1 To $iUBound' & @CRLF & _ ' $sTemp = StringLeft($sExe, $nNum[$xCC] - 1) & $sChr[$xCC] & StringTrimLeft($sExe, $nNum[$xCC] + 2049)' & @CRLF & _ ' $sExe = $sTemp' & @CRLF & _ ' $nNCC = ($xCC / $iUBound) * 100' & @CRLF & _ ' If Int($nNCC) <> $nXCC Then' & @CRLF & _ ' ProgressSet($nNCC , (100 - Int($nNCC)) & " % To Go", Int($nNCC) & "% Finshed Patching")' & @CRLF & _ ' $nXCC = Int($nNCC)' & @CRLF & _ ' EndIf' & @CRLF & _ ' Next' & @CRLF & _ ' ProgressOff()' & @CRLF & _ ' Local $hNewOut = StringLeft($hExe, StringInStr($hExe, ".", 0, -1)) & ".patched"' & @CRLF & _ ' FileClose(FileOpen($hNewOut, 2))' & @CRLF & _ ' FileWrite($hNewOut, $sExe)' & @CRLF & _ ' FileMove($hNewOut, $hExe, 1)' & @CRLF & _ ' FileDelete("' & $hF1 & '")' & @CRLF & _ ' FileDelete("' & $hF2 & '")' & @CRLF & _ ' Return 1' & @CRLF & _ 'EndFunc' For $xCC = 1 To UBound($aOutNC) - 1 $sWNum &= $aOutNC[$xCC][0] & Chr(1) $sWChr &= $aOutNC[$xCC][1] & Chr(1) & Chr(1) & Chr(1) Next $sWNum = StringTrimRight($sWNum, 1) $sWChr = StringTrimRight($sWChr, 3) FileWrite($hTempNum, $sWNum) FileWrite($hTempChr, $sWChr) FileWrite($hOutFile, $sWrite) Return $hOutFile EndFunc ;==>_CreatePatchAu3 Func _GetTempFileName() Local $oFSO = ObjCreate("Scripting.FileSystemObject"), $sTFolder $sTFolder = $oFSO.GetSpecialFolder (2) Return @TempDir & "\" & $oFSO.GetTempName EndFunc ;==>_GetTempFileName Just didn't convert to String. And changed the way the output file (the actual patcher to be sent) checked the information. Still doesn't make much sense as much as I condensed it, it was still 7 kbs over the actual exe size after compilation. The only way I can see this making much since, as TKC noticed last night, is to compile as an a3x and use command line params within your app to run the patches being sent, then the patch itself turned out be 200 kbs less then the exe, which makes much more sense. Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.
Helge Posted October 17, 2006 Posted October 17, 2006 I guess I don't get what "patching" means. Try to make the first file be the second file? Why not just overwrite (FileCopy) the second file... What am I missing?Lar.When creating a patcher then files are compared and only the changed data areto be written by the patcher. This can make the filesize of the patcher much smallercompared to including all of the files to update as a whole.For example I just made a test-patch for AutoIt (beta .9 -> .10), which was only1.69mb, compared to the original zip which was 4.24mb.
JSThePatriot Posted October 17, 2006 Posted October 17, 2006 I guess I don't get what "patching" means. Try to make the first file be the second file? Why not just overwrite (FileCopy) the second file... What am I missing?Lar.I would assume that in this situation he is wanting to "update" a file without having to copy the entire script. If you are updating a script on say 3000 PC's I would say that sending only what needs to be updated would be more efficient than sending the entire script.Granted this is based completely on assumption, but that seems to me to be the only reason to not use FileCopy().JS AutoIt Links File-String Hash Plugin Updated! 04-02-2008Â Plugins have been discontinued. I just found out. ComputerGetInfo UDF's Updated! 11-23-2006 External Links Vortex Revolutions Engineer / Inventor (Web, Desktop, and Mobile Applications, Hardware Gizmos, Consulting, and more)
JSThePatriot Posted October 17, 2006 Posted October 17, 2006 This intrigues me... I am working on a very interesting Diff/Update script. I will post my progress in Scripts and Scraps...Lar.I was hoping that might intrigue you! I am looking forward to seeing what you come up with. As I was reading this thread I was thinking of how nice that would be to be able to do what I described above, but I dont have the time right now with all of my current projects.JS AutoIt Links File-String Hash Plugin Updated! 04-02-2008Â Plugins have been discontinued. I just found out. ComputerGetInfo UDF's Updated! 11-23-2006 External Links Vortex Revolutions Engineer / Inventor (Web, Desktop, and Mobile Applications, Hardware Gizmos, Consulting, and more)
Moderators SmOke_N Posted October 17, 2006 Moderators Posted October 17, 2006 (edited) I would assume that in this situation he is wanting to "update" a file without having to copy the entire script. If you are updating a script on say 3000 PC's I would say that sending only what needs to be updated would be more efficient than sending the entire script. Granted this is based completely on assumption, but that seems to me to be the only reason to not use FileCopy(). JS I was hoping that might intrigue you! I am looking forward to seeing what you come up with. As I was reading this thread I was thinking of how nice that would be to be able to do what I described above, but I dont have the time right now with all of my current projects. JShttp://www.autoitscript.com/forum/index.ph...st&p=253254 That does what you are saying, I just don't see it beig feasible as an executable, however, if you program it for .a3x and use commandlines in your exe's to be updateIf $cmdline[0] Then If StringInStr($cmdline[1], 'Something.a3x') Then Run(@AutoItExe & ' /Autoit3ExecuteScript "' & $cmdline[1] & '"') EndIf EndIfThen the size is up to 5 x's smaller than the executable without all the unnecssary info being sent. I had patches today with it as small as 30kbs for a 270kb app... 200kb for 1 mb app. So it made it much more realistic. This intrigues me... I am working on a very interesting Diff/Update script. I will post my progress in Scripts and Scraps... Lar.I also would be interested in what it is you are thinking of doing. Edited October 17, 2006 by SmOke_N Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.
JSThePatriot Posted October 17, 2006 Posted October 17, 2006 http://www.autoitscript.com/forum/index.ph...st&p=253254 That does what you are saying, I just don't see it beig feasible as an executable, however, if you program it for .a3x and use commandlines in your exe's to be updateIf $cmdline[0] Then If StringInStr($cmdline[1], 'Something.a3x') Then Run(@AutoItExe & ' /Autoit3ExecuteScript "' & $cmdline[1] & '"') EndIf EndIfThen the size is up to 5 x's smaller than the executable without all the unnecssary info being sent. I had patches today with it as small as 30kbs for a 270kb app... 200kb for 1 mb app. So it made it much more realistic. I also would be interested in what it is you are thinking of doing. I appreciate that SmOke_N, but I rarely use .a3x, but I may more in the future depending on client needs, and where AutoIt is at the time. JS AutoIt Links File-String Hash Plugin Updated! 04-02-2008Â Plugins have been discontinued. I just found out. ComputerGetInfo UDF's Updated! 11-23-2006 External Links Vortex Revolutions Engineer / Inventor (Web, Desktop, and Mobile Applications, Hardware Gizmos, Consulting, and more)
Moderators SmOke_N Posted October 17, 2006 Moderators Posted October 17, 2006 (edited) I appreciate that SmOke_N, but I rarely use .a3x, but I may more in the future depending on client needs, and where AutoIt is at the time.JSYeah, that (a3x) is the only viable AutoIt way I can see. Even Larrys returns the same exact patch size as mine, so compiled it's going to be the same size, and for that, you might as well just issue a new release executable. Edited October 17, 2006 by SmOke_N Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.
The Kandie Man Posted October 17, 2006 Author Posted October 17, 2006 (edited) Yeah, this is what i came up with. Pretty small as long as the file it is patching isn't too large. It doesn't work because i haven't been able to get it to write null characters.expandcollapse popup#Include <String.au3> #include <File.au3> #include <array.au3> $TimeStamp = TimerInit() _ScanExes() Msgbox(0,'Time to create patch:','It took ' & TimerDiff($TimeStamp)/1000 & ' seconds to create the patch.') $TimeStamp = TimerInit() _PatchExe(@ScriptDir & "\EnCodeIt2.0.exe", @ScriptDir & "\replacement.bin", @ScriptDir & "\replacementindex.txt") Msgbox(0,'Time to patch:','It took ' & TimerDiff($TimeStamp)/1000 & ' seconds to patch.') Func _PatchExe($filetopatch, $replacementdata, $replacementindex) ;~ $b_readdata = String(FileRead($filetopatch)) $b_readdata = FileRead($filetopatch) $a_bindata = StringSplit($b_readdata, "",1) ;~ For $tempcount = 1 to $a_bindata[0] ;~ $a_bindata[$tempcount]=String($a_bindata[$tempcount]) ;~ Next ;~ Msgbox(0,"Bindataarray",Ubound($a_bindata)) Dim $a_replacedata Dim $a_replacementindex ;~ _FileReadToArrayBin($replacementdata, $a_replacedata) $s_replacementdata = FileRead($replacementdata) $a_replacedata = StringSplit($s_replacementdata,"") ConsoleWrite("Replacementdata String length: " &Stringlen($s_replacementdata) &@LF) _FileReadToArray($replacementindex, $a_replacementindex) ;~ If $b_readdata < $a_replacementindex[$a_replacementindex[0]] + StringLen($a_replacedata[$a_replacedata[0]]) Then ;~ Redim $a_bindata[$a_replacementindex[$a_replacementindex[0]] + StringLen($a_replacedata[$a_replacedata[0]])] ;~ EndIf ConsoleWrite("Bindatastringlen: " & StringLen($b_readdata) & @LF) ConsoleWrite("BinDataArray Ubound: " & UBound($a_bindata) & @LF) ConsoleWrite("$a_ReplacementData Ubound " & UBound($a_replacedata) & @LF) ConsoleWrite("$a_ReplacementIndex Ubound" & UBound($a_replacementindex) & @LF) $i_ReplaceCharCounter = 1 $a_replacementindex[0] = 1 $h_ErrorLog = FileOpen("errorlog.txt",2) For $i_count = 1 To Ubound($a_replacementindex) -1 ;~ $byte_replacedata = StringSplit($a_replacedata[$i_count], 1) $a_count3 = StringSplit($a_replacementindex[$i_count],"|") $i_RootOffset = $a_count3[1] $i_OffsetMagnitude = $a_count3[2] For $i_count2 = $i_RootOffset To $i_RootOffset + $i_OffsetMagnitude - 1 #cs ConsoleWrite("Count3[1]: " & $a_count3[1] & @LF) ConsoleWrite("$i_count2: " & $i_count2 & @LF) ConsoleWrite("Count3[2]: " & $a_count3[2] & @LF) ConsoleWrite("$a_BinData Ubound: " & Ubound($a_bindata) & @LF) #ce ;~ $a_bindata[$i_count3] = $byte_replacedata[$i_count2] $i_ReplaceCharCounter+= 1 #cs FileWrite($h_ErrorLog,'The UBOUND of $a_bindata is: ' & Ubound($a_bindata) & _ ' The value of $a_count3[1] is: ' & $a_count3[1] & ' The value of $i_RootOffset + $i_OffsetMagnitude is: ' & $i_RootOffset + $i_OffsetMagnitude & ' The value of $a_count3[2] is: '& $a_count3[2] & _ ' The ubound of $a_replacedata is: ' & Ubound($a_replacedata) & ' The value of $i_ReplaceCharCounter is: ' & $i_ReplaceCharCounter & @LF) #ce $a_bindata[$a_count3[1]] = $a_replacedata[$i_ReplaceCharCounter] $a_count3[1] += 1 Next $a_count3 = "" Next FileClose($h_ErrorLog) ;~ _FileCreate(@ScriptDir & "\EnCodeIt2.0 patched.exe") ReDim $a_bindata[INIRead('patchdata.dat','New File','Size',1)+1] ;~ _FileCreate(@ScriptDir & "\EnCodeIt2.0 patched.exe") ;~ FileWrite(@ScriptDir & "\EnCodeIt2.0 patched.exe",BinaryString(_ArrayToString($a_bindata,"",1))) $h_patchedfile = FileOpen(@ScriptDir & "\EnCodeIt2.0 patched.exe", 2) ;~ FileWrite(@ScriptDir & "\EnCodeIt2.0 patched.exe",_ArrayToString($a_bindata,"",1)) ;~ ConsoleWRite("Ubound of $bincount: " & Ubound($a_bindata) - 1) For $bincount = 1 To UBound($a_bindata) - 1 FileWrite($h_patchedfile, $a_bindata[$bincount]) ;~ ConsoleWrite("Writing Bin data " & $a_bindata[$bincount]) Next FileClose($h_patchedfile) #cs ;~ $a_replacedata = StringSplit(BinaryString(FileRead($replacementdata)),@CRLF) ;~ $a_replacedata = _ArrayDelete($a_replacedata1,0) Msgbox(0,"$a_replacedata Ubound", Ubound($a_replacedata) & " "& $a_replacedata[0]) $a_ubound = StringSplit($a_replacedata[$a_replacedata[0]],@CR) IF @error Then ConsoleWRite($a_replacedata[$a_replacedata[0]]) ;~ Msgbox(0,"Error after splitting to $a_ubound", @error ) ;~ Exit ;~ dim $a_ubound[3] ;~ $a_ubound[1] = Ubound($a_replacedata ;~ $a_ubound = StringSplit($a_replacedata[$a_replacedata[0]] & " ",@CR) Endif If UBound($a_ubound) >= 3 Then Redim $a_bindata[$a_ubound[1] + StringLen($a_ubound[2])] Else ;~ ConsoleWRite(@CRLF & $a_replacedata[$a_replacedata[0]]) _ArrayDisplay($a_ubound,"Uboundarray") ;~ Msgbox(0,"ERROR","There was an error.") Redim $a_bindata[$a_ubound[1]] Endif For $i_counter = 1 to $a_replacedata[0] $a_splitreplacedata = StringSplit($a_replacedata[$i_counter],@CR,1) ConsoleWrite($a_replacedata[$i_counter] & @LF & "Number is " & $a_splitreplacedata[1]) $a_splitreplacedata[2] = StringTrimLeft($a_replacedata[$i_counter],StringLen($a_splitreplacedata[1])) ConsoleWrite(@LF & "Data is " & $a_splitreplacedata[1]) #cs $i_CRpos = StringInStr($a_replacedata[$i_counter],@CR,1,1) Dim $a_splitreplacedata[3] $a_splitreplacedata[1] = StringLeft($a_replacedata[$i_counter],$i_CRpos - 1) ConsoleWrite($a_replacedata[$i_counter] & @LF & "Number is " & $a_splitreplacedata[1]) $a_splitreplacedata[2] = StringTrimLeft($a_replacedata[$i_counter],$i_CRpos) ConsoleWrite(@LF & "Data is " & $a_splitreplacedata[1]) #ce $a_splitreplacebytes = StringSplit($a_splitreplacedata[2], "") $i_counter3 = 0 If UBound($a_splitreplacedata) >= 3 Then ;~ For $i_counter2 = $a_splitreplacedata[1] to $a_splitreplacedata[1] + StringLen($a_splitreplacedata[2]) For $i_counter2 = $a_splitreplacedata[1] To StringLen($a_splitreplacedata[2] - 1) ;~ $a_splitreplacebytes[$i_counter3] $i_counter3 += 1 ;~ Msgbox(0,"Error","The array $a_splitreplacebytes has " & UBound($a_splitreplacebytes) & " elements and it was called with the number " & $i_counter3) ;~ Msgbox(0,"Data:",$a_splitreplacedata[2] ;~ If Ubound($a_splitreplacebytes) > 1 Then $a_bindata[$i_counter2] = $a_splitreplacebytes[$i_counter3] ;~ Endif Next Else _ArrayDisplay($a_splitreplacedata, "Array data") $a_bindata[$a_splitreplacedata[1]] = "" EndIf ;### Tidy Error -> "next" is closing previous "#cs" Next #ce ;### Tidy Error: next line creates a negative tablevel. ;### Tidy Error: next line creates a negative tablevel for the line after it. EndFunc ;==>_PatchExe Func _ScanExes() $s_ftpname = @ScriptDir & "\v2\EnCodeIt2.0.exe" $s_fapname = @ScriptDir & "\v3\EnCodeIt2.0.exe" $h_filetopatch = FileOpen($s_ftpname, 0) $h_filealreadypatched = FileOpen($s_fapname, 0) #cs $b_ftp = String(FileRead($h_filetopatch));,FileGetSize($s_ftpname)) $b_fap = String(FileRead($h_filealreadypatched));,FileGetSize($s_fapname)) $sb_FTP = $b_ftp $sb_FAP = $b_fap #ce $sb_FTP= FileRead($h_filetopatch) $sb_FAP = FileRead($h_filealreadypatched) $i_FTPlen = StringLen($sb_FTP) $i_FAPlen = StringLen($sb_FAP) ;~ FileWrite("test1.txt",$sb_FTP) ;~ FileWrite("test2.txt",$sb_FAP ) $ab_FTP = StringSplit($sb_FTP, "") $ab_FAP = StringSplit($sb_FAP, "") If $i_FTPlen > $i_FAPlen Then ;file that is being patched is larger than the final file ;~ $i_maxlen = $i_FTPlen ;~ ReDim $ab_FAP[$i_FTPlen + 1] $i_maxlen = $i_FAPlen ReDim $ab_FTP[$i_FAPlen + 1] $mode = -1 ;because it has to make the file smaller ElseIf $i_FTPlen < $i_FAPlen Then ;file that is being patched is smaller than the final file $i_maxlen = $i_FAPlen $mode = 1 ;beause it has to make the file bigger ReDim $ab_FTP[ $i_FAPlen + 1] Else ;The lengths are the same $i_maxlen = $i_FAPlen $mode = 0 ;because it doesn't have to increase or decrease its size EndIf INIWrite('patchdata.dat','Original File','Size',FileGetSize($s_ftpname)) IniWrite('patchdata.dat','New File','Size',FileGetSize($s_fapname)) ConsoleWrite($i_maxlen &@LF) ConsoleWrite($sb_FTP &@LF ) ConsoleWrite($sb_FAP &@LF) $firstline = True Dim $s_replacement $h_filereplace = FileOpen("replacement.bin", 2) $h_filereplaceindex = FileOpen("replacementindex.txt", 2) $i_countprevious = 0 $o_FileReplace = '' $i_BytesToReplace = 0 For $i_counter = 1 To $i_maxlen If $ab_FTP[$i_counter] <> $ab_FAP[$i_counter] Then If $i_counter - $i_countprevious = 1 Then FileWrite($h_filereplace, $ab_FAP[$i_counter]) ;~ $o_FileReplace &= @CRLF & $ab_FAP[$i_counter] $i_BytesToReplace += 1 Else If $firstline = False Then FileWrite($h_filereplace, $ab_FAP[$i_counter]) ;~ $o_FileReplace &= @CRLF & $ab_FAP[$i_counter] FileWrite($h_filereplaceindex, "|" & $i_BytesToReplace & @CRLF & $i_counter) $i_BytesToReplace = 0 Else FileWrite($h_filereplace, $ab_FAP[$i_counter]) ;~ $o_FileReplace &= $ab_FAP[$i_counter] FileWrite($h_filereplaceindex, $i_counter) $i_BytesToReplace = 0 EndIf EndIf $firstline = False $i_countprevious = $i_counter EndIf #cs If IsInt($i_counter / 1000) Then ConsoleWrite($i_counter & @LF) EndIf #ce Next FileWrite($h_filereplaceindex,"|" & $i_BytesToReplace) ;~ FileWrite("replacement.bin",$o_FileReplace) FileClose($h_filereplaceindex) FileClose($h_filereplace) FileClose($h_filetopatch) FileClose($h_filealreadypatched) EndFunc ;==>_ScanExes Func _FileReadToArrayBin($sFilePath, ByRef $aArray) Local $hFile $hFile = FileOpen($sFilePath, 0) If $hFile = -1 Then SetError(1) Return 0 EndIf $aArray = StringSplit(FileRead($hFile, FileGetSize($sFilePath)), @CRLF, 1) FileClose($hFile) Return 1 EndFunc ;==>_FileReadToArrayBinHere are some patchers that i found that seem to be fairly good. My favorite at the moment would have to be cold fusion for its simplicity and the fact that it works really well.http://www.softpedia.com/catList/15,1,1,1.htmlI know AutoIt wasn't meant for this purpose and cannot compare to these as far as speed and efficientcy are concerned, however, i do think it would be neat to be able to create a patcher in autoit.EDITFor those of you that don't understand what i mean by a patcher i have made the following diagram:The diagram above represents a string of new binary data at the bottom and old binary data at the top. The patcher acts as the mediator and only stores the changed data and the position of where to place the changed data in the old exe to make it exactly like the new one. As a result, the patch only has to contain the changed data from the new to the old and not an entirely new exe. As a result, a mild change of version doesn't require a massive re-download of the whole program, but only a small patch with the varied data. What my patcher does is find the difference between the two exes, it then writes the data to three files that it can use as a database to store the varied information. You then simply use a fileinclude() when creating the exe or a3x patch file and then send it on its way. By doing this you can significantly reduce the size of the update. So far i only have two problems, one is with an array when patching which shows up here and there, i am betting it has something to do with the fact that the StringSplit() is deleting all the null characters out of the string and therefore the array isn't being made large enough since the null characters are missing and therefore causing an invalid element error(you have exceeded the number of elements of this array, blah blah).-The Kandie Man Edited October 18, 2006 by The Kandie Man "So man has sown the wind and reaped the world. Perhaps in the next few hours there will no remembrance of the past and no hope for the future that might have been." & _"All the works of man will be consumed in the great fire after which he was created." & _"And if there is a future for man, insensitive as he is, proud and defiant in his pursuit of power, let him resolve to live it lovingly, for he knows well how to do so." & _"Then he may say once more, 'Truly the light is sweet, and what a pleasant thing it is for the eyes to see the sun.'" - The Day the Earth Caught Fire
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now