Sign in to follow this  
Followers 0

_GetSavedSource() - Retrieve the saved source file from an AutoIt exe.

42 posts in this topic

Posted (edited)

For those of us who use SciTE4AutoIt3 then you would've come across (at some stage) the directive #AutoIt3Wrapper_Res_SaveSource, it allows you to save the script to the compiled exe thus allowing you to retrieve at a later stage, great if you accidentally delete your source file.

_GetSavedSource() allows you to extract the source file from the compiled executable and save to a file of your choice.

Note: You must use #AutoIt3Wrapper_Res_SaveSource=Y at the top of the script for this to work & it must be compiled.

Function:

#include-once
#include <WinAPIRes.au3>

; #FUNCTION# ====================================================================================================================
; Name ..........: _GetSavedSource
; Description ...: Retrieve the source file from a compiled executable, #AutoIt3Wrapper_Res_SaveSource=Y must be used beforehand to embed the file to the executable.
; Syntax ........: _GetSavedSource([$sExecutable = ''[, $sSaveFilePath = '']])
; Parameters ....: $sExecutable         - [optional] Executable to retrieve the source file from.
;				   						        	 Use a blank string or the Default keyword to use the current executable. Default is ''.
;                  $sSaveFilePath       - [optional] FilePath to save the source file to. Nore: The file doesn't have to exist. Default is ''.
;				   									 Use a blank string or the Default keyword to save to the current directory and using the script's
;													 name with the au3 prefix. Default is ''.
; Return values .: Success - True
;                  Failure - False and sets @error to non-zero.
; Author ........: guinness
; Remarks .......:
; Example .......: Yes
; Note ..........: Thanks to Jos, Yashied & Zedna.
; ===============================================================================================================================
Func _GetSavedSource($sExecutable = '', $sSaveFilePath = '')
	Local Enum $GETSAVEDSOURCE_ERROR_NONE, _
			$GETSAVEDSOURCE_ERROR_FILEWRITE, _
			$GETSAVEDSOURCE_ERROR_FINDRESOURCE, _
			$GETSAVEDSOURCE_ERROR_LOADMODULE
	Local $iError = $GETSAVEDSOURCE_ERROR_LOADMODULE
	Local $hInstance = (($sExecutable = Default Or StringStripWS($sExecutable, $STR_STRIPALL) = '') ? _WinAPI_GetModuleHandle(Null) : _WinAPI_LoadLibraryEx($sExecutable, $LOAD_LIBRARY_AS_DATAFILE))
	If Not @error Then
		Local $hResource = _WinAPI_FindResource($hInstance, $RT_RCDATA, 999) ; Get the source file from the executable. This is located at resname 999.
		If @error Then
			$iError = $GETSAVEDSOURCE_ERROR_FINDRESOURCE
		Else
			Local $iSize = _WinAPI_SizeOfResource($hInstance, $hResource)
			Local $hData = _WinAPI_LoadResource($hInstance, $hResource)
			Local $pResource = _WinAPI_LockResource($hData)

			If $sSaveFilePath = Default Or StringStripWS($sSaveFilePath, $STR_STRIPALL) = '' Then
				$sSaveFilePath = @ScriptDir & '\' & StringLeft(@ScriptName, StringInStr(@ScriptName, '.', $STR_NOCASESENSEBASIC, -1) - 1)
			EndIf
			Local $hFilePath = FileOpen($sSaveFilePath, BitOR($FO_OVERWRITE, $FO_BINARY))
			If $hFilePath = -1 Then
				$iError = $GETSAVEDSOURCE_ERROR_FILEWRITE
			Else
				$iError = $GETSAVEDSOURCE_ERROR_NONE
				Local $tBuffer = DllStructCreate('byte array[' & $iSize & ']', $pResource)
				FileWrite($hFilePath, DllStructGetData($tBuffer, 'array'))
				FileClose($hFilePath)
			EndIf
		EndIf
		_WinAPI_FreeLibrary($hInstance)
	EndIf
	Return SetError($iError, 0, (($iError = $GETSAVEDSOURCE_ERROR_NONE) ? True : False))
EndFunc   ;==>_GetSavedSource
Example 1 of Function:

#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w 7
#AutoIt3Wrapper_Res_SaveSource=Y ; Use the full version of SciTE4AutoIt3 by Jos.
#AutoIt3Wrapper_UseX64=N

#include <MsgBoxConstants.au3>

#include '_GetSavedSource.au3'

Example()

Func Example()
	If @Compiled Then
		If _GetSavedSource(@ScriptFullPath, @ScriptDir & '\' & _ScriptName() & '.au3') Then
			MsgBox($MB_SYSTEMMODAL, 'Completed', 'The Au3 script was saved in the script directory and is called ' & _ScriptName() & '.au3')
		Else
			MsgBox($MB_SYSTEMMODAL, 'Error' & @error, 'An error occurred whilst extracting the Au3 script located in the resources.')
		EndIf
	Else
		MsgBox($MB_SYSTEMMODAL, 'Compile first', 'Please compile this script first and then run the compiled file, you''ll see a new file called "' & _ScriptName() & '.au3' & '" is created in the same directory.')
	EndIf

	Return True
EndFunc   ;==>Example

; Return the @ScriptName minus the .exe or .au3 extension and with _SAVEDSOURCE_ appended.
Func _ScriptName()
	Return StringLeft(@ScriptName, StringInStr(@ScriptName, '.', $STR_NOCASESENSEBASIC, -1) - 1) & '_SAVEDSOURCE_'
EndFunc   ;==>_ScriptName
Example 2 of Function:

#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w 7
#AutoIt3Wrapper_Res_SaveSource=Y ; Use the full version of SciTE4AutoIt3 by Jos.
#AutoIt3Wrapper_UseX64=N

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>

#include '_GetSavedSource.au3'

If Not @Compiled Then
	Exit MsgBox($MB_SYSTEMMODAL, 'Compile first', 'Please compile this script first and then run the compiled file, you''ll see a new file called "' & _ScriptName() & '.au3' & '" is created in the same directory.')
EndIf

_IsSaveSource() ; Check if the commandline parameter 'SaveSource' has been passed to the executable.

Example()

Func Example()
	; The example of using AutoItWinGetTitle() can be found at: http://www.autoitscript.com/forum/topic/133648-autoitwingettitleautoitwinsettitle-an-example-of-usage/
	Local $hAutoIt = AutoItWinShow() ; Get the handle of the AutoIt Hidden Window by finding out the title of the AutoIt Hidden Window.

	Local $sData = FileRead(@ScriptDir & '\' & _ScriptName() & '.au3') ; Read the source file that was extracted from the executable.
	If @error Then ; If the file wasn't extracted then show an error string.
		$sData = '## @error - can''t open the file ##'
	EndIf
	AutoItWinSetText($hAutoIt, $sData) ; Set the text of the edit box using the data returned from _GetFile.

	While 1
		Switch GUIGetMsg()
			Case $GUI_EVENT_CLOSE ; Just hit the close button to Exit the application.
				ExitLoop

		EndSwitch
	WEnd
EndFunc   ;==>Example

; Add text to AutoIt's Hidden Window.
Func AutoItWinSetText($sString, $hWnd = Default)
	If IsHWnd($hWnd) = 0 Or $hWnd = Default Then
		$hWnd = WinGetHandle(AutoItWinGetTitle()) ; Get the handle of the AutoIt Hidden Window by finding out the title of the AutoIt Hidden Window.
	EndIf
	Return ControlSetText($hWnd, '', ControlGetHandle($hWnd, '', 'Edit1'), $sString)
EndFunc   ;==>AutoItWinSetText

; Display AutoIt's Hidden Window. Returns the handle of the window.
Func AutoItWinShow()
	Local $hWnd = WinGetHandle(AutoItWinGetTitle()) ; Get the handle of the AutoIt Hidden Window by finding out the title of the AutoIt Hidden Window.
	WinMove($hWnd, '', (@DesktopWidth / 2) - 250, (@DesktopHeight / 2) - 250, 500, 500) ; Move the AutoIt Hidden Window and re-size for a better view of the data that will be set.
	WinSetState($hWnd, '', @SW_SHOW) ; Show the AutoIt Hidden Window, normally this is hidden, but in the interest of this example I'm displaying it.
	Return $hWnd
EndFunc   ;==>AutoItWinShow

; Check if the commandline parameter 'SaveSource' has been passed to the executable.
Func _IsSaveSource()
	Return (StringInStr($CmdLineRaw, 'SaveSource') ? _GetSavedSource(@ScriptFullPath, @ScriptDir & '\' & _ScriptName() & '.au3') : Null)
EndFunc   ;==>_IsSaveSource

; Return the @ScriptName minus the .exe or .au3 extension and with _SAVEDSOURCE_ appended.
Func _ScriptName()
	Return StringLeft(@ScriptName, StringInStr(@ScriptName, '.', $STR_NOCASESENSEBASIC, -1) - 1) & '_SAVEDSOURCE_'
EndFunc   ;==>_ScriptName
All of the above has been included in a ZIP file. GetSavedSource.zip

Previously downloaded 230+

Edited by guinness
yahaosoft likes this

Share this post


Link to post
Share on other sites



Posted

Wow, excellent, I had already done another way, but yours is much more elegant, thanks for sharing!

Regards,

João Carlos.

Share this post


Link to post
Share on other sites

Posted

How did you do it? FileInstall?

Share this post


Link to post
Share on other sites

Posted

No, it's much like the way you did, but a bit archaic...

This line could be inside the UDF, so ensure that the "Source" is written!

#AutoIt3Wrapper_Res_SaveSource=Y ; Use the full version of SciTE4AutoIt3 by Jos.
I tested here and works that way!

Regards,

João Carlos.

Share this post


Link to post
Share on other sites

Posted

OK cool. About your suggestion I'm not going to do that as a general rule of thumb (I don't know what Jos' take is on this) is to have the directives at the top of the script and secondly this should be used by someone who kind of knows what they're already doing. :)

Share this post


Link to post
Share on other sites

Posted

Yeah, that's true, you're right! But your UDF is really good, you can be sure!

Regards,

João Carlos.

Share this post


Link to post
Share on other sites

Posted

I like your script guinness. Thanks :)

Would it be better to have in your example a section like the following to show how it could be included in any script?

If @Compiled And $CmdLine[1] = 'ExtractSource' Then
    _GetSavedSource(@ScriptFullPath, @ScriptDir & '' & @ScriptName & '.au3')
EndIf

Share this post


Link to post
Share on other sites

Posted

Yeh I could provide a second example, I see no harm in doing that. Thanks martin.

Share this post


Link to post
Share on other sites

Posted

I updated the UDF as well as added an advanced example as suggested by martin. I've also included all of this in a ZIP for your convenience.

Share this post


Link to post
Share on other sites

Posted

I recently came across this function again because I was looking for a way to do what this does, excellent resource. Definitely going to be using this more often as I compile scripts that do stupid things to my files when I'm not paying attention to where I'm using them. :S

Just a couple of caveats though, this will NOT work for obfuscated scripts if you use anything other than /striponly or /striponlyincludes. It's a security measure so that you're not putting your obfuscated script where someone can find it easily. Second, there's a bug in the second example script, it will never find the extracted script and display it because it's looking for the wrong file name. Small change needed to look for the correct file name.

	$sData = _GetFile(@ScriptDir & "" & _ScriptNameStrip() & ".au3") ; Read the source file that was extracted from the executable.
	If @error Then ; If the file wasn't extracted then show an error string.
		$sData = "## @error - can't open the file ##"
	EndIf

This is located at around the 8th line of the Main() function.

Share this post


Link to post
Share on other sites

Posted

Thanks BrewManNH, simple mistake I failed to find.

Cheers for pointing out the caveats too, hopefully people won't start asking why isn't this possible :)

Share this post


Link to post
Share on other sites

Posted

Hopefully some one reads that before deleting their script accidently like I've done when testing a filemove operation on the wrong folder.

Share this post


Link to post
Share on other sites

Posted

We all strive for perfection but alas we're only human! I've been known to delete the wrong file, but thank goodness I still had SciTE open!

Share this post


Link to post
Share on other sites

Posted (edited)

Nice guinness!

I have tip for improvement: Make parameters optional also change order of optional parameters

example of calling (first one is the most frequent use)

_GetSavedSource()
_GetSavedSource("123.au3")
_GetSavedSource("123.au3", @ScriptFullPath)

#AutoIt3Wrapper_Res_SaveSource=Y

#include-once
#include <APIConstants.au3> ; Included with WinAPIEx.au3
#include <FileConstants.au3>
#include <WinAPIEx.au3> ; Download From http://www.autoitscript.com/forum/topic/98712-winapiex-udf/ by Yashied.

; #FUNCTION# ====================================================================================================================
; Name ..........: _GetSavedSource
; Description ...: Retrieve the source file from a compiled executable, #AutoIt3Wrapper_Res_SaveSource=Y must be used beforehand to embed the file to the executable.
; Syntax ........: _GetSavedSource($sExecutable, $sSaveFilePath)
; Parameters ....: $sExecutable - Executable to retrieve the source file from. (See remarks.)
;				 $sSaveFilePath - FilePath to save the source file to. Nore: The file doesn't have to exist.
; Return values .: Return value from _WinAPI_FreeLibrary or 0 and sets @error to non-zero.
; Author ........: guinness
; Modified ......:
; Remarks .......: $sSaveFilePath doesn't have to exist, but if it does then it will be overwritten.
; Related .......: WinAPIEx.au3 by Yashied is required [http://www.autoitscript.com/forum/topic/98712-winapiex-udf/]
; Link ..........:
; Example .......: Yes
; Note ..........: Thanks to Jos & Yashied.
; ===============================================================================================================================
Func _GetSavedSource($sSaveFilePath = '', $sExecutable = '')
	Local $hData, $hFilePath, $hInstance, $hResource, $iSize, $pData, $tData

	If $sSaveFilePath = '' Then $sSaveFilePath = @ScriptDir & "" & StringRegExpReplace(@ScriptName, ".[^.]*$", "") & ".au3" ; SRE by MrCreatoR.
	If $sExecutable = '' Then $sExecutable = @ScriptFullPath

	$hInstance = _WinAPI_LoadLibraryEx($sExecutable, $LOAD_LIBRARY_AS_DATAFILE)
	If $hInstance = 0 Then Return SetError(1, 0, 0)

	$hResource = _WinAPI_FindResource($hInstance, $RT_RCDATA, 999) ; Get the source file from the executable.
	If @error Then Return SetError(2, 0, 0) ; The source file isn't present.

	$iSize = _WinAPI_SizeOfResource($hInstance, $hResource)
	$hData = _WinAPI_LoadResource($hInstance, $hResource)
	$pData = _WinAPI_LockResource($hData)

	$tData = DllStructCreate('byte[' & $iSize & ']', $pData)
	$hFilePath = FileOpen($sSaveFilePath, $FO_OVERWRITE + $FO_BINARY)
	FileWrite($hFilePath, DllStructGetData($tData, 1))
	FileClose($hFilePath)

	Return _WinAPI_FreeLibrary($hInstance)
EndFunc   ;==>_GetSavedSource

_GetSavedSource()
_GetSavedSource("123.au3")
_GetSavedSource("123.au3", @ScriptFullPath)
Edited by Zedna

Share this post


Link to post
Share on other sites

Posted

Good idea Zedna. I'll update accordingly. Thanks.

Share this post


Link to post
Share on other sites

Posted (edited)

Updated the original code with the suggestion provided by Zedna, now the parameters are optional and will use the current executable and save to a file using the script's name and au3 prefix e.g. @ScriptDir & 'Example.au3'.

Edited by guinness

Share this post


Link to post
Share on other sites

Posted

I found a small issue in _ScriptName (the function used in the example) which would return the incorrect scriptname. Please see the original post for more details about this function.

Share this post


Link to post
Share on other sites

Posted

I've updated the UDF by changing the return values to True or False instead of True and 0. I also updated the second example by using the functions I created in the thread See the original post for more details.

Share this post


Link to post
Share on other sites

Posted

It would be better if the source it were saved encrypted and compressed in resource!

JS

Share this post


Link to post
Share on other sites

Posted

I would think that you wouldn't be embedding your source code if you didn't want anyone to be able to access it later. Which is why this won't work with an obfuscated script, if you've gone through the trouble of obfuscation, you usually don't want anyone to be able to read it. You can always encrypt the file before embedding it, but that kind of defeats the purpose of embedding it in the first place. The source code for the script isn't that hard to get at in a compiled exe anyways if you really wanted to get at it.

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0