Reducing the size of a dynamically expanding VHD file

All Microsoft virtualization software allows you to manipulate virtual hard disk files (VHDs). The standard operations you can perform are listen in the table below.

image

* To fixed of same size as source
** To dynamically expanding of same size as source

What is missing here is the ability to shrink disks, either dynamically expanding or fixed. This is something that the built in tools cannot do. Enter the guys at vmToolkit and their VHDResizer. VHDResizer will let you shrink a fixed or dynamically expanding disk, provided you do some preparation.

032709_2254_Reducingthe1

Notice how VHDResizer has determined that the source VHD is a dynamically expanding disk, and that the destination VHD can be set to either fixed or dynamically expanding. This particular source VHD has a maximum size of 16 GB. Because of this the minimum size we can select for the destination VHD is 16 GB, regardless of disk type. The reason we cannot get the disk smaller than 16 GB is that the partitions or volumes in the VHD take up the entire 16 GB of space, even though the actual physical file is much smaller. This is the very basis of a dynamically expanding disk; the guest operating system sees all the space and can address it, but only blocks that have data on them are written to the VHD file. So we need to shrink the volumes inside the VHD to free up space. I find that the easiest way to do this is with Diskpart.exe and the SHRINK command. As long as there is free space at the end of the volume, SHRINK can reduce the size of the volume. You can see how much you can shrink the volume by running SHRINK QUERYMAX. Then you can use SHRINK to shrink the volume by the maximum space available.

Microsoft Windows [Version 6.0.6001]
Copyright (c) 2006 Microsoft Corporation. All rights reserved.
C:UsersAdministrator.LAB>diskpart
Microsoft DiskPart version 6.0.6001
Copyright (C) 1999-2007 Microsoft Corporation.
On computer: LAB-RODC1
DISKPART> select disk 0
Disk 0 is now the selected disk.
DISKPART> select volume 1
Volume 1 is the selected volume.
DISKPART> shrink querymax
The maximum number of reclaimable bytes is: 15 GB
DISKPART> shrink
DiskPart successfully shrunk the volume by: 15 GB
DISKPART>

But sometimes there is data at the end of the volume or very close to it, making the size you can shrink a volume by very small. To get around this you need to move the files to the beginning of the volume. The best tool I have found to do this is JKDefrag. By using JKDefrag’s action option 5 (Force together) we can force all the files on the volume together at the beginning of the volume. This will cause fragmentation, but we can deal with that by doing a normal defragmentation run when the volume has reached its desired size.

JkDefrag.exe -a 5 c:

But sometimes even this isn’t enough. However many times you run JKDefrag you will still see data at the end of your volume. Chances are that this is the NTFS Master File Table (MFT) stored in the file $Mft. The MFT also reserves a portion of the volume it calls the MFT Reserved space. This is to guarantee that the MFT has space to grow in, even when the disk is nearly full. The inability to write to or update the MFT would lead to disk corruption and orphaned files, which is the reason for this precaution. But to achieve our goal, we need to move the MFT and the MFT Reserved space blocks from the end of the volume and towards the start of the volume. (The MFT isn’t really at the end of the volume, at least it wasn’t in the beginning. Windows places the MFT around the middle of the volume by default, but since we have shrunk our volume it is now at the end.) The author of JKDefrag says that version 4 of JKDefrag will be able to move and defragment the MFT, but until that version is available we have to use another tool. The best I have found is Raxco PerfectDisk 10. PerfectDisk is commercial software, but you can download a trial version to perform your MFT defragmentation. Remember to get the correct version of PerfectDisk, the Pro version will not install on Windows Server for example. Install PerfectDisk 10 inside your virtual machine and analyze the volume you want to shrink. Select the Boot check-box next to the volume drive letter and reboot the virtual machine.

032709_2254_Reducingthe2

During the boot PerfectDisk will defragment your volume and move the MFT to around the middle of it. You have no control of where PerfectDisk moves the MFT, it uses its own internal logic to determine that. You probably will also see that the MFT will grow, this is also due to PerfectDisk’s internal optimization settings. After the virtual machine has booted you can again use Diskpart.exe and the SHRINK command to further reduce the size of the volume. You can repeat this process until you have reached your desired size for the volume. Then, finally, you can run VHDResizer and shrink your VHD file, and also convert it at the same time.

Remember the HOSTS file!

After moving a virtual Exchange 2007 machine from Virtual Server to Hyper-V I started getting error messages both in the Event Logs and in the Exchange Management Console and Shell. During the move I had also changed the IP address of the server. Here are the error messages:

In the Application Log:

EventID: 4001
Source : MSExchange System Attendant Mailbox
EntryType : Error

Message: A transient failure has occurred. The problem may resolve itself in awhile. The service will retry in 56 seconds. Diagnostic information:

Cannot open mailbox /o=Lab Organization/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=LAB-EXCH/cn=Microsoft System Attendant.

Microsoft.Exchange.Data.Storage.ConnectionFailedTransientException: Cannot open mailbox /o=Lab Organization/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=LAB-EXCH/cn=Microsoft System Attendant. —> Microsoft.Mapi.MapiExceptionNetworkError: MapiExceptionNetworkError: Unable to make co

nnection to the server. (hr=0x80004005, ec=2423)

Diagnostic context:

……
Lid: 12952dwParam: 0x6BAMsg: EEInfo: prm[0]: Long val: 135
Lid: 15000dwParam: 0x6BAMsg: EEInfo: prm[1]: Pointer val: 0x00000000
Lid: 15000dwParam: 0x6BAMsg: EEInfo: prm[2]: Pointer val: 0x00000000
Lid: 16280dwParam: 0x6BAMsg: EEInfo: ComputerName: n/a
Lid: 8600 dwParam: 0x6BAMsg: EEInfo: ProcessID: 2372
Lid: 12696dwParam: 0x6BAMsg: EEInfo: Generation Time: 2009-03-26 13:01:49:138
Lid: 10648dwParam: 0x6BAMsg: EEInfo: Generating component: 8
Lid: 14744dwParam: 0x6BAMsg: EEInfo: Status: 10060
Lid: 9624 dwParam: 0x6BAMsg: EEInfo: Detection location: 318
Lid: 13720dwParam: 0x6BAMsg: EEInfo: Flags: 0
Lid: 11672dwParam: 0x6BAMsg: EEInfo: NumberOfParameters: 0
Lid: 19778
Lid: 27970StoreEc: 0x977
Lid: 17730
Lid: 25922StoreEc: 0x977

at Microsoft.Mapi.MapiExceptionHelper.ThrowIfError(String message, Int32 hresult, Int32 ec, DiagnosticContext diagCtx)

at Microsoft.Mapi.MapiExceptionHelper.ThrowIfError(String message, Int32 hresult, Object objLastErrorInfo)

at Microsoft.Mapi.ExRpcConnection.Create(ConnectionCache connectionCache, ExRpcConnectionCreateFlag createFlags, ConnectFlag connectFlags, String serverDn, String userDn, String user, String domain, String password, String httpProxyServerName, Int32 ulConMod, Int32 lcidString, Int32 lcidSort, Int32 cpid, Int32 cReconnectIntervalInMins, Int32 cbRpcBufferSize, Int32 cbAuxBufferSize)at Microsoft.Mapi.ConnectionCache.OpenMapiStore(String mailboxDn, Guid mailboxGuid, Guid mdbGuid, ClientIdentityInfo clientIdentity, String userDnAs, OpenStoreFlag openStoreFlags, CultureInfo cultureInfo, String applicationId)at Microsoft.Mapi.ConnectionCache.OpenMailbox(String mailboxDn, Guid mailboxGuid, Guid mdbGuid, WindowsIdentity windowsIdentityAs, String userDnAs, OpenStoreFlag openStoreFlags, CultureInfo cultureInfo, String applicationId)at Microsoft.Exchange.Data.Storage.ConnectionCachePool.OpenMailbox(String serverDn, String userDn, String mailboxDn, Guid mailboxGuid, Guid mdbGuid, Object identity, ConnectFlag connectFlag, OpenStoreFlag openStoreFlag, CultureInfo cultureInfo, String clientInfoString, Boolean secondTry)

— End of inner exception stack trace —

at Microsoft.Exchange.Data.Storage.ConnectionCachePool.OpenMailbox(String serverDn, String userDn, String mailboxDn, Guid mailboxGuid, Guid mdbGuid, Object identity, ConnectFlag connectFlag, OpenStoreFlag openStoreFlag, CultureInfo cultureInfo, String clientInfoString, Boolean secondTry)at Microsoft.Exchange.Data.Storage.ConnectionCachePool.OpenMailbox(String serverDn, String userDn, String mailboxDn, Guid mailboxGuid, Guid mdbGuid, Object identity, ConnectFlag connectFlag, OpenStoreFlag openStoreFlag, CultureInfo cultureInfo, String clientInfoString, Boolean secondTry)at Microsoft.Exchange.Data.Storage.MailboxSession.Initialize(LogonType logonType, ExchangePrincipal owner, DelegateLogonUser delegateUser, Object identity, OpenMailboxSessionFlags flags)at Microsoft.Exchange.Data.Storage.MailboxSession.CreateMailboxSession(LogonType logonType, ExchangePrincipal owner, DelegateLogonUser delegateUser, Object identity, OpenMailboxSessionFlags flags, CultureInfo cultureInfo, String clientInfoString)at Microsoft.Exchange.Data.Storage.MailboxSession.OpenAsAdmin(ExchangePrincipal mailboxOwner, CultureInfo cultureInfo, String clientInfoString, Boolean useLocalRpc, Boolean ignoreHomeMdb)at Microsoft.Exchange.Data.Storage.MailboxSession.OpenAsAdmin(ExchangePrincipal mailboxOwner, CultureInfo cultureInfo, String clientInfoString)at Microsoft.Exchange.Servicelets.SystemAttendantMailbox.Servicelet.Work()

In Exchange Management Console (EMC) and Exchange Management Shell (EMS) when viewing the Mailbox node under Server Configuration:

——————————————————–

Microsoft Exchange Warning

——————————————————–

The following warning(s) were reported while loading topology information:

get-MailboxDatabase

Completed

Warning:

ERROR: Could not connect to the Microsoft Exchange Information Store service on server <server FQDN>. One of the following problems may be occurring: 1- The Microsoft Exchange Information Store service is not running. 2- There is no network connectivity to server lab-exch.lab.net. 3- You do not have sufficient permissions to perform this command. The following permissions are required to perform this command: Exchange View-Only Administrator and local administrators group for the target server. 4- Credentials have been cached for an unpriviledged user. Try removing the entry for this server from Stored User Names and Passwords.

This last error occurs when either the Management Console or Management Shell executes the Get-MailboxDatabase -Status cmdlet.

Outlook Web Access also did not work and displayed this error:

Outlook Web Access could not connect to Microsoft Exchange. If the problem continues, contact technical support for your organization.

Request

Url: https://<servername>:443/owa/default.aspx

User host address: <address of client>

Exception

Exception type: Microsoft.Exchange.Data.Storage.ConnectionFailedTransientException

Exception message: Cannot open mailbox /o=Lab Organization/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=morgan.

Call stack

Microsoft.Exchange.Data.Storage.ConnectionCachePool.OpenMailbox(String serverDn, String userDn, String mailboxDn, Guid mailboxGuid, Guid mdbGuid, Object identity, ConnectFlag connectFlag, OpenStoreFlag openStoreFlag, CultureInfo cultureInfo, String clientInfoString, Boolean secondTry)

Microsoft.Exchange.Data.Storage.ConnectionCachePool.OpenMailbox(String serverDn, String userDn, String mailboxDn, Guid mailboxGuid, Guid mdbGuid, Object identity, ConnectFlag connectFlag, OpenStoreFlag openStoreFlag, CultureInfo cultureInfo, String clientInfoString, Boolean secondTry)

Microsoft.Exchange.Data.Storage.MailboxSession.Initialize(LogonType logonType, ExchangePrincipal owner, DelegateLogonUser delegateUser, Object identity, OpenMailboxSessionFlags flags)

Microsoft.Exchange.Data.Storage.MailboxSession.CreateMailboxSession(LogonType logonType, ExchangePrincipal owner, DelegateLogonUser delegateUser, Object identity, OpenMailboxSessionFlags flags, CultureInfo cultureInfo, String clientInfoString)

Microsoft.Exchange.Data.Storage.MailboxSession.Open(ExchangePrincipal mailboxOwner, WindowsPrincipal authenticatedUser, CultureInfo cultureInfo, String clientInfoString)

Microsoft.Exchange.Clients.Owa.Core.OwaWindowsIdentity.CreateMailboxSession(ExchangePrincipal exchangePrincipal, CultureInfo cultureInfo)

Microsoft.Exchange.Clients.Owa.Core.UserContext.CreateMailboxSession(OwaContext owaContext)

Microsoft.Exchange.Clients.Owa.Core.UserContext.Load(OwaContext owaContext)

Microsoft.Exchange.Clients.Owa.Core.RequestDispatcher.CreateUserContext(OwaContext owaContext, UserContextKey userContextKey, UserContext& userContext)

Microsoft.Exchange.Clients.Owa.Core.RequestDispatcher.PrepareRequestWithoutSession(OwaContext owaContext, UserContextCookie userContextCookie)

Microsoft.Exchange.Clients.Owa.Core.RequestDispatcher.InternalDispatchRequest(OwaContext owaContext)

Microsoft.Exchange.Clients.Owa.Core.RequestDispatcher.DispatchRequest(OwaContext owaContext)

Microsoft.Exchange.Clients.Owa.Core.OwaModule.OnPostAuthorizeRequest(Object sender, EventArgs e)

System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()

System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Inner Exception

Exception type: Microsoft.Mapi.MapiExceptionNetworkError

Exception message: MapiExceptionNetworkError: Unable to make connection to the server. (hr=0x80004005, ec=2423) Diagnostic context: …… Lid: 12952 dwParam: 0x6BA Msg: EEInfo: prm[0]: Long val: 135 Lid: 15000 dwParam: 0x6BA Msg: EEInfo: prm[1]: Pointer val: 0x00000000 Lid: 15000 dwParam: 0x6BA Msg: EEInfo: prm[2]: Pointer val: 0x00000000 Lid: 16280 dwParam: 0x6BA Msg: EEInfo: ComputerName: n/a Lid: 8600 dwParam: 0x6BA Msg: EEInfo: ProcessID: 3372 Lid: 12696 dwParam: 0x6BA Msg: EEInfo: Generation Time: 2009-03-25 20:59:22:652 Lid: 10648 dwParam: 0x6BA Msg: EEInfo: Generating component: 8 Lid: 14744 dwParam: 0x6BA Msg: EEInfo: Status: 10060 Lid: 9624 dwParam: 0x6BA Msg: EEInfo: Detection location: 318 Lid: 13720 dwParam: 0x6BA Msg: EEInfo: Flags: 0 Lid: 11672 dwParam: 0x6BA Msg: EEInfo: NumberOfParameters: 0 Lid: 19778 Lid: 27970 StoreEc: 0x977 Lid: 17730 Lid: 25922 StoreEc: 0x977

Call stack

Microsoft.Mapi.MapiExceptionHelper.ThrowIfError(String message, Int32 hresult, Int32 ec, DiagnosticContext diagCtx)

Microsoft.Mapi.MapiExceptionHelper.ThrowIfError(String message, Int32 hresult, Object objLastErrorInfo)

Microsoft.Mapi.ExRpcConnection.Create(ConnectionCache connectionCache, ExRpcConnectionCreateFlag createFlags, ConnectFlag connectFlags, String serverDn, String userDn, String user, String domain, String password, String httpProxyServerName, Int32 ulConMod, Int32 lcidString, Int32 lcidSort, Int32 cpid, Int32 cReconnectIntervalInMins, Int32 cbRpcBufferSize, Int32 cbAuxBufferSize)

Microsoft.Mapi.ConnectionCache.OpenMapiStore(String mailboxDn, Guid mailboxGuid, Guid mdbGuid, ClientIdentityInfo clientIdentity, String userDnAs, OpenStoreFlag openStoreFlags, CultureInfo cultureInfo, String applicationId)

Microsoft.Mapi.ConnectionCache.OpenMailbox(String mailboxDn, Guid mailboxGuid, Guid mdbGuid, WindowsIdentity windowsIdentityAs, String userDnAs, OpenStoreFlag openStoreFlags, CultureInfo cultureInfo, String applicationId)

Microsoft.Exchange.Data.Storage.ConnectionCachePool.OpenMailbox(String serverDn, String userDn, String mailboxDn, Guid mailboxGuid, Guid mdbGuid, Object identity, ConnectFlag connectFlag, OpenStoreFlag openStoreFlag, CultureInfo cultureInfo, String clientInfoString, Boolean secondTry)

The Exchange Best Practices Analyzer (BPA) also failed when run locally against the server. The error was: Exchange Server cannot be contacted.

Despite these errors all Exchange services were running and Outlook clients on the internal network could connect to Exchange and open their mailbox. Any access through CAS did not work, so Outlook Anywhere or OWA were unavailable.

After searching the web I did not find an exact match for these errors, at least none that had my particular symptoms. But from what I read it looked like an issue with the network configuration, i.e. the network card.

First I went into Device Manager and removed all missing hardware devices, this included the old Intel 21140 emulated NIC from Virtual Server. I had not removed the Virtual Server Virtual Machine Additions until after I had moved the server so its configuration was still in the Registry. For information on how to remove missing devices, have a look here. Finally I removed the Virtual Machine Bus Network Adapter, reinstalled it and set the correct IP address information. All this did not resolve the error either, but I discovered something interesting in the Registry regarding the Virtual Machine Bus Network Adapter, which I will cover in a later post.

Still working with the networking idea I ran the Exchange Best Practices Analyzer (BPA) from a different server, and this time I could connect and complete the scan. This meant that at least the network was working and that the Windows Firewall was not blocking the communication. The next step was to run Wireshark on the server while I ran the BPA against the local server, that is not over the network. This produced the first real indication on what the error was. Here is a screenshot from the capture:

032609_1821_Rememberthe1

The Exchange server’s new IP address on Hyper-V was 192.168.131.3. But while it was hosted on Virtual Server it’s IP address was 192.168.131.180. So judging from the ARP broadcasts, which are coming from the local server, the old IP address is still active somehow. To test this theory I changed the server’s IP address back to the old one 192.168.131.180. Now the BPA finished successfully and EMC/EMS were able to successfully run the Get-MailboxDatabase -Status cmdlet. I changed the IP address back to the new one, 192.168.131.3, hoping that this would somehow reset the erroneous configuration. It did not, and the errors immediately came back. So the old IP was still somewhere in the Registry. I did a search in the Registry for 192.168.131.180, and this is what I got:

reg query HKLM /s /f “192.168.131.180”
HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionNetworkListNlaCacheIntranetAuth2.4.fe80::7de2:4df0:fa6e:2231%10 1.1.192.168.131.180
HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionNetworkListNlaCacheIntranetAuth2.4.fe80::d0b2:3082:e67:d254%10 1.1.192.168.131.180
HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionNetworkListNlaCacheIntranetAuth2.4.fe80::e1e0:a13d:50cc:f9b3%10 1.1.192.168.131.180
HKEY_LOCAL_MACHINESYSTEMControlSet001Services{3832C4EC-AC88-42FA-B266-51D68342079A}ParametersTcpip
IPAddress REG_MULTI_SZ 192.168.131.180
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServices{3832C4EC-AC88-42FA-B266-51D68342079A}ParametersTcpip
IPAddress REG_MULTI_SZ 192.168.131.180
End of search: 5 match(es) found.

I ignored everything under the NLA key which is part of the Network Location Awareness service. That left the GUID key ({3832C4EC-AC88-42FA-B266-51D68342079A}) under Services. Each GUID key under the Services key represents a Network Card. So which card was this?

Windows maintains a list of the network cards in the system under the Registry key HKLMSOFTWAREMicrosoftWindows NTCurrentVersionNetworkCards. This is the list from my system:

reg query “HKLMSOFTWAREMicrosoftWindows NTCurrentVersionNetworkCards” /s
HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionNetworkCards8
ServiceName REG_SZ {3832C4EC-AC88-42FA-B266-51D68342079A}
Description REG_SZ Microsoft Virtual Machine Bus Network Adapter

So this was the Virtual Machine Bus Network Adapter. Time to examine the TCP/IP registry settings for this adapter more closely.

The main TCP/IP configuration location in the Registry is under HKLMSYSTEMCurrentControlSetServicesTcpip. The configuration of the network cards is in the subkey ParametersInterfaces:

reg query HKLMSYSTEMCurrentControlSetServicesTcpipParametersInterfaces /s
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesTcpipParametersInterfaces{3832C4EC-AC88-42FA-B266-51D68342079A}
UseZeroBroadcast REG_DWORD 0x0
EnableDeadGWDetect REG_DWORD 0x1
EnableDHCP REG_DWORD 0x0
NameServer REG_SZ 192.168.131.2
Domain REG_SZ
RegistrationEnabled REG_DWORD 0x1
RegisterAdapterName REG_DWORD 0x0
DhcpServer REG_SZ 255.255.255.255
Lease REG_DWORD 0x1c20
LeaseObtainedTime REG_DWORD 0x49caa3c7
T1 REG_DWORD 0x49cab1d7
T2 REG_DWORD 0x49cabc63
LeaseTerminatesTime REG_DWORD 0x49cabfe7
AddressType REG_DWORD 0x0
IsServerNapAware REG_DWORD 0x0
DhcpConnForceBroadcastFlag REG_DWORD 0x1
IPAddress REG_MULTI_SZ 192.168.131.3
SubnetMask REG_MULTI_SZ 255.255.255.0
DefaultGateway REG_MULTI_SZ 192.168.131.1
DefaultGatewayMetric REG_MULTI_SZ 0

As we can see there is a configuration mismatch between the configuration under the GUID key ({3832C4EC-AC88-42FA-B266-51D68342079A}) under Services, and the configuration under the Tcpip key. Seemed like a buggy TCP/IP stack so I decided to reset it:

  1. Uninstalled the Virtual Machine Bus Network card from Device Manager.
  2. Reset WinSock:
    netsh winsock reset catalog
  3. Reset TCP/IP:
    netsh int ip reset %temp%reset.log
  4. Reboot

These steps would completely reinstall TCP/IP and reinstall the NIC.

But after the reboot the errors were still present and Wireshark saw the same ARP requests for the old address 192.168.131.180. The old address was now completely gone from the Registry and Active Directory does not store IP addresses (usually). So where was this information coming from? I looked in the forward and reverse lookup zones on the DNS server, but the correct IP was present in the forward zone. The old address was in the reverse zone, but that was not relevant here. I did a ping from the command line for the server name, and it returned the old address! But Nslookup did not! Finally I was on to something! The HOSTS file!

Here is the hosts file on the server:

# Copyright (c) 1993-2006 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a ‘#’ symbol.
#
# For example:
#
# 102.54.94.97 rhino.acme.com # source server
# 38.25.63.10 x.acme.com # x client host
127.0.0.1 localhost
#::1 localhost
192.168.131.180    lab-exch
192.168.131.180    lab-exch.lab.net

And there was the answer and the explanation for everything. I had previously entered the information for the local server into the hosts file to work around a bug in the DSProxy components on the CAS server where DSProxy would not listen on IPv6 addresses. More info on this issue here. This also explained why other machines could connect to the server and why EXBPA failed when run locally.

I updated the addresses and rebooted. The issue with DSProxy and IPv6 was fixed in Update Rollup 4 for Exchange 2007 with Service Pack 1, but I was not able to make it work in my setup without the entries in the hosts file. My guess is that this is because I have an ISA server between the Exchange server and the clients.

So there you have it. A very simple solution arrived at via very long, cumbersome and unnecessary process. So remember that old hosts file guys.

How to remove orphaned hardware devices

  1. Open a command prompt
    If you are on an OS with User Account Control enabled, you need to run the command prompt as an Administrator.
  2. Type the following:
    set DEVMGR_SHOW_NONPRESENT_DEVICES=1
  3. In the same command prompt window, type:
    devmgmt.msc
  4. Device Manager opens.
  5. Select View, Show Hidden Devices
  6. Expand the various categories to display orphaned devices. They will be grayed out:
    032509_2212_Howtoremove1
  7. Right-click and select Uninstall to remove the device completely from the system.
  8. A reboot may be necessary after your have removed the devices. Sometimes Device Manager will inform you of this, sometimes not.

I find this extremely useful on virtual machines that have moved from one virtualization platform to another. In this situation old Network Interface Cards (NICs) can sometimes be problematic.

How to export a virtual machine directly to a network share

When moving virtual machines between Hyper-V servers it is often useful to be able to export directly into the folder where the virtual machine will reside on the new host. This saves a lot of time and disk space. Here is what you need to do:
  1. Make sure that both your source and destination Hyper-V servers are in the same forest.
  2. Share the folder where the virtual machine will be exported to.
    (This is on the destination server).
  3. Grant NTFS permissions to BOTH the user running the Hyper-V Manager on the source machine and the computer account of the source machine, for the export folder.
  4. Grant Sharing permissions to BOTH the user running the Hyper-V Manager on the source machine and the computer account of the source machine, for the export folder.
  5. Export the virtual machine using the UNC path of the share you created in step 2 as the destination.

These requirements are also covered in the Hyper-V release notes (http://technet.microsoft.com/en-us/library/cc754747.aspx).

Quick PowerShell script to query for installed hotfix

This is a quick and dirty PowerShell script to see if the local computer has a particular hotfix installed. It takes one argument; the number of the hotfix.
QueryHotfix.ps1:
$KB = $args[0]
Get-WMIObject -class “Win32_QuickFixEngineering” -namespace “root/CIMV2” | Where { $_.hotfixid -match $KB }
Enjoy.

How to install System Center Virtual Machine Manager 2008 prerequisites

Here is a short script that will install the prerequisites for System Center Virtual Machine Manager 2008:

ServerManagerCMD.exe -i PowerShell

ServerManagerCMD.exe -i Web-Server

ServerManagerCMD.exe -i Web-Asp-Net

ServerManagerCMD.exe -i Web-Metabase

ServerManagerCMD.exe -i Web-WMI

Since ServerManagerCMD.exe is deprecated in Windows Server 2008 R2 and has been replaced with PowerShell cmdlets, here is the PowerShell command as well:

Add-WindowsFeature Web-Server,Web-Asp-Net,Web-Metabase,Web-WMI

Remember to do ImportSystemModules or Import-Module Servermanager first.

No need to do PowerShell since it is already installed on Windows Server 2008 R2.

Also, remember that SCVMM needs the Domain Functional level to be at least 2, that is Windows Server 2003. The Configuration Analyzer will warn you of this:

image_2_757406E1

Backing up your Windows profile using Robocopy

Whenever I upgrade the OS on one of my computers or upgrade the computer itself, I always make a manual backup of the data I need to retain. There are many utilities that do this job for you, like User State Migration Tool and Windows Easy Transfer, but none of them give me that warm fuzzy feeling that total manual control provides.
The Robocopy utility, short for Robust File Copy, is one of my all time favorites when it comes to copying large amounts of data. Robocopy used to be part of the Windows Resource Kit, but at least since Windows Vista/Server 2008 it has been part of the base OS installation. This command is what I use to backup my Windows profile, which contains the bulk of my data:
robocopy.exe c:\Users\Morgan g:\ProfileBackup /E /ZB /R:0 /W:0 /XJ /NFL /XD OneDrive “Temporary Internet Files” OfficeFileCache Temp *cache* Spotify WER /XF *cache* *.ost
Note: If you decide to copy and use this command, pay special attention to the file (XF) and directory (XD) exclusions I use. You may have different requirements!
Parameter
Explanation
/E
Copy all subdirectories, even empty ones.
/ZB
Use restartable mode; if access denied use Backup mode.
/R:0
Number of Retries on failed copies, in this case 0.
/W:0
Wait time between retries, in this case 0.
/XJ
Exclude Junction points
/NFL
No File List – don’t log file names.
/XD Exclude selected directories; space delimited
/XF Exclude selected files; space delimited
Note that the command promp from which you run this command must be run as an administrator. This is because we tell Robocopy to use backup mode when it cannot access a file. The right to copy a file using the backup interface (Back Up Files and Directories) is reserved for the Administators and Backup Operators groups on Windows Vista/7.
The XJ paramtere requires some extra explanation. Windows Vista changed the layout of user profiles, making Vista profiles incompatible with profiles in earlier versions of Windows. To ensure compatibility with older applications the Windows Vista profile contains several NTFS junctions that map the old folder names to the new locations. If you try to run Robocopy without the XJ parameter the copy will loop creating nested folders in your target destination until the path length reaches the maximum (256) allowed by NTFS. Therefore we need to exclude juntions.
When you run this command you will see many files that cannot be accessed since they are in use. This can be safely ignored. These files are your actual registry hive etc that is loaded when you are logged on to the system. If you want a copy of these files as well you have to boot into WinPE and make a copy from there. Or log on as another user with administrative privileges and make a copy of the profile. I have never needed any of the data in these files.

Displaying the Volume GUID of a volume

The use of letters to identity volumes and partitions in Windows is something we have inherited from MS-DOS. Drive letters are still used today due to their ubiquity and for compatibility. However, the Windows operating system does not depend on them. Instead Windows uses a GUID to identify each volume or partition. (Windows Home Server, which is actually a custom version of Windows Server 2003 has done away with the use of drive letters completely.)This GUID is called the Volume GUID or the Unique Volume Name. The Volume GUID is assigned the first time the OS encounters a volume and it does not change. This ensures that Windows can always uniquely identify a volume, even though its drive letter has changed.

On systems with a lot of storage you will often run out of drive letters for your partitions and volumes. You can work around this by using mount points e.g., but you can also reference the volume by its GUID directly. This is actually the recommended practice in some situations. When configuring highly available virtual servers in Hyper-V with Windows Failover Clustering, for example.

So how do we find the Volume GUID? The easiest way I have discovered is by the use of the mountvol.exe utility. Running mountvol.exe without any arguments will show you help for the utility, but also the current Volume GUID to drive letter/mount point relationships.

 012609_2007_Displayingt1

To prove that the volume GUIDs really are the “true” path to the volume, copy one of the strings and past it into Explorer or the Run dialog.

 012609_2007_Displayingt2

Press enter and you will see the contents of the volume displayed.

 012609_2007_Displayingt3

(Notice the question mark by the drive icon in the navigation bar and the info pane.)

I have not been able to use the Volume GUID from the command line, but that is also the only limitation I have found. Not strange if you consider the command prompt’s origins.

You can also see all the volume GUIDs for every volume the OS has ever seen under the registry key:
HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices

 012609_2007_Displayingt4

At this location you will also find the “regular” drive letter assignments. They have the form \DosDevices\<drive letter>. If you compare the data in this key for the Volume GUID and the DOS drive letter for a given volume, you will see that they match meaning that they point to the same volume.

Strangely enough, the Swiss army knife of disk and volume management in Windows; diskpart.exe can’t display the Volume GUID. This is something that will change in future releases, hopefully. Diskpart can, however, display another interesting piece of data which resembles the Volume GUID, namely the disk signature. Just as volumes have unique IDs, so do disks (or what Windows perceives as disks). The DETAIL command in diskpart will display the disk signature as the Disk ID. It is an 8 digit hexadecimal number.

The string \\?\ is present in all volume GUIDs and it tells Windows to turn off path parsing. Windows NT/2000/XP/Vista have a maximum path length of 255 characters. It is possible to use more that 255 characters by prefixing the path with \\?\. This enables you to use paths that are up to 32,000 characters long, and is called using the “wide” version of a function. The \\?\ itself is ignored as part of the path. E.g.:

“\\?\C:\Users\Aquaman\Documents\test.docx” will be processed as “C:\ Users\Aquaman\Documents\test.docx”

Various problems with the Volume GUID may occur under some circumstances making Windows unable to boot or access the volume. Some of these situations are documented here: http://support.microsoft.com/kb/959573

How to exit explorer.exe gracefully on Windows XP and Windows Vista/7

When you install a piece of software that integrates with the Windows shell, typically explorer.exe, you have to restart your computer to complete the installation. If the installer were to close explorer.exe the user would be left without a usable GUI. However there is a supported way of closing the shell process, perhaps saving you from a reboot when installing software. Or just giving you something to test and play around with.

Windows Vista

Press the Start button, and while holding Ctrl+Shift, right-click any empty area of the menu, or the power or lock buttons. You will see this context menu:

012509_0220_Howtoexitex1

Hit Exit Explorer to exit the shell process.

Windows XP

Open the shutdown dialog, Log Off…/Shut Down/Restart, and while holding Ctrl+Alt+Shift hit the Cancel button. Explorer will exit cleanly.

So now what?

OK, so we have made our shell exit. So how do we control the computer now? Any applications you had running while the shell was running will still have their windows on your desktop, but you will not be able to do much with them. We need to restart the shell process. How, you say? Simple. Just bring up Task Manager (Press Ctrl+Shift+Esc) and select New Task… (Run) from the File menu. Enter explorer.exe and your shell will restart.

More info on Aaron Margosis’ Blog:
http://blogs.msdn.com/aaron_margosis/archive/2007/07/17/how-to-cleanly-stop-explorer-exe-on-windows-vista.aspx