user assistance 980227 andyp, lamadio, et. al. - abstract ... - contents ... overview ... events sessions, counts, and aging aging (todo) testing: hooks, utils, etc. testing: scenarios testing: specifics testing: anomalies - overview ... uassist events intelli-menu app mgmt - ... ... - events IUserAssist FireEvent(pguidGrp, eCmd, dword, wP, lP) Set/QueryEvent(..., puai) guid,cmd,dword,wP,lP events standard: UI*, RUN*, etc. user: USER+n (NYI) logging guid,cmd,wP,lP typically encoded as "cmd:wP,lP" RUNPIDL:%csidl2%/vb/readme.lnk RUNPIDL:%csidl2%/command prompt.lnk RUNWMCMD:0xff,1f8 instrumentation beta-only (but must test!) just like logging, but... not aged "UserAssist2" not UserAssist regkey Instrument = DWORD 1 registry set uassist=$HKCU/sw/msft/win/cv/explorer/UserAssist $uassist/{guid}/Count/... compression and encryption NYI - sessions, counts, and aging we have several records: ctlsession qtMru, sidCur ctlcount:ctor sidMru, cCnt foo sidMru, cCnt each daily login to windows defines (roughly) a session. a logged item consists of a 'decayed' count and a MRU session time. there is a magic default 'ctor' item which serves as a proxy for not-yet-created items. a UASession has a session id, and a timestamp for the last update to that id. sidCur is updated at shutdown time *if* 12 hours have passed since the last incr. the time is a UATIME, stored in 1-minute (approx) increments (we take a system time, turn it into a file time, and shift it by >> 29). we chose this to fit in a DWORD, last forever, be easy to compute, and (ideally) be in 'intuitive' units. (given that we only store it in one place this may not be necessary; originally the time was stored in many places, hence the constraints). a UACount has a count cCnt and a session id sidMru for the last update to that count. there is a special count, ctlcount:ctor, which we return on a Query for a non-existent entry. for correctness and perf, we don't want to create an entry on a Query (menu reference), only on a Set (menu leaf invoke). however we want the Query's to behave *as if* they started out w/ a count of 1 and then were aged. 'inheriting' ctlcount:ctor lets us do this. note that count:ctor is used for *all* counts: menus, app mgmt, etc. so once it ages down to 0, everyone who refs it will look like 0. BUGBUG this may cause pblms for app installs (if you install an app but haven't yet used it, it will look like its unused). there is a way to tell if a count came from a default or not, so probably that should be used in this case. similar issues exist when changing (adding/moving) menu items. should changing an item increment its count? if not, untouched things which are moved after count:ctor ages to 0 the sidMru's are kept around for aging. read on... - sessions a session is defined as a logoff *plus* a minimum time interval. that is, one can logon/off many times, but only 1 session will pass each 12 hours. we also have an idle timer. going idle for 12 hours forces a session. note however that we only force one such session (so if one is idle for a 1 week vacation, it is still just 1 session). 'idle' means no keyboard or mouse changes. on nt5 our idle detection is exact. on nt4 we must simulate some things, causing as much as a 2x error. (todo: checking for IdleTime more frequently, e.g. at 0.25*SessionTime, could reduce this error considerably). - aging aging is done lazily. (Query is really a GetCount, Set is really an IncCount) the cCnt in a UACount is (usually) unaged. it, together w/ the sidMru give an 'aged' count. on a Query, we age cCnt w.r.t. sidMru to give a 'real' count. a Query does not update the UACount; it simply computes what it 'should' be and returns the result. the only time we actually update a UACount is when we Set it. in that case, we age it (per Query), add 1, and then store back out the new (aged) cCnt and the new (now!) sidMru. we currently don't delete a UACount when it ages to 0 (on Query). BUGBUG we probably should. we currently don't scavenge UACounts which would be aged to 0 if queried. BUGBUG we probably should. - registry keys we support the following registry keys (currently just for debugging): $uassist/Settings/ SessionTime (12 hrs) min time (mins) between sessions IdleTime (12 hrs) min idle time (mins) before force session Backup (0) rename keys to "del.xxx" rather than deleting NoPurge (0) don't auto-delete keys when they decay to 0 NoEncrypt (0) don't encrypt keys NoLog (0) turn off all logging Instrument (0) turn on instrumentation (UserAssist2, no decay) while these could be exposed if we see fit, we should not do so w/o signoff from PM, dev, qa, and docs (since all would be impacted). the keys are read once on explorer startup. thus if they're changed you must restart explorer (e.g. logoff/logon). - todo (BUGBUG) version # in UserAssist section! done. naming: uem* -> ua* - testing: hooks, utils, etc. we have several hooks/etc. for testing. force a new session immediately (simulate a reboot and a 12-hour delay) set 'SessionTime' regkey to 0 minutes between sessions alt+F4 to shutdown windows cancel force the menus to refresh (simulate a reboot) turn off intelli-menus turn back on 'new session' (above) also does this turn off all logging (to measure perf hit) set 'NoLog' regkey to 1 BUGBUG this is obsolescent; fix this! (NYI: in progress) there are utils to dump IDMs, etc. these can form the basis for a dump utility which prints the UAssist data in symbolic form. - testing: scenarios ... - testing: specifics post-install - everything should look like it has a count of 1 - after a few sessions, everything which hasn't been clicked since install should disappear (since the 'default' count will age to 0) count aging: does it happen correctly time/count wrap: what happens when various counts wrap - session id and MRU time - item count and MRU session - ctlsession gets deleted/recreated to sid=0, so other counts reference bigger sids and math goes < 0 (like wrap?) default counts missing entries clicking on a leaf should create entries for it and all grand-parents extra entries querying an item should *not* create *any* reg entries top-level menu should never go away (e.g. docs, pgms, help, etc.). NYI: regkey should be deleted when count ages down to 0 (to keep size down). NYI: registry should be scavenged periodically to find 0's. NYI: reentrancy. e.g. browse in separate process! NYI: versioning. NYI: don't up session id on shutdown if it's not already there (for PSS). - testing: anomalies this section describes known 'weirdness' in the spec and/or implementation. it remains to be decided if they're bugs or features. 1. parent not aged, all kids aged, kids come up blank (chevron only). we've been debating what to do about this (and how frequent it will be). right now we're punting (i.e. we're calling this a feature). 2. installing a program doesn't do anything to the counts. so you can install office, then bring up the start menu and not see office! 2b. OEM install is potentially even worse... 3. (and 2c) moving a menu item leaves the old count orphaned, and creates no new item. 4. we're currently using office's definition of a 'session'. we probably need something better tailored to windows. 5. logging *must* be off in Germany.