AkelPad Forum Index AkelPad
Support forum
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Is there a command line variable for command line itself?

 
Post new topic   Reply to topic    AkelPad Forum Index -> Discussion (English)
View previous topic :: View next topic  
Author Message
danf84



Joined: 14 Mar 2011
Posts: 21

PostPosted: Wed Aug 12, 2015 2:10 pm    Post subject: Is there a command line variable for command line itself? Reply with quote

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
Back to top
View user's profile Send private message
Instructor
Site Admin


Joined: 06 Jul 2006
Posts: 5867

PostPosted: Wed Aug 12, 2015 3:40 pm    Post subject: Reply with quote

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

TransferCmdLine.js

Code:
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);
Back to top
View user's profile Send private message Send e-mail
danf84



Joined: 14 Mar 2011
Posts: 21

PostPosted: Thu Aug 13, 2015 6:25 pm    Post subject: Thank you - I've done a little something Reply with quote

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:
Quote:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options

Create a key called
Quote:
notepad.exe

Then create a string called
Quote:
Debugger
and set it to:
Quote:
C:\AkelPad\AkelPad.exe /Z


Go to
Quote:
cmd

CD to a directory with a text file, for example, 1.txt
Now type this:
Quote:
notepad 1.txt

Did it work? Not for me.

These commands do though:
Quote:
notepad "1.txt"

Quote:
"notepad" 1.txt

Bizarrely this one works too:
Quote:
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:
Quote:
/Z notepad 1.txt

Works:
Quote:
/Z notepad "1.txt"

Works:
Quote:
/Z "notepad" 1.txt

Works:
Quote:
/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
Back to top
View user's profile Send private message
danf84



Joined: 14 Mar 2011
Posts: 21

PostPosted: Thu Aug 13, 2015 6:51 pm    Post subject: My Notepad hijacking solution Reply with quote

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:
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:
/*
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
Quote:
notepad.exe
under
Quote:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options

Then create a string called
Quote:
Debugger
and set its value to
Quote:
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 Smile
Back to top
View user's profile Send private message
Instructor
Site Admin


Joined: 06 Jul 2006
Posts: 5867

PostPosted: Thu Aug 13, 2015 7:18 pm    Post subject: Re: Thank you - I've done a little something Reply with quote

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

Test version
Back to top
View user's profile Send private message Send e-mail
danf84



Joined: 14 Mar 2011
Posts: 21

PostPosted: Thu Aug 13, 2015 8:44 pm    Post subject: Reply with quote

Well, what can I say...

THANK YOU

/Z now works perfectly.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AkelPad Forum Index -> Discussion (English) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


SourceForge.net Logo Powered by phpBB © 2001, 2005 phpBB Group