sms: decoding advertflags for "asap"
before i start writing this, let me give some credit to robert mahle for getting me some information confirming stuff in this post. we've been working a bit (har har, no pun intended) trying to figure out how to decode the value of "asap" from the sms admin console into a spreadsheet. before i move too far ahead, some background for you...
in this previous post about displaying advertisement info via a script, we ran into some confusion trying to decode the advertflags value. trying to get "asap" to show up just wasn't happening. the real confusion about this is "asap" is not treated like other schedule data that you'd find by looking for the sms_scheduletoken data type. usually it's held under assignedschedule. despite the fact that "asap" shows up in the sms admin console as a schedule, it's held under advertflags. the sdk confirms this:
AdvertFlags Data type: uint32 Access type: Read/write Qualifiers: Bits When to announce the advertisement to the user. These bit flags must be coordinated with the bit flags specified in the ProgramFlags property of the advertised program. For example, if you set ONUSERLOGOFF, the NOUSERLOGGEDIN flag in the program must be set. If the flag settings do not match, the program will not be advertised. The default value is 0. Bit flags are as follows: IMMEDIATE (bit 5) ONSYSTEMSTARTUP (bit 8) ONUSERLOGON (bit 9) ONUSERLOGOFF (bit 10) NO_DISPLAY (bit 25) ONSLOWNET (bit 26)
in order to decode advertflags, you have to have a little bit of understanding regarding how bit flags work. don't worry; we'll get into all that in a second. you know, as long as we're covering "asap" stuff, i suppose we'll use that in our example.
alright, the first thing to do would be to create a little script that will dump out all of your advertisements that are set to "asap." don't sweat it. no coding required. here's a little something you can use. it's from the book sms 2003 recipes: a problem-solution approach. i modified it a little bit for the decoding work we'll be doing.
strSMSServer = "mySMSServer" Set objLoc = CreateObject("WbemScripting.SWbemLocator") Set objSMS= objLoc.ConnectServer(strSMSServer, "root\sms") Set Results = objSMS.ExecQuery("SELECT * From SMS_ProviderLocation WHERE ProviderForLocalSite = true") For each Loc in Results If Loc.ProviderForLocalSite = True Then Set objSMS = objLoc.ConnectServer(Loc.Machine, "root\sms\site_" & Loc.SiteCode) strSMSSiteCode = Loc.Sitecode End If Next Set colAdverts = objSMS.ExecQuery("Select * From SMS_Advertisement order by AdvertisementName") For Each objAdvert In colAdverts if (objadvert.advertflags AND 2^5) then wscript.echo objAdvert.AdvertisementName & " ------- " & objAdvert.AdvertFlags end if Next
if i run this script in my environment, i'd get output like the following... (i've changed the names around in case you thought we ran apps from a company called some).
C:\temp>cscript smsadvertisement.vbs Microsoft (R) Windows Script Host Version 5.7 Copyright (C) Microsoft Corporation. All rights reserved. Some Custom Screensaver ------- 33554464 Some Antivirus App ------- 33554464 Some Email Disaster Recovery Analyzer ------- 33554464 Some Monitoring Agent ------- 33554464 Some Zip Utility 9.0 ------- 33554464 Some Webby App ------- 33554464 |
the value following the ------- is the value of advertflags. in my environment, all of these advertisements contain the same value for me (may not be the case for you). i'm going to use the first one called "some custom screensaver." the value, obviously for this one is 33554464. as a reminder...
bit 1 | bit 2 | result |
---|---|---|
0 | 0 | 0 |
1 | 0 | 0 |
0 | 1 | 0 |
1 | 1 | 1 |
when using AND as a bitwise operator, this is basically what occurs: as you can see, anything with both comparison bits set to 1 will result in 1. otherwise, you get 0. hold on to that... if you look at the script above, we perform a bitwise AND operation. it happens right here:
if (objadvert.advertflags AND 2^5) then wscript.echo objAdvert.AdvertisementName & " ------- " & objAdvert.AdvertFlags end if
okay, real quick math lesson: 2 to the 5th is ... ? that's right, 32. keep that magic value in your head. it's easier to do it this way because in the sdk, it specifies it's the 5th value. instead of multiplying 2*2*2*2*2, we just raise it to the power of the 5. the 5th bit is "immediate" otherwise known as "asap". take the value you're working with and put it in your calculator as a decimal value. now, click the "bin" radio button. you'll see that the value of 33554464 is converted to 10000000000000000000100000. now, do the same thing for 32 (or 2^5). you'll get 100000. just to make it easier to understand visually, i added leading zeroes, getting this: 00000000000000000000100000. now stack them together:
10000000000000000000100000 00000000000000000000100000 -------------------------- 00000000000000000000100000 |
remember above when i told you that both comparison bits have to be 1 in order for the result bit to be 1? well, look at that. we only have a single place that it occurs.
ANDing the values together gives you a value of 32. (if you don't believe me, paste 100000 into your calculator as a hex value and convert it to dec.) the if/then script statement above is doing this for you.by the way, since you're only checking for one value, the result being greater than 0 is a successful return. technically you could write it as:but you get the idea. since we know the value we return is 32, which is greater than 0, then it successfully found the 5th bit to be turned on. you could also set it to = 2^5 instead.if (objadvert.advertflags AND 2^5) > 0 then wscript.echo objAdvert.AdvertisementName & " ------- " & objAdvert.AdvertFlags end if
I was trapped in AssignedScheduleEnabled, thanks for pointing me to AdvertFlags
ReplyDelete//Johan
awesome man. glad it helped!
Delete