Automounting a VHD at system boot on Windows 7
I'm playing around a bit more with my test machine at work, and I've been thinking, as excellent as my last setup was, it could be even better.
One way to make it better was to avoid duplicating installation data and instead to put that kind of stuff on a shared VHD that all the other machines can access - physical and virtual.
To start out I recreated a multi-boot-from-VHD setup as I had before. In addition, I created another VHD to be used in common among them; let's call this "shared.vhd".
Once I've installed the OS into the VHD, I can worry about trying to get the OS to mount the shared.vhd at boot time. There's three main steps involved.
The first thing to do is create a diskpart script. This is simply a text file that will be passed in as an argument later to the diskpart command. The script simply selects my shared VHD and attaches it. Here's the contents of my dpscript.txt file:
select vdisk file=D:\shared.vhd
attach vdisk
exit
In my case the shared.vhd file is located on D: — your mileage may vary.
The next thing to do is create a batch file that will run diskpart with the script we just created. I made mountvhd.bat with a single line:
diskpart /s C:\dpscript.txt
Both dpscript.txt and mountvhd.bat are located in my C: root folder, although that also is just down to personal preference.
Anyway, at this point if I run my batch file from a command prompt (with administrative privileges) I can see it select and attach the virtual disk file, so I know the script is working.
The last thing to do is set this up to run at startup time. There's a number of possible ways to do this but not all of them seemed to work well for me. For example, using the Task Scheduler to create a task that runs at startup time should work, but it doesn't seem to. However, adding this batch file as a startup script through Group Policy worked. Do the following:
- From an administrative command prompt, type "mmc" to bring up the management console.
- Under the File menu, choose "Add/Remove Snap-In".
- Choose "Group Policy Object Editor" in the left pane and click the "Add" button in the middle.
- Accept the defaults in the dialog.
- Click OK to dismiss the Add/Remove Snap-Ins dialog.
- In the tree view on the left of the main window, expand Local Computer Policy, then Computer Configuration, then Windows Settings, and select "Scripts (Startup/Shutdown)".
- In the main window, select "Startup".
- Click the "Properties" link to bring up a dialog for managing startup properties.
- Choose "Add" to add your new startup script.
- Browse for the batch file you created, click OK, then click OK again to exit the Startup Properties window.
- Close mmc. If prompted to save, do so.
Now when you reboot your machine, that VHD should be mounted as an additional volume.
Multi-booting Windows 7/2008R2 From VHD
One very useful feature of Windows 7 and Windows Server 2008 R2 is the ability to boot the OS directly from a virtual hard disk file (VHD). This can make it pretty straightforward to be able to run a number of different versions of Windows on a single machine.
I just finished converting my test machine to a boot-from-VHD scenario; before that, I was using a native Windows Server 2008 R2 install with Hyper-V. Here's some of my observations about the tradeoffs (remember, I DO NOT speak for Microsoft):
- Boot-from-VHD is not virtualized; you are just running the OS out of a mounted VHD file
- Because of this, you might expect boot-from-VHD to be a bit faster than a virtualized OS.
- Since a lot of our work is based on virtualization technologies, it seems weird to test it in Hyper-V (a VM within a VM) and sometimes I wonder if issues I see are a result of my environment.
- With Hyper-V, you can run all your test operating systems at once; boot-from-VHD is one OS at a time
- VMs in Hyper-V have snapshotting, so it's easy to roll back to a pristine state
There's a few other minor tradeoffs in the boot-from-VHD scenario, but not enough to fret about too much. So I thought I'd give it a try.
To start out, just plop in your Windows 7 media and start a clean new installation of Windows 7. Or, if you are like me, you can pixie boot it. Start the Windows 7 installation. Once you've passed the language selection screen, hit SHIFT+F10. This brings up a WinPE console. Type "diskpart" in the console to bring up the disk partitioning tool.
If you need to, reformat your primary drive:
- sel disk 0
- cre part pri
- format fs=ntfs quick
- assign
Now, create a VHD for each OS you want to install (put in a value for maxfilesize, in megabytes):
- create vdisk file=c:\vhdname.vhd maximum=maxfilesize type=expandable
- select vdisk file=c:\vhdname.vhd
- attach vdisk
- cre part pri
- format fs=ntfs quick
Exit diskpart and WinPE. When you get to the destination media selection screen, where you decide which volume to install your OS to, select the first VHD in the list, not your base drive. The size should be close to what you specified. IMPORTANT: Ignore the warning that Windows can't install to that disk - it will work just fine.
After you finish installing your first OS, you can insert the media for the next OS and restart. Go into setup the same as before, and just like before, enter WinPE after the language selection by pressing SHIFT+F10. This time you don't need to create the VHDs. They are still there, you just need to attach them again:
- select vdisk file=c:\vhdname.vhd
- attach vdisk
I attached all of mine in the same order as before. I don't know whether this is the right thing to do or not but it seems to have worked okay.
After exiting diskpart and WinPE, you should see the mounted VHDs listed in the media selection screen again. This time install to the second VHD in the list. You should be able to tell the difference because the first one shows less available space than the other VHD(s). Again, run through the install as before.
Now once you finish you can boot to any of the options in your boot loader menu, if you can distinguish them. You may wish to edit the boot loader config. Do the following:
- Launch an elevated command prompt
- Run bcdedit. Take note of the identifiers (GUIDs) for each of your machines - you will need this information momentarily.
- To change the description of an entry, type bcdedit /set {identifier} Description "a meaningful description" where:
- identifier is the GUID of the machine you want to change. {current} and {default} work for the machines they pertain to in bcdedit
- a meaningful description is the text you will use to identify this machine in the bootloader
- To set a different entry as the default, type bcdedit /default {identifier}
- To set the timeout value for the bootloader, type bcdedit /timeout <seconds> where <seconds> is the number of seconds you want to wait
- For help with bcdedit, type bcdedit /?
Using this technique, I set my machine up for a triple-boot with Windows 7 32-bit, Windows 7 64-bit, and Windows Server 2008 R2. And, within Windows Server 2008 R2, I should be able to run Hyper-V, where I can run additional Windows 7 test VMs with snapshotting. The best of both worlds!
Incentive Programs and Professional Motivation
I recall some years ago having read this Joel Spolsky post entitled "Incentive Pay Considered Harmful." In typical Spolsky fashion, he made a very compelling case that I had a very hard time coming to grips with. At the time I'd just recently made a series of contributions to Novell, outside of the scope of my job description, that I felt had an obvious positive impact on the company, but I had not received any sort of recognition at all for this.
Joel's article strongly disagreed with me. I felt I should have been recognized for my efforts; why else would I take the personal risk that comes with extending one's self in that fashion? Instead, nothing had been done.
I've been pretty interested in this topic and so I've been observing and evaluating ever since. What I've seen is that, for the most part, incentive programs tend to have the opposite effect of their purpose; namely, they tend to demotivate rather than motivate.
Outlined below are some reasons why.
People Get Rewarded Just For Doing Their Job
Maybe you've seen this too: You attend a quarterly all-hands meeting when an individual you know and work with is asked to come to the front. They announce, "Tom did a really great job running our beta program last release, and so we are giving him the quarterly Mega-Smiley-Face award, with a free dinner for two and a new iPod Touch." You sit there and stare, clapping insincerely. Sure, Tom did a great job running the beta program. But Tom is the beta program coordinator! It is his job to run the beta program! You did great work with your assigned responsibilities last quarter also. Why aren't you getting an award?
One problem with this scenario is that the rewards program now seems arbitrary. Tom was rewarded this quarter for doing his job. Who will be next? Who knows? Everyone is doing their job, but not everyone gets rewarded. The rest of the people feel discouraged. The recognition seems to be something worth earning, but they don't know how to earn it.
Another problem with this scenario is that it sends the wrong message to the team. Nobody should be rewarded just for completing their assignment — or everybody should be. Tom gets paid a salary for him to do his job. He's expected to do it well. If he gets rewarded just for doing his job, it tells the rest of the team that some jobs matter more than others. How do I get an assignment that matters? they wonder. And why am I wasting my time doing work that isn't important?
Luck and Timing Often Play a Bigger Role Than Excellence
In my nearly 15-year career I've delivered a lot of software to customers. I've invented things, learned difficult technology, solved complex problems, led and motivated teams, and proposed key strategic decisions that have helped the companies I've worked with become more successful. How many trophies do I have on my shelf? One. It is a beautiful blue piece of plastic that I got last summer when the Microsoft division we belong to eclipsed the $1 billion revenue mark for the first time. I'd been with Microsoft about six weeks at the time.
Earning that award (using that word very loosely, by the way) required nothing of me other than accepting a job at Microsoft at the right time. I hadn't written a line of production code yet, and certainly did not contribute to that revenue. I figure it replaces many others I should have earned but didn't.
I'm proud of the award, but I'm the first to admit that I earned it primarily due to fortuitous timing.
Positive Effects Are Usually Short-Lived
I remember one time being on a software team when we realized one morning that we had a serious bug. A problem had been reported by our released product that was having a significant customer impact. One member of the team stepped up to the task of digging into the issue and finding the problem. When he found and fixed the problem later in the day, he was genuinely thanked and given a gift certificate as a show of gratitude from the company.
The following day, our team was in a team meeting when the topic of the previous day's bug came up. We were being asked to identify what we were going to do differently in the future to avoid this problem. The same team member that had saved the team the day before took this as a personal offense. He muttered something to himself under his breath, slammed the lid of his laptop shut, picked it up and stormed out of the conference room.
Clearly, the special effort the company had made to thank him had been completely forgotten in less than 24 hours.
Abuse Makes The Programs Become Meaningless
I've frequently seen well-intentioned incentive programs become so abused that they become a laughing stock. One is almost embarrassed to truly earn an award because so many others have been similarly recognized for awards they acquired through dubious means.
Novell's Employee of the Year kind of took on this sentiment for me after I first saw one person get the award after taking full credit for something I knew full well he did not do (because I did it). Later I saw a colleague, the proven highest contributor on his team, get passed over for this award when his manager instead gave it to the lowest contributor in an effort to motivate him.
Probably the strangest of all of these though is for a company I've heard of with a very generous patent award program. One of their employees has learned to double his annual compensation by filing patent after patent through the company's patent program. Of course, filing all of these patents doesn't leave much time for him to do his regular job, and the patents being filed may not have anything at all to do with the company's products or strategy. But he's so innovative and valuable to their inconsistent patent portfolio that they've had no choice but to promote him over and over.
They Encourage Individualism Over Teamwork
Through a trusted source I heard about a support department for a software company years ago. They had instituted an incentive program called "55 Stay Alive". This great program with such a catchy name was very simple to understand: Each employee had to close 55 incidents each month or they were fired.
Awesome, huh.
One employee made a pitch to management, explaining that the incentive program was very negative and instead suggested they rearrange things to have a single goal that the whole team could work toward together. Management was hesitant but the team was willing to put it to a test.
So they did, with amazing results. Every month the team closed far more incidents working as a group than they ever had working as individuals before.
Logically, management was very unhappy about this insubordinate behavior so they fired the guy.
This might be an extreme example, but you've probably seen lots of examples of this. Many incentive programs reward people for behavior that leads them to focus on individual achievement at the expense of team achievement, which would be much better for the company.
So What Does Work Then?
One of the best incentive programs I've ever participated in was at Novell, working for a manager who ironically was really not that great of a manager. Novell being a Linux company, he had been given a small 6-inch figurine in the likeness of a Linux penguin which we called the Tuxen.
Every so often, in a team meeting, he would recognize someone for a specific assignment they'd done well. Then they would be awarded the Tuxen for a week. Each winner was expected to proudly display the Tuxen and take it places and publish photos of their adventures on the team wiki.
One week I was awarded the Tuxen for work I had done to help start the Eclipse Linux Tools project. I proudly took the Tuxen home with me, took photographs of the Tuxen with my family, and brought it along on a trip with my son to the Las Vegas Supercross. I gave it back a week later, but it was one of the most rewarding recognitions I'd ever had.
When I first read Joel's blog post, I immediately e-mailed him with my concerned, contrary opinion. "So how DO you reward people and make sure they know they've done well?" I asked.
"Just thank them," Joel said.
Maybe you're wondering, could it really be that simple? Instead I'd ask, why does it have to be more complicated?
Good Technical Interviews Require Good Technical Interview Questions
We're hiring at Microsoft UDC and interviewing a lot of people. Which is why this recent article on Coding Horror stood out to me, on the surprising fact that many software engineers struggle when it comes to actually writing code.
I haven't actually interviewed any of the people coming in yet, so I'm not really talking about any candidates that we've looked at because I have no experience with them. It was a timely article, though, and I am familiar with the struggle of the interviewer, having done it a lot at Mozy.
It's clear from the article, if you aren't already convinced, that asking interviewees to code as a part of the selection process is an absolute must. I'd also say, as a sidenote, it's also an indication of a serious software company. If you are interviewing with a company who doesn't test your programming skills, wouldn't you wonder how many people are on your team who can't code?
Anyway, coming up with good questions can seem hard, though. Some things to avoid:
- Complex problems that require even good engineers a lot of time to solve. You probably only have about 20 minutes for this question, which probably really only leaves the candidate about five to figure out how to solve the problem, and another fifteen of implementation and discussion. "Implement an ORM framework" is probably too complex or big.
- However, slightly complex problems can be good questions, if you provide enough background to cut the question down to the time you have.
- Domain-specific problems aren't that good at figuring out if someone can generally code. An outstanding C programmer who doesn't know C++ won't know how to implement their own insertion operator, even though they might be awesome and could easily learn it if they needed to. Even a great developer who has spent his whole life optimizing 3D rendering engines for computer games may have never once connected to a database, so he might not know anything about how to write a SQL query.
- Know the problem well enough to determine if any proposed solution will work; don't shut down a candidate just because he solves the problem differently than how you would do it.
The great thing is, apparently even simple problems can be good enough to find out if someone knows how to code. I wouldn't recommend you rely solely on the simplest, but coming up with a decent set of problems isn't too tough if you give it some thought. Here's some suggestions:
- Consider the source of your technical question and how long it took you to solve it. If you dredged it up out of your past experience, it might be a pretty good question because it obviously has some practical application. If you were able to come up with a solution to the problem after thinking about it for just a few minutes, and additionally if one of your colleagues is able to do the same, the problem is not too difficult for an interview question.
- This doesn't mean your candidates will easily get it, however. Don't get discouraged. If people on your team can solve this problem but your candidate cannot, that means the candidate is not of the same caliber as people on your team. That's not a good fit.
- It IS true that some people don’t think as well under pressure as they do on their own, or that your problem might just be in an area that they aren’t familiar with. It’s good to have a set of simpler questions on hand to ask them in case they stumble on the harder one. If they don’t get one of your hard questions but they can solve a simple one, at least you know they can solve SOME coding questions.
- Practice your questions with your colleagues. This will help you with clarifying the context and purpose of your question, make sure you structure it so there's enough time to answer the question, and make sure the question isn't too hard, too easy, or unclear.
- Choose questions that help you evaluate core competencies: algorithm and class design, proper use and understanding of data structures, pointer math, modulus math, understanding of data types, string manipulation, threading and thread safety, etc. Be sure your questions are designed to help you select the kind of people you want.
- For this reason, I don't like to ask really deep language-specific questions anymore (although if a candidate claims to be an expert in a specific language, these are fair game) or API-specific questions. Even if I use C++ and WxWidgets this year, I may not next year. What I want is someone who knows how to program. It doesn't take long at all for a good programmer to learn a new language; probably much less time than it takes to manage a bad programmer out of your team.
What really surprised me when I started interviewing at Mozy was that I'd heard all this stuff before, but had a hard time believing it. That is, until I experienced it firsthand during interviews there. I remember interviewing a candidate who had several years of experience in game development. Game development! These guys are the super-elite of developers, right? So I wondered if asking him to reverse a string might be too easy for him.
It wasn't.
Not a complex string reverse. Not a unicode string. Not in some obscure language he wasn't strong in. Just a basic string reverse in C, with a null-terminated char* argument containing the string to reverse. I even gave him the flexibility to reverse it in-line or to make a copy. I was surprised when he really struggled with this.
He wasn't the only one. String reverse is not a hard function, but I was surprised how many people struggled with it. So don't be surprised if people struggle with questions you think they should be able to answer. The numbers seem incredulous, but apparently it is really hard to find a good developer. So don't give up, my son.
The Truth About Novell Forge
I got an interesting e-mail the other day from Novell:
Please Note: You have been sent this email because you are listed as an administrator of one or more Novell Forge projects.
When Novell Forge was first launched Novell recognized the need for a site dedicated to providing hosting services to a growing number of software development projects, many supporting our open source initiatives. Novell Forge quickly grew and was soon providing these service to nearly 1000 such projects. Demand for new projects has all but disappeared during the past two years while a number of additional project hosting options have begun that can provide a similar set of services to those of Novell Forge.
Now that there are many other options, Novell can turn its focus to other areas and pass the project hosting responsibilities to these other dedicated hosting sites. Novell will be decommissioning the Novell Forge system on December 15, 2009.
This is interesting to me because it is not entirely true. I should know, because without me there would never have been a Novell Forge.
It's a bold statement, I know. It's one I'm happy to explain.
I came to Novell from IBM in 2000. It didn't take long to realize that Novell's developer story and strategy, or rather the complete lack thereof, was (and still is) a significant weakness in their overall execution. People buy a computer operating system in large part because of the applications that they can run on it; if a business wants to run a CRM system, they'll want to be sure that whatever platform they buy will run a CRM suite that is acceptable to them. This is why having a strong developer strategy is crucial to platform providers, and almost everyone seems to understand this. Novell certainly should; NetWare owned the x86 server market in the 80's and early 90's until Microsoft entered that market. Initially, the Microsoft offering was not necessarily better than NetWare in terms of stability or performance, but Microsoft definitely outgunned Novell when it came to applications. It was so much easier to create applications for Microsoft's platform that their supported portfolio dwarfed Novell's, and that was a significant key to dethroning Novell's dominant position in the x86 server market in the mid 90's.
Anyway, when I came to Novell and learned this, I thought that probably Novell's Developer Services organization just didn't know what to do (a mistaken analysis, I later learned) and if I worked there I could probably fix everything. I was pretty young, arrogant, and naive then. But in 2002 I was presented an opportunity to work in Developer Services and I took it.
One of the first things I was asked to do was to provide support to customers programming to eDirectory. I decided to try to learn more about how to do this the same way our third-party developers would, by using the resources that were available online. I found what appeared to be our authoritative how-to-program-to-eDirectory tutorial, got most of the way through my sample app, and got stuck. Finally I started asking questions. I quickly learned that everything I'd been doing was wrong; the authoritative documentation was incorrect. It used an out-of-date and deprecated API and was no longer considered best practice. It was some two or three years out of date, but hadn't been changed yet because changing the documentation was just too painful.
I felt this situation was unacceptable. We needed the freedom to create an abundance of rich and helpful developer content and to have it published and updated freely and frequently. We needed to be able to do this without going through drawn-out and tedious approval processes and staging phases for even minor edits. We needed to be able to continuously deliver not only whitepapers but tutorials and sample applications. I felt that what was needed was a complete overhaul of Novell's developer site, converting it into a web application where administrators (Novell Developer Services employees) could update the content and have complete control over what information was being provided to our developer community.
I discussed this with a colleague and my manager, and then we called a formal meeting to discuss this proposal. I think there were four Developer Services employees in the room. As we discussed the reasons to do this, other advantages surfaced. A key issue was that, in Novell's then-existing developer forums, many Novell developers were already contributing to solving each other's problems, including answering each other's questions and even sharing code, from small snippets to complete applications. We realized that instead of top-down support flowing from company to customer, what our customers really preferred was community support with Novell as an active participant. As we discussed this, one of my colleagues suggested that instead of writing the web app I suggested, we should do a project hosting site, like SourceForge. Such a site would allow us to participate as a community with our users to exchange sample code, documentation, tutorials, and other content. Novell Forge was born.
As we began to socialize the idea, we found out that a separate group within Novell had been tasked with creating a project hosting site for internal company use. When we both became aware of each other's goals, the synergies were obvious and it seemed apparent that we should try to coordinate our efforts. Interestingly, we had human resources to give to the project but lacked funding for capital expenses; the other group had capital expense budget but lacked human resources. Ultimately we agreed that, as my team developed the Novell Forge solution, we would also develop an internal-use version of the site to meet the goals of this team; in exchange, they would help us to get the hardware we needed to host Novell Forge.
Around the time Novell Forge was launched and completed, a number of people involved directly or indirectly from that team claimed credit for having launched Novell Forge. Some of them were quite handsomely rewarded by the company, presumably at least in part due to their claimed credit for the site. Others still claim in public that they are responsible for the site even though they had absolutely nothing to do with the conceptualization, proposal, approval, or implementation.
Meanwhile, those of us who did come up with the idea, who did make the business case and get the approval and deliver the site, well, we pretty much had to settle for a brief pat on the back from Novell. Or did we even get that? Anyway.
Novell Forge, despite its pretty lame name and humble beginnings, was actually quite well received by the press. It earned kudos for Novell from Dave Kearns of NetworkWorld, which was not exactly easy to come by. And as Novell tried to reinvent itself with an open source focus, purchasing such open source companies as Ximian and SUSE Linux, the existence of Novell Forge was frequently cited as evidence that Novell was serious about an open source strategy (example). Interest in the site grew quickly and it soon hosted over 1000 external projects, as stated in the e-mail I quoted above. My team was excited about the traction the site was gaining. We had many, many ideas for how to grow the site and make it an even more useful tool for software developers. We had more work to do than time to do it, and it was neat to feel like what we were doing had an impact to Novell.
Even though Novell didn't seem to care about it.
Oddly, in spite of what my team thought was a pretty obvious success, we could not get approval for funding to continue to promote the site. The team was gradually reduced in size, again and again. When people would leave, their vacancies would languish unfilled until that position was eventually lost. The team was instructed to not develop the site but instead to work on undefined new work in other undefined areas, wasting many person-years of development effort. The community could sense Novell's lack of investment and they lost interest. Novell Forge became a laughing stock. It was used as evidence of what a company does when they "just don't get" open source, when it was ironically used as evidence of Novell's good faith not too long before.
Things finally came to the point where there was only one employee assigned to maintain the site, along with other unrelated duties (I, and the rest of the team, had by now been reassigned to different projects). Novell Forge was completely unsupported by Novell's IT group, leaving instead the support of the site to this one individual. I recall an occasion where the site went down over the weekend and was out for a couple of days. It was obvious that the site was in demand, because users made Novell aware of the outage quite quickly. However, Novell was not willing to pay for 24/7 support for the site, so instead of being brought back online right away, the site was down for the entire weekend until that resource came in to work the next Monday. My manager brought this to the attention of our team with the insistence that we address it. He stated that from that point on, that one employee would be the primary off-hours maintenance person for the site, and I would be the backup.
I then asked if Novell was going to start reimbursing me for my cell phone bill. He said no. I asked if they were going to buy me an additional cell phone, pay that bill, and also pay me extra to carry that additional phone. He said no. He said they would just list my personal cell number in the emergency contact list, and would call it if there were an emergency. I stated that in that case I maintained the right to not answer. He stated that I would have to answer, that it was my assignment. I claimed that Novell could not require me to answer my personal cell phone if I'm the one paying the bill. I then reminded him that in Novell's support organization, at least at that time, people that were expected to respond 24/7 had their cell phone bill paid by Novell, were paid an additional amount to be on call, and were paid an additional amount if they actually took a call and worked that call during off hours. I said, "If the site is important to Novell, that is what Novell should do. If the site is important, it should be important enough that Novell is willing to pay in order to maintain uptime and keep our customers satisfied."
Novell was not willing to pay.
I shortly moved on to a different team within Novell, and the other guy left the company altogether. I'm not sure who has been maintaining the site since then.
What Novell chooses to do with their money and their human resources is their business. This isn't meant as a criticism; I don't claim to have the right experience to criticize their decision to strangle Novell Forge to death. This is simply meant as a statement of fact, and the facts are pretty clear:
- You get what you pay for.
- Novell did not pay for Novell Forge by giving due reward and recognition to those who truly brought this idea to the company.
- Novell did not pay for Novell Forge by feeding its success with additional funding, promotion, and development.
- Novell did not pay for Novell Forge by giving it the kind of support and maintenance that its customers expected.
- The customers of Novell Forge were initially enthusiastic, but grew to sense the lack of commitment by the company and thus stopped participating.
- Novell Forge died as a result.
Novell Forge may be planned for decommission this December, but it died years ago. And don't think you can fool me, Novell. Novell Forge did not die because of lack of interest by the user community. Novell Forge died because you did not care about it. Whether that was a good decision or not is not for me to decide, but please, Novell, at least be honest with your community. We did not kill Novell Forge — you did.
UPDATE: Dan Reese, a member of my team back then, corroborated this in his blog.
