Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Compile() - easy self-compiling with custom icons/resources


  • Please log in to reply
25 replies to this topic
gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
made a handy little function to compile my scripts for me, using custom .ico or modified AHkSC.bin from script's directory if found

Compile() 0.41
Download Compile.ahk or read the Documentation [ Alternate download link ]
Tested in _Basic and _L


i was thinking about making an app or modifying others i've seen, but this stdlib compliant function solves my needs pretty nicely

Example calls:
Compile("Run")      ;= compiles .ahk into .exe, runs the .exe and exits the .ahk
                    ;= making the .ahk like a shortcut to a freshly compiled exe when in the auto-execute section

Compile()           ;= compiles .ahk into .exe, but continues running the .ahk, for compiling on demand but to continue running the uncompiled .ahk

Example script:
#SingleInstance Force
SetWorkingDir, % A_ScriptDir
IfNotExist, % Icon := "CompileDemo.ico"
 GoSub, CreateIcon

Compile("Run") ; or try:
; Compile()
; Compile("NoWait")

MsgBox, The file currently running:`n`n%A_ScriptName%

Return


CreateIcon:
 IconData =
( join
000001000100101000000100080068050000160000002800000010000000200000000100080000000000000000
000000000000000000000000000000000000000000044f5b0013545f0016565f000c556000045b69000e5e6a00
15576100036f7f00046e7f000c6e7d001e6c780032626a002c6a7300346c750045717900527277007275760077
777700036f800005708100457c8500517980000485990007889b002c869400059ab100099ab100349dad0030ac
bf004a919d00798688007a888b00668c9300738c90007d8f9300679ca4006facb60005adc70005aec8001eadc4
0026b8cf0069b5c1006fb9c50010c1dd0006c2e00007c6e40011c5e10016c5e1001dcbe6003acbe10040c2d700
6fc5d20063cada006dcfde0053cee1004ed5e90073dcec00869b9f00939393009394940091999a009ca2a3008f
b1b600a1a1a100a0a5a500a6a6a600afbdbf00b1b2b200b3b4b400bbbbbb0084bbc40095bac10096c3ca0096cc
d5009acfd80095d4de0099d5df00b3c4c700bbced200b9d6db0096dce700a3dae300a3dde6008ee3ef00b2e8f0
00bbedf400c0c0c000c5c5c500c1c7c800cacaca00cacdcd00cecece00c7d4d600cad0d100c7dade00c9dadc00
d1d1d100d6d6d600d3d8d900d0dddf00d9d9d900d9dedf00dedede00c7dfe300c4e3e700cde0e400c7e4e800c6
e7ec00cee6e900d3e0e200dae1e200dee0e100d4e6e800dae6e800c6ebf100e1e1e100eaf5f600a9cf0000c2f0
0000d1ff1100d8ff3100deff5100e3ff7100e9ff9100efffb100f6ffd100ffffff00000000002f260000504100
00705b000090740000b08e0000cfa90000f0c30000ffd21100ffd83100ffdd5100ffe47100ffea9100fff0b100
fff6d100ffffff00000000002f1400005022000070300000903e0000b04d0000cf5b0000f0690000ff791100ff
8a3100ff9d5100ffaf7100ffc19100ffd2b100ffe5d100ffffff00000000002f03000050040000700600009009
0000b00a0000cf0c0000f00e0000ff201200ff3e3100ff5c5100ff7a7100ff979100ffb6b100ffd4d100ffffff
00000000002f000e00500017007000210090002b00b0003600cf004000f0004900ff115a00ff317000ff518600
ff719c00ff91b200ffb1c800ffd1df00ffffff00000000002f0020005000360070004c0090006200b0007800cf
008e00f000a400ff11b300ff31be00ff51c700ff71d100ff91dc00ffb1e500ffd1f000ffffff00000000002c00
2f004b0050006900700087009000a500b000c400cf00e100f000f011ff00f231ff00f451ff00f671ff00f791ff
00f9b1ff00fbd1ff00ffffff00000000001b002f002d0050003f007000520090006300b0007600cf008800f000
9911ff00a631ff00b451ff00c271ff00cf91ff00dcb1ff00ebd1ff00ffffff000000000008002f000e00500015
0070001b0090002100b0002600cf002c00f0003e11ff005831ff007151ff008c71ff00a691ff00bfb1ff00dad1
ff00ffffff00747474747474655a58627474747474747474747474675a423b466774747474747474747474625b
40124065747474747474747474745b5e3e113c5c74747474747474747474472a1e0f1f57747474747474747474
66281b170a16446774747474747474704b271a17130d3d62747474747474745033271a17130610456274747474
7464352c261a17130503205767747474744d302d261a181405010c416274747474372e2f291d1c190b04022361
7474747432313836342b25241507226174747474373854514c4a49483f0e3a6574747474523956736c6b685f4f
215974747474746e535575757575724e43677474747474746f6a696d71605d6367747474740000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000
)
 WriteFile(Icon,IconData)
Return

WriteFile(file,data)
{
 Handle :=  DllCall("CreateFile","str",file,"Uint",0x40000000
               ,"Uint",0,"UInt",0,"UInt",4,"Uint",0,"UInt",0)
  Loop
  {
   if strlen(data) = 0
    Break
   StringLeft, Hex, data, 2         
   StringTrimLeft, data, data, 2
   Hex = 0x%Hex%
   DllCall("WriteFile","UInt", Handle,"UChar *", Hex
  ,"UInt",1,"UInt *",UnusedVariable,"UInt",0)
 }
 DllCall("CloseHandle", "Uint", Handle)
 Return
}

Function code:
;;
;  Compile() - 0.41 - by gwarble
;    compile your script on demand, with local icons/AutoHotkey.bin
;
; Compile(Action,Name,Password)
;
;    Action   "" [Default]  -waits for the compiler to finish before returning
;             Run           -to run the compiled script and close the running script
;             NoWait        -starts compiling and continues running your script
;             Recompile     -closes the running .exe and launches the .ahk (if compiled)
;                             (useful for a self-editing compiled script)
;
;    Name     "" [Default]  -uses filename of script for exe/ico/bin filenames
;             Other         -specify a different name for the input ico/bin and output exe
;
;    Password **            -compilation password
;
;    Return   1 on success
;             0 on failure, compiler not found, already compiled, etc...
;
;    Notes    save custom icon as ScriptName.ico (in a subdir is ok) or
;             save modified AutoHotkeySC.bin as ScriptName.AHK.bin
;
Compile(Action="",Name="",Password="") {
 If A_IsCompiled	
  If Action <> Recompile	; unless "ReCompile", function does nothing when running compiled
   Return 0
  Else
  {
   SplitPath, A_ScriptFullPath,,,,ScriptName
   Run, %ScriptName%.ahk 	; if is Recompile, will close the running exe and launch the ahk script
   Return 1		; which should have its own auto-exeute Compile("Run")
  }
 SplitPath, A_ScriptFullPath,, ScriptDir,, ScriptName
 If Name <>
  ScriptName := Name	; Name parameter overrides icon/exe name from Scripts name
 Icon := ExeFile := ScriptDir "\" ScriptName ".exe"
 Loop, %ScriptName%.AHK.bin, 0, 1	; find .AHK.bin file if it exists, including subdirs
  IfExist %A_LoopFileFullPath%
  {
   Icon := CompilerBin := A_LoopFileFullPath
   Break
  }
 If CompilerBin =		; otherwise, use a found ScriptName.ico for the compile process
  Loop, %ScriptName%.ico, 0, 1	; including subdirs
   IfExist %A_LoopFileFullPath%	
   {
    ScriptIcon = /icon "%A_LoopFileFullPath%"
    Icon = %A_LoopFileFullPath%	; and sets it for the run string to run the compiler later
    Break
   }
 SplitPath, A_AhkPath,, Compiler,,,  ; find compiler...
 Compiler := Compiler "\Compiler\Ahk2Exe.exe"	; assumes compiler is in AHKPath default Compiler dir
 IfNotExist %Compiler%		; otherwise, checks registry for AHK install dir
 {			; poor method checks the context menu for the compile command
  RegRead, Compiler, HKCR, AutoHotkeyScript\Shell\Compile\Command ; for location of compiler
  StringReplace, Compiler, Compiler, ",,All
  StringReplace, Compiler, Compiler, % "/in %l"	; and clean up that context menu command to the exe path
  IfNotExist %Compiler%
  {
   Loop %A_StartMenuCommon%\*.*, 0, 1	; otherwise check the start menu for compiler's default shortcut
    If A_LoopFileName contains convert .ahk to .exe
    {
     FileGetShortcut, % A_LoopFileFullPath, Compiler
     Break
    }
   IfNotExist %Compiler%		; otherwise assumes AHK (and compiler) is not installed
    Loop, %A_ScriptDir%\Ahk2Exe.exe, 0, 1	; so checks the local dir for the compiler
     Compiler := %A_LoopFileFullPath% 	; including subdirs
  }
  IfNotExist %Compiler%		; and after all that if no compiler is found, returns error (0)
   Return 0   			; compiler not found
 }

 Prev_DetectHiddenWindows := A_DetectHiddenWindows
 DetectHiddenWindows On		; loop to WinClose all running processes before compiling
 Loop
  IfWinExist, % ExeFile,,30
   WinClose
  Else
   Break
 DetectHiddenWindows %Prev_DetectHiddenWindows%

 If (Password)  			; sets compilation password
  Password := "/pass " Password		; untested feature

 Loop, %ScriptName%.AHK.bin, 0, 1
  IfExist %A_LoopFileFullPath%		; if custom .bin is used, copy it in place
  {			; after backing up the original
   SplitPath, Compiler,, CompilerDir,,,
   CompilerBin := CompilerDir "\AutoHotkeySC.bin"
   FileCopy, % CompilerBin, % CompilerDir "\AutoHotkeySC.Last.bin", 1 ; backed up original every run
   FileCopy, % CompilerBin, % CompilerDir "\AutoHotkeySC.Orig.bin", 0 ; first backup made won't be overwritten
   FileCopy, % A_LoopFileFullPath , % CompilerBin, 1
   Break
  }			; and finally, put all those options together
 RunLine = %Compiler% /in "%A_ScriptFullPath%" /out "%ExeFile%" %ScriptIcon% %Password%
 If Action = NoWait		; decide how to run it (first parameter)
  Run,     % RunLine, % A_ScriptDir, Hide
 Else
  RunWait, % RunLine, % A_ScriptDir, Hide
 If (CompilerBin)			; restore the original SC.bin file if a custom one was used
  FileCopy, % CompilerDir "\AutoHotkeySC.Last.bin", % CompilerBin, 1
 If Action = Run			; and run the compiled script if "Run" option is used (typical)
 {
  Run, % ScriptName
  ExitApp
 }
Return 1
}

nothing ground-breaking here but handy nonetheless, hope you like it, feedback greatly appreciated

- gwarble

edit: bugfix version 4, recompile working properly 8/3/10
edit: new version .41, small fixes/improvements 1/2012

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
Edit: new version, everything i need from it is in there now:
save ScriptName.ico, modified AutoHotkeySC.bin (ScriptName.AHK.bin), desired for compiling into your ScriptDir (or a sub)

keeps your scripts (that you compile) portable... that way you can modify the .bin for your app, and leave it with the script and still compile with it (mainly for multiple icons, or whyever you might edit the .bin before compiling)

before, my compiler directory had a bunch of .bin's for different projects (apps mostly, normal little scripts don't matter) that i would rename... this takes care of it for you...

- gwarble

what it does behind the scenes for AutoHotkeySC.bin:

copies original AutoHotkeySC.bin to:
overwrites AutoHotkeySC.Last.bin
ifnotexist, creates AutoHotkeySC.Original.bin
copies ScriptName.AHK.bin from ScriptDir (or subdir) to compiler directory
compiles sript
copies AutoHotkeySC.Last.bin back over AutoHotkeySC.bin, so other scripts aren't affected



gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
i added notifications [using Notify() (see thread)] to this function (dynamically, not required) since i like it for feedback during the process... i'll make this parameter based if anyone shows any interest

fixed a couple little bugs and order of operations...

trying to decide if .ahk.bin should take precedence or the .ico, if both are found... feedback? for now its the .bin...

Example:

download Min2Tray.ahk (code removed, just download)

i took Sean's nice WinTrayMin script (minimize to tray with right click) and made an example showing off Compile() and Notify():
name some icon as Min2Tray.ico (or a custom AutoHotkeySC.bin as Min2Tray.AHK.bin) to see the effects


are [IsFunc] and [#inc... *i] the prefered way to do this dynamically, the goal to be universal and failsafe

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
i guess no one cares about this, from what i've read most people don't compile their scripts, is that true?


if you use Compile("Run") in the autoexec section, it basically turns your .ahk into a shortcut to a freshly compiled exe

in that case, try this somewhere to replace your normal reload procedure:
^F12::                   ; i use this in place of:
ReCompile:               ; ^F12::
Run, %Name%.ahk          ; Reload:
ExitApp                  ;  Reload

otherwise put this somewhere when you're running the .ahk and want to compile:
^F12::Compile() ; don't forget to use Script.ico or Script.AHK.bin!! (modified AutoHotkeySC.bin)


  • Guests
  • Last active:
  • Joined: --
haha, yes
i always keep scripts, much smaller size, and i can edit scripts immediately when i think of something new or need to improve
compiling doesnt even exists once a month
besides, its not too hard to right click icon and press compile scripts...

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
i agree, many quick little scripts are better left uncompiled... but applications written with AHK, as well as any script i always run (ie: at startup, so you can tell the process name like any other program, don't get confused with too many ahk.exe processes, included icons...

but the real purpose of this is, if you do compile, it will grab your custom icon or custom AutoHotkeySC.bin and apply it in the compilation process...

so right click compile always works the same and is easy, but Compile() from the script will compile with a local .ico or .AHK.bin


i learned ahk by writing an app for my shop (cnc machine shop), which has successfully evolved into a shop monitoring application that i run on all computers in the shop... in this case distributing compiled scripts is WAY better than keeping all the pcs (not that many, but like 9 or 10) up to date with autohotkey, stdlib, etc... and ahk makes it so easy to create professional apps (even the installer i wrote in ahk) this was just a logical step for the way i use it...

Tuncay
  • Members
  • 1945 posts
  • Last active: Feb 08 2015 03:49 PM
  • Joined: 07 Nov 2006
I am one of those who don`t really compile. But in future there are scrnarios for need to compile, i.e. if I share with non AutoHotkey`lers. The idea of a compile function is very good and flexible usable in user scripts. Thx for making this and sharing with us. I have this in my mind and will definetely use if need in near future.

Keep your work. Dont forget peaple dont allways reply if they use something.

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
thanks for the feedback... i'm kind of new to ahk and always appreciate others' points of view and ideas... puts me in check when i think writing something is a good idea when it may not be (or vice versa, or its already been shared)

i realize users of some code may not reply, so its not all in vain... plus its good practice for me anyway... but next time you write a script (especially one with a custom icon or modified autootkeysc.bin) that is planned to be compiled i'd love if you try it out...



personally, if the script is a "script" in functionality, i use the uncompiled .ahk... but if the script becomes, to the untrained eye at least, an application, then i like to compile...

so if it functions like an application, i end up compiling my scripts (like the WinTrayMin example above (thanks sean)...) often with modified AutoHotkeySC.bin for multiple self-contained icons... which makes them easy to use/distribute/diagnose (task manager)/explain to others...

as far as size...? a 205kb .exe vs. a 5kb script makes no difference to me whatsoever... i don't know if there is more overhead required by the OS running a .exe or a .ahk, but not that i've noticed... and storage space makes no difference... and a 200kb download time is pretty much neglible these days... so i don't really see a negative in most cases

- gwarble

Tuncay
  • Members
  • 1945 posts
  • Last active: Feb 08 2015 03:49 PM
  • Joined: 07 Nov 2006
The reason why i never compile even on my usb disk drive (or how it is called outside of the world {Germany}) is because I love open source and want the ability to change the source everytime and use without recompiling. For this, I wroted in early days a program in FreeBasic to run those scripts from portable device where Ahk was not installed on that computer, or an old version.

I have one AutoStart script, which starts several other programs and exits. One of those programs is a permanent script. It does not matter if the AutoStart Script would be compiled or not. The config is saved in a xml file and it exits.

The permanent script have some hotkeys and other things monitoring and waiting for special actions. This script could be compiled, so that I can differentiate the process easily by name and icon. BUT still today I have not compiled it one time, because I need to change it sometimes. That is the only reason.
With your code this process could be automated and I could have advantage of compiled AND non-compiled scripts, but also the trouble of those two.

So my conclusion is to compile sometimes in future, if it seems to be reasonable. (thx to you :p ) ... hmmm what else to say? I am tired. Its late now and have to work in some hours. :D But I cant sleep. Have a nice day.

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
exactly, thats my mentality (except i do it :) )... i've had good success compiling my scripts... this makes it easier, here's a super-simple working example (Compile() and Notify() are included)

- gwarble

(creates its own icon and .exe if run)
; Compile() and Notify() are included at the bottom of this script, and can be removed
; if you use them in your stdlib


#SingleInstance Force
SetWorkingDir, %A_ScriptDir%

 IfNotExist, % Icon
  GoSub, CreateIcon

  Compile("Run")
; Compile()

 MsgBox, The file currently running:`n`n%A_ScriptName%

Return

CreateIcon:
 IconData =
( join
000001000100101000000100080068050000160000002800000010000000200000000100080000000000000000
000000000000000000000000000000000000000000044f5b0013545f0016565f000c556000045b69000e5e6a00
15576100036f7f00046e7f000c6e7d001e6c780032626a002c6a7300346c750045717900527277007275760077
777700036f800005708100457c8500517980000485990007889b002c869400059ab100099ab100349dad0030ac
bf004a919d00798688007a888b00668c9300738c90007d8f9300679ca4006facb60005adc70005aec8001eadc4
0026b8cf0069b5c1006fb9c50010c1dd0006c2e00007c6e40011c5e10016c5e1001dcbe6003acbe10040c2d700
6fc5d20063cada006dcfde0053cee1004ed5e90073dcec00869b9f00939393009394940091999a009ca2a3008f
b1b600a1a1a100a0a5a500a6a6a600afbdbf00b1b2b200b3b4b400bbbbbb0084bbc40095bac10096c3ca0096cc
d5009acfd80095d4de0099d5df00b3c4c700bbced200b9d6db0096dce700a3dae300a3dde6008ee3ef00b2e8f0
00bbedf400c0c0c000c5c5c500c1c7c800cacaca00cacdcd00cecece00c7d4d600cad0d100c7dade00c9dadc00
d1d1d100d6d6d600d3d8d900d0dddf00d9d9d900d9dedf00dedede00c7dfe300c4e3e700cde0e400c7e4e800c6
e7ec00cee6e900d3e0e200dae1e200dee0e100d4e6e800dae6e800c6ebf100e1e1e100eaf5f600a9cf0000c2f0
0000d1ff1100d8ff3100deff5100e3ff7100e9ff9100efffb100f6ffd100ffffff00000000002f260000504100
00705b000090740000b08e0000cfa90000f0c30000ffd21100ffd83100ffdd5100ffe47100ffea9100fff0b100
fff6d100ffffff00000000002f1400005022000070300000903e0000b04d0000cf5b0000f0690000ff791100ff
8a3100ff9d5100ffaf7100ffc19100ffd2b100ffe5d100ffffff00000000002f03000050040000700600009009
0000b00a0000cf0c0000f00e0000ff201200ff3e3100ff5c5100ff7a7100ff979100ffb6b100ffd4d100ffffff
00000000002f000e00500017007000210090002b00b0003600cf004000f0004900ff115a00ff317000ff518600
ff719c00ff91b200ffb1c800ffd1df00ffffff00000000002f0020005000360070004c0090006200b0007800cf
008e00f000a400ff11b300ff31be00ff51c700ff71d100ff91dc00ffb1e500ffd1f000ffffff00000000002c00
2f004b0050006900700087009000a500b000c400cf00e100f000f011ff00f231ff00f451ff00f671ff00f791ff
00f9b1ff00fbd1ff00ffffff00000000001b002f002d0050003f007000520090006300b0007600cf008800f000
9911ff00a631ff00b451ff00c271ff00cf91ff00dcb1ff00ebd1ff00ffffff000000000008002f000e00500015
0070001b0090002100b0002600cf002c00f0003e11ff005831ff007151ff008c71ff00a691ff00bfb1ff00dad1
ff00ffffff00747474747474655a58627474747474747474747474675a423b466774747474747474747474625b
40124065747474747474747474745b5e3e113c5c74747474747474747474472a1e0f1f57747474747474747474
66281b170a16446774747474747474704b271a17130d3d62747474747474745033271a17130610456274747474
7464352c261a17130503205767747474744d302d261a181405010c416274747474372e2f291d1c190b04022361
7474747432313836342b25241507226174747474373854514c4a49483f0e3a6574747474523956736c6b685f4f
215974747474746e535575757575724e43677474747474746f6a696d71605d6367747474740000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000
)
 SplitPath, A_ScriptFullPath , , , , ScriptName
 Icon = %ScriptName%.ico
 WriteFile(Icon,IconData)
Return

WriteFile(file,data)
{
 Handle :=  DllCall("CreateFile","str",file,"Uint",0x40000000
               ,"Uint",0,"UInt",0,"UInt",4,"Uint",0,"UInt",0)
  Loop
  {
   if strlen(data) = 0
    Break
   StringLeft, Hex, data, 2         
   StringTrimLeft, data, data, 2 
   Hex = 0x%Hex%
   DllCall("WriteFile","UInt", Handle,"UChar *", Hex
  ,"UInt",1,"UInt *",UnusedVariable,"UInt",0)
 }
 DllCall("CloseHandle", "Uint", Handle)
 Return
}

;
; Compile() - 0.3 - by gwarble - oct 09
;  a simple function to auto-compile your scripts
;   -save custom AutoHotkeySC.bin as ScriptName.AHK.bin
;   -save custom icon as ScriptName.ico
;   -subdirs below A_ScriptDir are checked for ico/bin
;
;
;
;  Compile(Action,Name,Password)
;    Action   ""        -waits for the compiler to finish before returning [default]
;             Run       -to run the compiled script and close the running script
;             NoWait    -starts compiling and continues running your script
;             
;
;    Name     ""        -uses filename of script for exe/ico/bin
;             Other     -specify a different name for the input ico/bin and output exe
;
;    Return   1 on success
;             0 on failure, compiler not found,
;
;    Note       Name your icon to ScriptName.ico (can be in a subdir)
;               Name your modified AutoHotkeySC.bin to ScriptName.AHK.bin
;;

Compile(Action="",Name="") {

 If A_IsCompiled
  Return 0   ;=== does nothing when running already compiled


 SplitPath, A_ScriptFullPath , , ScriptDir, ScriptExt, ScriptName  ;=== find script
 If (Name)   ;=== override .ahk's file name [optional]
  ScriptName := Name                                      ;=  (add support for .scr)?
 Icon := ExeFile := ScriptDir "\" ScriptName ".exe" ;=== output exe file


 Loop, %ScriptName%.AHK.bin, 0, 1 ;=== use first file found named
  IfExist %A_LoopFileFullPath%    ;=== ScriptName.AHK.bin
  {                               ;=== as the AutoHotkeySC.bin file when compiling
   Icon := CompilerBin := A_LoopFileFullPath
   Break
  }
 If (CompilerBin = "") ;= should .ico override .bin or .bin override .ico (now)?
  Loop, %ScriptName%.ico, 0, 1   ;=== use first icon found under
   IfExist %A_LoopFileFullPath%  ;=== ScriptDir\ named ScriptName.ico
   {
    ScriptIcon = /icon "%A_LoopFileFullPath%"
    Icon = %A_LoopFileFullPath%
    Break
   }

 If IsFunc(Notify := "Notify")
  NotifyID := %Notify%("Compiling...",A_ScriptName,0,"IN=1",Icon)



 SplitPath, A_AhkPath , , Compiler, , ,  ;=== find compiler
 Compiler := Compiler "\Compiler\Ahk2Exe.exe"
 IfNotExist %Compiler%
 {
  RegRead, Compiler, HKCR, AutoHotkeyScript\Shell\Compile\Command
  StringReplace, Compiler, Compiler, ",,All
  StringReplace, Compiler, Compiler, % "/in %l"
  IfNotExist %Compiler%
  {
   Loop %A_StartMenuCommon%\*.*, 0, 1
    If A_LoopFileName contains convert .ahk to .exe
    {
     FileGetShortcut, % A_LoopFileFullPath, Compiler
     Break
    }
   IfNotExist %Compiler%
    Loop, %A_ScriptDir%\Ahk2Exe.exe, 0, 1 ;=== check local dir for ahk2exe
     Compiler := %A_LoopFileFullPath%
  }
  IfNotExist %Compiler%
  {
   If IsFunc(Notify := "Notify")
    %Notify%("Compiler could not be found!","",3)
   Return 0                ;=== compiler couldn't be found
  }
 }




 Prev_DetectHiddenWindows := A_DetectHiddenWindows  ;=== kill if running
 DetectHiddenWindows On   ;=== saves scripts current setting
 WinClose, % ExeFile      ;=== closes the resultant exe if running
 DetectHiddenWindows %Prev_DetectHiddenWindows% ;=== restore setting
 
 If (Password)                    ;=== sets compilation password (not tested)
  Password := "/pass " Password

 Loop, %ScriptName%.AHK.bin, 0, 1 ;=== use first file found named
  IfExist %A_LoopFileFullPath%    ;=== ScriptName.AHK.bin
  {                               ;=== as the AutoHotkeySC.bin file when compiling
   SplitPath, Compiler , , CompilerDir, , ,  ;=== find compiler's AutoHotkey.bin
   CompilerBin := CompilerDir "\AutoHotkeySC.bin"
   FileCopy, % CompilerBin, % CompilerDir "\AutoHotkeySC.Last.bin", 1
   FileCopy, % CompilerBin, % CompilerDir "\AutoHotkeySC.Orig.bin", 0
   FileCopy, % A_LoopFileFullPath ,   % CompilerBin, 1
   Break
  }

 RunLine = %Compiler% /in "%A_ScriptFullPath%" /out "%ExeFile%" %ScriptIcon% %Password%

 If Action = NoWait
  Run,     % RunLine, % A_ScriptDir, Hide
 Else
  RunWait, % RunLine, % A_ScriptDir, Hide

 If (CompilerBin)
  FileCopy, % CompilerDir "\AutoHotkeySC.Last.bin", % CompilerBin, 1

 If IsFunc(Notify := "Notify")
  %Notify%("","",0,"Wait",NotifyID)

 If Action = Run
 {
  Run, % ScriptName
  ExitApp
 }

Return 1
}


;;;;;;;
;;;;;  Notify() 0.441                made by gwarble - sept 09
;;;      multiple tray area notifications
;          thanks to Rhys/engunneer/HugoV/Forum Posters
;
;   Notify([Title,Message,Duration,Options,Image])
;
;     Title      [!!!]          "" to omit title line
;     Message      []           "" to omit message line
;     Duration    [15]          seconds to show notification
;                                0 to flash until clicked
;                               <0 to ExitApp on click/timeout
;                               -0 not yet implemented (perm/exit)
;     Options                   string of options... see function
;          [SI=999 GC=Blue...]  most options are remembered (static)
;                               "Reset" to restore default options
;                                 if you want to show as well, use NO=Reset
;                               "Wait" to wait for a notification  ***
;       Image []                 Image file name/library or
;                                number of icon in shell32.dll
;                                Gui Number to "Wait" for          ***
;
;     Return                     Gui Number used                   ***
;                                0 if failed (too many)
;
Notify(Title="!!!",Message="",Duration=30,Options="",Image="")
{
 Static                ;Options string: "TS=12 GC=Blue..."
 static GF := 50       ;    Gui First Number  ;= override Gui: # used
 static GL := 74       ;    Gui Last Number   ;= between GF and GL
 static GC := "FFFFAA" ;    Gui Color         ;   ie: don't use GF<=Gui#<=GL
 static GR := 9        ;    Gui Radius        ;       elsewhere in your script
 static GT := "Off"    ;    Gui Transparency
 static TS := 8        ;  Title Font Size
 static TW := 625      ;  Title Font Weight
 static TC := "Black"  ;  Title Font Color
 static TF := "Arial"  ;  Title Font Face
 static MS := 8        ;Message Font Size
 static MW := 550      ;Message Font Weight
 static MC := "Black"  ;Message Font Color
 static MF := "Arial"  ;Message Font Face
 static BC := "Black"  ; Border Colors
 static BW := 2        ; Border Width/Thickness
 static BR := 13       ; Border Radius
 static BT := 105      ; Border Transpacency
 static BF := 150      ; Border Flash Speed
 static SI := 250      ;  Speed In (AnimateWindow)
 static SC := 100      ;  Speed Clicked (AnimateWindow)
 static ST := 500      ;  Speed TimeOut (AnimateWindow)
 static IW := 32       ;  Image Width
 static IH := 32       ;  Image Height
 static IN := 0        ;  Image Icon Number (from Image)
 local AC, AT          ;Actions Clicked/Timeout
 local _Notify_Action, ImageOptions, GY, OtherY


_Notify_:

 local NO := 0                ;NO is Notify Option [NO=Reset] ;local
 If (Options)
 {
  IfInString, Options, =
  {
   Loop,Parse,Options,%A_Space%
    If (Option:= SubStr(A_LoopField,1,2))
     %Option%:= SubStr(A_LoopField,4)
   If NO = Reset
   {
    Options := "GF=50 GL=74 GC=FFFFAA GR=9 GT=Off TS=8"
. " TW=625 TC=Black TF=Arial MS=8 MW=550 MC=Black MF=Arial"
. " BC=Black BW=2 BR=9 BT=105 BF=150 SC=300 SI=250 ST=100"
. " IW=32 IH=32 IN=0"
    Goto, _Notify_
   }
  }
  Else If Options = Wait
   Goto, _Notify_Wait_
 }


 GN := GF
 Loop
  IfNotInString, NotifyList, % "|" GN
   Break
  Else
  If (++GN > GL)
    Return 0              ;=== too many notifications open!
 NotifyList .= "|" GN
 GN2 := GN + GL - GF + 1
 If AC <>
  ActionList .= "|" GN "=" AC

 Prev_DetectHiddenWindows := A_DetectHiddenWindows
 Prev_TitleMatchMode := A_TitleMatchMode
 DetectHiddenWindows On
 SetTitleMatchMode 1
 If (WinExist("NotifyGui"))  ;=== find all Notifications from ALL scripts, for placement
  WinGetPos, OtherX, OtherY  ;=== change this to a loop for all open notifications?
 DetectHiddenWindows %Prev_DetectHiddenWindows%
 SetTitleMatchMode %Prev_TitleMatchMode%

 Gui, %GN%:-Caption +ToolWindow +AlwaysOnTop -Border
 Gui, %GN%:Color, %GC%
 Gui, %GN%:Font, w%TW% s%TS% c%TC%, %TF%
 If (Image)
 {
  If FileExist(Image)
   Gui, %GN%:Add, Picture, w%IW% h%IH% Icon%IN%, % Image
  Else
   Gui, %GN%:Add, Picture, w%IW% h%IH% Icon%Image%, c:\windows\system32\shell32.dll
  ImageOptions = x+10
 }
 If Title <>
  Gui, %GN%:Add, Text, % ImageOptions, % Title
 Gui, %GN%:Font, w%MW% s%MS% c%MC%, %MF%
 If ((Title) && (Message))
  Gui, %GN%:Margin, , -5
 If Message <>
  Gui, %GN%:Add, Text,, % Message
 If ((Title) && (Message))
  Gui, %GN%:Margin, , 8
 Gui, %GN%:Show, Hide, NotifyGui
 Gui  %GN%:+LastFound
 WinGetPos, GX, GY, GW, GH
 Gui, %GN%:Add, Text, x0 y0 w%GW% h%GH% g_Notify_Action BackgroundTrans
 If (GR)
  WinSet, Region, % "0-0 w" GW " h" GH " R" GR "-" GR
 If (GT)
  WinSet, Transparent, % GT

 SysGet, Workspace, MonitorWorkArea
 NewX := WorkSpaceRight-GW-5
 If (OtherY)
  NewY := OtherY-GH-5
 Else
  NewY := WorkspaceBottom-GH-5
 If NewY < % WorkspaceTop
  NewY := WorkspaceBottom-GH-5

 Gui, %GN2%:-Caption +ToolWindow +AlwaysOnTop -Border +E0x20
 Gui, %GN2%:Color, %BC%
 Gui  %GN2%:+LastFound
 If (BR)
  WinSet, Region, % "0-0 w" GW+(BW*2) " h" GH+(BW*2) " R" BR "-" BR
 If (BT)
  WinSet, Transparent, % BT

 Gui, %GN2%:Show, % "Hide x" NewX-BW " y" NewY-BW " w" GW+(BW*2) " h" GH+(BW*2)
 Gui, %GN%:Show,  % "Hide x" NewX " y" NewY, NotifyGui
 Gui  %GN%:+LastFound
 If SI
  DllCall("AnimateWindow","UInt",WinExist(),"Int",SI,"UInt","0x00040008")
 Else
  Gui, %GN%:Show, NA, NotifyGui
 Gui, %GN2%:Show, NA
 WinSet, AlwaysOnTop, On

 If Duration < 0
  Exit := GN
 If (Duration)
   SetTimer, % "_Notify_Kill_" GN - GF + 1, % - Abs(Duration) * 1000
 Else
  SetTimer, % "_Notify_Flash_" GN - GF + 1, % BF

Return % GN

;==========================================================================
;========================================== when a notification is clicked:
_Notify_Action:
 ;Critical
 SetTimer, % "_Notify_Kill_" A_Gui - GF + 1, Off
 Gui, % A_Gui + GL - GF + 1 ":Destroy"
 Gui  %A_Gui%:+LastFound
 If SC
  DllCall("AnimateWindow","UInt",WinExist(),"Int",SC,"UInt", "0x00050001")
 Gui, %A_Gui%:Destroy
 If (ActionList)
  Loop,Parse,ActionList,|
   If ((Action := SubStr(A_LoopField,1,2)) = A_Gui)
   {
    Temp_Notify_Action:= SubStr(A_LoopField,4)
    StringReplace, ActionList, ActionList, % "|" A_Gui "=" Temp_Notify_Action, , All
    If IsLabel(_Notify_Action := Temp_Notify_Action)
     Gosub, %_Notify_Action%
    _Notify_Action =
    Break
   }
 StringReplace, NotifyList, NotifyList, % "|" GN, , All
 SetTimer, % "_Notify_Flash_" A_Gui - GF + 1, Off
 If (Exit = A_Gui)
  ExitApp
Return

;==========================================================================
;=========================================== when a notification times out:
_Notify_Kill_1:
_Notify_Kill_2:
_Notify_Kill_3:
_Notify_Kill_4:
_Notify_Kill_5:
_Notify_Kill_6:
_Notify_Kill_7:
_Notify_Kill_8:
_Notify_Kill_9:
_Notify_Kill_10:
_Notify_Kill_11:
_Notify_Kill_12:
_Notify_Kill_13:
_Notify_Kill_14:
_Notify_Kill_15:
_Notify_Kill_16:
_Notify_Kill_17:
_Notify_Kill_18:
_Notify_Kill_19:
_Notify_Kill_20:
_Notify_Kill_21:
_Notify_Kill_22:
_Notify_Kill_23:
_Notify_Kill_24:
_Notify_Kill_25:
 ;Critical
 StringReplace, GK, A_ThisLabel, _Notify_Kill_
 SetTimer, _Notify_Flash_%GK%, Off
 GK += GF - 1
 Gui, % GK + GL - GF + 1 ":Destroy"
 Gui  %GK%:+LastFound
 If ST
  DllCall("AnimateWindow","UInt",WinExist(),"Int",ST,"UInt", "0x00050001")
 Gui, %GK%:Destroy
 StringReplace, NotifyList, NotifyList, % "|" GK
 If (Exit = GK)
  ExitApp
Return

;==========================================================================
;======================================== flashes a permanent notification:
_Notify_Flash_1:
_Notify_Flash_2:
_Notify_Flash_3:
_Notify_Flash_4:
_Notify_Flash_5:
_Notify_Flash_6:
_Notify_Flash_7:
_Notify_Flash_8:
_Notify_Flash_9:
_Notify_Flash_10:
_Notify_Flash_11:
_Notify_Flash_12:
_Notify_Flash_13:
_Notify_Flash_14:
_Notify_Flash_15:
_Notify_Flash_16:
_Notify_Flash_17:
_Notify_Flash_18:
_Notify_Flash_19:
_Notify_Flash_20:
_Notify_Flash_21:
_Notify_Flash_22:
_Notify_Flash_23:
_Notify_Flash_24:
_Notify_Flash_25:
 StringReplace, FlashGN, A_ThisLabel, _Notify_Flash_
 FlashGN += GF - 1
 FlashGN2 := FlashGN + GL - GF + 1
 If Flashed%FlashGN2% := !Flashed%FlashGN2%
  Gui, %FlashGN2%:Color, Silver
 Else
  Gui, %FlashGN2%:Color, Black
Return

;==========================================================================
;============================= wait (or force) for a notification to close:
_Notify_Wait_:
 ;Critical
 If (Image)
 {
  Gui %Image%:+LastFound
  If NotifyGuiID := WinExist()
  {
   WinWaitClose, , , % Abs(Duration)
   If (ErrorLevel && Duration < 1)
   {
    Gui, % Image + GL - GF + 1 ":Destroy"
    DllCall("AnimateWindow","UInt",NotifyGuiID,"Int",ST,"UInt", "0x00050001")
    Gui, %Image%:Destroy
   }
  }
 }
 Else
  Notify("No Notification specified to wait for!"
,"waiting for all notifications is not yet implemented"
,10,"IN=8",A_WinDir "\explorer.exe")
Return
}


gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
new version, new parameter "Recompile" in first post... pulled back out Notify() so you can use it script-side, or whatever user feedback method you prefer

here's how i use it with Recompile:
#SingleInstance Force
SetWorkingDir, %A_ScriptDir%
If !A_IsCompiled              ; not necessary
 Notify("Compiling...",A_ScriptName,0) ; not necessary
Compile("Run")   ;this will close the .ahk after compiling, and run the .exe
Return ;end autoexecute section

^+F12::Compile("Recompile") ; this will close the .exe and run the .ahk

so "Recompile" makes ctrl-shift-F12 act as Reload hotkey, which really runs the .ahk of the same name, and closes this running .exe... the called .ahk then calls "Run" which does the opposite, and you're back to the updated .exe!

KooKsTeR
  • Members
  • 157 posts
  • Last active: Aug 21 2015 09:55 PM
  • Joined: 19 Feb 2010
gwarble this is really cool!

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
thanks... I'm glad u like it

I always like to here how and why people use my stuff, if u care to share

- gwarble

KooKsTeR
  • Members
  • 157 posts
  • Last active: Aug 21 2015 09:55 PM
  • Joined: 19 Feb 2010
I did a search and found this and was dude sweet!!! and I was seeing the lack of posts and was like dang this is seriously under noticed and used.

Hey would it be cool if i included parts of this in a possible program/script of mine im working on? Credit will be given of coarse. Im starting a text editor for ahk scripts. Yes I know there are many out there already. But here is a list of features I have plans to include:
-open
-save
-support to have multiple files opened at once (tabs)
-find/replace
-find/replace in selected text
-play/pause the current script
-stop the current script
-compile the current script

awannaknow
  • Members
  • 372 posts
  • Last active: Mar 03 2019 05:18 AM
  • Joined: 14 Jun 2009
It may seems obvious to the script creator but sometimes it'll be very helpful to have examples of what can be done with a script.
As it is the case for me about this one . . .
:oops:

I did a search and found this and was dude sweet!!! and I was seeing the lack of posts and was like dang this is seriously under noticed and used.