Jump to content

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

Visual Basic Script support in AutoHotKey


  • Please log in to reply
54 replies to this topic
Nemroth
  • Members
  • 278 posts
  • Last active: Dec 31 2011 10:53 PM
  • Joined: 07 Sep 2004

Thanks guys, I greatly appreciate everyone that is helping on this.


Me too. Thanks a lot. :D

corrupt
  • Members
  • 2558 posts
  • Last active: Nov 01 2014 03:23 PM
  • Joined: 29 Dec 2004
Although it may not work for what is requested... Script Encoder

Nemroth
  • Members
  • 278 posts
  • Last active: Dec 31 2011 10:53 PM
  • Joined: 07 Sep 2004

Although it may not work for what is requested... Script Encoder


Thanks for the link. I downloaded (a long time ago, I must say, when I was under W98) WSH but I never seen that. I will test it to see if it can be used elsewhere than in a web page (in a "local" VBScript). I thought too that to protect the code, it would be possivle to use a temp file, but with a RAM-Disk. I don't know if it is possible at my work (if my boss would let me install a RAM Disk...) As soon as a file is deleted from a RAM-Disk, it can't be retreived. It's an alternative way to protect the code. Thank for sharing your research results.

savage
  • Members
  • 207 posts
  • Last active: Jul 03 2008 03:12 AM
  • Joined: 02 Jul 2004
Instead of making a Othersyntax command, I think it would be better if ahk supported file-here notation - this would have more general usage. This could be supported by a dll that hosts an ActiveScript engine - allowing the usage of all ActiveScript compatible scripting languages -Perl, Python, VbScript, JScript, RubyScript and others. Then you'd have wrapper functions for the dll - like with the perl interface.

File-here is like this -

var = << EOF
#some ruby code
class Blah
      def sneeze(duration)
           puts "Ach" + ("o" * duration)
      end
end
EOF

ActiveEval(var,"RubyScript")

Basically everything between the << EOF (which can be any word)
and it's counter part is totally excluded from parsing by ahk - so you can use quotes and such freely, except maybe for %variable%. Avoiding the need for escapes would greatly ease the use of other scripting languages. The contents of these blocks would be stuck into whatever variable they would be pointed at. Maybe the syntax could leave off the = as well.

I'll look at making the dll.

EDIT:
F*ck this. Leave it up to M$ to write a completely unusable api. Practically no documentation and waaay to much code to just tack on an ActiveScript site. If someone more comfortable with c++ wants to take a stab at it
http://www.codeproje...cscripthost.asp seems to be a good resource.

EDIT:
NYAHAHAHAHA! :D 8) I WIN!

Put this in peval.vbs
Dim StdIn, script
script = ""
Set StdIn = WScript.StdIn
Do While Not StdIn.AtEndOfStream
    script = script + StdIn.ReadLine
Loop
execute script

Here's an example:
F1::
    text := RunVBS("WScript.echo ""howdy""")
    Msgbox, %text%
return

;CMDRet functions
RunWaitEx(CMD, CMDdir, CMDin, ByRef CMDout, ByRef CMDerr)
{
  VarSetCapacity(CMDOut, 100000)
  VarSetCapacity(CMDerr, 100000)
  RetVal := DllCall("cmdret.dll\RunWEx", "str", CMD, "str", CMDdir, "str", CMDin, "str", CMDout, "str", CMDerr)
  Return, %RetVal%
}

Capture(CMD, input)
{
    CMDOUT =
    CMDERR =
    RunWaitEx(CMD, a_scriptdir, input, CMDOUT, CMDERR)
    return %CMDOUT%
}

;let's run some vbscript stuff
RunVBS(script)
{
    return Capture("cscript.exe peval.vbs",script)
}

It uses CMDRet and a pipe-reading vbscript to do it. Basically you pipe the script you want to run into peval.vbs and IT runs the code in execute(). Doesn't need a special dll, and doesn't need a temporary file. Just needs CMDRet.dll and peval.vbs.

So lets look at what this would look like with CMDRet built into AHK, and file-here syntax added :

adminstuff = << EOF
Option Explicit

Dim FSO
Dim Services
Dim SecDescClass
Dim SecDesc
Dim Trustee
Dim ACE
Dim Share
Dim InParam
Dim Network

Const FolderName = "C:\Public"
Const AdminServer = "\\AdminMachine"
Const ShareName = "Pubs"
Const PrinterShare = "\\CorpPrinters\PrinterShare"

' First we add a printer to this machine and make it the default.

Set Network = CreateObject("Wscript.Network")
Network.AddWindowsPrinterConnection PrinterShare
Network.SetDefaultPrinter PrinterShare

' Next we create a folder and populate it with some files.

Set FSO = CreateObject("Scripting.FileSystemObject")
If Not FSO.FolderExists(FolderName) Then 
   FSO.CreateFolder(FolderName)
End If

Call FSO.CopyFile(AdminServer & "\Public\Images\*.*", FolderName)

' Make the folder into a share using WMI
' See the WMI SDK for information on how this code works.

Set Services = GetObject("WINMGMTS:{impersonationLevel=impersonate,(Security)}!" & AdminServer & "\ROOT\CIMV2")
Set SecDescClass = Services.Get("Win32_SecurityDescriptor")
Set SecDesc = SecDescClass.SpawnInstance_()
Set Trustee = Services.Get("Win32_Trustee").SpawnInstance_
Trustee.Domain = Null
Trustee.Name = "EVERYONE"
Trustee.Properties_.Item("SID") = Array(1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0)
Set ACE = Services.Get("Win32_Ace").SpawnInstance_
ACE.Properties_.Item("AccessMask") = 2032127
ACE.Properties_.Item("AceFlags") = 3
ACE.Properties_.Item("AceType") = 0
ACE.Properties_.Item("Trustee") = Trustee
SecDesc.Properties_.Item("DACL") = Array(ACE)
Set Share = Services.Get("Win32_Share")
Set InParam = Share.Methods_("Create").InParameters.SpawnInstance_()
InParam.Properties_.Item("Access") = SecDesc
InParam.Properties_.Item("Description") = "Public Share"
InParam.Properties_.Item("Name") = ShareName
InParam.Properties_.Item("Path") = FolderName
InParam.Properties_.Item("Type") = 0
Share.ExecMethod_("Create", InParam)
EOF

RunVBS(adminstuff)

RunVBS(script)
{
    return Capture("cscript.exe peval.vbs",script)
}

There's little weird syntax and it's readily adaptable to a variety of scripting languages and other programs.

And python and ruby both support piping scripts into them, so there's those working with no trouble. Come to think of it, embedding ActiveScript probably wouldn't be the answer anyway, because you would lose the functionality of WSH, leaving vbscript considerably less useful.

Here's a quick example for piping scripts to ruby.

F2::
text := Capture("ruby", 
(
"class Blah
      def sneeze(duration)
           puts ""Ach"" + (""o"" * duration)
      end
end
Blah.new.sneeze(5)") 
)
    Msgbox, %text%
return


Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004

I think it would be better if ahk supported file-here notation - this would have more general usage.

...[the text] is totally excluded from parsing by ahk

Have you seen the recently-added continuation section? Hopefully it is very close to what you had in mind.

Avoiding the need for escapes would greatly ease the use of other scripting languages.

By default, only percent signs and accents need to be escaped inside a continuation section. But those can be avoided too via the section's options.

http://www.codeproject.com/com/mfcscripthost.asp seems to be a good resource

Great link. I'm definitely going to take a close look at it.

Put this in peval.vbs
...
Here's an example:
...
text := RunVBS("WScript.echo ""howdy""")

Great demonstration and proof of concept. With this in hand, one path toward the integration of external scripting languages becomes clearer, and cmdret is also of great value.

Come to think of it, embedding ActiveScript probably wouldn't be the answer anyway, because you would lose the functionality of WSH, leaving vbscript considerably less useful.

I could use more detail about this because I know so little about WSH vs. ActiveScript.

Thanks for sharing your work and discoveries!

savage
  • Members
  • 207 posts
  • Last active: Jul 03 2008 03:12 AM
  • Joined: 02 Jul 2004
Well, the short version is that vbscript is useless on its own. It gets all of its ability to actually do things from its host application. The ability to use vbscript to manipulate the registry, use com objects, etc comes from the Windows Script Host (WSH), which basically is an ActiveScript host hooked to a back end that interacts with the operating system. There's no way that I know of to interact with WSH without using cscript.exe or wscript.exe. Basically, just embedding an ActiveScript engine or, more accurately, making some part of AHK an ActiveScript site, would allow you to expose the functionality of AHK to ActiveScript languages (this may be useful on its own), but wouldn't allow you to, say, use WSH from within AHK without using an external executable. And since the WSH programs only take scripts in files rather than pipes, I think the only way to get it's functionality in AHK would be to use the pipe.

I just played with continuation sections again and found that they do work the way I wanted in commands but they don't seem to work without quotes in the context of function calls or other expressions.

To use one in a function call this is what I got:

text := Capture("ruby", 
(
"class Blah
      def sneeze(duration)
           puts ""Ach"" + (""o"" * duration)
      end
end
Blah.new.sneeze(5)"
))
Note all the quotation marks

Using it in a command I can do this:

Msgbox, 
(
    class Blah
      def sneeze(duration)
           puts "Ach" + ("o" * duration)
      end
    end
    Blah.new.sneeze(5)
)
Notice the lack of quotes. This way works fine, though I think file-here is a little easier to read. If continuation sections worked the same in expressions as they do in commands, or if there was a way to assign a continutation section directly to a variable, they would do nicely for this.

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
Thanks for the extra details about WSH.

[continuation sections] don't seem to work without quotes in the context of function calls or other expressions.

This is because a continuation section joins lines together at a very early stage. It has no knowledge of expressions or parameters; all it sees is raw text.

if there was a way to assign a continutation section directly to a variable, they would do nicely for this.

It's already possible:

var =
(
Every line here is treated literally.
Only percent signs and accents need to be escaped, which
can be avoided by adding %` after the open-parenthesis.
)

Until something better comes along, this will probably be the preferred means of having scripts contain other scripts.

Thanks again for posting your proof of concept.

savage
  • Members
  • 207 posts
  • Last active: Jul 03 2008 03:12 AM
  • Joined: 02 Jul 2004
Okay, I tried assigning a continuation to a variable earlier and it didn't work right. I just tried again using your example and it works fine. I must have just put the parentheses in the wrong place. This works well then, you can put in your code with almost no alteration.

AHKnow
  • Members
  • 121 posts
  • Last active: May 17 2009 09:11 PM
  • Joined: 03 Jul 2004
Savage, I like the concept.

Obviously, CMDret would have to be built in to make this method as viable as using Fileappend.

I was still hoping for perhabs:

. Some syntax specific to the purpose of running other scripts

. No temp files

. No other files needed, except the "other" .exe that will run the "other" script syntax and commands. Though CMDret (and hopefully becomes part of AHK) and peval.vbs are great.

daonlyfreez
  • Members
  • 995 posts
  • Last active: Jan 23 2013 08:16 AM
  • Joined: 16 Mar 2005
@savage: Excellent! :)

I have been trying something equal with a temporary vbs-piping-file, but your version is way better 8)

It may be possible to use SendMessage from VBScript to get data back to the AHK script with OnMessage on runtime... Ideally one would be able to add VBScript scripts/functions to the VBS-stack at runtime, and call/unload them directly, so, not the whole loaded 'scriptlets', but a particular function.

Much like what is possible with JavaScript, for example thru the address bar already. Any functions you write and load thru the address bar are added to the loaded JavaScripts of that page. You can have full control if you want.

Getting data back from JavaScript might also be a good 'hack' to work on.

A message-box, or a dedicated browser window are not very elegant, let alone a cookie... just as much as using temporary files isn't very elegant either :wink: ... Some sort of SendMessage from JavaScript? Seems impossible...

I'm very busy at the moment, and I doubt I will have much time diving into this subject, moreover, since I'm an absolute (Visual) Basic (Script) syntax loather :p , why do I bother in the first place... :wink:

No, will post available results...
Posted Image mirror 1mirror 2mirror 3ahk4.me • PM or Posted Image