Is there a command line variable for command line itself?

English main discussion
Post Reply
  • Author
  • Message
Offline
Posts: 21
Joined: Mon Mar 14, 2011 1:27 pm

Is there a command line variable for command line itself?

Post by danf84 »

I'll ask by giving example:

Let's say I have some program that is configured to run AkelPad with some parameters e.g. AkelPad "somefile.txt"
But I also specify that that program to pass an additional parameter like "/Exec("SomeProgram %*")

Do you see what I mean? I need to access the command line parameter within the Exec() function in the command line parameter itself.

Thanks
Last edited by danf84 on Thu Aug 13, 2015 8:51 pm, edited 1 time in total.

Offline
Site Admin
Posts: 6311
Joined: Thu Jul 06, 2006 7:20 am

Post by Instructor »

danf84
Command line:
AkelPad.exe "somefile.txt" /Call("Scripts::Main", 1, "TransferCmdLine.js")

Code: Select all

var oSys=AkelPad.SystemFunction();
var lpCmdLine=oSys.Call("kernel32::GetCommandLine" + _TCHAR);
var pCmdLine=AkelPad.MemRead(lpCmdLine, _TSTR);

//Remove executable
pCmdLine=pCmdLine.replace(/(\".+?\"|[^ $]+)( ?)(.*)/g, "$3");

//Remove "TransferCmdLine.js" call
pCmdLine=pCmdLine.replace(/ \/Call\(\"Scripts::Main\", 1, \"TransferCmdLine\.js\"\)/g, "");

AkelPad.Exec("notepad.exe " + pCmdLine);

Offline
Posts: 21
Joined: Mon Mar 14, 2011 1:27 pm

Thank you - I've done a little something

Post by danf84 »

Thanks for your quick reply. I dived in and learned a bit of scripting in AkelPad.

As an AkelPad user and developer I was unhappy with its Notepad replacement solution, so I've been trying to get the "Image File Execution Options" solution to work (I'll post the full solution in a separate post). In my opinion it is a better solution to use that registry hack as you maintain 1 place where AkelPad is installed, works for x64 and x86 processes, requires only 1 small change - the registry. The current solution uses a stub process to ensure that any waits done on the processes work (and not immediately return), as well as pass process exit codes from the real AkelPad instance to the stub and then to the caller (I haven't tested the latter, but I trust it works). This stub process has to be placed in several locations in the system - and I can tell you as a daily user of AkelPad (sometimes with 50+ instances opened at once) that Explorer gets confused when it tries to group them in the task bar. For some reason, sometimes it happens, that when I start Notepad (AkelPad) it opens up as the last process on the task bar, not grouped with other AkelPad instances. The other obvious disadvantage of the stub process is double the amount of processes.

So with those disadvantages in mind, I decided to make the "Image File Execution Options" method work as best as possible because it is the cleanest way. I've seen other solutions posted online and they overlook things here and there, like waiting on process, or other various ways the original Notepads get called, and nuances of command line parameters (quotes, spaces etc, etc).

Before I post my solution in the next post, I want to say this: AkelPad has "\Z" switch. It *almost* works.


See where it doesn't:
First, set up AkelPad as Notepad replacement by navigating to this key in the registry:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
Create a key called
notepad.exe
Then create a string called
Debugger
and set it to:
C:\AkelPad\AkelPad.exe /Z
Go to
cmd
CD to a directory with a text file, for example, 1.txt
Now type this:
notepad 1.txt
Did it work? Not for me.

These commands do though:
notepad "1.txt"
"notepad" 1.txt
Bizarrely this one works too:
notepad "1.txt

The kind of command line parameters AkelPad receives is different there, and it's very subtle.
Corresponding to commands entered above, these are the command line parameters AkelPad would receive from Windows:
Doesn't work:
/Z notepad 1.txt
Works:
/Z notepad "1.txt"
Works:
/Z "notepad" 1.txt
Works:
/Z notepad "1.txt

If you fix this, whatever it is, that would be great.

I will post a solution in the next post, long, with scripts, but fun.
Last edited by danf84 on Thu Aug 13, 2015 8:51 pm, edited 2 times in total.

Offline
Posts: 21
Joined: Mon Mar 14, 2011 1:27 pm

My Notepad hijacking solution

Post by danf84 »

So here's what I've done.
I wrote the script that handles command line parameters when something calls "notepad.exe", so first of all, the script:

"NPHijacker.js" (I wanted to call it NotepadHijacker but the code inside won't like that as it's looking for the first instance of the word "notepad")

"NPHijacker.js":

Code: Select all

var oSys = AkelPad.SystemFunction(); 
var lpCmdLine = oSys.Call("kernel32::GetCommandLine" + _TCHAR); 
var pCmdLine = AkelPad.MemRead(lpCmdLine, _TSTR);
var idx = pCmdLine.toLowerCase().indexOf("notepad") + 7;
if (pCmdLine.substr(idx, 5).toLowerCase() == ".exe\"") {
  var s=pCmdLine.substring(idx + 6, pCmdLine.length);
} else if (pCmdLine.substr(idx, 4).toLowerCase() == ".exe") {
  var s=pCmdLine.substring(idx + 5, pCmdLine.length);
} else if (pCmdLine.substr(idx, 1) == " ") {
  var s=pCmdLine.substring(idx + 1, pCmdLine.length);
} else if (pCmdLine.substr(idx, 1) == "\"") {
  var s=pCmdLine.substring(idx + 2, pCmdLine.length);
} else if (pCmdLine.substr(idx, 1) == "") {
  var s=pCmdLine.substring(idx + 2, pCmdLine.length);
}
s=s.replace(/^\s+|\s+$/g, '');
if ((s != "") && (s.substr(0, 1) == "\"")) s=s.substring(1, s.length - 1);
if (s != "") AkelPad.OpenFile(s);
The longer version I used while making it:

Code: Select all

/*
19:36 13/08/2015
*** Don't include the word "Notepad" in the file name of this script or change how this script works ***
Needs a bit more testing.
Doesn't support /p switch.
Doesn't support multiple files (notepad "1.txt" "2.txt").
*/

var bDebugging=false;
if (bDebugging) {
  var sDebug="";
  function debug(debugStr) {
    sDebug = sDebug + debugStr + "\n";
  }
}

var oSys = AkelPad.SystemFunction(); 
var lpCmdLine = oSys.Call("kernel32::GetCommandLine" + _TCHAR); 
var pCmdLine = AkelPad.MemRead(lpCmdLine, _TSTR);
if (bDebugging) debug("Cmd line: {" + pCmdLine + "}");
var idx = pCmdLine.toLowerCase().indexOf("notepad") + 7;

if (pCmdLine.substr(idx, 5).toLowerCase() == ".exe\"") {
  var s=pCmdLine.substring(idx + 6, pCmdLine.length);
  if (bDebugging) debug("Case 1:{" + s + "}");

} else if (pCmdLine.substr(idx, 4).toLowerCase() == ".exe") {
  var s=pCmdLine.substring(idx + 5, pCmdLine.length);
  if (bDebugging) debug("Case 2:{" + s + "}");

} else if (pCmdLine.substr(idx, 1) == " ") {
  var s=pCmdLine.substring(idx + 1, pCmdLine.length);
  if (bDebugging) debug("Case 3:{" + s + "}");

} else if (pCmdLine.substr(idx, 1) == "\"") {
  var s=pCmdLine.substring(idx + 2, pCmdLine.length);
  if (bDebugging) debug("Case 4:{" + s + "}");

} else if (pCmdLine.substr(idx, 1) == "") {
  var s=pCmdLine.substring(idx + 2, pCmdLine.length);
  if (bDebugging) debug("Case 5:{" + s + "}");

} else {
  if (bDebugging) {
    debug("Unhandled case of Notepad command line parameters");
    WScript.Echo(sDebug);
  } else throw false;
}

s=s.replace(/^\s+|\s+$/g, '');
if (bDebugging) debug("Trimmed:" + s);

if (s != "") {
  if (s.substr(0, 1) == "\"") {
    s = s.substring(1, s.length - 1);
    if (bDebugging) debug("Dequoted:" + s);
  }
}
if (bDebugging) WScript.Echo(sDebug);
if (s != "") AkelPad.OpenFile(s);

The script is a little rough, maybe someone can make it smaller. I am pretty sure once all cases are captured, the big "if-then-else" chain can be refactored and made very small.

The next step, as explained in my previous post, is to add a registry key called
notepad.exe
under
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
Then create a string called
Debugger
and set its value to
C:\AkelPad\AkelPad.exe /Call("Scripts::Main", 1, "NPHijacker.js") /End
Obviously change the path of your AkelPad executable.

Don't forget to copy NPHijacker.js to C:\AkelPad\AkelFiles\Plugs\Scripts (or wherever your AkelPad is installed).

Hope this helps someone! I've been looking for a good solution, and I am happy with this one :)

Offline
Site Admin
Posts: 6311
Joined: Thu Jul 06, 2006 7:20 am

Re: Thank you - I've done a little something

Post by Instructor »

danf84 wrote:If you fix this, whatever it is, that would be great.
Test version

Offline
Posts: 21
Joined: Mon Mar 14, 2011 1:27 pm

Post by danf84 »

Well, what can I say...

THANK YOU

/Z now works perfectly.
Post Reply