Contact

Subscribe via Email

Subscribe via RSS/JSON

Categories

Creative Commons Attribution 4.0 International License
© Rakhesh Sasidharan

Elsewhere

Recreating Windows profiles; Internet Explorer passwords

I had to recreate a user’s Windows profile the other day and made the novice mistake of removing the profile from his computer by just deleting the folder from c:\Users. Not a good idea coz that leaves all the registry stuff behind. The correct way to remove his profile would have been to go via the System properties, User Profiles, and then delete the profile. If it complains about the folder not being removed, then remove the folder.

What happened in my case since the registry stuff was still leftover is that Windows wouldn’t create a new profile folder because it thought the profile folder had an error. It kept logging the user in with a temporary profile and complained so: “You have been logged on with Temporary profile”.

Worse, I always thought HKEY_USERS was where all the registry stuff was stored so that’s where I kept looking to try and delete the registry bits manually. Finally I realized it’s under HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList – doh! HKEY_USERS only has the registry hives for actively loaded profiles – not necessarily the one logged in interactively, but also user accounts running in the background or that have recently run (via “run as” etc).

So I went to HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList, found the profile (which now had a .bak suffixed to it), deleted it (because I want him to start afresh), and that got things working again.

After recreating the profile the user told me he wanted his Internet Explorer saved passwords. These are stored under HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\IntelliForms\Storage2 but I hadn’t saved his HKCU hive before deleting the profile. Not a problem – I had a backup of the profile folder, so I:

  1. Copied the NTUSER.DAT file from there to my computer (NTUSER.DAT is basically the HKCU hive for his account),
  2. Loaded it into my registry as a temporary hive,
  3. Exported ...\Software\Microsoft\Internet Explorer\IntelliForms\Storage2 from this temporary location to a .reg file,
  4. Opened this file in notepad and renamed the root to HKEY_CURRENT_USER.

I then sent the .reg file to the user and once he opened it the passwords were imported into his registry.

Here’s the command I ran from an elevated command prompt to load the ntuser.dat file to a temporary location HKLM\TempHive:

Using the above temporary location, I had to rename HKLM\TempHive to HKEY_CURRENT_USER once I exported the key and opened in notepad.

[Aside] What’s up with LibreSSL?

Good read: LibreSSL: More Than 30 Days Later

I loved this bit:

I could spend an hour explaining why supporting obsolete broken systems is detrimental, but if I told you all the things I have learned about VMS, it would probably violate your human rights. Instead, I think one example will suffice.

In theory, this looks like we’re going to use the good code on a posix system. But there’s just one problem. The code is testing for FIONBIO, which is only defined if you include the right header. If you forget to include the right header, the compiler falls back to the workaround. The mere existence of workarounds means they can be picked up accidentally, and you’ll never know.

[Aside] Shellshock – Stop blaming Bash!

Am sure everyone’s heard of the Bash Shellshock bug by now. Basically, Bash (like most other shells) has environment variables. When launching Bash you can set an environment variable too, and the newly launched Bash process will inherit that variable. So far so good, but what researchers discovered is that due to the bug you can also set environment variables such that you sneak in some commands into them; and the resulting Bash process will execute these commands for you. That’s wicked because you (the admin) might not want users to run such commands, or worse the Bash process might be running with additional rights in which case the sneaked in commands too will run with these additional rights.

There’s a lot of hue and cry over this and blame assigned to the GNU project and its creator Richard Stallman, but I liked this post by Andrew Auernheimer. The whole post is a must read but here’s the bit I would like to highlight (emphasis mine):

Shellshock is not a critical failure in bash. It is a critical failure in thousands of people who knew a tool so useful that they decided to deploy it far beyond its scope. A tool so resilient that it it did not fall over when everyone deployed against best practices. Everyone knew in the nineties that when you execute a UNIX command with untrusted input, you clear away the environment variables first. Anyone that has untrusted input embedded within a shell script does not know what they are doing. The fact that there is a way to get bash to execute untrusted code is unsurprising. The thing that surprises me is the sheer number of developers who thought it would be otherwise in complete contrast to UNIX parables and common sense.

Spot on!

Here’s a blog post on clearing the environmental variables. More techniques are in this StackOverflow post. (I haven’t made Bash scripts for a long time now, so I just got these via a quick DuckDuckGo search. There might be other/ better techniques around!)

ps. Since posting this I came across a post on the bad code state of Bash. It doesn’t take away the fact that Bash isn’t solely to be blamed for Shellshock but I thought to mention it because I found it an interesting read.

Outlook 2010, Contacts, InterAction

Had a good time with one the secretaries today helping him out with Outlook contacts and the Country field.

By default Outlook has a Country field you can sort on or group by. But what is this Country field? You have the option of setting a business address, a home address, and an “other” address; but there’s no option to define a Country value independent of these. Through trial and error I figured that the Country field is automatically set by Outlook when you set a Business/ Home/ Other country. Which makes sense. (I didn’t test what happens if the countries for each of these are different. My guess is the last modified entry takes precedence).

Anyways, there’s a catch with the Country field being automatically set this way. If you create a contact in Outlook it works, but what if the contact is added some other way? Maybe the contact is imported, or in our case we use a CRM software called InterAction which syncs Outlook contacts with its database.

When someone adds a contact to InterAction and set the Business Country as something, Outlook doesn’t automatically set the Country value while syncing. Even opening and save/ closing the contact in Outlook doesn’t help. You have to open the contact, go to the Business address field, and then save/ close for Outlook to set the Country field. That’s not very practical so in general it’s wiser to ignore the Country field in Outlook and use the Business/ Home/ Other country field.

That was the first issue the secretary had. Next was that many Outlook contacts that didn’t have a Business Country had the value set as United Kingdom in InterAction. That’s odd because the value should have synced! I tracked it down to an InterAction setting. You see, when you make a new contact in InterAction it expects a Business Country field and leaves the default as United Kingdom (possibly a setting from our admins). But what happens is that – and this is a big I think – if a contact you open in InterAction does not have a Business Country value then it shows a value of United Kingdom even though the value is actually empty! That’s why InterAction showed these contacts as of being in the UK while Outlook had a null value.

Nice. That’s two things sorted for the secretary.

The last thing was how can he enter the correct Business Country values? For this I first grouped his contacts by the Business Country field and then sorted by the Business Phone field. This way I could see in one place all the entries that needed fixing, and based on their phone number I can decide which country they must belong to. So can I batch change the Business Country value? Sure! Once you group the contacts thus (by the field you want changing, in this case Business Country) select multiple contacts and drag and drop to the group you want and their field is automatically updated. Sweet! To make it even easier if you have many groups, simply go to the View tab and collapse all groups initially. Then expand the one without Business Country, and drag and drop to the group you want. Easy peasy!

That’s all. No screenshots as I typed this post from my iPhone using the WordPress app.

[Aside] Creating a Windows USB to Go drive

Starting today I plan to make posts like these which are just links to other blogs. I find myself referring to this blog nowadays just to check out my notes on a topic or to see the links I refer to. It’s more convenient than my browser bookmarks as there’s more context in a blog post and it’s quicker to search.

Initially I thought of having a separate blog to post such “asides” but that’ll just be one more blog to maintain and search and make a decision when I want to post something. So I’ll just stick to this blog, but put these posts in a separate category and mark them so in the title.

Context is everything …

Some of my colleagues call me “Mr. Fix It” while the users I support call me a magician. That’s because I am good at fixing problems and getting to the root of an issue. I tend to immerse myself in the problem I am solving and easily pick up whatever techniques and knowledge that might aid in troubleshooting. I think this is because I have a problem solving mind and I enjoy finding out why things don’t work the way they are supposed to. My mind likes to understand how things work and fit together. Not all things mind you so I wouldn’t really call myself a geek, just things to do with computers. The weirder the problem is, the happier I am to take a stab at it! And my day is made if solving a problem also involves me picking up new stuff I didn’t know so far.

Now, in the context of my work life this is a very useful skill to have. I think it gives me an edge over my colleagues because I am like a hungry warrior. They might be stronger and bulkier than me (read: know more stuff than me because of experience) but they are not as hungry nor do they live for fixing stuff. As long as things work, they are happy to let it be. They don’t go about poking beneath it or ask questions to understand why things are so. Nor do they lose themselves in a problem and chase it down to its end. These are advantages I have over most people I have worked with, and I am happy about that.

But take these skills out of this context and they backfire. When my wife tells about a problem for instance, my mind goes on a tangent thinking how to fix the problem. I ask questions to try and understand the problem. I offer solutions – maybe crazy ones – to try and solve the problem. And if she gets put off by the questions or doesn’t like the solutions, I just move on because as far as I am concerned there’s nothing more for me to do. My mind lacks the emotional element that empathizes with her. It doesn’t understand that sometimes asking more questions isn’t the correct response to the situation. It is not willing to just listen to the problem without thinking of ways to solve it. And if the problem is something which I can’t find a solution for immediately – most “life problems” are that way – then my mind ends up ruminating over it as is my nature. That doesn’t work well for such problems; so rather than get bogged down it, a more practical part of my mind kicks in and tells me not to ruminate like this. That’s easier said than done, so over time I have developed a shield to such situations – if the problem’s fixable, I offer suggestions; if it’s not, or the other person doesn’t seem interested, I just don’t care about it. Which again doesn’t work out well in this context because now I give an impression of someone who doesn’t care! Not only am I a jerk now who can’t empathize and keeps asking questions, I am also someone who actively doesn’t care and blocks himself from the situation.

Context is everything!

These same skills and strategy however work well when it comes to work colleagues and users. When a colleague calls me up to talk about some work problem they don’t really want empathy or for me to care much. They want someone who listens and offers practical suggestions. They want someone who can offer a different point of view to the problem. They want zero emotional investment from you, just a listening box.

Had the above illumination when I was driving to work today, so thought I’d put it down before I forget …

WordPress post formats

Today I learnt of WordPress post formats. They are useful if you want to have a blog of links for instance, wherein the title of the post will be the link you are referring to and the content is some blurb about the post.

There are many post formats but the formats you can actually use depend on theme you have. Not all themes support asides; here is a list of themes that do. You can also search for themes that support post formats by doing a feature filter for “Post Formats”:

feature-filter

Mind you though, not all themes support all the post formats so it’s important to do a preview to see if the formats you want are supported.

Once you install a theme that supports post formats the supported formats will appear when you compose a new post:

formats

I was confused initially on how to make an “aside” post. This is the type of post you need for a link blog as above. After a bit of trial and error I realized what I have to do is (a) set the post type to “Aside”, (b) Leave the title blank, and (c) have the first entry of the post be a link. Like this:

new-aside

Nexus 7 OTA errors

Today I finally upgraded my Next 7 (2013) tab to Android 4.4.4. Finally!

For the past few months it’s been stuck on 4.4.2. I tried OTA updates but each time it would download and try to install – and fail. On the recovery screen it would throw errors about signatures not matching. Initially I thought maybe my ISP or someone in the middle was trying to hijack the update, so I tried couple of times via VPN too. Not that that helped!

Finally I decided to try a manual update via sideloading. Followed the instructions at this link (note: at step 4, if you are using Clockwork Mod Recovery like I was, go to the option that says install ZIP and then you’ll find an option to install ZIP via sideload). Did that, and sideloading failed with an error (from Recovery) that /system/lib/hw/power.msm8960.so has unexpected contents. Great!

Went to that location using Solid Explorer on the tablet and found there’s no file with such a name. Instead there was a power.msm8960.so.bak so I renamed that to power.msm8960.so. Repeated above process; and got an even more weird error:

error

This time I couldn’t find any file in the location shown.

By now I was having a suspicion that something I changed in the base system was what’s causing there errors (I got a similar impression from various other posts too). Two things I did do to this tab were to 1) root it and 2) install the Franco Kernel. Either of these could be the issue but I decided to start with Franco. Thankfully I had backed up my previous kernel – note to self & readers: always backup the original kernel! – so I restored that, rebooted, and tried to sideload. This time I got the power.msm8960.so error again, so I rebooted again, renamed the file again, and tried. And – phew! – it worked this time.

So the problem was Franco kernel. Wish I was aware of this beforehand, I could have updated a long time ago! Anyhow, for next time I know I have to restore the old kernel and rename any such missing files and that will be good to go. I think I’ll skip moving to Franco for now though; I forget why I started using it in the first place, and I am feeling too lazy to do all these the next time I need an update. Plus Android L is around the corner, so apart from rooting I don’t want to make too many other changes.

Speaking of rooting, sideloading the update resulting in loosing root access. Not an issue – use the excellent Nexus Root Toolkit (NRT) to get access again. NRT is an excellent piece of software, a huge time saver (I must donate to the author sometime but I keep procrastinating). I keep changing laptops or re-installing the OS, so each time I use NRT I have to go through the hassle of installing the drivers and that usually requires a reboot and some extra steps. Did that this time too and now my Nexus 7 has Android 4.4.4 rooted.

Hyper-V NAT & virtual switches

Played with Hyper-V on my laptop after a long time today. For the past 6 months or so I’ve been exclusively with VMware Workstation on my primary laptop, and things are so much easier there if you just want some VMs running on your laptop. Installing VMs is a snap because most OSes will be automatically installed for you. Similarly, networking is straight-forward as VMware Workstation provides NAT out of the box. Hyper-V being more of an “enterprise” thingy (to be compared with VMware ESXi) you have to do these yourself.

For instance NAT. Hyper-V offers three type of network switches to connect your VM to the outside world. These are:

  • External switch: This creates a virtual switch that is bound to your physical network adapter. What happens when you make such a switch is that: (1) a new virtual switch is created with the name you provide, (2) this switch is bound to your physical network adapter (think of it as though your physical network adapter has become a switch), (3) a new virtual network adapter is created on your physical machine with the name “Hyper-V Virtual Ethernet Adapter #X” (replace X with a number), and (4) this virtual adapter is hooked up to the aforementioned switch and gets the IP address etc that was assigned to your physical adapter.

    So your physical adapter has become a virtual switch. And your physical machine uses a virtual adapter – connected to this virtual switch – to connect to the network.

    Other VMs you create and connect to this External switch have virtual adapters in them that too connect to this virtual switch. So it’s as if all these VMs and your physical machine are connected directly to a switch that is connected to your physical network. That’s why it’s called an External switch – everything is connected directly to the external world.

  • Internal switch: This too creates a virtual switch, but this virtual switch is not bound to your physical adapter. It’s just a virtual switch in a virtual ether of its own! What happens when you create an Internal switch is quite similar to the steps for an External switch: (1) a new virtual switch is created with the name you provide, (2) a new virtual network adapter is created on your physical machine with the name “Hyper-V Virtual Ethernet Adapter #X” (replace X with a number), and (3) this virtual adapter is hooked up to the aforementioned switch.

    Notice your physical adapter is left as it is. The newly created virtual adapter and switch have nothing to do with it. They exist in a world of their own. When you create new VMs connecting to this Internal switch, all their virtual adapters too connect to this virtual switch. The VMs and your physical machine can thus talk to each other, but they can’t jump over to the physical network.

    If you want your VMs to be able to talk to the outside world in such a scenario, you must make provisions for the communication. Like install & enable a routing service between the virtual adapter on the physical machine that’s connected to the Internal switch, and the physical adapter that’s connected to the physical network. Or enable NAT if routing isn’t possible. Either ways, the idea behind an Internal switch is that all your VMs are hooked up to that switch, and they can talk to your physical machine but they can’t talk to the outside world.

  • Private switch: Lastly we have a Private switch. This is just like an Internal switch, with the difference that there’s no virtual adapter created on the physical machine. So the physical machine has no connection to the Private switch. Meaning – all the VMs connected to the Private switch cannot contact the physical machine. They are in a bubble of their own.

So that’s that.

In my case I wanted to have all my VMs be in an Internal switch and also have them talk to the outside world. I couldn’t enable routing due to my network configuration, so I decided to enable NAT. To do this I created an Internal switch as usual and then (1) went to “Control Panel” > “Network and Internet” > “Network Connections”, (2) right clicked on my physical adapter that’s connected to the outside world, (3) went to the Sharing tab, (4) ticked the box that said “Allow other network users to connect …” and selected the adapter connected to the Internal switch from thee drop-down menu, and (5) clicked OK.

ICS

This enables NAT on my physical machine, as well as a DHCP server for the Internal switch network.

Here’s ipconfig for the virtual adapter connected to the Internal switch before I enable sharing:

And here’s the same once I enable sharing:

Unfortunately you don’t get much control over the NAT in terms of choosing the IP address network (it’s always the 192.168.137.0/24 network). You do get to choose what ports are forwarded (click “Settings” in the previous screenshot) and that’s about it.

If I check the VM now it has got an IP address from this network as expected:

The DNS server for this interface is set to the virtual adapter on the physical machine (which will perform the query on behalf of the VM and get back). The VM now has connectivity to the outside world as expected.

That’s all for now! Hope this helps someone.

Nostalgia – FreeBSD

Stumbled upon this via The Wayback Machine last week.

rakheshnet

Sigh. Rakhesh Sasidharan – FreeBSD administrator. Good ol’ days! :)

Sadly this front page and one or two others are all that The Wayback Machine archived of this site. And I don’t have a backup of the site either as I clumsily lost it (I have a habit of being excellent at taking backups but also somehow managing to delete/ misplace those backups just when I need them).

The site was a wiki running DokuWiki atop Nginx and FreeBSD from a desktop PC at home. DNS was via TinyDNS and some script that would update the A records whenever my ADSL dynamic IP would change. I had three FreeBSD machines at home, they were called Asterix, Obelix, and Dogmatix. Apart from this wiki the machines also hosted an IMAP server (Courier IMAP, I think) for my emails and Postfix for sending emails. It had some more bits and pieces but I don’t recollect them now. The wiki itself was mostly about FreeBSD administration. I love (loved?) FreeBSD – I have always been more partial to the *BSD Operating Systems than Linux, maybe because they felt like an underdog but also because these OSes felt more coherent than the hotchpotch that is Linux.

Anyways, all those are days of the past now … but it was a good trip down memory lane to see that wiki pop up when I least expected it!

Here’s a photo of Asterix, Obelix, and Dogmatix at my parents’ house:

DSC01205

It’s sad that I don’t even have a good picture of them! Here’s a photo of the three machines after I moved out of my parents’ house:

DSC00047

In both pics Asterix, Obelix, and Dogmatix are the two black Compaq and one white IBM machines. The fourth machine was a regular Windows XP desktop.

The second pic’s from Dec 2007. I think these three machines stayed on for one more year; sometime between 2008 and 2009 I decided to stop spending so much time at home on FreeBSD and shut them down.

After that I had a FreeBSD VPS and also some FreeBSD VMs at home, but I didn’t do as much with them as I did with the three physical machines.

GPO errors due to SYSVOL replication issues

So the other day at my test lab I noticed many of my GPOs were giving errors. Ran gpupdate /force and it gave the following message:

User policy could not be updated successfully. The following errors were encountered:

The processing of Group Policy failed. Windows attempted to read the file \\rakhesh.local\SysVol\rakhesh.local\Policies\{F28486EC-7C9D-40D6-A243-F1F733979D5C}\gpt.ini from a domain controller and was not successful. Group Policy settings may not be applied until this event is resolved. This issue may be transient and could be caused by one or more of the following:
a) Name Resolution/Network Connectivity to the current domain controller.
b) File Replication Service Latency (a file created on another domain controller has not replicated to the current domain controller).
c) The Distributed File System (DFS) client has been disabled.
Computer Policy update has completed successfully.

To diagnose the failure, review the event log or run GPRESULT /H GPReport.html from the command line to access information about Group Policy results.

Looked like a temporary thing so I didn’t give it much thought first. But when policies were still not being read after half an hour or so I figured something is broken.

Running gpresult /h didn’t have much to add. I noticed the there were errors similar to the one above. I also noticed that another policy had a version mismatch to the one on the server (this wasn’t highlighted anywhere, I just happened to notice).

I went to the path in the error message on each of my DCs (replace rakhesh.local with your DC name) to find out which DC had a missing file. As the message indicated, it was a replication issue. I had updated the GPO on one of the DCs but looks like it didn’t replicate to some of the other DCs; and my clients were trying to find the policy files on this DC where it didn’t replicate to, thus throwing errors.

Event Logs on the clients didn’t have much to add except for error messages similar to the above.

Event Logs on the DCs were more useful. “Applications and Services Logs” > “DFS Replication” is the place to look here. Interestingly, the DC where I couldn’t find the GPO above reported no errors. It had an entry like this:

The DFS Replication service successfully established an inbound connection with partner WIN-DC01 for replication group Domain System Volume.

Additional Information:
Connection Address Used: WIN-DC01.rakhesh.local
Connection ID: 11C8A7A0-F8A5-4867-B277-78DDC66E3ED3
Replication Group ID: 7C0BF99B-677B-4EDA-9B47-944D532DF7CB

This gives you the impression that all is fine. The other DC though had many errors. One of them was event ID 4012:

The DFS Replication service stopped replication on the folder with the following local path: C:\Windows\SYSVOL\domain. This server has been disconnected from other partners for 118 days, which is longer than the time allowed by the MaxOfflineTimeInDays parameter (60). DFS Replication considers the data in this folder to be stale, and this server will not replicate the folder until this error is corrected.

To resume replication of this folder, use the DFS Management snap-in to remove this server from the replication group, and then add it back to the group. This causes the server to perform an initial synchronization task, which replaces the stale data with fresh data from other members of the replication group.

Additional Information:
Error: 9061 (The replicated folder has been offline for too long.)
Replicated Folder Name: SYSVOL Share
Replicated Folder ID: 0546D0D8-E779-4384-87CA-3D4ABCF1FA56
Replication Group Name: Domain System Volume
Replication Group ID: 7C0BF99B-677B-4EDA-9B47-944D532DF7CB
Member ID: 93D960C2-DE50-443F-B8A1-20B04C714E16

Good! So that explains it. Being a test lab, all my DCs aren’t usually online. In this case, WIN-DC01 is what I always have online but WIN-DC02 is only powered on when I want to test anything specific. Since the two weren’t in touch for more than 60 days, WIN-DC01 had stopped replicating with WIN-DC02. Makes sense – you wouldn’t want stale data from WIN-DC02 to overwrite fresh data on WIN-DC01 after all.

The steps in the Event Log entry didn’t work though. Being a SYSVOL folder there’s no option to remove a server from the replication group in DFS Management.

I searched online for any suggestions related to event ID 4012 and SYSVOL, adn found a Microsoft KB article. This article suggested running two commands which I’d like to post here as a reminder to myself as they are generally useful to quickly pinpoint the source of an error. Being a test lab I have just 2-3 DCs so I can go through them manually; but if I had many DCs it is useful to know how to find the faulty ones fast.

First command simply checks whether the SYSVOL folder is shared on each DC:

Next command uses WMIC to get the replication state of this folder on each DC.

A state of 5 indicates the group is in error. Interestingly, the “Access denied” message is one I had noticed earlier too when running dcdiag on the faulty DC.

I didn’t think much of it that time as there were no errors when running dcdiag from the working DC and also because I ran this command while I thought the error was a temporary thing. I still don’t think this is a permissions issue. My guess is that it is to do with the content freshness error I found in the Event Logs earlier. Possibly due to that the second DC is being denied access to replicate and that’s why I get the “access denied” error above.

From the KB article above I came across another one that has steps on how to force a of SYSVOL from one server to all the others. (In the linked article, the section ‘How to perform an authoritative synchronization of DFSR-replicated SYSVOL (like “D4” for FRS)’ is what I am talking about). Here’s what I did:

  1. I launched adsiedit.msc and connected with the default settings
  2. Then I opened CN=SYSVOL Subscription,CN=Domain System Volume,CN=DFSR-LocalSettings,CN=WIN-DC01,OU=Domain Controllers,DC=rakhesh,DC=local (replace the DC name and domain name with yours; in my case WIN-DC01 is the DC I want to set as authoritative) and …
  3. … I set msDFSR-Enabled=FALSE and msDFSR-options=1

    adsiedit

  4. Next, I opened CN=SYSVOL Subscription,CN=Domain System Volume,CN=DFSR-LocalSettings,CN=WIN-DC02,OU=Domain Controllers,DC=rakhesh,DC=local – WIN-DC02 being the DC that is out of sync – and set msDFSR-Enabled=FALSE.
  5. For AD replication through out the domain:

  6. The result of the above steps will be that SYSVOL replication is disabled through out the domain. I confirmed that by going to the “DFS Replication” logs and noting an event with ID 4114:

    The replicated folder at local path C:\Windows\SYSVOL\domain has been disabled. The replicated folder will not participate in replication until it is enabled. All data in the replicated folder will be treated as pre-existing data when this replicated folder is enabled.

    Additional Information:
    Replicated Folder Name: SYSVOL Share
    Replicated Folder ID: 0546D0D8-E779-4384-87CA-3D4ABCF1FA56
    Replication Group Name: Domain System Volume
    Replication Group ID: 7C0BF99B-677B-4EDA-9B47-944D532DF7CB
    Member ID: 09E14860-47F6-49EE-820E-43F7ED015FEB

  7. Then I went back to CN=SYSVOL Subscription,CN=Domain System Volume,CN=DFSR-LocalSettings,CN=WIN-DC01,OU=Domain Controllers,DC=rakhesh,DC=local but this time I set msDFSR-Enabled=TRUE.
  8. Again, I forced AD replication through out the domain.
  9. Next, I ran dfsrdiag pollad on WIN-DC01 (the DC with the correct copy) to perform an initial sync with AD. (Note: My DC was a Server 2012 Core install. This didn’t have dfsrdiag by default. I installed it via Install-WindowsFeature RSAT-DFS-Mgmt-Con in PowerShell).
  10. I checked the Event Logs of WIN-DC01 to confirm SYSVOL is now replicating (event ID 4602 should be present):

    The DFS Replication service successfully initialized the SYSVOL replicated folder at local path C:\Windows\SYSVOL\domain. This member is the designated primary member for this replicated folder. No user action is required. To check for the presence of the SYSVOL share, open a command prompt window and then type “net share”.

    Additional Information:
    Replicated Folder Name: SYSVOL Share
    Replicated Folder ID: 0546D0D8-E779-4384-87CA-3D4ABCF1FA56
    Replication Group Name: Domain System Volume
    Replication Group ID: 7C0BF99B-677B-4EDA-9B47-944D532DF7CB
    Member ID: 93D960C2-DE50-443F-B8A1-20B04C714E16
    Read-Only: 0

  11. Finally, I went back to CN=SYSVOL Subscription,CN=Domain System Volume,CN=DFSR-LocalSettings,CN=WIN-DC01,OU=Domain Controllers,DC=rakhesh,DC=local and set msDFSR-Enabled=TRUE. You can see what’s happening, don’t you? First we disabled SYSVOL replication on all the DCs. Then we enabled it on the authoritative DC and got it to sync to AD. And now we are re-enabling it on all the other DCs so they get a fresh copy from the authoritative DC.
  12. Lastly, I did a dfsrdiag pollad on WIN-DC02 … and while it should have worked without any issues, I got the following error:

    C:\Users>dfsrdiag pollad
    [ERROR] Access is denied when connecting to WMI services on computer: WIN-DC02.r
    akhesh.local

    Operation Failed

However, Event Logs on WIN-DC02 showed that SYSVOL was now replicating successfully and clients are now able to download GPOs successfully. So it looks like the “access denied” error is something else altogether (as I suspected initially, yaay!). I’ll have to look into that later – I know in the past I’ve fiddled with the WMI settings on this machine so maybe I made some change that I forgot to reset.

Good stuff!

Enabling disabled Office add-ins automatically

So as I mentioned yesterday I have been thinking of using Task Scheduler to try and enable disabled Office add-ins automatically.

The Problem

Here’s what happens. Every so often when users open Word, Outlook, Excel, etc they get a prompt like the one below:

addin-error

We don’t know why they keep getting it, but ideally users should be clicking “NO” as we use all these add-ins and don’t want them disabled. But users being users they click “YES” intentionally or inadvertently and then call IT with complaints that their Word, Outlook, etc aren’t working as expected. Then we in IT have to do the boring task of going to their add-ins screen and enabling these items; followed by closing and opening Word, Outlook, whatever.

What I want to do here is (1) warn users when the above dialog box comes up, advising them not to click the “YES” button; and (2) if they do click “YES” then somehow enable the add-ins behind their back and get them to close and open the affected program.

Add-ins and the registry

I started off thinking I might need to do some fancy stuff to enable add-ins, but soon realized that they are all controlled by the registry. Nice!

  • Add-ins can be installed for all users on the machine or just a specific user. So you have to look under both HKLM and HKCU. The two locations are: addin-registryHKCU\Software\Microsoft\Office\(application)\Addins\ and HKLM\Software\Microsoft\Office\(application)\Addins\ (replace (application) with Word, Outlook, Excel, or PowerPoint). These two locations contain keys for each add-in installed for that particular application.Here’s a screen shot for the Outlook InterAction add-in for a user.
  • The key thing in the registry keys above is the LoadBehavior entry. This can take many values – the default is a value of 3 which means the add-in is loaded automatically at startup and is currently loaded. If the value is 2 it means the add-in is loaded automatically at startup but is currently not loaded.
  • My initial hunch was that LoadBehavior is what I must target. I thought when a user disables an add-in the LoadBehavior value of that add-in probably changes to 2, so all I need to do is switch it back to 3. But I was wrong (as I quickly figured after crashing Word a couple of times and choosing to disable add-ins).
  • Then I discovered that add-ins which are disabled via a user dialog box as above don’t have their LoadBehavior value changed; rather they are set as disabled at another place in the registry. And that is under the HKCU hive, at HKCU\Software\Microsoft\Office\(version)\(application)\Resiliency\DisabledItems (replace (version) with 15.0 for Office 2013, 14.0 for Office 2010, 12.0 for Office 2007, 11.0 for Office 2003, you get the idea … and replace (application) with Word, Outlook, etc as before).

Each time an add-in is disabled, a REG_BINARY entry is created under HKCU\Software\Microsoft\Office\(version)\(application)\Resiliency\DisabledItems with a binary value. I didn’t experiment to see if there’s a one-to-one mapping between this entry and an add-in, and also whether the entry is same for an add-in across all machines; the important finding for me was that if I delete this entry, it enables the add-in. So all I really needed to do to see if there are disabled add-ins for a program is to just check this key, and if there are any entries I can delete them all to re-enable all the add-ins. Nice! This doesn’t require a PowerShell script really. Good old reg can do the trick too. So a batch file is more than sufficient.

Below is what I came up with:

I could probably make it shorter if I pick up more batch file scripting but this does the trick for me.

Let’s break it down for Outlook. I enumerate the registry key. The results of this are iterated over by a FOR loop. If the list isn’t empty – i.e. there are disabled add-ins – the loop exits and goes to a different section.

This section that the loop exits to simply deletes all entries under that key, shows a message to the user asking them to close and open Outlook, and goes up the batch file to check Word next.

Repeat and rinse for each application and there you have it! Like I said, easy peasy, quick and dirty!

Maybe I should improve the script later – I don’t know. An overhaul using PowerShell might be a good idea I think. Specifically, there are a few things I am already thinking of adding:

  1. Currently the message box goes away if the user clicks OK. Would be nice if I could keep an eye out for whether they actually close the program later, and if not keep popping up reminders – maybe a ballon tip?
  2. Would be nice if I could close the application for the user. I could do that in the batch file too via taskkill but I was wary of doing that lest it cause any corruptions. I wouldn’t want Outlook OST and PST files or Word templates getting corrupted because I closed the program. Maybe PowerShell has a more graceful way of shutting down an app? I don’t think so, but that could be my ignorance.
  3. Currently I enable all add-ins. While that’s fine for our case maybe I should have a list of add-ins that are to be excluded from being enabled? Or only enable a whitelist of add-ins?

So that’s that. Next step is to find a way to trigger the batch file.

Scheduled task triggers and Event Viewer

Each time the dialog box asking a user to disable an add-in appears, an entry is logged in Event Viewer. This looked like a promising way to hook on to that event and warn the user not to click “YES”. These entries are logged under “Application and Services Logs” > “Microsoft Office Alerts”.

addin-ev-alert

The joy of discovering that was short lived though, as I realized the same sort of alerts are generated for many other Office related things: spell check notifications, connectivity to Exchange, etc.

misc-ev-alert

All these alerts had the same source and ID and there was nothing for me to distinguish between them! Sure the data part was different, and while Event Viewer (and thus Task Scheduler) supports XPath for searching the Event Logs it has limitations in that I can’t do wildcard searches. Thus while I could do an XPath search for all events that have the exact error message in the first Event Log entry above, I can’t do an XPath search for all events that contain the text “Do you want to disable this add-in?”. This is a big limitation because now I will have to (a) find the exact message for each add-in and program, and (b) create XPath queries for each of these – eugh! That’s too much work for now (and not very elegant either!) so I decided to not pursue that route.

Once a user decides to enable or disable an add-in though, I found a different alert is generated for that. Under the “Application” log, from source “Microsoft Office 14” (since we have Office 2010), alerts with event ID 2001 are generated each time a user selects to disable an add-in (and alerts with event ID 2000 are generated when they choose not to disable).

2001-alert

That’s convenient, coz now I can create a task that is triggered on such events and whose action is to run the previous batch file. Nice!

Putting it all together

End result is a task I can import as in the case of the laptop lid issue. Here’s the XML file of the task:

Once again, I install it for the users I want via a batch file like this:

Not done yet!

I am not done yet though. It’s not practical installing it like this for each user in my domain. I chose the above approach just to get it installed for a few test users; next step is to roll it out via GPO to the whole domain. Stay tuned for a post on that later …!

And one more thing …

Something I learnt while reading about add-ins.

Windows Task Scheduler quirks; Changing what happens when a laptop lid is closed … (part 3)

The other day I posted on how I use Task Scheduler to run a batch file that changes what happens to a laptop when the lid is closed depending on where it is located.

I have been fiddling with the Task Scheduler since then and thinking of how I can use it for other tasks. Specifically, at work we have a lot of add-in issues with Office products wherein every so often Word/ Excel/ Outlook/ PowerPoint give a message when launching that such and such add-in caused issues and it is recommended the user disables them; users click “Yes” to such messages inadvertently or intentionally, after which whatever functionality the add-in provides does not work any more and we at IT get calls! I had an idea to create a PowerShell script that will re-enable the add-in in such cases and maybe use Task Scheduler to hook into any Event Log entries that are generated when add-ins are disabled to trigger the running of this script. That’s the topic of another post however but as a result of exploring this I have been playing with Task Scheduler a bit and revisited the Task Scheduler entry I made for the laptop lid closing problem.

First off, here’s an exported version of the Task Scheduler entry I created:

Note the highlighted lines:

  • Line 5 – the “Author” – doesn’t matter much. It merely specifies who the author of the Task is.
  • Line 23 – the “UserID” – matters. This is the user ID under which the task runs. If you specify a user ID here, you must use the same ID when importing the task. You could specify a user ID here and specify a different ID when importing (via schtasks /ru ...) and the latter will over-ride the ID in the XML file. If you will always be specifying a user ID when importing, you can skip the user ID in the XML file too. I chose to leave it commented so I remember it for later.
  • Line 17 – yet another “UserID” – matters. This user ID is to do with the “run when a user logs in” trigger. If your task doesn’t have such a trigger this user ID won’t be present. You have two choices here really: either you could specify a user ID and that is the user account whose login will trigger the task, or you could skip that tag (remove the whole line) and the task will trigger when any user account logs in. The latter has a catch though. If you do this, then you cannot skip the UserID of line 23. In my case I chose to use a marker here “–REPLACE–” and modify the XML file to replace this with a user ID later on (see below).

Gist of the matter for my specific scheduled task entry is that I can’t import this task willy for any user. When importing I have to (1) specify the user in whose context the task will run – I must do that via schtasks /ru ... or modify the XML file directly – and (2) if I am not modifying the XML file in the previous step, I can’t leave the UserID element of line 17 blank and so I must modify the XML file to put a user ID here. This user ID would be that of the user I am installing it for of course.

To that end I modified the install batch file I had created:

The important bit here is the 4th line, where I use PowerShell to read the XML file and replace the bit that says “–REPLACE–” (which is the marker I use at line 17 of the XML file) with the user ID of the user I am installing this task for. Apart from that, on line 6 when I import the task I get the user ID from the environment variables and prompt for a password. This way the install batch file and task XML files are generic and I can run them for any user.

That’s all for now!

Update: I realized I could simplify things further since I am using PowerShell any ways to replace text in the task scheduler XML file. I can specify the “run as” user too and thus avoid prompting for a password when installing! :)

Notice I have set the marker “–REPLACE–” in two places now. Both will get replaced while installing. The batch file can be modified as below to omit the /RU & /RP switches:

Outlook search and additional mailboxes

Something to keep in mind regarding Outlook searches and additional mailbox. The comments below are in the context of Outlook 2010 and Exchange 2010 as that’s what we use at work.

There’s two different search providers that come into play when searching via Outlook. They are used depending on how the mailbox is accessed by Outlook.

search optionsIf the mailbox is accessed in cached mode (so the folders are actually in an OST file on your computer) or if you are searching a PSTsearch locations file, Outlook uses Windows Desktop Search (WDS) to do the search. WDS is set to index many locations on your computer and if there are OST and PST files in Outlook it indexes these too. You can tweak WDS’s options by clicking on “Search Tools” and then “Search Options”. Click “Indexing Options” in the window that opens to change the locations and file types that are indexed.

However, if the mailbox is accessed in online mode (so there are no OST files involved) Outlook passes your search query to the Exchange server who then returns with results.

This distinction doesn’t usually matter except when searching attachment contents. In that scenario WDS returns more results as it is able to index more file types. The Exchange server in contrast has a lesser number of default file types it can index and it is up to the Exchange admin to install filters for additional file types.

At work, for instance, all our users access their own mailboxes in cached mode – so search results there are more comprehensive when compared to search results from additional shared mailboxes that are accessed in online mode. The PDF file type is not included in the default file types for Exchange 2010, so shared mailbox searches don’t return emails with PDF attachments even if they contain the search term. Excel and Word file types are returned in the results though.

This is a good link to read for more info.

 

 

 

schtasks specifying username to run an imported task under

Note to self: if you want to import a Task Scheduler task that will “run as” a different user you must specify both the “run as” user name and password on the command line. The XML file containing the task already contains the user name but that won’t cause schtasks to prompt for a password. Here’s an example command line:

If you don’t want to specify the password leave it blank or put an asterisk * instead. This will cause schtasks to prompt for a password.

There isn’t a way to specify a password in the XML file itself. Here’s the relevant snippet from the XML file above where the “run as” user is specified:

security options

If you compare with the GUI, the child element LogonType corresponds to the “Run only when user is logged on” and “Run whether user is logged on or not” options. It can take one of three values:

  • S4U: Which corresponds to “Run whether user is logged on or not” and “Do not store password”. In this case the user account is expected to be a local service account. The account won’t have access to any network resources and its password isn’t stored by the system.
  • Password: Which corresponds to “Run whether user is logged on or not”. If this option is checked in the GUI a password is prompted. But if this option is present in the XML file a password is not prompted and must be entered via the schtasks command as above.
  • InteractiveToken: Which corresponds to “Run only when user is logged on”. The task will only run in an interactive session in this case.

In the first two cases the UserId child element specifies the username under which the task will run. In the second case though the username must be specified again when using the schtasks command even if you specify it in the UserId element.

Hope this helps somebody.