Shoutbox

[Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 - Printable Version

-Shoutbox (https://shoutbox.menthix.net)
+-- Forum: MsgHelp Archive (/forumdisplay.php?fid=58)
+--- Forum: Messenger Plus! for Live Messenger (/forumdisplay.php?fid=4)
+---- Forum: Scripting (/forumdisplay.php?fid=39)
+----- Thread: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 (/showthread.php?tid=97202)

[Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 by Domsy on 03-24-2011 at 03:33 PM

Resolved! Thanks, matty!

Hi everyone,

I've been avoiding updating to WLM 2011 and Plus 5 on my main machine for a while now because of a huge issue with one of the scripts I've developed. Basically, it adjusts the taskbar icon for the chat conversation depending upon the contact's current status. It works perfectly on Plus 4.9 with WLM 2009, but when using the exact same script with Plus 5 and WLM 2011 on another machine, it just doesn't. This feature has become essential for me and I just cannot update without it.

My issue is this function I wrote doesn't seem to work anymore:

code:
function ChangeIcon(Window, Icon)
{
    var icon = Interop.Call("user32.dll", "LoadImageW", null, Icon, IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
    Interop.Call("user32.dll", "SendMessageW", Window.Handle, WM_SETICON, ICON_SMALL, icon);
    Interop.Call("user32.dll", "SendMessageW", Window.Handle, WM_SETICON, ICON_BIG, icon); // Required for bigger icon for Windows 7
}
Can anyone please give me some advice on why this is? I cannot explain it. What would be stopping this from suddenly working? It works perfectly before :(

Without this working, I also cannot hope to release the script on the site for others to use.

Thank you very much!

Also, just as a notice, tabbed chats has to obviously be disabled for this to be of any benefit.

Edit: I just did a test to determine if Plus 5 or WLM 2011 is at fault, and it seems it's WLM 2011. I installed WLM 2009 with Plus 5 on my other machine and the script still works fine, so it's a change made with WLM 2011 that's causing the problem. Anyone know what is causing this?
RE: Interop.Call SendMessageW not working since Plus 5/WLM 2011 by matty on 03-24-2011 at 04:52 PM

Last time I looked (investigated) it was something to do with tabbed chats and their container they were placed in. Now since you have disabled tabbed chats it should work.

I just bought a netbook as my main laptop died and obviously programming on a 10 inch screen is next to impossible. Therefore unfortunately I cannot help you any further than this at the moment (plus I am at work).


RE: RE: Interop.Call SendMessageW not working since Plus 5/WLM 2011 by Domsy on 03-24-2011 at 05:02 PM

quote:
Originally posted by matty
Last time I looked (investigated) it was something to do with tabbed chats and their container they were placed in. Now since you have disabled tabbed chats it should work.

I just bought a netbook as my main laptop died and obviously programming on a 10 inch screen is next to impossible. Therefore unfortunately I cannot help you any further than this at the moment (plus I am at work).
Thanks for taking an interest!

Yeah, I was wondering if it was anything to do with the tabbed chats that WLM themselves introduced, but as you said, I've disabled them and it still doesn't work. Still, I'm not sure why the interop call should fail, regardless.

If it would help, I could send you the whole script later when you are available? Although the only part that actually seems to be affected is the function I posted.

Perhaps if nothing else can be figured out, would there be an alternative, perhaps more aggressive, way to change the icon? I'm wondering if it could be done via a custom DLL (maybe C# or something, if C# is capable of doing that without further DLLs, lol). I have no experience with Plus scripts interacting with C# DLLs though, so I'd be at a loss.

Thanks :)
RE: Interop.Call SendMessageW not working since Plus 5/WLM 2011 by matty on 03-24-2011 at 05:06 PM

When you say SendMessageW is failing do you mean the icon just isn't being applied (which is what I assume). What is the return value of the function call?

What I would like you to try is this:

js code:
function OnEvent_ChatWndCreated(pChatWnd) {
    /*
   
        Value           Meaning
        GA_PARENT(1)    Retrieves the parent window. This does not include the owner, as it does with the GetParent function.
        GA_ROOT(2)      Retrieves the root window by walking the chain of parent windows.
        GA_ROOTOWNER(3) Retrieves the owned root window by walking the chain of parent and owner windows returned by GetParent.
       
    */
   
    var hWnd;
    var MAX = 255;
    for (var i=1;i<4;i++) {
        hWnd = Interop.Call('user32', 'GetAncestor', pChatWnd.Handle, i);
        var lpszClassName = Interop.Allocate(2*MAX+2);
        Interop.Call('user32', 'GetClassNameW', hWnd, lpszClassName, lpszClassName.Size);
        Debug.Trace('i :: '+i);
        Debug.Trace('   pPlusWnd.Handle :: '+pChatWnd.Handle);
        Debug.Trace('   hWnd :: '+hWnd);
        Debug.Trace('   lpszClassName :: '+lpszClassName.ReadString(0));
        lpszClassName.Size = 0;
    }
}
Wondering if the Chat Window is still in a container. Running the code will tell us who the parent (if any) is.

Codes ugly I know :P
RE: RE: Interop.Call SendMessageW not working since Plus 5/WLM 2011 by Domsy on 03-24-2011 at 07:28 PM

Oh, thanks! That looks rather awesome.

Unfortunately, it seems it can't locate GetClassName in user32 :| That's weird...

quote:
Interop.Call failed to locate function "GetClassName"

Also, I don't see a definition for pPlusWnd. Is that meant to be pChatWnd?

Edit: Oh and is that a semicolon missing on the hWnd assignment line? Weird how that didn't produce an error.

Edit2: Oh, and yes, sorry... By failing, I meant it just wouldn't assign the icon. The function call seemed fine (can't confirm this very second as I'm waiting for Live Essentials to reinstall after I tested out 2009).
RE: Interop.Call SendMessageW not working since Plus 5/WLM 2011 by matty on 03-24-2011 at 08:33 PM

Check for the updated code in the post. My bad I was in a rush at work.

And just as I suspected. There is still a container around the chat windows:

With tabbed chats enabled (opened 2 chats)
Function called: OnEvent_ChatWndCreated
i :: 1
   pPlusWnd.Handle :: 722674
   hWnd :: 722626
   lpszClassName :: MsgrViewHost View Host
i :: 2
   pPlusWnd.Handle :: 722674
   hWnd :: 722620
   lpszClassName :: TabbedHostWndClass
i :: 3
   pPlusWnd.Handle :: 722674
   hWnd :: 722620
   lpszClassName :: TabbedHostWndClass
Function called: OnEvent_ChatWndCreated
i :: 1
   pPlusWnd.Handle :: 788166
   hWnd :: 722626
   lpszClassName :: MsgrViewHost View Host
i :: 2
   pPlusWnd.Handle :: 788166
   hWnd :: 722620
   lpszClassName :: TabbedHostWndClass
i :: 3
   pPlusWnd.Handle :: 788166
   hWnd :: 722620
   lpszClassName :: TabbedHostWndClass

Tabbed chats disabled (opened 2):
Function called: OnEvent_ChatWndCreated
i :: 1
   pPlusWnd.Handle :: 591454
   hWnd :: 787436
   lpszClassName :: MsgrViewHost View Host
i :: 2
   pPlusWnd.Handle :: 591454
   hWnd :: 722550
   lpszClassName :: TabbedHostWndClass
i :: 3
   pPlusWnd.Handle :: 591454
   hWnd :: 722550
   lpszClassName :: TabbedHostWndClass
Function called: OnEvent_ChatWndCreated
i :: 1
   pPlusWnd.Handle :: 1049672
   hWnd :: 853746
   lpszClassName :: MsgrViewHost View Host
i :: 2
   pPlusWnd.Handle :: 1049672
   hWnd :: 721894
   lpszClassName :: TabbedHostWndClass
i :: 3
   pPlusWnd.Handle :: 1049672
   hWnd :: 721894
   lpszClassName :: TabbedHostWndClass



So instead of passing Window.Handle try calling GetAncestor with either GA_PARENT or GA_ROOTOWNER
RE: Interop.Call SendMessageW not working since Plus 5/WLM 2011 by Domsy on 03-24-2011 at 09:56 PM

OMG! Thank you so much! You are awesome! I had thought it was something to do with tabbed chats, but I didn't know why, and why it would still be an issue even with them disabled.

I've managed it with GA_ROOTOWNER and it works again! YAY!

Thank you! All I need to figure out now, if it's possible, is to detect if tabbed chats are enabled or not, and not to update the icon if not, but it's not that crucial as anyone who would use this when I release it would have them disabled anyway. Still, it would be nice to just avoid it doing it.

Thank you again! I'll consider releasing it at some point soon as others should hopefully benefit from this as well :)


RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 by matty on 03-24-2011 at 10:31 PM

quote:
Originally posted by Domsy
All I need to figure out now, if it's possible, is to detect if tabbed chats are enabled or not, and not to update the icon if not, but it's not that crucial as anyone who would use this when I release it would have them disabled anyway. Still, it would be nice to just avoid it doing it.
HKEY_CURRENT_USER\Software\Microsoft\MSNMessenger\PerPassportSettings\%Messenger.MyUserId%\DisableTabs
0: Enabled
1: Disabled
RE: Interop.Call SendMessageW not working since Plus 5/WLM 2011 by Matti on 03-24-2011 at 10:37 PM

The setting for tabbed chats in WLM 2011 is stored in the registry at
HKEY_CURRENT_USER\Software\Microsoft\MSNMessenger\PerPassportSettings\USERID
under the binary registry value ShowConvWndTabs. This REG_BINARY value consists of 4 bytes representing a little-endian 32-bit integer which equals 1 (01 00 00 00) when tabbed chats are enabled or 0 (00 00 00 00) when they are disabled. Actually, this format is identical to REG_DWORD which defaults to little-endian.

Normally, you should only have to read the value and check whether it's non-zero to determine the state. :)

As for reading a REG_BINARY from the registry, you'll probably want to use some registry functions for that. Screenshot Sender 5 comes with a nifty set of registry functionalities which support REG_BINARY. Feel free to use that script file but please credit the original authors in a comment block at the top of the file.

However, the Screenshot Sender implementation reads binary values as strings where each two bytes represents a Unicode character (as it's mainly used for string data in the script). If you're planning to use this, you'll either need to modify Registry_GetKeyValue to read the value as a number or convert the string data to a number first after calling Registry_GetKeyValue. That's up to you. ;)


quote:
Originally posted by matty
HKEY_CURRENT_USER\Software\Microsoft\MSNMessenger\PerPassportSettings\%Messenger.MyUserId%\DisableTabs
0: Enabled
1: Disabled
That registry value doesn't seem to reflect the tabbed chats setting... I think it's some kind of leftover from previous versions for the tabs in the contact list. ShowConvWndTabs does reflect the correct setting though.
RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 by Domsy on 03-24-2011 at 10:53 PM

Oh, wow, thanks! That's quite involved just to check for something that's not too crucial in my case, particularly if I'm going to be doing that every single event (not sure how heavy registry checks are)... May not be worth it...

Might be best to check this value once on OnEvent_Intialize and if it's enabled, notify the user and disable the script.

... except I can't seem to find a disable script command. Doh... Is there one? Lol. Maybe an 'artificial disable' would be needed instead, but that's extra script that's probably not worthwhile.


RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 by CookieRevised on 03-24-2011 at 10:56 PM

For stuff like checking what windows are created and which childs and parents there are, the well known developers tool Spy++ which comes with Visual Studio (or any other clone like Systree++) is essential.

Also see:
http://blogs.msdn.com/b/vcblog/archive/2007/01/16/spy-internals.aspx
http://blogs.msdn.com/b/vcblog/archive/2007/03/22/spy-update.aspx
if you're interested in how this tool works


----

To detect if tabbed chats is enabled the easiest would be to check that option's registry value. You can also check if the TabbedHostWndClass class exists. I see others already said this...

EDIT:

quote:
Originally posted by Matti
As for reading a REG_BINARY from the registry, you'll probably want to use some registry functions for that. Screenshot Sender 5 comes with a nifty set of registry functionalities which support REG_BINARY. Feel free to use that script file but please credit the original authors in a comment block at the top of the file.
You don't need to read it as a REG_BINARY if that binary string represents a DWORD (4 bytes). Just read it as a REG_DWORD in that case.

As such, a full blown registry libary for just checking 1 value is also very much over the top. Reading that registry key can also be done using the build-in regkey functions.

quote:
Originally posted by Domsy
Oh, wow, thanks! That's quite involved just to check for something that's not too crucial in my case, particularly if I'm going to be doing that every single event (not sure how heavy registry checks are)... May not be worth it...
Depends on what 'event' you mean. If it is just the OnEvent_ChatWndCreated function then there is nothing wrong with that. In fact, it would be essential to first check that registry key before you do anything else. Although it also highly depends if you can enable/disable tabbed chats in WLM 2011 on the fly though. If the user can only enable/disable it with a restart of WLM then doing the check in OnEvent_Initialize is sufficient, but if the user can change that setting whenever he wants you must always check the value before you do what you need to do (eg changing the icon of the chatwindow upon creation of that window).

And as said above, you don't need any library to check just one registry value. Use the build in functions in JScript for that.

quote:
Originally posted by Domsy
... except I can't seem to find a disable script command. Doh... Is there one?
You wont find one because you should not be disabling scripts! You should use programming logic (IF THEN ELSE) to control what your script should do (or not do).
RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 by Matti on 03-24-2011 at 11:08 PM

Disabling your script is not possible and is not such a great idea either. It's not up to the script to decide whether it should be enabled or not. Cookie's suggestion is much better. :)

quote:
Originally posted by CookieRevised
You don't need to read it as a REG_BINARY if that binary string represents a DWORD (4 bytes). Just read it as a REG_DWORD in that case.

As such, a full blown registry libary for just checking 1 value is also very much over the top. Reading that registry key can also be done using the build-in regkey functions.
I fully agree with you, but the RegRead function provided by WScript.Shell will return a VBArray of integers when reading from a REG_BINARY. It doesn't provide a way to override how the value is read, thus one will need to fall back on the Windows API functions to read as a different type. I don't know how a VBArray would look like in JScript though but it doesn't sound too great. :P
RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 by Domsy on 03-24-2011 at 11:10 PM

Ok, wow, thanks for all the info.

My concern about 'every single event' was due to the fact I have to hook many events for my script to work: OnEvent_ContactStatusChange, _ContactSignin, _ContactSignout, and _ChatWndCreated. But yes, ChatWndCreated is probably the only event I actually need to do the registry check for. Cool! I can just do an unobtrusive toast notification, then, notifying the user the script won't function while tabbed chats is enabled.

Thanks very much! If it's ok with you, I'd like to send one/all of you my script when I'm done if you'd be willing to try it out, if you have the time? I'd appreciate your input! Also, you might actually find it really helpful; I don't know what I'd do without it now! (I've actually been using it since 2009!)


RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 by matty on 03-24-2011 at 11:17 PM

You need to check the registry value each time because Microsoft allows the user to, in real time, disable and enable tabbed chats.


RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 by CookieRevised on 03-24-2011 at 11:26 PM

quote:
Originally posted by Matti
quote:
Originally posted by CookieRevised
You don't need to read it as a REG_BINARY if that binary string represents a DWORD (4 bytes). Just read it as a REG_DWORD in that case.

As such, a full blown registry libary for just checking 1 value is also very much over the top. Reading that registry key can also be done using the build-in regkey functions.
I fully agree with you, but the RegRead function provided by WScript.Shell will return a VBArray of integers when reading from a REG_BINARY. It doesn't provide a way to override how the value is read, thus one will need to fall back on the Windows API functions to read as a different type. I don't know how a VBArray would look like in JScript though but it doesn't sound too great. :P
Correct though (I forgot there was no second parameter to specify the type when you read a key). However, there is nothing difficult about a VBArray. In fact using toArray() is all it takes to convert it.

js code:
try {
    var oShell = new ActiveXObject("WScript.Shell");
    var bTabsEnabled = oShell.RegRead("HKCU\\Software\\Microsoft\\MSNMessenger\\PerPassportSettings\\" +  Messenger.MyUserID + "\\DisableTabs");
    bTabsEnabled = new Boolean(bTabsEnabled.toArray().join(""));
} catch(e) {
    var bTabsEnabled = false;
}
the join is just a trick to join all 'integers' elements together like a string to form one number (it doesn't matter what the joined value would be, since we're only interested in true or false, or "0000" or not "0000".

Note that new Boolean(bTabsEnabled.toArray()[0]) could also be used, but then again, that wont work when the binary value would be something like '00 00 33 00'.



RE: RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 by Domsy on 03-24-2011 at 11:27 PM

quote:
Originally posted by matty
You need to check the registry value each time because Microsoft allows the user to, in real time, disable and enable tabbed chats.
Good point. I did just notice this myself while I was testing, and unfortunately no events get fired when the setting is changed.

However, because of how I've structured my code, I can keep the registry check being done only when absolutely required. For instance, it would only ever need to be fired on a contact sign-in event, for example, if a conversation is open with that user.

This should be fine! All I have to do now is figure out how I should be reading this value ;) Fun!

Edit:
quote:
Originally posted by CookieRevised
Correct though (I forgot there was no second parameter to specify the type when you read a key). However, there is nothing difficult about a VBArray. In fact using toArray() is all it takes to convert it.

js code:
try {
    var oShell = new ActiveXObject("WScript.Shell");
    var bTabsEnabled = oShell.RegRead("HKCU\\Software\\Microsoft\\MSNMessenger\\PerPassportSettings\\" +  Messenger.MyUserID + "\\DisableMSNToday");
    bTabsEnabled = new Boolean(bTabsEnabled.toArray().join(""));
} catch(e) {
    var bTabsEnabled = false;
}

Oh wow, ok, I guess you did it for me. Thanks! Lol! I had never expected this much help today. I really appreciate it, everyone :)
RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 by CookieRevised on 03-24-2011 at 11:33 PM

PS: note that I my example code I used
"DisableMSNToday" instead of "DisableTabs" (for testing purposes). So make sure you edit it to the correct key :p
I've edited my previous post....


RE: RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 by Domsy on 03-24-2011 at 11:38 PM

quote:
Originally posted by CookieRevised
PS: note that I my example code I used
"DisableMSNToday" instead of "DisableTabs" (for testing purposes). So make sure you edit it to the correct key :p
I've edited my previous post....
Yep, thanks! I did notice, hehe. I was taking the code as advice rather than a complete copy-paste (I'm not actually as hopeless as I'm seeming in this thread, LOL! :D)

I think we also need to check ShowConvWndTabs anyway, right? ;)
RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 by CookieRevised on 03-24-2011 at 11:41 PM

quote:
Originally posted by Domsy
My concern about 'every single event' was due to the fact I have to hook many events for my script to work: OnEvent_ContactStatusChange, _ContactSignin, _ContactSignout, and _ChatWndCreated.
in that case you must check the value in each and every event!
Because between contact status changes for example, the user could have enabled/disabled tabbed chatting. In essence, you need to check the value each time your script manipulates (sets) the icon!!

This said, depending on what your script _exactly_ does, and how WLM 2011 _exactly_ uses its container windows and what the function is of that other key (ShowConvWndTabs) - can't check, I don't run WLM 2011 atm- it may also be possible to simply forget about checking those registry keys, and simply check if the container window, for which you want to manipulate the icon, exists (which you should do anyways or your icon APIs might fail). It might be enough.
RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 by Domsy on 03-24-2011 at 11:46 PM

quote:
Originally posted by CookieRevised
in that case you must check the value in each and every event!
Because between contact status changes for example, the user could have enabled/disabled tabbed chatting. In essence, you need to check the value each time your script manipulates (sets) the icon!!
Yep! Luckily, I did a main function that does this so I just need to modify that rather than each event :) Of course, you'd be expecting that of me anyway, hehe.

I think there will be a slight issue if someone is to disable tabbed chats with conversations already open. No matter what, they'll all revert to the default icon and won't change until there's a relevant event update. I don't think I can avoid this, but it's no biggie... I don't expect tabbed chats to be enabled and disabled constantly all the time! It should be a one-time issue, and it's not disastrous anyway, hehe.

This, luckily, doesn't apply to enabling tabbed chats as well, as the icon gets replaced with the default.

Edit (crazy quote madness! lol):
quote:
Originally posted by CookieRevised
This said, depending on what your script _exactly_ does, and how WLM 2011 _exactly_ uses its container windows and what the function is of that other key (ShowConvWndTabs) - can't check, I don't run WLM 2011 atm- it may also be possible to simply forget about checking those registry keys, and simply check if the container window, for which you want to manipulate the icon, exists (which you should do anyways or your icon APIs might fail). It might be enough.
Oh! Yes, I was wondering that myself... Ahhhhh! I'll investigate. I guess Spy++ should be handy (thanks for that! I have it with Visual Studio but have never used it).

Edit 2:
Looks like when you have tabbed chats disabled, every single conversation has it's own tab container (class: TabbedHostWndClass) whereas if tabbed chats is enabled, there's only one of them, which holds all the actual conversation windows (IMWindowClass).

As far as I can tell, from that, it won't be of any help as you can't determine, this way, if tabbed chats is enabled or not unless you have more than one window, and it would be awkward to figure out anyway. I guess the registry option is the only way! (Unless I've missed something, which is probable, lol).

Edit 3:
All done! Works great so far! Thanks for all the help :)

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('')));
Without the typecasting, I think it was using a string literal of "0000".

Thanks! Any of you willing to try it out before I make an attempt at releasing at some point? :)
RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 by matty on 03-25-2011 at 01:50 PM

Cookie couldn't you do something along these lines?

js 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.
RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 by CookieRevised on 03-25-2011 at 03:50 PM

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'
RE: [Resolved] Interop.Call SendMessageW not working since Plus 5/WLM 2011 by Matti on 03-25-2011 at 07:24 PM

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:

js code:
var bool = (Boolean)(5);
is identical to:
js 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.
js 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:
js 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!
js 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:
js code:
bTabsEnabled = (Boolean)((Number)(reg.toArray().join('')));
or simply:
js code:
bTabsEnabled = !!(1*(reg.toArray().join('')));
At least it'll have the proper type. :P