April, 2012

  • Updated Archive of the NtDebugging Twitter Debug Tips

    Every Wednesday (usually) we post a debug tip to our twitter page at https://twitter.com/#!/ntdebugging . This blog is an archive of these tips to allow our readers to find this information easily. Periodically we post an updated blog with the current ...read more
  • How to: VSS Tracing

    How VSS Tracing Works!

    Where to start? Well this depends on your current level of knowledge on the topic. So let’s start with a basic understanding of what VSS is. If you are just starting to work with VSS I suggest reading the articles below.

    The key points to focus on in this article are:

    • Volume Shadow Copy Service Components
    • Copy-on-Write (Differential Copy)
    • Hardware-based Providers
    • Software-based Providers
    • How Shadow Copies Are Created

    Below are a couple of TechNet articles as a reference.

    How Volume Shadow Copy Service Works


    Volume Shadow Copy Service

    I like to think about VSS as being camera that takes pictures of your data. Like a picture a VSS snapshot is a point in time view of a volume. The overall concept is rather simple. We hold writes to a disk so we can take a picture of the blocks on that disk. We then release the hold and are left with a view of the data at the time we took the picture. In the case of a client-accessible snapshot we then use COW or Copy-on-Write to make a copy of any blocks that change. This allows you to build a view of your data from the time of the snapshot. Since we have any a copy of the changed blocks we can use them to restore our view of the volume. Backup applications use this same type of process only they use different types of snapshot depending on the type of backup being run.

    The Tools

    Now that you have a basic understanding of how VSS works we can look at what to do when you run into errors. We have several tools at our disposal. VSSTrace.exe, Logman.exe, and TraceLog.exe are all tools that we can leverage to capture traces. Tracing VSS will provide you with a log file that contains what function was called and the result. From this we can see where VSS is failing and the error being returned.

    One of the more common ways to capture a VSS trace is with Vsstrace.exe. Using this tool and a few other tools from the VSS SDK, like Vssagent.exe we can capture additional diagnostics data that helps provide a better understanding of the type of snapshot being ran and details about the error we encountered. VSSAgent collects disk, volume, shadowcopy storage, events log entries and other critical information necessary to provide context to the trace you are capturing.

    One of the most important things to know when reviewing a VSS trace is the context. Case in point, are you looking at the actions of a software provider or hardware provider? Or, maybe the trace is simply a command being run in which case we would not be expecting the see the same function calls as we would with a complete snapshot. For example,

    vssadmin list writers

    Knowing the intention of the requestor at the time of the snapshot is important to understanding what to look for in the trace.

    Tracing Options Explained

    Let’s spend some time and talk about the options available when capturing tracing of VSS. For this I am going to focus on VSSTRace.exe. VSSTRace.exe allows us to use the various tracing levels and options available to us from the VSS service. For example:

    vsstrace.exe -o trace.txt

    This will generate a trace file in plain text format. Where this command:

    vsstrace.exe -etl trace.etl

    This would create an ETL formatted file which you would not be able to read with a text editor.

    So let’s say you were having an issue where you wanted to only capture tracing from action performed by the writers. You could run the following command:

    vsstrace.exe -f 0 +WRITER

    In this command the “-f” would indicate the enabling of flags and the “0” would indicate no modules are going to be traced. Now that we have told tracing to not capture anything we have to add back the stuff we want. That is where the “+WRITER” comes into play. This enables tracing for just the writers.

    There is a great chart on MSDN that provides you with all the various modules and flags that can be turned on (http://msdn.microsoft.com/en-us/library/windows/desktop/dd765233(v=vs.85).aspx). To find out more about Vsstrace.exe, please see:

    Using VSS Diagnostics

    Level is the next thing we should cover. There are 21 different log levels for VSS tracing. The most commonly used is 170. This is the default log level for Vsstrace.exe; however, this can be adjusted by appending to the command line we use to start the trace. Here is the command you would use with VSSTrace.exe to capture all events for only the VSS service components.

    vsstrace.exe +f 0xffff -COORD -l 255

    This chart has all the log levels listed for you. This can also be found in greater detail on the above mentioned links to MSDN.


    Information included in trace output




    Fatal errors


    Unhandled exceptions








    Exception handling


    Event Log activity


    General information


    Code flow


    Function enter and exit


    Function return values


    Function parameters (terse)


    Function parameters (verbose)


    Verbose information level 1


    Verbose information level 2


    Verbose information level 3


    Fast Code Level 1


    Fast Code Level 2


    Fast Code Level 3



    Taking a Trace

    Now it’s time for us to do some tracing. Earlier we talked about the options available to us, now let’s put them practice. We will start with a basic trace that will capture all modules and write the trace data to a plain text file on C:\TEMP.

    vsstrace.exe +f 0xffff -o C:\temp\trace.txt

    Now say you need a trace of only the Windows built-in in software provider. You would run the following command:

    vsstrace.exe -f 0 +SWPRV -o C:\trace.txt

    Here we see that the “-f 0” indicates no modules to be traced, and then we add the “+SWPRV” to indicate that we will be only tracing the built-in software provider to a text file located at “C:\Temp\Trace.txt”. This kind of granularity is useful when trying to isolate a particular module.

    If you need to capture a greater level of detail within the trace. We can add the “-l” flag to set the level of logging to capture. By default we use 170 from the above chart. Let’s turn that up to the maximum setting of 255. The command would now look like this:

    vsstrace.exe -l 255 –o C:\trace.txt

    This setting will get you every possible message from all modules. That being said, keep in mind that this comes at the cost of space. The trace file will grow in size quickly depending on the flags set. In contrast to this by limiting logging to specific modules and trace levels you can limit the overall size on lengthy captures.

    Reading the Trace

    Now that we understand the options and tracing levels and have captured our trace, it’s time to figure out what’s wrong. The best way to do this is to use a text analysis tool like Notepad++ or some other tool with a filtering option. You are going to want to create filters on the following key words.

    • Failure
    • Warning
    • abort
    • 0x8004
    • 0x8007
    • 0x8000f

    These key words should help point out where the trace is failing. Please remember that there are all kinds of patterns and failures that will be shown in these logs. Understanding them comes in time so don’t get discouraged if you cannot figure these out easily.

    Here is an example of a VSS Trace.

    ---Trace Snip ---

    12402 [0480230921,0x001e34:0x1864:0x3bc9015a] modules\writers\evtlogwriter.cxx(0460): CEventLogWriter::BackupLogs: Failed to backup event log Microsoft-Windows-EventCollector/Operational to C:\WINDOWS\Repair\Backup\ServiceState\EventLogs\Microsoft-Windows-EventCollector/Operational.evt. [0x0000007b]
    12403 [0480230937,0x001e34:0x1864:0x3bc9015a] modules\writers\evtlogwriter.cxx(0460): CEventLogWriter::BackupLogs: Throwing HRESULT code 0x8000ffff. Previous HRESULT code = 0x00000000
    12404 [0480230937,0x001e34:0x2438:0x3bc9015a] coord\src\async.cxx(0509): CVssAsync::QueryStatus: Returning *pHrResult: 0x00042309
    12466 [0480231203,0x001e34:0x1864:0x36bde5db] modules\registry\registry.cxx(1277): CVssDiag::RecordGenericEvent: Event name: VSS_WS_FAILED_AT_PREPARE_SNAPSHOT (SetCurrentState)

    ---End Snip---

    In the example, you can see a failure to access a particular resource during the snapshot process. Let’s break this down. The first line in example 1 shows that VSS was running the CEventLogWriter::BackupLogs: function and its result was:

    Failed to backup event log Microsoft-Windows-EventCollector/Operational to C:\WINDOWS\Repair\Backup\ServiceState\EventLogs\Microsoft-Windows-EventCollector/Operational.evt. [0x0000007b]

    Looking deeper at the results, we see that the failure code was 0x0000007b.

    To see what the this error code is indicative of, you can run the following at an administrative command prompt:

    C:\> slui.exe 0x2a 0x0000007b

    This will give you a dialog box that gives the description:


    You can also use a tool such as Err.exe.

    Taking what we just learned about the error code we can look at the path to the object that we were trying to access. Notice that the path is invalid as the path contains a “/”. From this we can now investigate that issue with that path.


    Now that we have taken tracing from A-Z, you should be well armed to get out there and collect some traces. Remember it takes time to get the hang of what's going on in a trace.

    Good luck and successful backups!

    Randy Monteleone
    Sr. Support Escalation Engineer

  • Improve caching for CSR

    In previous versions of Windows, clients with remote connections would often initiate network traffic to retrieve remote information from a print server, resulting in a resource-consuming call to the server.  This behavior was more significant when Client Side Rendering (CSR) was used that caused increased communication with the remote server. Many applications use certain APIs to query the print spooler for print information at startup, at document creation time, and when displaying available fonts. This often resulted in visible delays or hangs in the applications from the user’s perspective. In Windows 7 and Windows Server 2008 R2, the performance of many spooler API calls has been improved through more aggressive caching that will reduce the remote server calls and improve end user performance.

    In general, the intent of the enhancements has been to decouple applications that use client print APIs (winspool.drv) from the print server to avoid application UI delays. Some of the APIs that are used by major client applications such as the print dialog and Microsoft Office have had their caching behavior improved. OpenPrinter, EnumJobs, and some forms of GetPrinterDriver are the main APIs that will see caching improvements.

    Overview of CSR caching behavior

    The CSR provider maintains a cache of print connection data for remote connections. This cache is persisted in the registry and loaded at provider startup.  The cache follows a “pull” model and in general operates asynchronously.  Calls requesting remote connection data are serviced from the local cache immediately where possible, and an asynchronous work item is queued that will synchronize with the remote server if necessary. Only in the case where the remote data is not cached locally will the call go over the network synchronously. The asynchronous synchronization with the remote server is done only periodically; most cache entries have an expiry time of 120 seconds. Cache coherency is enforced by checking Change IDs associated with both the local cache and the remote connection. If a request is made for cached data last accessed over 120 seconds ago, the remote Change ID will be compared to the local one, incurring a single RPC call of overhead. If they differ the cache will be updated from the remote server, incurring one or more RPC calls.

    Caching behavior of common APIs

    The table below shows the caching characteristics of common print APIs. The cache refresh interval for each caching mode is described in the next section.

    Caching behavior of key print APIs


    Caching Behavior

    Caching Mode

    Changed from previous versions ?


    Cached.  Client spooler still initiates network traffic for “Set” API calls and opens the remote printer handle when absolutely necessary.  OpenPrinter learns the server response per access mask; this it may block while populating the cache with results for masks it hasn't seen before. 




    Cached. Certain operations, like creating a job, cause an update of the EnumJobs cache.




    Cached when there is a printer connection to the target server. 


    Yes, but only for level 8 calls


    Cached for both server and printer handles when there is at least one printer connection to the target server. Not cached otherwise.




    Not cached.








    Cached when there is a printer connection to the target server.  Not cached otherwise.




    Not cached.




    Cached for Level 4.  Level 4 only returns data when there are print connections.




    Not cached. 




    Cached based on flag.  Calls with ‘NO_CACHE’ flag will not be cached.  Calls without the ‘NO_CACHED’ flag will be cached.



    Registry keys for cache refresh intervals

    Two registry key values control the cache refresh behavior for print APIs. Caching mode “Normal” is controlled by the following registry key value and defaults to 120 seconds:

    HKLM\Software\Policies\Microsoft\Windows NT\Printers\SyncCacheAgeUser

    Caching mode “Volatile” is controlled by the following registry key value and defaults to 0 seconds:

    HKLM\Software\Policies\Microsoft\Windows NT\Printers\SyncCacheAgeVolatile

    -Bernd Hogen

  • Troubleshooting Memory Leaks With Just a Dump

    Hello debuggers, the debug ninja is back again.   Sometimes we have a scenario where a process is using a lot of memory, and the only data we are able to get at the moment is a user dump.   Ordinarily data from tools such as umdh or xperf would ...read more
  • Task Scheduler Error “A specified logon session does not exist”

    Good morning AskPerf!  Kapil Patry here from the Microsoft Platforms Support Team.  I am blogging today about an issue I recently worked.  This particular issue dealt with the creation of a task using Task Scheduler on a Windows 2008 R2 Server (can occur on Windows 7 as well).  When I attempted to create a scheduled task, the following error appeared:


    Task Scheduler

    An error has occurred for the task <task name>. Error message: The following error was reported: A specified logon session does not exist. It may have already been terminated..

    This error came up whether I was logged on as a Local Administrator, Domain Administrator, or any other user that had rights to log on locally.

    After extensive research, I found that the above error will only occur if the following Security Policy is enabled and you select the “Run whether user is logged on or not” Security option on the General tab, when creating a new task:

    SECPOL.MSC | Security Settings | Local Policies | Security Options

    Network access: Do not allow storage of passwords and credentials for network authentication


    To resolve this issue, simply Set this policy to Disabled:


    The new version of Task Scheduler (Windows Vista onwards) uses Windows Credential Manager to store the credentials of the account that is specified to perform a task.  If the Network access: Do not allow storage of passwords and credentials for network authentication policy is enabled and applied, Credential Manager cannot store the credentials locally, thus this error message appears.

    NOTE you will not receive this error if the “Run only when user is logged on” Security option on the General tab is selected (we do not store passwords in this scenario).

    Addition Resources

    -Kapil Patry

  • Troubleshooting Boot Issues due to missing Driver signature (x64)

    Today, I am going to discuss how to troubleshoot a scenario where the system does not boot in normal mode; however, boots up fine upon selecting F8 -> Disable Driver Signature Enforcement.

    In 64-bit operating systems starting with Windows Vista, Windows will load a kernel-mode driver only if the driver is signed. You might get different fatal errors during the boot process depending on the driver that was blocked from loading and how it impacted the further processes. While some of the fatal system errors reference the driver on the blue screen, some may not.

    Here is an example of how we can diagnose the problem and fix it. When booting normally, you may receive this error and the machine halts:


    This article explains this type of stop error.



    In decoding the stop error, you should look at the second parameter.

    (0X00000000 0XC0000428 0X00100588)  <--- second parameter indicates error code


    To translate the hex code, you can use the inbox SLUI.EXE tool or look up the error code from ntstatus.h file in the Windows SDK.

    Command Usage:

    slui.exe 0x2a 0xC0000428


    Restart your computer and start pressing the <F8> key on your keyboard. On a computer that is configured for booting to multiple operating systems, you can press the <F8> key when the Boot Menu appears. On the Advanced Boot Options menu, select Disable Driver Signature Enforcement press <ENTER>.


    If the server boots up after selecting this mode, we now know that it is some driver or module which is unsigned or being detected as unsigned that is preventing the system from booting up properly.

    Our next task is to find out the module name and devise a remedy. You would need to open Event Viewer and go to Applications and Services Logs -> Microsoft -> Windows -> CodeIntegrity -> Operational.

    Note: Check if you can see events like the ones depicted below.
    In case you get “access denied” while accessing the “operational” log create a folder on the root of the C drive and give Everyone full rights.
    Redirect the ETL file path to the newly created folder. Disable and enable the logging again.


    Once logging is enabled, you will find the unsigned driver name from the events.



    The driver can be a Microsoft inbox driver or a 3rd party driver. For drivers that have newer versions available and can be updated, that is the first thing to try. In most cases, this will fix the problem.

    However, you might encounter a scenario when there is no update available. Here are the steps to find out the required catalog file and place it accordingly.

    Files can be copied from another working server with similar file versions and extracted from the update that was the source of the file version.

    We can use the SIGCHECK.EXE tool to find the catalog file for a file.



    Step -1 : Verify if the driver is really Unsigned:

    Note: The full path of the driver file should be passed as a command line parameter


    You can run the command as described in the screenshot above to make sure the driver is indeed being detected as unsigned.


    Step – 2 : Get the Signed driver from a working server:


    The actual file and the catalog can be copied from a working server and placed in respective locations as depicted above. Once the copy completes, use the SIGCHECK tool to verify and make sure that the file is detected as signed and displays the name of the catalog. Reboot the server and ensure it comes up fine in the normal mode.


    Appendix - A


    To find the catalog for the file, you can also enable verbose logging for CodeIntegrity on the working server.  This will log the name of the CAT file where the file hash was found during the verification.


    Steps to enable CodeIntegrity verbose logging:

    i. Open Event Viewer
    ii. Select the View drop down menu and choose Show Analytic and Debug Logs from the list
    iii. Navigate to Applications and Services Logs -> Microsoft -> Windows -> CodeIntegrity -> Verbose
    iv. Right – click and select enable log

    More information on the Code Integrity can be found here:

    Code Integrity Diagnostic System Log Events


    Appendix - B

    Note: The SIGNTOOL application can be used to get similar information.


    Mentioned below is an example of this:

    C:\WinDDK\7600.16385.1\bin\amd64>SignTool.exe verify /a /v c:\windows\system32\win32k.sys

    Verifying: c:\windows\system32\win32k.sys
    File is signed in catalog: C:\Windows\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Package_7_for_KB2661001~31bf3856ad364e35~amd64~~
    Hash of file (sha1): DEDF7D339D8355A9875661559BD582FA46008AE5

    Signing Certificate Chain:
        Issued to: Microsoft Root Certificate Authority
        Issued by: Microsoft Root Certificate Authority
        Expires:   Mon May 10 04:58:13 2021
        SHA1 hash: CDD4EEAE6000AC7F40C3802C171E30148030C072

            Issued to: Microsoft Windows Verification PCA
            Issued by: Microsoft Root Certificate Authority
            Expires:   Wed Mar 16 03:35:41 2016
            SHA1 hash: 5DF0D7571B0780783960C68B78571FFD7EDAF021

                Issued to: Microsoft Windows
                Issued by: Microsoft Windows Verification PCA
                Expires:   Tue May 15 02:41:44 2012
                SHA1 hash: 5C616DC011E309DFCD15C0EA32494186654A2CDC

    The signature is timestamped: Mon Jan 16 15:24:23 2012
    Timestamp Verified by:
        Issued to: Microsoft Root Certificate Authority
        Issued by: Microsoft Root Certificate Authority
        Expires:   Mon May 10 04:58:13 2021    

    SHA1 hash: CDD4EEAE6000AC7F40C3802C171E30148030C072
            Issued to: Microsoft Time-Stamp PCA
            Issued by: Microsoft Root Certificate Authority
            Expires:   Sat Apr 03 18:33:09 2021
            SHA1 hash: 375FCB825C3DC3752A02E34EB70993B4997191EF            

                Issued to: Microsoft Time-Stamp Service
                Issued by: Microsoft Time-Stamp PCA
                Expires:   Fri Oct 26 02:12:17 2012
                SHA1 hash: FC33104FAE31FB538749D5F2D17FA0ECB819EAE5

    Successfully verified: c:\windows\system32\win32k.sys

    Number of files successfully Verified: 1
    Number of warnings: 0
    Number of errors: 0


    Below are articles you should review that discuss more details about this subject.

    Driver Signing Requirements for Windows

    Driver Signing Guidelines for ISVs

    Kernel-Mode Code Signing Walkthrough

    Installing an Unsigned Driver during Development and Test


    Hope this helps and until next time, Take care.

    Parthiv Seth
    Support Escalation Engineer
    Microsoft Windows Server Core Team

  • Migrating Print Queues quickly using PRINTBRM, configuration files, and the Generic/Text Only Driver

    Good morning AskPerf! Digvijay here to chat about print server migration. All server admins have probably had an opportunity to migrate print servers. This process can be fast and easy when migrating between the same versions of operating systems; and can be done with a bit of effort moving between Operating Systems with different architecture (e.g., moving from 32-bit to 64-bit versions of Server 2008). However, things really get challenging when we have to migrate from an older Operating System to the latest Operating System on a different architecture. (e.g., from Windows 2003 Server x86 to Windows Server 2008 R2 x64). Fortunately, there are new tools such as the Print Management Console that ships with Server 2008 R2 or, if you prefer the command line interface, then you can use PRINTBRM.EXE. However, there can be some hurdles getting all the printers migrated successfully if we do not understand the Printer restoration process and fulfill necessary pre-requisites.

    Things to keep in mind during printer migrations:

    1. A print queue cannot function without a driver of the same server architecture (x86 or x64) on which it exists. 

    2. Unless the print processor is migrated successfully, the print queue will not show up.

    3. If you are migrating from a 32-bit Operating System to a 64-bit Operating System, it is important that you have 64-bit drivers pre-installed for all of your printers, along with the 32-bit drivers. (Remember that for a 64-bit client to print to print server hosted on 32-bit Operating System, you need the 64-bit version of the driver.)

    4. When a cross-architecture migration includes the migration of printer language monitors, an error will occur during the process of restoring the printers to the destination server using the PRINTBRM command-line tool. The reason for the error is that language monitor driver architecture must always be the same as the source server architecture. Therefore, when migrating from x86-based architecture to x64-based platforms, language monitor migration cannot be successful. An error posted to the event log will state that the source architecture is not the same as that of the destination server. More info about this behavior can be found in the Print Services Migration Guide.

    5. When using PRINTBRM, always run commands from an Administrative command prompt

    If performing a 32-bit to 64-bit migration and all the existing client machines are 32-bit, then you will have to install 64-bit drivers for all the 32-bit drivers before starting the migration. It is common to have third-party 32-bit printer drivers that do not have 64-bit equivalents. For those instances, we typically suggest using universal drivers if available but contacting the printer vendor for their input is the safest bet.

    During the Printer restore in cross-platform scenarios, if the backup file does not contain driver binaries for target server platform, PRINTBRM will attempt to install the drivers from the target server’s driver store if a matching driver is available. If a matching driver for the target platform is not available (either in the backup or on the server) then the print queue will not be created and there will be errors. See below:



    We will see relevant events in the event viewer also:




    So to make it easy for everyone to understand, here is the straightforward way to successfully restore all the printers:

    1. Install 64-bit drivers on the Windows 2003 x86 Print server (source) or install all the required 64-bit drivers on the 2008/R2 Server (target). Keep in mind that the driver name string must be an exact match. If the names do not match exactly, the migration will treat it as if the driver is not present.

    2. Take a backup of the printers on the Windows 2003 source server using the Print Management Console or printbrm.exe run from the Windows 2008 R2 Server.

    3. Import the backup to the 2008 R2 server.

    NOTE We need to preinstall any driver that has different components when installed on x86 than when installed on x64. As long as the driver is installed then the printer installation will not be blocked unless there is a non-existent Monitor value in the Printer registry key.  If the printer (not the driver) requires this setting, then we will need to install the driver that uses this monitor on the x64 machine.  If there is no x64 monitor provided by the vendor or if the vendor provides a new x64 monitor that uses a different name, then you will need to add a printer using the x64 version of the driver on the new machine since the vendor providing the driver did not provide compatibility to the new OS.

    Keeping it simple

    To avoid most of these driver and component pitfalls, it’s often easiest to switch all the print processors and print monitors on the source server over to some basic defaults ones (eg: cleaning up the PRINT registry before starting with the migration). This will speed up the process and maximize the number of queues successfully migrated.

    Microsoft has provided a Spooler FixIT for Windows 2003/2008 to automate the spooler cleanup process. See our previous AskPerf blog entry for information about the functionality and usage of this tool.

    We also recommend removing old and unused drivers from the server before taking a backup.

    However, if you do not want to go through this lengthy process of fulfilling these prerequisites, are on a time crunch, want to quickly restore the print queue information on the target server and deal with the driver worries later, then read on.

    In order to quickly get the queues migrated to the new server, we can create them using the “Generic / Text only” printer driver without restoring any of original the drivers on the target. Remember that we need to have 64-bit drivers present either in the package or on the target server for the restore to finish and the print queue to be available for printing.

    Here are the steps to successfully migrate all of your print queues using the in-box “Generic/Text Only” print driver:

    1. On the source Windows 2003 Server, change all print processors to winprint using the following setprinter.exe command:

    SetPrinter.exe \\Servername 2 pPrintProcessor="Winprint"

    This can also be accomplished using WMI:

    wmic printer set PrintProcessor = WinPrint

    2. Install the latest update for Printbrm on the target 2008R2 server:

    KB 2636591  An update to improve the restore operation performance of Printbrm.exe in Windows 7 or in Windows Server 2008 R2

    3. Install a local printer on the target 2008 R2 server using the Generic / Text Only driver and share it to enable the firewall exceptions for the Print Services.

    4. From the Windows 2008R2 server, take a backup of the 2003 print server using the nobin switch

    (we are using the nobin switch since we don’t want to migrate any of the print drivers):

    Printbrm.exe –b –s \\servername –f nobin.printerexport –nobin

    5. Next, we have to modify the contents of the backup files. Expand the printerexport backup to a directory and the replace the BrmDrivers.xml, BRMLMons.xml and PProcs.xml files. The command to extract the files to a directory is:

    printbrm.exe  -r -d c:\temp\expand  -f nobin.printerexport


    The Expanded directory will look similar to this:



    • BrmDrivers – contains a list of every driver installed on the computer and the driver files for each driver
    • BrmForms – contains a list of all the installed forms
    • BrmLMons – will usually contain either Windows NT x86 or Windows x64 as the architecture and a list of port monitors and the port monitor files installed
    • BrmPorts – contains a list of all the installed printer ports
    • BrmPrinters – contains a list of all printers that have been installed
    • BrmSpoolerAttrib – contains information about the spooler directory path and also indicates whether or not the source server was a cluster server

    6. Now we need to edit the existing xml files and delete the information about unused print processors, language monitors and drivers in them and then create a new file without these components.

    NOTE You may ask if we already set all the printers to use WinPrint as default print processor using the earlier methods, then why do I need to do this? The answer is that when we take a backup using PRINTBRM, the tool copies all the files from their respective directories inside C:\Windows\System32\spool\. Hence even if we have replaced the information on the queues, these files will be backed up and at the restore operation, they will also be restored. So even though we took a backup using the nobin switch, the xml files contains information about all the drivers. When you attempt to restore, the server will try to look for these drivers and restore them. Also, the -nobin switch only omits the driver files, the Language monitor and the Print processors are still backed-up.

    For creating new BrmDrivers.xml, BRMLMons.xml and PProcs.xml files, we can use the following templates:







    <LMONS Arch="Windows x64"/>







    7. Once we have saved the new xml files in place, we will re-pack the backup using this command to get a new backup file that we will use to restore on the target server:

    printbrm.exe  -b -d c:\temp\expand  -f newbackupfile.printerexport

    8. Now that we have a clean printer backup, we will use the BRMConfig file to create all the printers using the “Generic / Text only” driver. The BRMConfig.xml file needs to have a mapping of all the drivers present on the source server that we want to restore with the Generic / Text Only driver.

    A sample BRMConfig file may look like this:






    <DRV old="HP Universal Printing PCL 6" new="Generic / Text Only"/>

    <DRV old="HP Laserjet 5000 PCL 6" new="Generic / Text Only"/>

    <DRV old="HP Universal Printing PS 6" new="Generic / Text Only"/>




    For restoring all the printers from the backup, we need to mention all the existing drivers here.

    NOTE The name of the driver has to be an exact match.

    9. Once you have your brmconfig.xml file finished, run this command to start the restore:

    printbrm –r –s \\2008R2Servername  –f newbackupfile.printerexport -c c:\temp\brmconfig.xml

    NOTE We need to provide the absolute path of the BrmConfig.xml file here.

    10. If all the mentioned instructions have been followed, you will see all the print queues getting created on the server using the Generic / Text Only driver.


    This is where we started from:


    And this is what we have accomplished:


    11. Verify that the printers are working fine by sending some test pages to the printers.

    12. After the queues are created on the target server, you can install the 64bit drivers for the printers as per your convenience and then switch the queues again.

    Simplifying the BRMConfig.xml file creation

    Considering most typical production scenarios, Print Servers you have hundreds of print queues and many print drivers, creating the BrmConfig.XML file for mapping each driver to Generic / Text Only driver can be real time consuming process. To ease the pain of creating this file yourself, there’s a BRMC tool that will come in handy. Download the tool from https://brmc.codeplex.com/ and run it from the directory where the BRMDrivers.XML is located. (So run it from the expanded location). Once the tool is run, and it creates a BRMConfig.xml file, pack the backup and then run the restore using the BrmConfig.XML file (to to step 8 and then go to step 10).


    The BRMC tool creates the brmconfig.xml file that has the driver mappings. It also creates clean BrmDrivers.xml, BRMLMons.xml and PProcs.xml in the same directory. Be aware, the tool overwrites the original files, so save the original .printerexport file as a backup of BrmDrivers.xml, BRMLMons.xml and PProcs.xml.


    If you encounter any errors during a Print Migration restore, check the event logs for possible causes. Common ones may be Print Processor is unknown, Unknown Port, or Print driver is unknown which usually means that the spooler was not cleaned properly on the source server when the initial backup was generated. Look for more in-depth troubleshooting of these kinds errors in a future blog.

    I hope this information will come in handy the next time you are working through a printer migration. Until next time…

    Addition Resources