Help convert this VBScript to AHK

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
XJDHDR
Posts: 15
Joined: 30 Nov 2014, 23:44

Help convert this VBScript to AHK

15 May 2018, 04:49

I would like some help if possible to convert the following VBScript into an AutoHotkey script:

Code: Select all

'Retrieves launcher/client path from .ini or ask user to point them
	gameLauncher = ReadIni(iniFile, "General", "Launcher")
	if gameLauncher = "" or gameLauncher = " " Then
		MSGBOX "Select the LAUNCHER please"
		WriteIni scriptDir & iniFile, "General", "Launcher", BrowseForFile()
		gameLauncher = ReadIni(iniFile, "General", "Launcher")
	end if
	
	gameClient = ReadIni(iniFile, "General", "Client")
	if gameClient = "" or gameClient = " " Then
		MSGBOX "Select the CLIENT please"
		WriteIni scriptDir & iniFile, "General", "Client", BrowseForFile()
		gameClient = ReadIni(iniFile, "General", "Client")
	end if
	
	
'Divide the full path into two variables containing respectively
'only the .exe and only the path without the .exe
	Set objFile = oFSO.GetFile(gameLauncher)
	lName = objFile.Name
	lPath = objFile.Path
	lPath = Left(lPath, Len(lPath)-Len(lName))
	
	Set objFile = oFSO.GetFile(gameClient)
	cName = objFile.Name
	cPath = objFile.Path
	cPath = Left(cPath, Len(cPath)-Len(cName))
		
'Here comes the script	
	scriptHome = WScript.ScriptFullName
	scriptHome = Left(scriptHome, InStr(scriptHome, WScript.ScriptName) - 1)

	WScript.Echo "[1/5] starting laucher"
	SET objShell = WScript.CreateObject("Shell.Application")
	objShell.ShellExecute lName, "", lPath

	WScript.Echo "[2/5] waiting for launcher to start game..."
	SET objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
	DO WHILE TRUE
		SET objInstanceList = objWMIService.ExecQuery("Select * from Win32_Process Where Name = '" & cName & "'")
		FOR EACH objInstance IN objInstanceList
		WScript.Echo "[3/5] game instance detected"
		commandLine = objInstance.CommandLine
 
		WScript.Echo "[4/5] killing game instance"
		objInstance.Terminate()
		EXIT DO
		NEXT
		WScript.Sleep 1000
	LOOP

	commandLine = Right(commandLine, Len(commandLine) - (InStr(1, commandLine, """ ") + 1))

	WScript.Echo "[5/5] starting game again"
	SET objShell = CreateObject("Shell.Application")
	objShell.ShellExecute cName, commandLine, cPath
I didn't include the contents of the "ReadIni" or "WriteIni" functions because AHK has native support for INI files.
I can see how most of the commands can be converted to AHK equivalents but I'm puzzled on what exactly these lines are doing:

Code: Select all

SET objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
commandLine = objInstance.CommandLine
I'm assuming the second line is grabbing the command line arguments that were passed to a particular program. If this is the case, then can one even do that in an AHK script?

If anyone can help me out, I would greatly appreciate it.
User avatar
TLM
Posts: 1608
Joined: 01 Oct 2013, 07:52
Contact:

Re: Help convert this VBScript to AHK

15 May 2018, 12:00

Please post your AutoHotkey code.
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: Help convert this VBScript to AHK

15 May 2018, 13:04

XJDHDR wrote:I can see how most of the commands can be converted to AHK equivalents but I'm puzzled on what exactly these lines are doing:

Code: Select all

SET objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
commandLine = objInstance.CommandLine
I'm assuming the second line is grabbing the command line arguments that were passed to a particular program. If this is the case, then can one even do that in an AHK script?
GetObject is aquivalent to ComObjActive and ComObjCreate in AutoHotkey. Most things that VBA can do then AHK can do. At their heart, both are scripting languages that tap into underlying Windows componets.

This VBA script does not look complete (oFSO for example is not defined) but it looks like it is starting a gameLauncher, waiting for it to open, getting its command line parameters, close it, then starting a gameClient using part of those parameters. That all seems very doable with AHK.

The AHK code would be similar; command names a little different and different syntax.

There are also options to run VBA macros, vbs files, or actual VBA code from within AHK.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
XJDHDR
Posts: 15
Joined: 30 Nov 2014, 23:44

Re: Help convert this VBScript to AHK

15 May 2018, 14:16

Thanks for the help. This is the AHK code I currently have:

Code: Select all

; Recommended settings for performance
#NoEnv
ListLines, Off
DetectHiddenWindows, On

; Retrieves launcher/client path from .ini or ask user to point them
IniRead, sGameLauncher, %A_ScriptDir%\SteamOverlayFix.ini, General, Launcher,
If (sGameLauncher = "") Or (sGameLauncher = " ")
{
	MsgBox, Please select the location of the game's launcher.
	FileSelectFile, sSelectedFile, 3, %A_ScriptDir%\, Please select the location of the game's launcher, Executables (*.exe)
	IniWrite, %sSelectedFile%, %A_ScriptDir%\SteamOverlayFix.ini, General, Launcher
	IniRead, sGameLauncher, %A_ScriptDir%\SteamOverlayFix.ini, General, Launcher,
}

IniRead, sGameClient, %A_ScriptDir%\SteamOverlayFix.ini, General, Client,
If (sGameClient = "") Or (sGameClient = " ")
{
	MsgBox, Please select the location of the game's Client.
	FileSelectFile, sSelectedFile, 3, %A_ScriptDir%\, Please select the location of the game's Client, Executables (*.exe)
	IniWrite, %sSelectedFile%, %A_ScriptDir%\SteamOverlayFix.ini, General, Client
	IniRead, sGameClient, %A_ScriptDir%\SteamOverlayFix.ini, General, Client,
}


; Divide the full path into two variables containing respectively
; only the .exe and only the path without the .exe
SplitPath, sGameLauncher , sLauncherName, sLauncherPath, 
SplitPath, sGameClient , sClientName, sClientPath, 


; Here comes the script
OutputDebug, [1/5] starting laucher
Run, %sGameLauncher%, 

OutputDebug, [2/5] waiting for launcher to start game...
; Translation of  SET objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
WinWait, ahk_exe %sClientName%,
WinGet, iClientPID, PID, ahk_exe %sClientName%,
While(iClientPID <> 0)
{
	OutputDebug, [3/5] game instance detected
	; Translation of sGameCommandLine = objInstance.CommandLine
	
	OutputDebug, [4/5] killing game instance
	WinKill, ahk_pid %iClientPID%,
	Sleep 1000
	WinGet, iClientPID, PID, ahk_exe %sClientName%,
}

; Translation of commandLine = Right(commandLine, Len(commandLine) - (InStr(1, commandLine, """ ") + 1))
OutputDebug, [5/5] starting game again
Run, "%sGameClient%" %commandLine%, 
I am not very familiar with COM Objects or how AHK uses them so I can't currently figure out how to make three of the commands work in AHK syntax.
FanaticGuru wrote:... but it looks like it is starting a gameLauncher, waiting for it to open, getting its command line parameters, close it, then starting a gameClient using part of those parameters.
That was my interpretation of the script as well.
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: Help convert this VBScript to AHK

15 May 2018, 17:15

XJDHDR wrote:I am not very familiar with COM Objects or how AHK uses them so I can't currently figure out how to make three of the commands work in AHK syntax.
Here is an equivalent example to some of the tricker VBA code:

Code: Select all

cName := "notepad.exe"
objWMIService := ComObjGet("winmgmts:")
Loop
{
	for objInstance in objWMIService.ExecQuery("Select * from Win32_Process where Name='" cName "'")
		break 2
	Sleep 1000
}
commandLine := objInstance.CommandLine
objInstance.Terminate
MsgBox % "Found:`t" cName "`nCommand Line:`t" commandLine
This code will loop every second querying for a process named "notepad.exe". As soon as it is detected the loop is broken, the commandLine is saved, the process is terminated, and some results info is shown.

Simplified some of the flow commands and took out the {impersonationLevel=impersonate}!\\.\root\cimv2 which looks like all optional defaults.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
XJDHDR
Posts: 15
Joined: 30 Nov 2014, 23:44

Re: Help convert this VBScript to AHK

16 May 2018, 01:45

Thanks for the help so far everyone. I have written my script to the point where it will grab the Command Line arguments and put it into a message box. Unfortunately, I am currently getting an error once the game's launcher launches the game.
The error message says:
Error: 0x80020006 - Unknown name.

Specifically: CommandLine
And it points to Line 41 which contains:

Code: Select all

sGameClientCommandLine := objGameInstance.CommandLine
Here is the script as I currently have it:

Code: Select all

; Recommended settings for performance
#NoEnv
ListLines, Off
DetectHiddenWindows, On

; Retrieves launcher/client path from .ini or ask user to point them
IniRead, sGameLauncher, %A_ScriptDir%\SteamOverlayFix.ini, General, Launcher,
If (sGameLauncher = "") Or (sGameLauncher = " ")
{
	MsgBox, Please select the location of the game's launcher.
	FileSelectFile, sSelectedFile, 3, %A_ScriptDir%\, Please select the location of the game's launcher, Executables (*.exe)
	IniWrite, %sSelectedFile%, %A_ScriptDir%\SteamOverlayFix.ini, General, Launcher
	IniRead, sGameLauncher, %A_ScriptDir%\SteamOverlayFix.ini, General, Launcher,
}

IniRead, sGameClient, %A_ScriptDir%\SteamOverlayFix.ini, General, Client,
If (sGameClient = "") Or (sGameClient = " ")
{
	MsgBox, Please select the location of the game's Client.
	FileSelectFile, sSelectedFile, 3, %A_ScriptDir%\, Please select the location of the game's Client, Executables (*.exe)
	IniWrite, %sSelectedFile%, %A_ScriptDir%\SteamOverlayFix.ini, General, Client
	IniRead, sGameClient, %A_ScriptDir%\SteamOverlayFix.ini, General, Client,
}


; Divide the full path into two variables containing respectively
; only the .exe and only the path without the .exe
SplitPath, sGameLauncher , sLauncherName, sLauncherPath, 
SplitPath, sGameClient , sClientName, sClientPath, 


; Here comes the script
OutputDebug, [1/5] starting laucher
Run, %sGameLauncher%, 

OutputDebug, [2/5] waiting for launcher to start game...
WinWait, ahk_exe %sGameClient%,
OutputDebug, [3/5] game instance detected
WinGet, iGameClientPID, PID,
objGameInstance := ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process where ProcessID='" iGameClientPID "'")
sGameClientCommandLine := objGameInstance.CommandLine
OutputDebug, [4/5] killing game instance
WinKill,

; Translation of commandLine = Right(commandLine, Len(commandLine) - (InStr(1, commandLine, """ ") + 1))
OutputDebug, [5/5] starting game again
;Run, "%sGameClient%" %commandLine%, 
MsgBox, %sGameClientCommandLine%
It is mostly the same as before except with FanaticGuru's contributions added with a few changes (specifically, using the WinWait command instead of the query process loop, using PID with ExecQuery instead of Process Name and using the WinKill command instead of Terminate).
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: Help convert this VBScript to AHK

16 May 2018, 13:39

XJDHDR wrote:It is mostly the same as before except with FanaticGuru's contributions added with a few changes (specifically, using the WinWait command instead of the query process loop, using PID with ExecQuery instead of Process Name and using the WinKill command instead of Terminate).

Code: Select all

objGameInstance := ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process where ProcessID='" iGameClientPID "'")
This does not return an instance, this returns a collection of instances. Even though you are using PID and there should only be one process found, it is returned as a collection never the less; a collection with only one member. A collection is a type of array.

You could do this to get a member instance:

Code: Select all

Collection := ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process where ProcessID='" iGameClientPID "'")
Collection._NewEnum.Next(objGameInstance) ; enumerate collection and get next/first member and store in objGameInstance
You can also condense all in one line:

Code: Select all

ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process where ProcessID='" iGameClientPID "'")._NewEnum.Next(objGameInstance)
You could also do a for/loop to get the first (technically last) member of the collection:

Code: Select all

for objGameInstance in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process where ProcessID='" iGameClientPID "'")
	sGameClientCommandLine := objGameInstance.CommandLine
This creates a for/loop that should only loop once. It will loop none if a process is not found and a null collection is returned. If you were Query by name and more than one was found the for/loop would loop to the last one.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: marypoppins_1, mikeyww, Rohwedder, RussF and 136 guests