What happened to the Messenger Plus! forums on msghelp.net?
Shoutbox » MsgHelp Archive » Messenger Plus! for Live Messenger » Scripting » [Release] Exit WLM

Pages: (3): « First « 1 [ 2 ] 3 » Last »
[Release] Exit WLM
Author: Message:
Matti
Elite Member
*****

Avatar
Script Developer and Helper

Posts: 1646
Reputation: 39
31 / Male / Flag
Joined: Apr 2004
RE: [Release] Exit WLM
code:
function ExitWindowsLiveMessenger() {
         /* Exit the process */
function ExitWindowsLiveMessenger() {
         /* Exit the process */
Not difficult if you repeat things... :P

Spunky, try this one:
code:
function OnEvent_ChatWndSendMessage(pChatWnd, sMessage){
         /* Check if the message sent is to exit Windows Live Messenger */
        if (sMessage === '/exit'){
                ExitWindowsLiveMessenger();
                return ""; //Not that should do anything... ^o)
        }
}

function ExitWindowsLiveMessenger() {
         /* Exit the process */
         Interop.Call('kernel32', 'ExitProcess', Interop.Call('kernel32', 'GetExitCodeProcess', Interop.Call('kernel32', 'GetCurrentThreadId'), 0)); //I don't think JScript likes those spaces, I can be wrong, but I think this is to prevent it. :P
}
Plus! Script Developer | Plus! Beta Tester | Creator of Countdown Live | Co-developer of Screenshot Sender 5

Found my post useful? Rate me!
11-13-2006 08:16 PM
Profile E-Mail PM Web Find Quote Report
Spunky
Former Super Mod
*****

Avatar

Posts: 3658
Reputation: 61
35 / Male / Flag
Joined: Aug 2006
O.P. RE: [Release] Exit WLM
Same problem again I'm afraid
<Eljay> "Problems encountered: shit blew up" :zippy:
11-13-2006 08:23 PM
Profile PM Find Quote Report
CookieRevised
Elite Member
*****

Avatar

Posts: 15519
Reputation: 173
– / Male / Flag
Joined: Jul 2003
Status: Away
RE: [Release] Exit Messenger - script attached
quote:
Originally posted by SpunkyLoveMuff
If no-one finds it useful, new scripters can still learn things from it...
  1. Don't use split(" ") like that to split up a command from its parameters. Split(" ") does not take in account multiple spaces after eachother; they all will be split out in seperate array elements.
    This makes that your parameter isn't always in the second array element. I know extremely many scripts use that method, but it is really the worsed way of all...

    It also doesn't take in account other spacing characters than ascii 32 (spacebar), which can occur on the command line. To overcome all this use regular expressions.

    If you aren't up to using regular expressions you can still use a combination of substr() and IndexOf().

    Or easier, use the split() method but with the optional limit parameter:
    stringObj.split(" ", 2). This will limit your array to 2 elements, and the second element will always be the parameter.


    But also note that with any method you use (except for the regular expression method) you need to take in account additional leading and trailing spaces. Thus you also need to trim the parameter element before using it.

    (and take in account the casing of letters too)

  2. I see you used Messenger.MyUserID to avoid that a new user is sign out. This is often forgotten when timers are used, so (y)(y)... However, in this case you don't need to check upon Messenger.MyUserID if you simply cancel the timers when the user signs out.

  3. Don't use the word exit in the command. You're not exiting messenger, but signing out. This doesn't matter for private use, but if you're going to release something in public such things are to be considered.

  4. Nice idea about the "5 seconds remaining" toast.

    However, when toasts are involved with timers like this it is very tricky. Toasts don't always immediatly show up. eg: if a messenger toast is shown, no plus! toasts will be shown and they will be held back until all messenger toasts are gone. Also, there is no way to check how long a toast is going to be visible unfortunatly (hence why you probably used 5 seconds, as a toast displays longer -good thinking-).

    Maybe these are two ideas for Patchou to implement:
    - a callback for when the toast is displayed
    - a method to know how long the toast is displayed (and/or another callback for when the toast is removed)

Anyways, I've taken the idea of your script and put it in the attached script.
If you want to find the fixes for points 1 and 2 yourself, don't look at the source of the script. Otherwise, feel free to peek. ;)

For people who want to learn scripting there is one big golden rule: read the documentation! In fact, one should lookup each and every single jscript command he is using. A nice example is this split() issue; I haven't seen one script using it to split up a command line using the optional limit parameter. Do never assume that the things you see in scripts are the proper ways, even if it is used by everybody, and even if it seems ok to you. Look things up, starting with the most smallest and obvious commands, especially if you're a beginning scripter...

JScript 5.6 Scripting Documentation
Plus! Live Scripting Documentation

;)


------------------------------------------------------------------------------------------


quote:
Originally posted by Mattike
code:
function ExitWindowsLiveMessenger() {
         /* Exit the process */
function ExitWindowsLiveMessenger() {
         /* Exit the process */
Not difficult if you repeat things... :P
Though, this will not crash messenger. It can't because that is simply a syntax error, hence the script wouldn't even start but simply give a friendly syntax error message that "} is expected on line x"...

quote:
Originally posted by Mattike
Spunky, try this one:
code:
function OnEvent_ChatWndSendMessage(pChatWnd, sMessage){
         /* Check if the message sent is to exit Windows Live Messenger */
        if (sMessage === '/exit'){
                ExitWindowsLiveMessenger();
                return ""; //Not that should do anything... ^o)
        }
}

function ExitWindowsLiveMessenger() {
         /* Exit the process */
         Interop.Call('kernel32', 'ExitProcess', Interop.Call('kernel32', 'GetExitCodeProcess', Interop.Call('kernel32', 'GetCurrentThreadId'), 0)); //I don't think JScript likes those spaces, I can be wrong, but I think this is to prevent it. :P
}

Have you tried that before you posted it? Because the spaces have got nothing todo with this. In fact, if you look around a bit in other scripts, spaces are constantly used to make scripts more readable...

Try not to post such things (and especially not fixes) if you don't know what you're talking about though. That's harsh I know, but still... it makes things more confusing for people and makes things much harder to fix and explain.


------------------------------------------------------------------------------------------


Nevertheless, Matty indeed screwed up too (must have been drunk :p). The first (and only) parameter of the ExitProcess API is an exit value you assign yourself. Not an exit value which is gotten from a process which isn't yet closed. And you can certainly not write a value (that exit value which doesn't exist, thus 0) to the memory offset of a pointer (the deepest nested API he used), which is what he did with the GetExitCodeProcess API... Hence crashes...

If ExitProcess is being used, it should be like this:
    Interop.Call('kernel32', 'ExitProcess', whatever value you like)

eg:
    Interop.Call('kernel32', 'ExitProcess', 1234)

Whatever application which monitoring the process you just ended, can now check by the exit value (use GetExitCodeProcess API) if the process was ended by you. In that case the process' exit value will be 1234.


------------------------------------------------------------------------------------------


Anyways, using the ExitProcess API isn't going to work to end Messenger (Messenger is a special case, just like mothers in law :p)...

But, there is a build in method (which I forgot about it too when writing my previous post) which you can use the close Messenger in a proper way. Thus without forcing anything, and thus without possible crashes, data loss, etc...

It comes down to sending the registered windows message "TryMsnMsgrShutdown" to the hidden messenger window, that's all it takes.

Note 1: If you have any conversation windows open you will get a "all conversation windows will be closed" message first. To overcome this you can close all conversation windows first (do this also gracefully). Or set the Plus! registry value DisableConfirmSignout (see registry help).

Note 2: If any applications are using messenger, you still will get a "first close all applications using Messenger" message. But this can be suppressed by setting a parameter in the API call.

code:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//    This function will attempt to gracefully close Messenger (polygamy safe)
//    parameters:
//        bSuppressCloseMsg (optional // default: false)
//        If this is true, it will not show the message "first close all applications using Messenger".
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function ExitWindowsLiveMessenger(bSuppressCloseMsg) {
    if (typeof(bShowCloseMsg) === 'undefined') bSuppressCloseMsg = false;
    if (CloseAllConversations() === 0) {
        var hWnd = GetMSNHiddenWindowHandle();
        var lMsg = Interop.Call('User32', 'RegisterWindowMessageW', 'TryMsnMsgrShutdown');
        Interop.Call('User32', 'SendMessageW', hWnd, lMsg, bSuppressCloseMsg?1:0, 0);
    }
    /*
    If you come here, the gracefull closing of Messenger has failed.
    Either because the user has cancelled the closing of some conversations,
    or either because another application is still using Messenger.
    */
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//    This function will attempt to gracefully close all conversation windows (polygamy safe)
//    Return value: 0 upon success; otherwise the returned value is the number of still open conversations
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function CloseAllConversations() {
    // Loop thru all the open conversation windows
    for (var e = new Enumerator(Messenger.CurrentChats); !e.atEnd(); e.moveNext())
        // Gracefully close the conversation window
        Interop.Call('User32', 'PostMessageW', e.item().Handle, 0x0111, 40017, 0);

    // Return the number of still open conversation windows
    return Messenger.CurrentChats.Count
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//    This function will find our own hidden Messenger window (polygamy safe)
//    Return value: handle to our own hidden Messenger window
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function GetMSNHiddenWindowHandle() {
    // Get our own thread id
    var tIDCurrent = Interop.Call('Kernel32', 'GetCurrentThreadId');
    var hWnd = 0;
    // Loop through the hidden Messenger windows to find the one that belongs to our process
    while (hWnd = Interop.Call('User32', 'FindWindowExW', 0, hWnd, 'MSNHiddenWindowClass', 0))
        // Compare the thread id of the window with our own thread id
        if (Interop.Call('User32', 'GetWindowThreadProcessId', hWnd, 0) === tIDCurrent)
            // Return the window handle if the thread id is the same
            return hWnd;
}




The full script which adds the commands:

/quit
and /exit                   to exit Messenger
/closeall                             to close all current conversation windows
/signout <optional delay>   to signout after an optional delay in seconds (between 10 and 86400 seconds)
/stopsignout                     to stop the delayed signout countdown


http://www.msgpluslive.net/scripts/view/241-Exit-Messenger/

Previous downloads from forum: 20


This post was edited on 03-25-2011 at 02:06 AM by CookieRevised.
.-= A 'frrrrrrrituurrr' for Wacky =-.
11-15-2006 12:14 AM
Profile PM Find Quote Report
Spunky
Former Super Mod
*****

Avatar

Posts: 3658
Reputation: 61
35 / Male / Flag
Joined: Aug 2006
O.P. RE: [Release] Exit WLM
I want a little CookieRevised to keep in my pocket. Excellent response as always :p

I've taken a look at the regular expression you used to "grab" the commands and might try to implement it in my other scripts. (Obviously I chose to peek :p It's the only way I'll learn ;))

I always try to check the user when a timer event is triggered since I saw one of your posts. I'm just in the habit of doing it all the time now without thinking. :D

I've got you to thank for a lot of things I've learnt to do with scripting (as a lost of people here have)
<Eljay> "Problems encountered: shit blew up" :zippy:
11-15-2006 12:29 AM
Profile PM Find Quote Report
CookieRevised
Elite Member
*****

Avatar

Posts: 15519
Reputation: 173
– / Male / Flag
Joined: Jul 2003
Status: Away
RE: [Release] Exit WLM
quote:
Originally posted by SpunkyLoveMuff
I always try to check the user when a timer event is triggered since I saw one of your posts. I'm just in the habit of doing it all the time now without thinking. :D
hehe...

Well, the difference between these methods is that if you check with the Userid, you can still let the timers run while another temporary user is signed in if you give your timers an unique name (like an added userid string as in my 'signin flood protection' script).

And in case that this other temporary user gives the PC back to the original user, and the timers are still running, the script actually will do as if nothing happened, so to speak.

It will also allow you to run timers of two uses at the same time for example; while one user is logged in, the timer of the other user is still running so it can trigger when he signs back in, etc...

eg: when you implement this method in the 'exit messenger' script above, one user can set his 'delayed signout' and he doesn't need to worry about it when his little sister wants to sign in for one minute. After his sister is done, he simply can sign in himself, and the 'delayed signout' will still be counting down happy, he doesn't need to set it again or calculate again how many minutes he must set....

-

If you use the other method (canceling timers at signout), then the timers need to be initialized each time again and you can't run timers for two different users. This method is of course easier to keep track of timers too.

-

So that's the difference....

Despite what method you choose, if you don't take in consideration that another user can sign in (and that timers do not cancel automatically when this happens), many errors can occur:

eg: ... all of a sudden his little sister comes crying downstair because she suddenly was signed out and she didn't do anything....

This post was edited on 11-15-2006 at 01:25 AM by CookieRevised.
.-= A 'frrrrrrrituurrr' for Wacky =-.
11-15-2006 01:17 AM
Profile PM Find Quote Report
Aristide
New Member
*


Posts: 1
Joined: Dec 2006
RE: [Release] Exit WLM
Is there a way to perform the script command "/quit" from outside a chat window just by a doubleclick on some desktop icon? Greetz, Aristide
(MPL newby)
12-17-2006 01:56 PM
Profile E-Mail PM Find Quote Report
BraydenP
Disabled Account


Posts: 20
Reputation: 2
43 / – / –
Joined: Dec 2006
Re; [Release] Exit WLM
Hello,

I have tested this script and I rate it 10/10.

Well done Spunky Love Muff! .. (Y) ..

Thanks,

BraydenP.

This post was edited on 12-18-2006 at 12:37 PM by BraydenP.
12-18-2006 12:37 PM
Profile E-Mail PM Find Quote Report
Jesus
Scripting Contest Winner
****

Avatar
Koffie, my cat ;)

Posts: 623
Reputation: 15
37 / Male / Flag
Joined: Jul 2005
RE: RE: [Release] Exit Messenger - script attached
quote:
Originally posted by CookieRevised
It also doesn't take in account other spacing characters than ascii 32 (spacebar), which can occur on the command line. To overcome all this use regular expressions.

If you aren't up to using regular expressions you can still use a combination of substr() and IndexOf().

Or easier, use the split() method but with the optional limit parameter:
stringObj.split(" ", 2). This will limit your array to 2 elements, and the second element will always be the parameter.

But also note that with any method you use (except for the regular expression method) you need to take in account additional leading and trailing spaces. Thus you also need to trim the parameter element before using it.

(and take in account the casing of letters too)

Cookie, I don't mean to criticise you, but the stringObj.split(" ", 2) method won't work any better than just using stringObj.split(" ").
The only difference is that with the optional limit parameter, your array is limited to 2 elements, without using the rest of the string.
eg:
code:
var str = "The quick brown fox jumps over the lazy dog.";
return str.split(" ",2);
will return a 2-element array: "The,quick"
so a command like "/command  parameter" (2 spaces in between) will become "/command," with an empty 2nd element.
I had to try this to see it, as it's not in the docs (the limit parameter is, but the fact that it leaves the rest of the string isn't) so even with reading the docs you don't always get where you want ;)

My conclusion is that regular expressions are the best way to go (unfortunately I don't know how to use them yet), but that using stringObj.toLowerCase().split(" ") is an acceptable second, which also takes casing of letters into account.
You could even use a loop to filter out the empty elements caused by extra spaces.

I totally agree with the rest of your post, as usual ;)
12-18-2006 01:37 PM
Profile PM Find Quote Report
markee
Veteran Member
*****

Avatar

Posts: 1621
Reputation: 50
35 / Male / Flag
Joined: Jan 2006
RE: RE: RE: [Release] Exit Messenger - script attached
quote:
Originally posted by Jesus
quote:
Originally posted by CookieRevised
It also doesn't take in account other spacing characters than ascii 32 (spacebar), which can occur on the command line. To overcome all this use regular expressions.

If you aren't up to using regular expressions you can still use a combination of substr() and IndexOf().

Or easier, use the split() method but with the optional limit parameter:
stringObj.split(" ", 2). This will limit your array to 2 elements, and the second element will always be the parameter.

But also note that with any method you use (except for the regular expression method) you need to take in account additional leading and trailing spaces. Thus you also need to trim the parameter element before using it.

(and take in account the casing of letters too)

Cookie, I don't mean to criticise you, but the stringObj.split(" ", 2) method won't work any better than just using stringObj.split(" ").
The only difference is that with the optional limit parameter, your array is limited to 2 elements, without using the rest of the string.
eg:
code:
var str = "The quick brown fox jumps over the lazy dog.";
return str.split(" ",2);
will return a 2-element array: "The,quick"
so a command like "/command  parameter" (2 spaces in between) will become "/command," with an empty 2nd element.
I had to try this to see it, as it's not in the docs (the limit parameter is, but the fact that it leaves the rest of the string isn't) so even with reading the docs you don't always get where you want ;)

My conclusion is that regular expressions are the best way to go (unfortunately I don't know how to use them yet), but that using stringObj.toLowerCase().split(" ") is an acceptable second, which also takes casing of letters into account.
You could even use a loop to filter out the empty elements caused by extra spaces.

I totally agree with the rest of your post, as usual ;)


I think what you are after in regular expressions is the follow, though if someone is will to suggest a better regular expression I will be happy to accept it (assuming it works).

code:
if((arr = /\/([^ \s]*) (.*)/i.exec(stringObj) != null){
var command = arr[1];
var param = arr[2];
}

Btw, im not sure if it worked as I'm busy trying to do other things (and too tired too test), but I'm quite sure it should work, the only thing I'm unsure of it the space character.

EDIT: Tested and fixed Regular Expression ;)

This post was edited on 12-18-2006 at 02:22 PM by markee.
[Image: markee.png]
12-18-2006 02:06 PM
Profile PM Find Quote Report
CookieRevised
Elite Member
*****

Avatar

Posts: 15519
Reputation: 173
– / Male / Flag
Joined: Jul 2003
Status: Away
RE: RE: RE: [Release] Exit Messenger - script attached
quote:
Originally posted by Jesus
code:
var str = "The quick brown fox jumps over the lazy dog.";
return str.split(" ",2);
will return a 2-element array: "The,quick"
You are correct (Y)(Y)

The reason of my mistake is because at that time I was busy with VB6 and in VB6 the limit parameter limits the amount of array elements without loosing anything from the string. In JScript it does loose all the rest of the string.

quote:
Originally posted by markee
I think what you are after in regular expressions is the follow, though if someone is will to suggest a better regular expression I will be happy to accept it (assuming it works).
code:
if((arr = /\/([^ \s]*) (.*)/i.exec(stringObj) != null){
var command = arr[1];
var param = arr[2];
}

almost, since that regular expression does not work properly.

What you need to take in account:

- a command always starts with only 1 slash "/" (not two, or more)
^^ your reg exp fails here since you don't exclude second or more slashes.

- after the slash there can not be a spacing character
^^ your reg exp fails here since you define the exclussion list to be 0 or more times ("*") when it should be 1 or more times ("+").
PS: a space (ascii 32) is also a spacing character ("\s") so you don't need to define that seperatly in the exclussion list.


- commands should be case insensitive, but parameters are not!
^^ your reg exp fails here since you don't lowercase the command. Yet you use the case insensitive marker. But this does not do anything, since there are no characters in the regular expression. That marker is for searching on all cases, not to convert cases.

- after the command there can be many spacing characters. In many cases (if not all), the user/coder simply wants the parameter to begin without any spacing characters. But Plus!'s default behaviour is to take every occuring spacing character after the first spacing character after the command as part of the parameter (though not that usefull for almost all scripts).
^^ your reg exp fails here since you don't specify a spacing character ("\s") but only a space (ascii 32).

- a parameter can contain multiple lines.
^^ your reg exp fails here too since you check on 'any' character ("."),  but 'any' character does not include new line characters ("\n").


A more accurate regular expression to seperate the command and parameter which is also already used in my Exit Messenger script:
code:
function OnEvent_ChatWndSendMessage(oChatWnd, sMessage) {
    if (/^\/([^\s\/]+)\s*([\s\S]*)$/.exec(sMessage) !== null) {
        var command = RegExp.$1.toLowerCase();
        var parameter = RegExp.$2;
        switch (command) {
            case 'quit':
                // <- Do something when the user typed the command quit
                return '';
            case 'exit':
                // <- Do something when the user typed the command exit
                return '';
            case 'cancel':
                // <- Do something when the user typed the command cancel
                return '';
        }
    }
}
In above snippet:
- to let the parameter include all leading spacing characters like Plus! nativly does, change  \s* or  \s?
- to dismiss any trailing spacing characters after the parameter, you could replace  ([\s\S]*)  with  ([\s\S]*?)\s*

If you only have 1 command in your script (eg: /explode) your can use something like:
code:
function OnEvent_ChatWndSendMessage(oChatWnd, sMessage) {
    if (/^\/explode(?:\s+([\s\S]*)|$)/i.exec(sMessage) !== null) {
        var parameter = RegExp.$1;
        // <- Do something when the user typed the command explode
        return '';
    }
}
In above snippet:
- to let the parameter include all leading spacing characters like Plus! nativly does, change  \s+  to  \s{1}

;)

--------------

PS: note that I talk about spacing characters. But in fact Plus! doesn't consider all spacing characters as spacing characters. the tab character is a spacing character, but Plus! handles this as a normal non-spacing character. So the above regular expressions aren't entirly 100% like Plus! behaves though. But I'm too tired atm to make them exactly alike. Though, for most people the above will be more than sufficient and accurate enough (especially since most would only use things like split(), substr(), etc anyways).

EDIT: More accurate regular expressions to handle Plus!-style commands and a detailed explanation of them can be found here:
post 1: CookieRevised's reply to Gettin data from "/" commands
post 2: CookieRevised's reply to Gettin data from "/" commands

This post was edited on 03-25-2011 at 12:10 AM by CookieRevised.
.-= A 'frrrrrrrituurrr' for Wacky =-.
12-19-2006 12:27 AM
Profile PM Find Quote Report
Pages: (3): « First « 1 [ 2 ] 3 » Last »
« Next Oldest Return to Top Next Newest »


Threaded Mode | Linear Mode
View a Printable Version
Send this Thread to a Friend
Subscribe | Add to Favorites
Rate This Thread:

Forum Jump:

Forum Rules:
You cannot post new threads
You cannot post replies
You cannot post attachments
You can edit your posts
HTML is Off
myCode is On
Smilies are On
[img] Code is On