What happened to the Messenger Plus! forums on msghelp.net?
Shoutbox » MsgHelp Archive » Messenger Plus! for Live Messenger » Scripting » my first script any help would be appriciated..

Pages: (2): « First « 1 [ 2 ] Last »
my first script any help would be appriciated..
Author: Message:
CookieRevised
Elite Member
*****

Avatar

Posts: 15519
Reputation: 173
– / Male / Flag
Joined: Jul 2003
Status: Away
RE: my first script any help would be appriciated..
quote:
Originally posted by Yustme
Im trying to create a script which logs me in automatically in several accounts. I know there is one out there, but its bugged. Tried fixing it, but it's too messed up to understand it.

One of the reasons is because such scripts are complicated. There are many circumstances you need to take into account and it all requires deep knowledge of how the scripting engine works in order to make such a thing always working in all circumstances.

As you have already noticed, there are many things which will break this script or which will make it not work like you'd expect. And there are probably also things which you haven't noticed yet which might break it.

quote:
Originally posted by Yustme
Well the script executes all the messenger windows and signs in all the email addresses. Then it stops. It doesn't repeat this step for all instances of messenger.
That would actually be a bug in your script (the script you have, thus without the addition of Whiz) and a manifestation of how scripts are loaded in Messenger/Messenger Plus! and the delays, etc...

quote:
Originally posted by whiz
You could get the script to check for a registry key, and if it doesn't exist, it should create one because it is the first launch.
Javascript code:
// add to the top
var shell = new ActiveXObject("WScript.Shell");
 
// ...
 
function OnEvent_Initialize(MessengerStart)
{
    try {
        // value exists, already running, exit now
        shell.RegRead(MsgPlus.ScriptRegPath + "\\IsRunning");
        return false;
    } catch (error) {
        // not yet running, make a registry value, continue
        shell.RegWrite(MsgPlus.ScriptRegPath + "\\IsRunning", "1");
    }
 
    // Check if there's anything to be done
    if(emailList.length > 0) {
        MsgPlus.AddTimer('windowDelayer', delayOpenWnd);
    } else {
        // finished, delete the registry key
        shell.RegDelete(MsgPlus.ScriptRegPath + "\\IsRunning");
    }
}
 
// ...


This will not work in all circumstances!

You have no control with this over the other scripts. Especially when you're executing multiple Messengers quickly after eachother, delays in loading (and loading Plus!, skins and scripts) will start to happen. This makes that another instance of this script might still be running (or still need to start running) by the time the 'main' script finishes. In other words, the 'main' script will remove the registry check before one of those other scripts get executed, and you're back to square one...

So, do not use a single boolean, instead you must keep track of what accounts have been signed in, or rather in the process of signing in because the actual sign in might fail.

quote:
Originally posted by Yustme
I got another quick question. Is there any way to check which email addresses have been logged in?
yes, but not directly. You either need to manipulate the other instances of Messenger directly as there is no easy way to 'talk' to other instances of the same script running in other Messengers.

Or you either need to find a common storage which is available for all other scripts at any time (eg: registry).

And if you go about it in a smart way, you can actually combine this with what I've suggested as a reply to Whiz' addition.

But either way, it is very tricky because signing in can take a very long time (even minutes). And it is only when you're signed in that you can 'store' the email account as being 'signed in'.

In other words, you can not use something like this to check what account has been signed in during the whole process of multiple sign ins. You can however use this to detect what accounts are already signed in *prior* to starting the whole multiple signin process, so you don't sign in an account twice (and thus sign out an account in one of the already existing Messenger instances).

To do this in the most easiest way:
In the OnEvent_SignIn() add (not replace) the email address to a registry string value if it doesn't already exist in that value (REG_MULTI_SZ is the preferred type, though REG_SZ will work too).

In the OnEvent_SignOut() you remove the email address again from that same registry value.

Then in your OnEvent_Timer() function you first check upon this registry value and only add accounts to the list if they don't exist in that registry value.

This method will prevent you from first signing out already signed in accounts, before signing them in again.

This post was edited on 07-03-2010 at 12:21 PM by CookieRevised.
.-= A 'frrrrrrrituurrr' for Wacky =-.
07-03-2010 11:11 AM
Profile PM Find Quote Report
whiz
Senior Member
****


Posts: 568
Reputation: 8
– / – / Flag
Joined: Nov 2008
RE: my first script any help would be appriciated..
quote:
Originally posted by CookieRevised
This will not work in all circumstances!

You have no control with this over the other scripts. Especially when you're executing multiple Messengers quickly after eachother, delays in loading (and loading Plus!, skins and scripts) will start to happen. This makes that another instance of this script might still be running (or still need to start running) by the time the 'main' script finishes. In other words, the 'main' script will remove the registry check before one of those other scripts get executed, and you're back to square one...

So, do not use a single boolean, instead you must keep track of what accounts have been signed in, or rather in the process of signing in because the actual sign in might fail.
How about this?

Javascript code:
// add to the top
var shell = new ActiveXObject("WScript.Shell");
 
// ...
 
function OnEvent_Initialize(MessengerStart)
{
    try {
        // value exists, check the count, write the new one
        var Count = shell.RegRead(MsgPlus.ScriptRegPath + "\\RunCount");
        shell.RegWrite(MsgPlus.ScriptRegPath + "\\RunCount", Count--, "REG_DWORD");
        if (Count === 0) {
            // we're finished, delete the (correct) key :)
            shell.RegDelete(MsgPlus.ScriptRegPath + "\\RunCount");
        }
        return false;
    } catch (error) {
        // not yet running, make a registry value, continue
        shell.RegWrite(MsgPlus.ScriptRegPath + "\\RunCount", emailList.length, "REG_DWORD");
    }
 
    // Check if there's anything to be done
    if(emailList.length > 0) {
        MsgPlus.AddTimer('windowDelayer', delayOpenWnd);
    }
}
 
// ...


This post was edited on 07-03-2010 at 12:15 PM by whiz.
07-03-2010 11:35 AM
Profile E-Mail PM Find Quote Report
CookieRevised
Elite Member
*****

Avatar

Posts: 15519
Reputation: 173
– / Male / Flag
Joined: Jul 2003
Status: Away
RE: RE: my first script any help would be appriciated..
Sorry, the reason I gave why your addition would fail was slightly wrong...  it isn't the main reason (you get that from being a guy and being busy with multiple things at once :p).

The main reason for not working is that the boolean value will never be removed after the first execution:
emailList.length is always bigger than 0 (well, as long as you have hardcoded some accounts to sign in), so the script will never get to shell.RegDelete. Aka, it would work the first time (when there are no other delays that is), but not the second time.

But say you got the removal of the registry key correct, or that there were some delays in the loading of the other instances, then it would indeed fail for the reason I gave before. You indeed need to have at least a counter instead of a simple boolean, so:
quote:
Originally posted by whiz
How about this?
Javascript code:
...


Now the count is only initiated by the 'main' script, but further handled by the other instances and thus it wont be influenced by possible delays when loading scripts etc. Which looks alright at first sight....

...except for the small booboo:
    shell.RegDelete(MsgPlus.ScriptRegPath + "\\IsRunningRunCount");







PS: Yustme, there are some other things you do a bit wrong in your script and might result in bugs now or in the futur.

1) move the whole if (Messenger.Version >= 8.5) check inside OnEvent_Initialize().

This because the Messenger object might not be initiated yet when the script is loaded (it should, but there are no garantees, and it might change it in futur versions also).

You should never assume specific objects created by Messenger Plus! exist in the global scope of a script!

btw, as for the PerPassportSettings registry key, that can still be found under HKCU\SOFTWARE\Microsoft\MSNMessenger and it's still not version dependant. You also don't need the WLMexe variable anywhere. In other words, that whole version check can actually be removed.

--
But if you ever need to refer to the HKLM registry keys of Messenger, you should use:
Javascript code:
if (Messenger.Version >= 9) {
    var WLM_HKLM = 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Live\\Messenger';
} else {
    var WLM_HKLM = 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSNMessenger';
}

Notice the 9 and not 8.5 !.


----------

2) You hard coded the path to the Messenger executable. This is not the proper way to handle this. Instead you should get the current path from the registry:
Javascript code:
// Get the installation path in a proper and secure way
try {
    var WSH = new ActiveXObject('WScript.Shell');
    if (Messenger.Version >= 9) {
        var sPath = WSH.RegRead('HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Live\\Messenger\\InstallationDirectory');
    } else {
        var sPath = WSH.RegRead('HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSNMessenger\\InstallationDirectory');
    }
} catch(e) {
    Debug.Trace('Error: the mandatory registry key \'InstallationDirectory\' is missing.');
}

But, for your script, all you actually need is the executable of Messenger. In other words, the module of the process you are already running. You can get this very easily by using the Windows API GetModuleFileName:
Javascript code:
function GetMessengerExecutable() {
    var sBuffer = Interop.Allocate(2050);
    Interop.Call('Kernel32', 'GetModuleFileNameW', 0, sBuffer.DataPtr, sBuffer.Size / 2);
    return sBuffer.ReadString(0, true);
}


----------

3) Your SetBinaryValue() function (and thus possibly SetStringValue() too) can also use some work and a lot of optimizations. It also includes a major bug in the way it is coded and made to be used!!

For starters the content of the allocated datablock lBufferSize is calculated wrong for most binary values. It is not 2*stringsize+2, but just 2*stringsize in case you are passing a JScript string to it (like the function is currently set up).

The extra 2 bytes which are hard coded in that function come from the fact that this function was probably made with null terminated unicode JScript strings in mind. But not all binary variables consist of null terminated unicode string! In fact, most of them even don't (because strings can better be written as a REG_SZ)!!

You're simply lucky that it works because the DefaultMemberName registry key accidently needs a null terminated unicode string too.

This is highly important to know if you ever want to use that same function to write other binary values to the registry. In fact, even many binary registry keys which are in fact unicode strings aren't null terminted at all. So you wouldn't even be able to use this function as-is for such binary strings either.

Either way, this lBufferSize datablock isn't needed at all. The size parameter you need to pass is the length of the binary content (and nothing extra), and if you pass a JScript string you can just as well use a normal JScript variable for that or even directly using sKeyValue.length * 2.

And instead of adding the extra two bytes to accomodate the unicode null character in the size calculation inside the function, you should actually be passing a null terminated string to the function instead! Thus "MyString\0"

Then there is also the issue that unicode strings in JScript can not handle every possible character combination properly! Some character combinations will be converted automatically internally. This means that you actually should not use a JScript string to pass to such a function. Instead it should be made so you can pass a datablock.

And there is the issue that if you use that function with a registry path which doesn't exist yet, it will fail.

To make it short: that function needs a rewrite or should not be used as-is or be copied to another script like it is. Because it will fail for many binary values! Aka: it does not write all binary values properly.

Thus:
Javascript code:
SetBinaryValue(HKEY_CURRENT_USER, 'SOFTWARE\\Microsoft\\MSNMessenger\\PerPassportSettings', 'DefaultMemberName', email + '\0');
 
 
function SetBinaryValue(lKeyLocation, sKey, sKeyName, sKeyValue) {
    // Warning: this function can only be used to write unicode strings!!!
    // Any other attempt to write true binary content with this function might fail due to internal unicode conversions.
    var hKey = Interop.Allocate(4);
    var lRetVal = Interop.Call('advapi32.dll', 'RegCreateKeyExW', lKeyLocation, sKey, 0, 0, 0, KEY_WRITE, 0, hKey.DataPtr, 0);
    if (lRetVal === ERROR_SUCCESS) {
        lRetVal = Interop.Call('advapi32.dll', 'RegSetValueExW', hKey.ReadDWORD(0), sKeyName, 0, REG_BINARY, sKeyValue, sKeyValue.length * 2);
        Interop.Call('advapi32.dll', 'RegCloseKey', hKey.ReadDWORD(0));
    }
    return lRetVal === ERROR_SUCCESS;
}

- notice the addition of a null terminator character in the passed string instead of hard coding it in the function.
- notice the use of sKeyValue.length * 2 instead of that unneeded and wrong calculated datablock.
- notice the use of === (identity operator) which is faster than == (equality operator), also see here
- notice the use of RegCreateKeyExW instead of RegOpenKeyExW which will also create the registry path if it doesn't already exist.
- notice the smarter use of the return value lRetVal, making the code a whole lot shorter, yet the output will be identical as before.


;)

This post was edited on 07-03-2010 at 03:02 PM by CookieRevised.
.-= A 'frrrrrrrituurrr' for Wacky =-.
07-03-2010 11:56 AM
Profile PM Find Quote Report
petsas
New Member
*


Posts: 4
Joined: Jul 2010
RE: my first script any help would be appriciated..
Really thank you all for your answers! :)

One more question:

When I run the code, it occurs an error regarding the HKEY_CURRENT_USER:

Error: 'HKEY_CURRENT_USER' is undefined (code: -2146823279)

       File: multiply_auto_login.js. Line: 120.

Function OnEvent_Timer returned an error. Code: -2147352567

Moreover, I want to use different accounts to sign in from the list. When I run the code,
the accounts that are created are the same as the initiator that runs the script..

Any ideas?
07-05-2010 11:13 AM
Profile E-Mail PM Find Quote Report
matty
Scripting Guru
*****


Posts: 8336
Reputation: 109
39 / Male / Flag
Joined: Dec 2002
Status: Away
RE: my first script any help would be appriciated..
Javascript code:
var HKEY_CLASSES_ROOT = 0x80000000;
var HKEY_CURRENT_USER = 0x80000001;
var HKCU = HKEY_CURRENT_USER;
var HKEY_LOCAL_MACHINE = 0x80000002;
var HKEY_USERS = 0x80000003;
var HKEY_PERFORMANCE_DATA = 0x80000004;
var HKEY_PERFORMANCE_TEXT = 0x80000050;
var HKEY_PERFORMANCE_NLSTEXT = 0x80000060;
var HKEY_CURRENT_CONFIG = 0x80000005;
var HKEY_DYN_DATA = 0x80000006;

07-05-2010 01:26 PM
Profile E-Mail PM Find Quote Report
petsas
New Member
*


Posts: 4
Joined: Jul 2010
RE: my first script any help would be appriciated..
Thank you very much!!

But, I realized that there are some more that are not defined in my code yet, such as:

KEY_WRITE, ERROR_SUCCESS and REG_BINARY!

Where did you find them? Is there any file that contains all such kind of macros!!

Thank you again :)
07-05-2010 01:42 PM
Profile E-Mail PM Find Quote Report
Matti
Elite Member
*****

Avatar
Script Developer and Helper

Posts: 1646
Reputation: 39
31 / Male / Flag
Joined: Apr 2004
RE: my first script any help would be appriciated..
There used to be a list of them hosted on m00.cx, but apparently that server is down now. Luckily, I made a local copy of the list when it was still up - it's a pretty long list and I didn't have to wait that long every time I needed to look something up. I uploaded my copy as a TXT file to localhostr, go get it. In that list, you'll find that:
Javascript code:
var ERROR_SUCCESS = 0;
var REG_BINARY = 3;

Now, this list is just a rip-off from the Win32 C++ header files, so you'll find that most of the constants are defined as a combination of other constants. For example, KEY_WRITE is defined as:
Javascript code:
var KEY_WRITE = ((STANDARD_RIGHTS_WRITE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY) & (~SYNCHRONIZE));

If you want to use the constant in your script, you have to include all references constants as well, or you calculate the result and assign it to your constant directly.

Or you just Google something like "const KEY_WRITE" and see if there's a result with the value in it. :P
Plus! Script Developer | Plus! Beta Tester | Creator of Countdown Live | Co-developer of Screenshot Sender 5

Found my post useful? Rate me!
07-05-2010 02:26 PM
Profile E-Mail PM Web Find Quote Report
Pages: (2): « First « 1 [ 2 ] 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