Jump to content

Executable Wrapper!


Matt @ MPCS
 Share

Recommended Posts

Hello everyone! I have just completed the alpha version of my ExeWrap application. This program is intended to wrap application dependencies with an executable so you dont have to register runtime libraries and other dependent files related to the executable. It was designed with Visual Basic developers in mind. This program will allow a VB developer to wrap his creation with the VB runtime libraries and requred OCX's for simple deployment of a single file.

Code as follows, also available zipped with sample project files (see attachment):

#comments-start
****************************************************************************************************

**********************************
AutoIt Information
--------------------------------------------------------------------------------------------------------------------------------------
   AutoIt Version:   3.0.103.0
   Language:         English
   Platform:         Win9x/NT

====================================================================================================

==================================
Script Information
--------------------------------------------------------------------------------------------------------------------------------------
   Name:             ExeWrap.au3
   Author:         Matthew Babcock
   Date:             09/14/2004
   
   Purpose:
      This script is used to wrap executables, with their dependencies based on settings in the passed INI project file.

====================================================================================================

==================================
Function Directory
--------------------------------------------------------------------------------------------------------------------------------------
   ProcessCL()                ; Parses the command-line parameters
   ExeWrap( $IniFile )        ; Generates the wrapped executable file defined in the passed Ini File.
   ParseFile( $FullPath )      ; Gets the filename out of a path
   FillString( $char, $length ) ; Generates a string containing a the passed character repeated the passed length
   
====================================================================================================

==================================
Change Log
--------------------------------------------------------------------------------------------------------------------------------------
   09/14/2004: Release of ExeWrap v0.5a
               Created ExeWrap.au3
               Created function ProcessCL v0.5a
               Created function ExeWrap v0.5a
               Created function ParseFile v0.5a
               Created function FillString v0.5a
****************************************************************************************************

**********************************
#comments-end

;***************************************************************************************************

**********************************
; Begin Open Code
;===================================================================================================

==================================

; Global declaration of the Temporary directory the application is run from
;-------------------------------------------------------------------------------------------------------------------------------------
Global $ActiveDir = FileGetLongName( @TempDir ) & "\ExeWrap" & Int(Random(0, 999)) & "\"
;-------------------------------------------------------------------------------------------------------------------------------------
;  Initialization of the application options
;-------------------------------------------------------------------------------------------------------------------------------------
Opt("MustDeclareVars", 0); All variables must be declared

If( @Compiled = 1 ) Then
   Opt( "TrayIconHide", 1 ); Hide the tray icon when script is compiled
EndIf
;-------------------------------------------------------------------------------------------------------------------------------------
; Create temporary directory structure
;-------------------------------------------------------------------------------------------------------------------------------------
DirCreate( $ActiveDir )
DirCreate( $ActiveDir & "Aut2Exe\" )
;-------------------------------------------------------------------------------------------------------------------------------------
; Extract the files needed for compiliation of generated scripts
;-------------------------------------------------------------------------------------------------------------------------------------
FileInstall( "Files\Aut2Exe.exe", $ActiveDir & "Aut2Exe\" )
FileInstall( "Files\AutoItSC.bin", $ActiveDir & "Aut2Exe\" )
FileInstall( "Files\upx.exe", $ActiveDir & "Aut2Exe\" )
;-------------------------------------------------------------------------------------------------------------------------------------
; Process command-line
;-------------------------------------------------------------------------------------------------------------------------------------
ProcessCL()

;===================================================================================================

==================================
; End Of Open Code
;***************************************************************************************************

**********************************

;***************************************************************************************************

**********************************
Func ProcessCL( )
;-------------------------------------------------------------------------------------------------------------------------------------
;  Name:    ProcessCL
;  Author:  Matthew Babcock
;  Date:    09/14/2004
;
;  Parameters:
;    None
;
;  Returns:
;    None
;
;  Notes:
;    None
;===================================================================================================

==================================

;  Local variable declaration
;-------------------------------------------------------------------------------------------------------------------------------------
   Local $tmpFilename
;-------------------------------------------------------------------------------------------------------------------------------------
;  Run function ExeWrap() based on the command-line parameters accepted
;-------------------------------------------------------------------------------------------------------------------------------------
   Select
      Case $CmdLine[0] = 0; No project file accepted, prompt the user to select a file
         
         $tmpFilename = FileOpenDialog( "Open Project...", @DesktopDir, "ExeWrap Projects (*.ini)", 1)
         
         If( @error = 1 ) Then Exit
         
;       Check is the selected file exists
         If( FileExists( $tmpFilename ) ) Then
            Return ExeWrap( $tmpFilename )
         Else
            MsgBox( 16, "ExeWrap Error", "The selected file is invalid." )
         EndIf
      
      Case $CmdLine[0] = 1; Project file accepted
   
;       Check for validity of the project file accepted
         If( FileExists( $CmdLine[1] ) ) Then
            ExeWrap( $CmdLine[1] )
         Else
            MsgBox( 16, "Project Error", "The project file does not exist." )
         EndIf

   EndSelect

;===================================================================================================

==================================
EndFunc; << = End of function ProcessCL()
;***************************************************************************************************

**********************************

;***************************************************************************************************

**********************************
Func ExeWrap( $IniFile )
;-------------------------------------------------------------------------------------------------------------------------------------
;  Name:    ExeWrap
;  Author:  Matthew Babcock
;  Date:    09/14/2004
;
;  Parameters:
;    $IniFile            This is the project file to be parsed
;
;  Returns:
;    None
;
;  Notes:
;    None
;===================================================================================================

==================================

;  Local variable declaration
;-------------------------------------------------------------------------------------------------------------------------------------
   Local $AppName, $ExeFile, $TmpFile, $TmpDir, $IncCount             ; Main project settings
   Local $OutFile, $IconFile, $Compression, $NoDecompile, $PassPhrase  ; Compile settings
   Local $Includes[1]                                                 ; An array for the files listed to be included
   Local $i, $file, $retValue, $CompileOptions                       ; Miscellaneous variables
;-------------------------------------------------------------------------------------------------------------------------------------
;  Retieval of project settings
;-------------------------------------------------------------------------------------------------------------------------------------
   $AppName = IniRead( $IniFile, "Main", "AppName", "" )
   $ExeFile = IniRead( $IniFile, "Main", "ExeFile", "" )
   $TmpFile = IniRead( $IniFile, "Main", "TempFile", "TempScript" & Random(0, 999) )
   $TmpDir = IniRead( $IniFile, "Main", "TempDirName", FileGetLongName( @TempDir ) & "\Temp" & Int(Random(0, 999)) )
   $IncCount = IniRead( $IniFile, "Main", "IncludeCount", "0" )
;-------------------------------------------------------------------------------------------------------------------------------------
;  Validation of project settings
;-------------------------------------------------------------------------------------------------------------------------------------
; Make sure required parameters are defined
   If( ($ExeFile = "") Or ($AppName = "") ) Then
      MsgBox( 16, "ExeWrap Error", "An error has occurred within your project configuration. Please verify your project is setup properly then try again." )
      Return -1
   EndIf
;-------------------------------------------------------------------------------------------------------------------------------------
;  Retrival of project compile options
;-------------------------------------------------------------------------------------------------------------------------------------
   $OutFile = IniRead( $IniFile, "Compile", "OutputFile", @DesktopDir & "\" & $AppName & ".exe" )
   $IconFile = IniRead( $IniFile, "Compile", "Icon", "" )
   $Compession = IniRead( $IniFile, "Compile", "Compression", "0" )
   $NoDecompile = IniRead( $IniFile, "Compile", "NoDecompile", "0" )
   $PassPhrase = IniRead( $IniFile, "Compile", "PassPhrase", "" )
;-------------------------------------------------------------------------------------------------------------------------------------
;  Validation of compile options
;-------------------------------------------------------------------------------------------------------------------------------------
   $CompileOptions = " /out """ & $OutFile & Chr(34)
   
   If( FileExists( $IconFile ) ) Then
      $CompileOptions = $CompileOptions & " /icon """ & $IconFile & Chr(34)
   EndIf
   $CompileOptions = $CompileOptions & " /comp " & $Compression
   If( $NoDecompile = 1 ) Then
      $CompileOptions = $CompileOptions & " /nodecompile"
   EndIf
   If( $PassPhrase <> "" ) Then
      $CompileOptions = $CompileOptions & " /pass " & $PassPhrase
   EndIf
;-------------------------------------------------------------------------------------------------------------------------------------
;  Retrival of project inclusions
;-------------------------------------------------------------------------------------------------------------------------------------
;  Make sure the Inclide count is greater than 0 before getting the inclusions
   If( ($IncCount <> "0") And ($IncCount <> "") ) Then
      ReDim $Includes[ $IncCount ]

      For $i = 0 to $IncCount - 1
         $Includes[$i] = IniRead( $IniFile, "Includes", "Include" & $i, "" )
      Next
   EndIf
;-------------------------------------------------------------------------------------------------------------------------------------
;  Creation of temporary script file
;-------------------------------------------------------------------------------------------------------------------------------------
;  Attempt to open the script file
   $file = FileOpen( $ActiveDir & $TmpFile, 2 )
   
;  If creation of script file fails then error and exit
   If( $file = -1 ) Then
      
      MsgBox( 16, "ExeWrap Error", "The temporary script could not be created, please verify your project settings then try again." )
      Return -1
      
   EndIf

;  Check the formatting of the Temporary Directory for validity
   If ( StringRight( $TmpDir, 1 ) <> "\" ) Then
      $TmpDir = $TmpDir & "\"
   EndIf
;-------------------------------------------------------------------------------------------------------------------------------------
;  Begin writting to temporary script
;-------------------------------------------------------------------------------------------------------------------------------------
   FileWriteLine( $file, "#comments-start" )
   FileWriteLine( $file, FillString( "*", "135" ) )
   FileWriteLine( $file, "   This code was generated using ExeWrap, by Matthew Babcock" )
   FileWriteLine( $file, FillString( "*", "135" ) )
   FileWriteLine( $file, "#comments-end" )
   FileWriteLine( $file, "" )
   FileWriteLine( $file, "DirCreate( """ & $TmpDir & """ )" )
   FileWriteLine( $file, "" )
   FileWriteLine( $file, "FileInstall( """ & $ExeFile & """, """ & $TmpDir & """, " & "1 )" )
   For $i = 0 to UBound($Includes) - 1
      If( $Includes[$i] <> "" ) Then
         FileWriteLine( $file, "FileInstall( """ & $Includes[$i] & """, """ & $TmpDir & """, " & "1 )" )
      EndIf
   Next
   FileWriteLine( $file, "" )
   FileWriteLine( $file, "RunWait( """ & $TmpDir & ParseFile( $ExeFile ) & """ )" )
   FileWriteLine( $file, "" )
   FileWriteLine( $file, "FileDelete( """ & $TmpDir & ParseFile( $ExeFile ) & """ )" )
   For $i = 0 to UBound($Includes) - 1
      If( $Includes[$i] <> "" ) Then
         FileWriteLine( $file, "FileDelete( """ & $TmpDir & ParseFile($Includes[$i]) & """ )" )
      EndIf
   Next
   FileWriteLine( $file, "" )
   FileWriteLine( $file, "DirRemove( """ & $TmpDir & """ )" )

   FileClose( $file )
;-------------------------------------------------------------------------------------------------------------------------------------
;  Finished writting to temporary script file
;-------------------------------------------------------------------------------------------------------------------------------------
;  Compile the temporary script to specified executable
;-------------------------------------------------------------------------------------------------------------------------------------
   RunWait($ActiveDir & "Aut2Exe\Aut2Exe /in """ & $ActiveDir & $TmpFile & Chr(34) & " " & $CompileOptions )
;-------------------------------------------------------------------------------------------------------------------------------------
;  Cleanup temporary files from process
;-------------------------------------------------------------------------------------------------------------------------------------
   DirRemove( $ActiveDir, 1 )
;===================================================================================================

==================================   
EndFunc
;***************************************************************************************************

**********************************

;***************************************************************************************************

**********************************
Func ParseFile( $FullPath )
;-------------------------------------------------------------------------------------------------------------------------------------
;  Name:    ParseFile
;  Author:  Matthew Babcock
;  Date:    09/14/2004
;
;  Parameters:
;    $FullPath           This is the path from which to parse the filename
;
;  Returns:
;    A string containing the parsed filename
;
;  Notes:
;    None
;===================================================================================================

==================================

;  Local variable declaration
;-------------------------------------------------------------------------------------------------------------------------------------
   Local $tmp
;-------------------------------------------------------------------------------------------------------------------------------------
;  Parse the filename
;-------------------------------------------------------------------------------------------------------------------------------------
   $tmp = StringSplit( $FullPath, "\" )
   Return $tmp[$tmp[0]] 
;===================================================================================================

==================================
EndFunc
;***************************************************************************************************

**********************************

;***************************************************************************************************

**********************************
Func FillString( $char, $length )
;-------------------------------------------------------------------------------------------------------------------------------------
;  Name:    FillString
;  Author:  Matthew Babcock
;  Date:    09/14/2004
;
;  Parameters:
;    $char           This is the character from which to build the string
;    $length           This is the number of characters for the string
;
;  Returns:
;    A string containing the passed character repeated the passed length
;
;  Notes:
;    None
;===================================================================================================

==================================

;  Local variable declaration and initialization
;-------------------------------------------------------------------------------------------------------------------------------------
   Local $i, $tmpString

   $tmpString = ""
;-------------------------------------------------------------------------------------------------------------------------------------
;  Build the requested string
;-------------------------------------------------------------------------------------------------------------------------------------
   For $i = 1 to Number($length)
      $tmpString = $tmpString & $char
   Next

   Return $tmpString
;===================================================================================================

==================================   
EndFunc
;***************************************************************************************************

**********************************

;***************************************************************************************************

**********************************
;  END OF SCRIPT
;***************************************************************************************************

**********************************

I would like as many people to try this as possible, and I am looking for suggestions to expand the usability and user-friendliness of the application. If you try it I would like some sort of feedback as to know that someone has read this post.

Thanks for your time and Happy Posting!

*** Matt @ MPCS

ExeWrap.zip

Link to comment
Share on other sites

This program is intended to wrap application dependencies with an executable so you dont have to register runtime libraries and other dependent files related to the executable. It was designed with Visual Basic developers in mind. This program will allow a VB developer to wrap his creation with the VB runtime libraries and requred OCX's for simple deployment of a single file.

Nice, I like it but how do you plan on handling Com interfaces that must be registered on the users computer such as AutoItX.dll ? Is there a way you can check to see if the Com is already registered and if not then register it ?

Link to comment
Share on other sites

Nice, I like it but how do you plan on handling Com interfaces that must be registered on the users computer such as AutoItX.dll ? Is there a way you can check to see if the Com is already registered and if not then register it ?

The idea is that most languages will look first in the application directory for the dependent files, then search the registered files so initially I didn't see this as an issue, but after running through more extensive testing I see a need for it in the next version so I will be adding another Section in the next couple of versions that handles files that need to be registered.

As for the AutoItX.dll, in Vb if you include it using the references dialog it does not need to be registered if placed in the application directory. It all depends on how the library is accessed through the application.

Thanks for the input, keep it coming! Happy Posting!

*** Matt @ MPCS

NOTE OF CURRENT DEVELOPMENT:

I am currently working on a GUI that generates the Project INI files based on user selections. This is a perfect application for VB development, and a good target for use of ExeWrap (Wrapping the GUI app with the VB dependencies) :ph34r:

Edited by Matt @ MPCS
Link to comment
Share on other sites

As for the AutoItX.dll, in Vb if you include it using the references dialog it does not need to be registered if placed in the application directory. It all depends on how the library is accessed through the application.

When you add it as a reference at the project level VB registers for you at that time. Unregister AutoItX.dll then run an app with AutoItX.dll added as a reference, try then to utilize any of AutoItX functions and you will see what I mean.

Link to comment
Share on other sites

  • 3 weeks later...

When you add it as a reference at the project level VB registers for you at that time.  Unregister AutoItX.dll then run an app with AutoItX.dll added as a reference, try then to utilize any of AutoItX functions and you will see what I mean.

<{POST_SNAPBACK}>

I don't see why the application wouldn't register/unregister the dll that way the developer of the application can register it based on their application handle and not windows. If you need a function that does this in VB:

Public Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Public Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Public Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long


Public Sub RegisterServer(lngHwnd As Long, strDllServerPath As String, boolRegister As Boolean)

 ' lngHwnd is hWnd of some form in your project.

On Error Resume Next

Dim lngResult As Long
Dim lngProcAddress As Long
dim strProc As String

 ' Check if file have length > 0
If FileLen(strDllServerPath) > 0 Then
    ' Load file for use in our app
   lngResult = LoadLibrary(strDllServerPath)
    ' If result differs from 0 then loading was successful
   If lngResult <> 0 Then
       ' If we must register
      If boolRegister = True Then
         strProc="DllRegisterServer"
      Else ' If we must unregister
         strProc="DllUnregisterServer"
      End If
       ' Get procedure address
      lngProcAddress = GetProcAddress(lngResult, strProc)
       ' Call the appropriate procedure in DLL file (DllRegisterServer or DllUnregisterServer)
       ' It's address is in lngProcAddress variable
      CallWindowProc lngProcAddress, lngHwnd, ByVal 0&, ByVal 0&, ByVal 0&
       ' Unload file
      FreeLibrary lngResult
   End If
End If

End Function

To register DLL use this:

Call RegisterServer(Form1.hWnd,"C:\Windows\System\Mydll.dll",True)

To unregister DLL use this:

Call RegisterServer(Form1.hWnd,"C:\Windows\System\Mydll.dll",False)

This code can be found here.

*** Matt @ MPCS

EDIT: Just found a single line way to do what the above function does.

Public function DllRegisterServer Lib "yourdll" Alias "DllRegisterServer"() as Long

I haven't tried it yet but I have seen it from a few reliable sources. If this does work then as soon as we get the DllCall function working stably I will be adding DLL register support to my script. :)

*** Matt @ MPCS

Edited by Matt @ MPCS
Link to comment
Share on other sites

I don't see why the application wouldn't register/unregister the dll that way the developer of the application can register it based on their application handle and not windows. If you need a function that does this in VB:

Not to discourage you but:

I hear there are a few dependencies that will prevent your app from running if the are not registered beforehand. Probably depends on what OS you are running.

I think a proper setup installation is the best way, that way the dll - ocx are registered only once, this way there is less registry manipulation.

I use Inno Setup Compiler with 3rd party addons to compile the setup installation for my appz. There is even an addon for that extracts all the dependencies from your .vbp file and adds them to the setup script.

Link to comment
Share on other sites

Not to discourage you but:

I hear there are a few dependencies that will prevent your app from running if the are not registered beforehand. Probably depends on what OS you are running.

I think a proper setup installation is the best way, that way the dll - ocx are registered only once, this way there is less registry manipulation.

I use Inno Setup Compiler with 3rd party addons to compile the setup installation for my appz. There is even an addon for that extracts all the dependencies from your .vbp file and adds them to the setup script.

<{POST_SNAPBACK}>

This was not intended to be an everything for everyone solution... I understand there are solutions better than mine (starting with the commercial versions of this type of application). There are exceptions to every rule and these exceptions are handled when they arrise. Give me an application that proves the concept you are introducing and then I will consider a change. As I have stated, the original purpose for this application is to wrap VB references with the executable so you don't always need to worry about the end user having those references available. It works as such. If people want to use other third party references in their code then they can find a way to bend the solution provided to fit their problem... or they can find another solution.

In addition, I posted a piece of code that if it executes successfully will fix the problem suggested. I am only waiting for a new solution from the developers of this language to catch up to where I need them to be before I can provide a complete solution.

*** Matt @ MPCS

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...