Windows makes it possible to map drives on network servers to local drive letters so they can be accessed by users as if they were a local drive. This is a very powerful feature of Windows, which many applications take advantage of.

The problem, however, is that Windows is not very consistent about how it handles such mapped drives when accessed from a Windows Service. When the service is started manually, the drives will be available, but when the system is rebooted, the service will no longer be able to access them.

The Java Service Wrapper provides a simple way to tell the service to map network drives itself when they are not available. This means that they can be accessed reliably at any time.

Solution

The solution is to give the service the ability to map its own drives. The Java Service Wrapper provides a flexible set of properties that make it possible to map network drives as well as printers on startup. By doing so, Java applications will be able to reliably make use of such shares regardless of when the service is started.

In Windows, network shares can be mapped to drive letters so they can be accessed as if they were local drives. Many applications make use of this ability to seamlessly access files that are shared across the network.

However, when such an application is converted into a service, access to the mapped drives will become unreliable, because the mapping is potentially only done in the session of the user. They are available in some cases but not others, depending on when the service is started, and who was logged in to the machine at the time.

Technical Overview

Compatibility :3.5.0
Editions :Professional EditionStandard EditionCommunity Edition (Not Supported)
Platforms :WindowsMac OSX (Not Supported)Linux (Not Supported)IBM AIX (Not Supported)FreeBSD (Not Supported)HP-UX (Not Supported)Solaris (Not Supported)IBM z/Linux (Not Supported)

It is possible to configure a Windows Service to run as a specific account. However, the mapped drives that are setup in that account will not be available when the system first boots up, and will thus not be available to the service. If a user logs on with the same account, then the drives will be setup, but they will still not be available to the service unless it is completely restarted.

Traditionally, this has meant that it was necessary to access files on the network using the UNC (Uniform Naming Convention):

\\myfileserver\commonshare\myfiles\data.txt

This UNC syntax works with some applications, but it is not as convenient or portable as a mapped drive:

S:\myfiles\data.txt

Many applications that were originally not designed to be run as a Windows Service, or that access network drives, will fail when they encounter a UNC path in a configuration file.

The Java Service Wrapper makes it easy for services to access shared resources. With just a set of "share" properties, you can easily configure mappings to remote locations or printers and make them available to the running account, before the Java application is launched.

Simple Mapping of Public Share

Many organizations have common shared drives that can be used by anyone with access to the network via a guest account. These are by far the easiest to set up as they only require a location to be mapped, and the drive letter (alphabet indicating a drive) to map it to.

Configuration Example:
wrapper.share.1.location=\\myfileserver\commonshare
wrapper.share.1.target=S:
wrapper.share.1.type=DISK
Log Example Mapping to "S" Drive:
wrapper  | Attempting to map the "\\myfileserver\commonshare" share to "S:"...
wrapper  | Mapped "S:".

Once this is set up, the application will be able to access the S: drive in the same way as any other local drive. This is a very simple example that does not provide any authentication credentials, handle connection failures, or specify what to do with the mapped drive when the service stops.

Mapping of Public Share with Authentication

It is common for network drives to be protected by a password, and access only given to specific accounts. The Wrapper makes it possible to specify a particular account to connect and optionally assign a password for the account.

Configuration Example:
wrapper.share.1.location=\\myfileserver\commonshare
wrapper.share.1.target=S:
wrapper.share.1.type=DISK
wrapper.share.1.account=domain\user
wrapper.share.1.password=password

If the user account that the Wrapper is running has access to the shared network, then it may not be necessary to specify an account and password even though access to the network is restricted. This is possible because Windows is often able to reuse the current account authentication information when connecting to the shared network.

Example Mapping to "S" Drive:
wrapper  | Attempting to map the "\\myfileserver\commonshare" share to "S:"...
wrapper  | Mapped "S:".

Windows assigns unique letters to Drives to map resources and services. If for any reason a Drive letter is already in used, the Wrapper automatically reacts either by shutting down (SHUTDOWN) or continuing (CONTINUE) to start the JVM and assign a different Network Drive 'Y:' letter.

The Wrapper by default will try a number of times to connect to a Network Drive. May this not be possible because of unknown errors or the like, the options to follow are to UNMAP the Drive or to SHUTDOWN. On the other hand, the Wrapper makes sure there are no open files at that moment before disconnecting and then continue.

Handling a Mapping Failure

Whenever more than one server or a network is involved, there is a chance that something can go wrong. If the problem is a temporary issue, then the Wrapper will by default try up to 5 times to connect before finally continuing.

Log Example of Output:
wrapper  | Attempting to map the "\\myfileserver\commonshare" share to "S:"...
wrapper  |   Unable to map "S:".  Attempt #1 (The network name cannot be found. (0x43))
...
wrapper  | Attempting to map the "\\myfileserver\commonshare" share to "S:"...
wrapper  |   Unable to map "S:".  Trying to continue. (The network name cannot be found. (0x43))

But if the network share is critical to the operation of the service, then you may wish to have the Wrapper fail to start up.

Configuration Example:
wrapper.share.1.startup.failure=SHUTDOWN
Log Example of Output:
wrapper  | Attempting to map the "\\myfileserver\commonshare" share to "S:"...
wrapper  |   Unable to map "S:".  Attempt #1 (The network name cannot be found. (0x43))
...
wrapper  | Attempting to map the "\\myfileserver\commonshare" share to "S:"...
wrapper  |   Unable to map "S:".  Shutting down. (The network name cannot be found. (0x43))
wrapper  | <-- Wrapper Stopped

It is possible to control how many times the Wrapper retries the mapping, as well as how long to wait between each attempt. Note that retries will not be done for problems that are permanent.

Configuration Example:
wrapper.share.1.startup.max_retries=2
wrapper.share.1.startup.retry_interval=10

Handling a Premapped Share

It is fairly common for a network share to be mapped with the Wrapper to a drive that is normally mapped by a logged in user. When this happens, it is possible that the service will be started with the drive already mapped.

Log Example of Output:
wrapper  | Attempting to map the "\\myfileserver\commonshare" share to "S:"...
wrapper  |   "S:" is already defined.  Trying to continue

The problem with this is that you cannot be 100% sure that the drive is mapped to the correct server. If this concern is a problem, you may wish to abort the startup of the service.

Configuration Example:
wrapper.share.1.startup.premapped=SHUTDOWN
wrapper.share.1.startup.max_retries=2
wrapper.share.1.startup.retry_interval=10
Log Example of Output:
wrapper  | Attempting to map the "\\myfileserver\commonshare" share to "S:"...
wrapper  |   "S:" is already defined.  Shutting down.
wrapper  | Leave "S:" mapped.
wrapper  | <-- Wrapper Stopped

Unmapping on Shutdown

By default, the Wrapper will leave any network shares mapped when it shuts down. This is usually the best choice, as the shares may be getting used by other users or applications.

Log Example of Output:
wrapper  | Leave "S:" mapped.
wrapper  | <-- Wrapper Stopped

Sometimes you may want to make sure that the drive is unmapped on shutdown.

Configuration Example:
wrapper.share.1.shutdown.unmap=TRUE
Log Example of Output:
wrapper  | Unmapped "S:".
wrapper  | <-- Wrapper Stopped

If the share was not mapped by the current Wrapper instance, then it will be left mounted.

Log Example of Output:
wrapper  | Leave "S:" mapped.
wrapper  | <-- Wrapper Stopped

If there are open files on the share, then the unmapping may also fail. The unmapping can be forced if so desired. Note that the Wrapper will still leave the share if it was not mapped by the current Wrapper instance.

Configuration Example:
wrapper.share.1.shutdown.unmap=TRUE

Mapping of a Network Printer

Printers that are located on a remote machine can also be mapped in the same way as a drive. The difference is that a printer port is specified rather than a drive letter:

Configuration Example:
wrapper.share.1.location=\\myserver\printer
wrapper.share.1.target=LPT2:
wrapper.share.1.type=PRINTER
Log Example of Output:
wrapper  | Attempting to map the "\\myserver\printer" share to "LPT2:"...
wrapper  |   Mapped "LPT2:".

Potential Problems

There are a number of fairly common problems that you are likely to encounter when mapping network shares.

Server not found.

If the server is down or there are network problems, then it is possible that the connection attempt could fail.

Log Example for Mapping Failure:
wrapper  | Attempting to map the "\\myfileserver\commonshare" share to "S:"...
wrapper  |   Unable to map "S:".  Attempt #1 (The network name cannot be found. (0x43))
wrapper  | Attempting to map the "\\myfileserver\commonshare" share to "S:"...
wrapper  |   Unable to map "S:".  Trying to continue. (The network name cannot be found. (0x43))

If you do not specifically specify the share type as DISK, then Windows will not be able to tell whether you are trying to connect to a Disk or a Printer, and the error message will look like this:

Log Example for Mapping Failure:
wrapper  | Attempting to map the "\\myfileserver\commonshare" share to "S:"...
wrapper  |   Unable to map "S:".  Trying to continue. (The network resource type is not correct. (0x42))

Access Denied

If the configured account or password are incorrect, then the mapping will fail with a message like the following. Please double check with your system administrator to make sure the connection information is correct.

Log Example for Mapping Failure:
wrapper  | Attempting to map the "\\myfileserver\commonshare" share to "S:"...
wrapper  |   Unable to map "S:".  Trying to continue. (Access is denied. (0x5))

Debugging

If the mapping is not working as expected, please try enabling debug output.

Configuration Example:
wrapper.debug=TRUE

The debug output will include confirmation of the configuration as well as provide additional information about what the Wrapper is trying to do.

Log Example for Mapping Failure:
wrapper  | Network Mapping Details:
wrapper  |   Location:         \\myfileserver\commonshare
wrapper  |   Target:           S:
wrapper  |   Account:          domain\user (Password: password)
wrapper  |   Type:             ANY
wrapper  |   Startup:
wrapper  |     On Failure:     CONTINUE
wrapper  |     On Premapped:   CONTINUE
wrapper  |     Max Retries:    5
wrapper  |     Retry Interval: 10
wrapper  |   Shutdown:
wrapper  |     Unmap:          FALSE (Force: FALSE)
wrapper  | Attempting to map the "\\myfileserver\commonshare" share to "S:"...
wrapper  |   Unable to map "S:".  Trying to continue. (Access is denied. (0x5))

Reference: wrapper.share.<n>.* Properties

These properties are used to configure the mapping of Network Resources to local drives.