What happened to the Messenger Plus! forums on msghelp.net?
Shoutbox » MsgHelp Archive » Messenger Plus! for Live Messenger » Scripting » [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011

Pages: (3): « First « 1 2 [ 3 ] Last »
[Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011
Author: Message:
matty
Scripting Guru
*****


Posts: 8336
Reputation: 109
39 / Male / Flag
Joined: Dec 2002
Status: Away
RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011
Cookie couldn't you do something along these lines?

Javascript code:
// Registry key locations  
var HKEY_CURRENT_USER = 0x80000001;
var HKCU = HKEY_CURRENT_USER;
var HKEY_LOCAL_MACHINE = 0x80000002;
 
// Registry key constants
var ERROR_SUCCESS = 0;
var KEY_ALL_ACCESS = 0xf003f;
 
// Registry Notify Filters
var REG_NOTIFY_CHANGE_LAST_SET = 0x4;
 
// Script variables
var MAX = 255;
var RegHandle;
var INFINITE = 0xFFFFFFFF;
var WAIT_FAILED = 0xFFFFFFFF;
 
function Registry_OpenKey(HKEY, lpSubKey, samDesired) {
    if (typeof samDesired === 'undefined') samDesired = KEY_ALL_ACCESS;
    var h = Interop.Allocate(4);
    Interop.Call('advapi32', 'RegOpenKeyExW', HKEY, lpSubKey, 0, samDesired, h);
    return h.ReadDWORD(0);
}
 
function Registry_CloseKey(HKEY) {
    return Interop.Call('advapi32', 'RegCloseKey', HKEY) === ERROR_SUCCESS;
}
 
function OnEvent_Initialize() {
    if (Messenger.MyStatus < STATUS_INVISIBLE) return false;
    MonitorRegistry(HKCU, 'Software\\Microsoft\\MSNMessenger\\PerPassportSettings\\' +  Messenger.MyUserID, true);
}
 
function OnEvent_SigninReady() {
    OnEvent_Initialize();
}
 
function OnEvent_Uninitialize() {
    Registry_CloseKey(RegHandle);
}
 
function MonitorRegistry(HKEY, lpSubKey, bContinueMonitoring) {
    RegHandle = Registry_OpenKey(HKEY, lpSubKey);
   
    var SECURITY_ATTRIBUTES = Interop.Allocate(12);
        SECURITY_ATTRIBUTES.WriteDWORD(0, 12);
       
    var lpszName = Interop.Allocate(2*MAX+2);
        lpszName.WriteString(0, 'MonitorRegistry');
    var lpName = Interop.Allocate(4);
        lpName.WriteDWORD(0, lpszName.DataPtr);
       
    var hEvent = Interop.Call('kernel32', 'CreateEventW', SECURITY_ATTRIBUTES.DataPtr, true, false, lpName.DataPtr);
   
    var retVal = Interop.Call('advapi32', 'RegNotifyChangeKeyValue', RegHandle, false, REG_NOTIFY_CHANGE_LAST_SET, hEvent, false);
   
    if (retVal === ERROR_SUCCESS) {
        if (Interop.Call('kernel32', 'WaitForSingleObject', hEvent, INFINITE) === WAIT_FAILED) {
            // WAIT_FAILED, NO CHANGE OCCURED
        } else {
            // CHANGE OCCURED
            // READ ShowConvWndTabs
           
            Registry_CloseKey(RegHandle);
            Interop.Call('kernel32', 'CloseHandle', hEvent);
            if (bContinueMonitoring) {
                MonitorRegistry(HKEY, lpSubKey, bContinueMonitoring);
            }
        }
    }
}


By the looks of things doing this will crash WLM as WaitForSingleObject is a synchronous call. You would have to externalize it.

This post was edited on 03-25-2011 at 02:05 PM by matty.
03-25-2011 01:50 PM
Profile E-Mail PM Find Quote Report
CookieRevised
Elite Member
*****

Avatar

Posts: 15519
Reputation: 173
– / Male / Flag
Joined: Jul 2003
Status: Away
RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011
As you found out, nope you can't because the scripting engine doesn't support such calls (same with subclassing).
You could indeed write a DLL for that though. Although for this particular script I think it is not worth the hassle.



quote:
Originally posted by Domsy
A little modification I had to make. It didn't seem to like the "new Boolean()" thing, and I had to typecast the join result as a Number. Ended up with:
code:
bTabsEnabled = (Boolean)((Number)(reg.toArray().join('')));

(y)...
Yeah, my 'trick' always returned true, because apparently no matter what string you got, it always is converted to true as a boolean. I didn't tested it with a binary value of 0x0, sorry about that....
(seems strange that a string of "0" would result in true though - coming from VB point of view which does this automatic typecasting a lot better in this case :p)

So, all you indeed needed todo was to first convert that string into a number:
bTabsEnabled = new Boolean((Number)(reg.toArray().join('')));

btw, this is the same (and shorter) and would work as expected too (as long as the binary value consists of 4 bytes):
bTabsEnabled = reg.toArray().join('') != '0000'

This post was edited on 03-25-2011 at 04:33 PM by CookieRevised.
.-= A 'frrrrrrrituurrr' for Wacky =-.
03-25-2011 03:50 PM
Profile PM Find Quote Report
Matti
Elite Member
*****

Avatar
Script Developer and Helper

Posts: 1646
Reputation: 39
31 / Male / Flag
Joined: Apr 2004
RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011
Note that there actually is no such thing as type casting in JScript. It may look and work like type casting, but actually you're calling a function which happens to behave like a cast. :P

The following code:
Javascript code:
var bool = (Boolean)(5);

is identical to:
Javascript code:
var bool = Boolean(5);

The Boolean() function acts like a cast, in the sense that it takes any variable and produces a boolean. When working with inheritance, the difference is much more clear.
Javascript code:
var A = function(){};
var B = function(){};
B.prototype = new A;
 
var b = new B;
Debug.Trace(b instanceof A); // -> true
Debug.Trace(b instanceof B); // -> true
var a = (A)(b);
Debug.Trace(a instanceof A); // -> false?!?!
Debug.Trace(a instanceof B); // -> false?!?!

When B inherits from A, one could try to cast an object b of class B to class A using something like (A)(b). However, this simply calls the function (constructor) A with the (unused) parameter b and thus this call returns void. Because JScript uses prototypical inheritance, such casting is simply not possible. Even with primitive types such as Number or Boolean, you'll always end up with a copy of the original. You probably won't even notice this since those primitive types don't compare by reference, but it happens. :P



Another suggestion: don't use "new Boolean(o)" when converting to a boolean, either use "Boolean(o)" or "!!o". Here's why:
Javascript code:
var a = Boolean( "true" );
Debug.Trace(a); // -> true
Debug.Trace(typeof a); // -> boolean
 
var b = !!"true";
Debug.Trace(b); // -> true
Debug.Trace(typeof b); // -> boolean
 
var c = new Boolean( "true" );
Debug.Trace(c); // -> true
Debug.Trace(typeof c); // -> object?!?!

The explanation for this is that when using "new", you're always creating an object. The same happens with the "this" object, it's always an object - even when you're working on a primitive class!
Javascript code:
Number.prototype.isFive = function() {
   Debug.Trace(typeof this); // -> object?!?!
   return this === 5;
}
Debug.Trace( (5).isFive() ); // -> false?!?!



So yes, either compare the string to '0000' or use a conversion such as:
Javascript code:
bTabsEnabled = (Boolean)((Number)(reg.toArray().join('')));

or simply:
Javascript code:
bTabsEnabled = !!(1*(reg.toArray().join('')));

At least it'll have the proper type. :P
Plus! Script Developer | Plus! Beta Tester | Creator of Countdown Live | Co-developer of Screenshot Sender 5

Found my post useful? Rate me!
03-25-2011 07:24 PM
Profile E-Mail PM Web 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