AHK.Interop/AHK.Dll - embed scripts in .resx Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
burque505
Posts: 1736
Joined: 22 Jan 2017, 19:37

AHK.Interop/AHK.Dll - embed scripts in .resx

10 Feb 2017, 19:21

Hi, I'd like to embed some AHK files as resources in a Visual Studio VB.Net program, so I can run the script(s) without (hopefully) having to add " & vbLf &" to each line of the scripts, and double-quoting things like "Word.Application" in scripts which are hundreds of lines long. I'm also hoping the script(s) won't need extracting to the filesystem before being run.

Can anyone help me with the right syntax to call the scripts once added to the .Net program as resources?

Maybe an example of what I'm trying to do would explain better than I can. Here's code that runs in a WinForm just fine:

Code: Select all

Imports AutoHotkey.Interop
Public Class Form1
    Public ahkWord As Object
    Public iOp = AutoHotkeyEngine.Instance
    Public ahk = CreateObject("AutoHotkey.Script")
    Private Sub btnWord_Click(sender As Object, e As EventArgs) Handles btnWord.Click
        SendAHKeys()
    End Sub
    Sub SendAHKeys()
        'Dim ahkWord As Object
        ahk.ahktextdll("ahkWord := ComObjCreate(""Word.Application"")" & vbLf &
                        "ahkWord.Documents.Add" & vbLf &
                        "ahkWord.Visible := 1, ahkWord.Activate" & vbLf &
                        "FilePath := ""C:\test\AHK_test\WL-RTF.docx""" & vbLf &
                        "oDoc := ComObjGet(FilePath)" & vbLf &
                        "Sleep, 100" & vbLf &
                        "oDoc.Range.FormattedText.Copy" & vbLf &
                        "oDoc.Close(0)" & vbLf &
                        "WinActivate, ahkWord" & vbLf &
                        "Send, ^v" & vbLf &
                        "Send, {Backspace}")


    End Sub
End Class
For the sake of example, in the above instance I would want to call a script (let's call it AHKTest.ahk) that looks like this (there's an RTF file called RTFFile.rtf in .resx also),
instead of typing it in the VS code as above:

Code: Select all

ahkWord := ComObjCreate(""Word.Application"") ; do I still need the double quotes if I'm calling the script  from .resx?
ahkWord.Documents.Add
ahkWord.Visible := 1, ahkWord.Activate
FilePath := ""?????????"""				;what do I use for the filepath? My.Resources.RTFFile? Does it need quotes?
	oDoc := ComObjGet(FilePath)
        Sleep, 100
        oDoc.Range.FormattedText.Copy
        oDoc.Close(0)
        WinActivate, ahkWord
        Send, ^v
        Send, {Backspace}
Also, if the .ahk script I'm calling has #INCLUDES, how would I handle that?

I know I'm asking a lot here, and I really appreciate you taking the time to look at it.
burque505
Posts: 1736
Joined: 22 Jan 2017, 19:37

Re: AHK.Interop/AHK.Dll - embed scripts in .resx

11 Feb 2017, 11:59

Okay, some success. Far from complete, yet a good start. My VB.NET program is using an embedded AHK script to show a messagebox (from AHK) with "HelloWorld".
So far it won't run twice in a row, maybe because I don't have #SingleInstance Force in the HelloWorld.AHK file. I'll try that soon.
(It occurs to me that another thing I could do is compile the AHK file, and embed the .exe as a resource. One thing at at a time, though...)

I haven't answered my own question yet, though, because I still don't know how to get #INCLUDES into the mix. Any and all help greatly appreciated.

Helpful links are: http://stackoverflow.com/questions/8851 ... -resources
and http://stackoverflow.com/questions/1003 ... -to-string.

1) I used Method 1 from first post to get HelloWorld.ahk into My.Resources.
2) Public ahk = AutoHotkeyEngine.Instance

From the second post, I got "Public script As String = Encoding.UTF8.GetString(My.Resources.HelloWorld)".
As I understand it (however dimly), HelloWorld.ahk gets stored in .resx as type "System.Byte[]". The line above gets it out of that byteArray into a string.
That lets me use it as a script to pass to either the DLL or the Interop.

I'm experimenting with both AutoHotkey.DLL and AutoHotkey.Interop, so I hope what I'm trying to do is clear from the code below.
It's just a VB.NET Winform with one button.

Code: Select all

Imports AutoHotkey.Interop
Imports System.IO
Imports System.Text
Public Class Form1
    Public ahk = AutoHotkeyEngine.Instance
    Public ahkscript = CreateObject("AutoHotkey.Script")
    Public script As String = Encoding.UTF8.GetString(My.Resources.HelloWorld)

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        'This gets a String from a System.Byte[] array, which Is what scripts are in .resx
        'ahkscript.ahktextdll("var = " & script) 'This works for some reason, even though I don't do anything with "var" except assign it; I found it by accident, and it seems kludgey.
        ahk.ExecRaw(script) 'This works, and accomplishes my purpose of not having to quote anything in the parameter.
    End Sub
End Class
burque505
Posts: 1736
Joined: 22 Jan 2017, 19:37

Re: AHK.Interop/AHK.Dll - embed scripts in .resx

11 Feb 2017, 17:17

Great, thank you! I'll try that now.
By the way, the following script so far works better. In the line with "ahkscript.ahktextdll("" & script), I tried it without the empty quotes and it doesn't work.
With the ExecRaw() version above, I could only click the button once before getting a System.Reflection exception.

Imports AutoHotkey.Interop
Imports System.IO
Imports System.Text
Public Class Form1
Public ahk = AutoHotkeyEngine.Instance
Public ahkscript = CreateObject("AutoHotkey.Script")
'This gets a String from a System.Byte[] array, which Is what scripts are in .resx
Public script As String = Encoding.UTF8.GetString(My.Resources.PUMtest)

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

Try
ahkscript.ahktextdll("" & script)
Catch ex As Exception
MessageBox.Show("Unknown exception")
End Try

End Sub
End Class

I'm very encouraged, thanks again.
burque505
Posts: 1736
Joined: 22 Jan 2017, 19:37

Re: AHK.Interop/AHK.Dll - embed scripts in .resx

11 Feb 2017, 17:59

HotKeyIt, thanks. I used the PUM test suite as a guinea pig. I changed the #Include statements in test.ahk to:
#Include <PUM>
#Include <PUM_API>
and renamed the file "test2.ahk".
I added "test2.ahk" to the Resources via the Project->Resources menu.
I did not embed the libraries, as I was unable to get them to work so far except this way (if you embed them, I think they become System.Byte[]. I haven't figured out a workaround yet.)
I tried leaving the libs in Path-to-Autohotkey (i.e. on my system C:\AutoHotkey\Lib), but they were not found. In all fairness, the documentation says "A script may call a function in an external file without having to use #Include." This seems to contradict the statement "path-to-the-currently-running-AutoHotkey.exe\LIB\ ; Resource library saved in resources of executable.", as what's running here is the DLL, correct? I do have the libraries working, but they are not strictly "saved in resources of executable", but are external to the resources and the executable.

Then I put the libraries in (VS-Path-to-debug-exe)\LIB.

Then this code works. I click the button, and the PUM test suite pops up.

Imports AutoHotkey.Interop
Imports System.IO
Imports System.Text
Public Class Form1
Public ahk = AutoHotkeyEngine.Instance
Public ahkscript = CreateObject("AutoHotkey.Script")
'This gets a String from a System.Byte[] array, which Is what scripts are in .resx
Public script As String = Encoding.UTF8.GetString(My.Resources.test2)

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

Try
ahkscript.ahktextdll("" & script)
Catch ex As Exception
MessageBox.Show("Unknown exception")
End Try

End Sub
End Class

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Descolada, Jimmysan and 146 guests