Pitfalls of Network Drives and UNC Paths — Working With File Servers (Shared Folders) From a Business Application

· · Network Drive, UNC Path, SMB, File Sharing, Windows Service, File Server, C#, .NET, Networking, Bug Investigation, Windows Development, Technical Consulting

“It worked on my dev machine, but on the customer’s environment we get ‘Z:\ cannot be found.’” “The moment we put it on Task Scheduler, writing to the shared folder started failing.” “As soon as we turned it into a Windows service, the file server became invisible.” — In consultations about business applications, trouble involving a file server (shared folder) is about as classic as it gets. Ingesting order data, writing out reports or CSVs, watching for files a device drops onto the share: on-premises business systems still rely on shared folders as a working integration layer today.

What makes this kind of trouble annoying is that most of it isn’t a bug in the code at all — it’s rooted in Windows-side mechanics: the relationship between drive letters and logon sessions, the service’s execution account and authentication, and SMB’s connection management. Stepping through it with a debugger gets you nowhere, and “it doesn’t reproduce on my PC” eats up the hours.

This article is aimed at business-application developers (WinForms/WPF/Windows services) implementing file output, ingestion, or watching against a shared folder. It works through the pitfalls of network drives and UNC paths from first principles, and rounds up the practical rules of thumb into a decision table.

1. The Bottom Line First

  • A drive letter (Z: and the like) is not a system-wide resource — it belongs to a single logon session. Each logon session gets its own full set of drive letters from A to Z, so a drive a user mapped is invisible to a process running under a different user, or to a service running under a different logon session.1
  • When UAC is enabled for an administrator, two logon sessions are created — a standard one and an elevated one — and drive mappings (DosDevices symbolic links) are independent per session. This is why “Z: only disappears from the elevated app.” A workaround exists via the EnableLinkedConnections registry value that shares mappings across both sessions, but Microsoft explicitly documents it as an unsupported setting that “may make the system less secure.”23
  • When a service (or any process running under a different security context) needs to reach a remote resource, the official guidance is to use a UNC path (\\server\share\...). Mapping a drive letter from inside a service using net use or the WNet APIs is not recommended, on grounds of credential exposure and interference between services.1
  • Who gets granted permission on the share side is determined by the service’s execution account. LocalSystem and NetworkService authenticate on the network as “the computer’s own credentials,” while LocalService presents anonymous credentials and is unsuitable for share access. A service running under a local user account cannot reach network resources at all. In practice, the real options are a domain account, or a gMSA that lets the OS manage the password for you.45678
  • You cannot hold simultaneous connections to the same server under two different sets of credentials. The second connection fails with error 1219 (ERROR_SESSION_CREDENTIAL_CONFLICT), and this is by design.910
  • “Slow, dropped, sometimes unreachable” is the normal case for a shared folder, not an edge case. An idle connection is disconnected by the server after 15 minutes by default (and silently reconnected on the next access). File.Exists returns false on insufficient permissions or other errors without throwing, so it cannot distinguish “the file doesn’t exist” from “the server is unreachable.”1112
  • FileSystemWatcher does support watching a network drive or a remote computer, but you must design around it missing events. A buffer overflow can drop events, and when watching over the network, the internal buffer size is capped at 64 KB. Pairing it with polling (a full scan) is standard practice.13

2. How Drive Letters and UNC Paths Relate — Z: Belongs to “Your Logon Session”

When you map \\fileserver\share to Z: in Explorer, it looks very much as if a “Z: drive” has sprouted for the whole machine. That’s the first misconception.

The official documentation is unambiguous here. A drive letter is not global to the system — each logon session gets its own set from A to Z. A redirected drive (a network drive) cannot be shared between processes running under different user accounts, and a service running under a different logon session cannot access a drive letter established in another session.1 The system manages drive mappings based on the logon SID that uniquely identifies each logon session.1

In other words, Z: is nothing more than “a shorthand for a path, one set per logon session” — the underlying thing is always a UNC path. From here, a whole string of symptoms commonly seen in the field falls neatly into place.

Symptom Underlying reason
Z: is missing when run as a different user Drive letters are per logon session; another user’s mapping is invisible1
Z: is missing when running “as Administrator” UAC creates two logon sessions, standard and elevated, and mappings are not shared between them2
Z: is missing once put on Task Scheduler or a service It runs under a different logon session. Even if the service is configured to run under a user account, the system still creates a new logon session for it1

The UAC case is worth understanding in a bit more depth. When a user in the administrators group logs on, the system creates two linked logon sessions: one with a restricted token, and one with the full administrator token. The physical thing behind a drive mapping is a symbolic-link object (DosDevices) tying a drive letter to a UNC path, and this object is specific to a single logon session — it is never shared across sessions.2 Logon scripts run in the standard-privilege session, so that mapping simply isn’t visible from an elevated process — that’s the whole story.

Setting EnableLinkedConnections (a DWORD value under HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System) to 1 makes the symbolic link get written into both linked sessions, which makes this symptom go away. However, the official documentation explicitly states: “this workaround may make the system less secure. Microsoft doesn’t support this workaround, and it’s provided as-is.”3 Planting an unsupported registry setting on a customer’s environment is a poor solution for a business application. Writing your app against UNC paths is the correct approach. Official guidance on troubleshooting Folder Redirection also recommends “always using UNC paths instead of a mapped drive letter.”3

The implementation is simple: just store paths in your configuration as UNC.

// appsettings.json -- store paths as UNC, not drive letters
{
  "FileTransfer": {
    "IncomingDir": "\\\\fileserver01\\edi\\incoming",
    "ProcessedDir": "\\\\fileserver01\\edi\\processed"
  }
}

If your app lets a user pick a location under Z: via a folder-selection dialog, normalizing it to UNC at save time keeps things from breaking later when the execution context changes. The WNetGetUniversalName API is provided specifically for converting a drive-letter path into UNC form.14

3. Accessing a Shared Folder From a Windows Service — UNC Is Mandatory, and “As Whom” Are You Accessing It?

As covered in the previous chapter, a mapped drive isn’t available from a service. The official documentation states that a service (and any process running under a different security context) should access remote resources by UNC name, and explicitly discourages mapping a drive letter at runtime from inside a service using net use or the WNet APIs. The reasons given are that the mapping becomes visible to other services running in the same context, that credentials passed to net use can leak outside the service’s boundary, and that multiple services trying to establish the same mapping interfere with each other with an “already connected” error.1

Once you’re on a UNC path, the next question is authentication. As whom does the service reach the file server? That is determined by the execution account, and it also determines who needs to be granted permission on the share side.

Execution account Network identity Permission grant on the share Verdict
LocalSystem The computer’s own credentials4 In a domain, grant share/NTFS permissions to the computer account (DOMAIN\MACHINE$) Works, but over-privileged. Replacing the machine means redoing the permissions
NetworkService The computer’s own credentials5 Same as above Minimal local privileges, but the same network identity as LocalSystem
LocalService Anonymous credentials6 Nothing you can grant it Unsuitable for share access
Local user account Cannot reach network resources7
Domain user That account Grant permission to that account The practical standard. Managing password changes is the operational cost
gMSA That account Grant permission to that account The OS manages the password automatically (auto-rotated every 30 days). The best option where supported815

That LocalSystem and NetworkService go out onto the network “as the computer itself” is an officially documented fact.45 The BITS documentation spells out the practical fallout directly: if the source file’s ACL restricts access to a user account, a service (which authenticates with computer credentials) will get access denied, and system accounts should not use mapped drives.16

Three practical guidelines follow from this:

  • When “turning it into a service breaks access,” the first thing to check is the execution account. What ran under “your” permissions on the desktop gets checked against the identity in the table above once it’s a service. Verify both the share permissions and the NTFS ACL against that identity.
  • For long-term operation in a domain environment, run the service under a domain account or a gMSA. A gMSA has a 240-byte random password that the OS automatically rotates every 30 days, which structurally eliminates the class of incidents where “everything stopped Monday morning because the service account’s password expired.”15
  • In a workgroup environment (no domain), computer-credential authentication doesn’t apply, so this is where the explicit credentials covered in the next chapter come into play.

We cover how to build the service itself (setting the execution account, recovery options, safe shutdown) in “How to Build and Operate a Windows Service,” and the mechanics of sessions and logons in “Making Sense of Windows Session Isolation.”

4. Handling Credentials — net use, Credential Manager, and Error 1219

When the execution account itself cannot be granted permission on the share (a workgroup, or a NAS with its own account system, for example), you have to explicitly pass credentials when connecting. There are mainly three ways to do this:

  • net use \\server\share /user:... – establishes the connection for that logon session. It’s handy for interactive confirmation, but as covered above, running it from inside a service is discouraged.1
  • Credential Manager (cmdkey) – saving credentials with cmdkey /add:server /user:svc-file /pass:... makes them get used automatically for subsequent authentication against that server.1718 The catch is that this storage is per user profile, so if you’re going to use it from a service, you must register it in the context of the service’s execution account.
  • Connecting programmatically (WNetAddConnection2) – lets you establish a connection to a network resource by specifying the client’s credentials directly. The official documentation lists this as one strategy a server process can use to access network resources.19 Using a “deviceless connection” that assigns no drive letter lets you keep accessing the resource purely via UNC path.

And the single most infamous trap in this area is error 1219.

Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed. (ERROR_SESSION_CREDENTIAL_CONFLICT, 1219)10

You cannot hold more than one connection to the same server, using different user names, from the same logon session. Try connecting to the same file server with two kinds of credentials — say, your own account for a sales share and a dedicated account for system-integration purposes — and the second one fails with 1219. The official documentation states plainly that this is “by design,” and the workarounds it lists are “connect by IP address” or “create a separate DNS alias” — in other words, make the server look like a different server.9

In practice, the first choice is to avoid a design that uses multiple credentials against a single server in the first place: consolidate onto one integration account and grant that account permission on every share it needs. Only when that isn’t possible should you split the paths using an alias.

That said, an alias is not as simple as “add one CNAME record to DNS and you’re done.” In a Kerberos environment, an SMB client tries to authenticate using the SPN (service principal name) that corresponds to the target’s name, so accessing the resource via a CNAME can fail outright if no SPN is registered for the alias. Official troubleshooting guidance lists this missing SPN as one of the causes, and recommends configuring the alias as a computer-name alias via netdom computername <server-name> /add:<alias> rather than a DNS CNAME.20 Before you build an alias-based route into your design as a fix for 1219, always verify it actually works in the target environment.

One more note: the more advanced requirement of “having the service access the file server using the permissions of whichever client user connected to it” is the territory of impersonation, not of juggling credentials. The official documentation likewise recommends impersonation over a service holding its own credentials.1 For how to implement impersonation correctly, and the extra considerations that apply for remote resources, see “Handling Windows Impersonation Tokens Correctly.”

5. Design Around “Slow, Dropped, Sometimes Unreachable”

Code written with the same mental model as a local disk will always break somewhere against a shared folder. There are three realities you need to build in from the start.

First, connections dropping is normal. An idle connection is disconnected by default after a 15-minute timeout, to keep from wasting server resources — this is exactly the familiar red X you see on a mapped network drive in Explorer, and the next access reconnects promptly.11 In other words, a business app that only accesses the share occasionally getting momentarily stalled on each access, or a monitoring tool crying “disconnected!” with no actual harm done, are both simply the system behaving as designed. Instead of monitoring whether the connection exists, judge based on whether actual I/O succeeds.

Second, errors are unhelpfully vague. File.Exists returns false — without throwing — whether the path is invalid, permissions are insufficient, or there’s a disk failure.12 Locally, “false means it’s not there” almost never causes trouble; but against a share, “the file doesn’t exist” and “unreachable / no permission” all collapse into the same false, so code that branches on Exists to make a business decision fails silently as ‘nothing found’ during a network outage — an unpleasant way to break. A design that skips the existence check and opens the file directly, distinguishing cases by the exception thrown, is easier to diagnose against a share.

Third, the other side might not be there yet. Right after a machine boots, service startup can happen before the network is ready, or the file server itself might be mid-reboot. A persistent connection is a mechanism restored at the user’s logon,21 so in the world of a service, which never goes through a logon, there is no guarantee that “the share is visible as soon as the service starts.” The correct behavior isn’t to check connectivity once at startup and exit on failure — it’s to retry while waiting.

Weaving all three of these in, the skeleton of the write side looks like this:

// Retry transient network errors; fail immediately on business errors
private static async Task WriteToShareAsync(string finalPath, byte[] content, CancellationToken ct)
{
    var dir = Path.GetDirectoryName(finalPath)!;
    var tempPath = Path.Combine(dir, $"~{Guid.NewGuid():N}.tmp");

    try
    {
        for (var attempt = 1; ; attempt++)
        {
            try
            {
                await File.WriteAllBytesAsync(tempPath, content, ct);
                File.Move(tempPath, finalPath); // Rename within the same directory publishes "completion"
                return;
            }
            catch (IOException ex) when (attempt < 5 && IsRetryable(ex))
            {
                // Retry only transient network failures, with a capped exponential backoff
                _logger.LogWarning(ex, "Write to share failed (attempt {Attempt}). Retrying", attempt);
                await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)), ct);
            }
        }
    }
    catch
    {
        // If we're giving up and propagating the exception, clean up the temp file on a best-effort basis
        try { File.Delete(tempPath); } catch { /* Swallow cleanup failures */ }
        throw;
    }
}

// IOException arrives with the same type whether it's "network disconnected," "a file
// with the same name already exists at the destination," or "disk full." Use the low 16
// bits of HResult (the Win32 error code) to select only failures where a retry is meaningful
private static bool IsRetryable(IOException ex)
{
    var win32 = ex.HResult & 0xFFFF;
    return win32 is 53   // ERROR_BAD_NETPATH: the network path was not found
              or 59   // ERROR_UNEXP_NET_ERR: an unexpected network error occurred
              or 64   // ERROR_NETNAME_DELETED: the network name is no longer available
              or 121; // ERROR_SEM_TIMEOUT: the semaphore timeout period has expired
}

It also matters that you don’t write “retry on any IOException” carelessly. Failures that produce the same result no matter how many times you try — a same-named file already at the destination, a path that’s too long, a full disk — arrive as the exact same IOException type, so judging purely by exception type means retrying a permanent error five times and wasting time on backoff for nothing. As in the example above, filter down to “failures where retrying is actually worthwhile” using the Win32 error code (53/59/64/121 and similar disconnect/timeout-class codes for share access22). Building this list up from codes you actually observe in production logs is the realistic way to operate it.

The point isn’t adding retries per se — it’s pairing retries with a hand-off protocol that stays safe to retry (temp -> rename, idempotency). If a write is interrupted midway, a half-finished file is left behind. If the promise is that the final name only ever appears via a rename after the file is closed, you prevent the receiving side from ever reading a half-baked file. Note also that a process crash or power loss means the cleanup code inside the function never runs, so it’s worth also having a periodic sweep over the hand-off folder — “delete any ~*.tmp file that hasn’t been touched in a while” — so leftover junk doesn’t pile up and clog things. We cover the full picture of this hand-off design in “The Basics of Locking for File Integration.”

There’s one more network-specific gotcha worth noting. A result of “failure” doesn’t actually guarantee failure happened. If the connection drops right after the server-side rename completes, the client can get an exception back even though the file under the final name has already been published. If you naively retry at that point, you’ll either get stuck on a “file already exists at the destination” error, or — if the receiving side had already ingested the first one — end up publishing the same data twice. The fix is to check and reconcile against the state at the destination before retrying a failed rename step. If you embed a processing ID (a slip number or an execution GUID) in the final filename, you can treat “a final file with the same ID already exists” as meaning the previous rename actually succeeded, and exit treating it as a success — and the receiving side can likewise reject a duplicate ingestion by that same ID.

6. Locking Over SMB and the Reliability of FileSystemWatcher

6.1. Don’t over-trust locks

A shared folder gets touched by multiple clients at once. Opening with FileShare.None does give you exclusivity while the handle is open, even over SMB, but a design that leans on “if I got the lock, it’s safe” falls apart when a handle is lost to a disconnect, or when something that doesn’t take a lock (a manual copy, another system) enters the mix. The real substance of mutual exclusion should live not in an OS-level lock but in the hand-off protocol itself: temp -> rename, an atomic claim (only the winner of an incoming-to-processing rename gets to process the file), and idempotency. See the locking article linked above for the details of that thinking.

6.2. The reality of using FileSystemWatcher on a remote share

FileSystemWatcher is officially documented as supporting file watching not just locally but on network drives and remote computers.13 Using it at all is legitimate. There are, however, two reliability caveats.

  • Notifications arrive through a buffer, and an overflow drops them. If changes come in a short burst, events beyond the buffer size get lost.13
  • When watching over the network, the cap on InternalBufferSize is 64 KB. This “can’t go as big” constraint is documented explicitly, compared with local watching.13

I’ve also repeatedly seen, in the field of bug investigation, a symptom where the watcher on the far side simply dies silently when the server reboots or disconnects, with no notification ever arriving to say so. The practical conclusion is to treat a FileSystemWatcher on a remote share as merely a hint for reacting faster, and to make a full scan (polling) on startup, on error, and on a schedule the actual source of truth. We go into the design patterns for this — including handling duplicate and out-of-order events — in detail in “A Practical Guide to FileSystemWatcher.”

7. A Practical Decision Table

Here is a decision table for the recurring design questions covered so far.

Question Options Guidance
How to store paths Drive letter / UNC path Every path your app handles should be UNC. Treat a drive letter as purely a user-facing convenience on screen1
Writing to the share Write directly / temp -> rename Writing directly gives no guarantee that “the in-progress file won’t be read.” The final name should mean “complete,” as a rule
Detecting new files FileSystemWatcher alone / polling / both Assume a remote share drops events. If a delay of a few minutes is acceptable, polling alone is simpler and more robust; combine both if you need immediacy13
Service execution account LocalSystem / domain account / gMSA If there’s share access, use a domain account or gMSA. Where a gMSA is available, you can eliminate password operations entirely8
When separate credentials are unavoidable Calling net use from code / WNetAddConnection2 / pre-registered cmdkey net use inside a service is discouraged. Multiple credentials against the same server get blocked by 1219, so avoid it from the design stage by consolidating accounts or using a DNS alias19
Many clients accessing directly Each device hits UNC directly / via an intermediary service (an API) Once the number of devices times credentials times concurrent access becomes unmanageable, consolidate share access into a single service and have clients talk to it through an API

That last row deserves a note. Shared-folder integration is convenient, but the more access points there are, the more exponentially difficult it becomes to manage who has which permissions and who conflicts with whom. Past a certain scale, consolidate the process that touches the file server into a single Windows service, and have each client talk to it over HTTP or gRPC. Demoting the shared folder from “the interface between systems” to “an internal implementation detail of that one service” is, in the long run, the most maintainable shape.

8. Summary

  • A drive letter is nothing more than a symbol scoped to a logon session. It being invisible to a different user, an elevated process, or a service is by design — write your app against UNC paths. EnableLinkedConnections is an unsupported workaround.
  • Share access from a service requires UNC. Who it authenticates as is determined by the execution account: LocalSystem/NetworkService use computer credentials, LocalService is anonymous. In practice, grant share-side permission to a domain account or a gMSA.
  • Simultaneous connections to the same server under multiple credentials fail with error 1219 (by design). Avoid it from the design stage via account consolidation or a DNS alias.
  • “Slow, dropped, sometimes unreachable” is the normal case for a share. An idle disconnect (15 minutes by default) is not an anomaly, and a false from File.Exists cannot be distinguished from a network failure. Build in retries, temp -> rename, and idempotency together.
  • FileSystemWatcher supports remote watching, but a buffer overflow can drop events and the cap is 64 KB, so pairing it with a full scan is standard practice.
  • When in doubt, refer to the decision table in Chapter 7 — and if the scale grows, consider consolidating share access behind an intermediary service.

At Komura Software LLC, we handle the design and implementation of file-integration systems built around shared folders, working through access-rights and authentication configuration when turning something into a Windows service, and investigating bugs such as “the share becomes invisible once it’s a service” or “it only fails in one specific environment.”

References

  1. Microsoft Learn, Services and Redirected Drives. On drive letters being assigned per logon session rather than system-globally, on services being unable to access another session’s drive letters and needing to use UNC names instead, on why mapping drives from inside a service via net use or the WNet functions is discouraged (credential exposure, interference between services, and so on), on a new logon session being created even for a service configured under a user account, and on client impersonation being recommended over a service holding its own credentials.  2 3 4 5 6 7 8 9 10 11

  2. Microsoft Learn, Mapped drives are not available from an elevated prompt when UAC is configured to Prompt for credentials. On the two linked logon sessions created when UAC is enabled, on drive mappings being backed by a symbolic-link object (DosDevices) that is specific to a single logon session and not shared between sessions, and on EnableLinkedConnections forcing the symbolic link to be written into both sessions.  2 3

  3. Microsoft Learn, Folder Redirection fails to apply when redirected to mapped drive letter, instead of UNC path. On the LSA creating two access tokens at an administrator logon and the drive being mapped under the standard token, on the steps for setting the EnableLinkedConnections registry value along with the warning that “this workaround may make the system less secure” and is unsupported by Microsoft, and on UNC paths always being recommended over drive letters.  2 3

  4. Microsoft Learn, LocalSystem Account. On LocalSystem holding extensive local privileges while presenting the computer’s own credentials to remote servers on the network.  2 3

  5. Microsoft Learn, NetworkService Account. On NetworkService holding minimal local privileges while presenting the computer’s own credentials to remote servers on the network.  2 3

  6. Microsoft Learn, LocalService Account. On LocalService presenting anonymous credentials on the network.  2

  7. Microsoft Learn, About Service Logon Accounts. On a service’s logon account determining its runtime security context, and on a service running under a local user account’s security context being unable to access network resources.  2

  8. Microsoft Learn, Group Managed Service Accounts overview. On a gMSA being a domain account that provides automatic password management and simplified SPN management, letting password management be delegated to the Windows OS.  2 3

  9. Microsoft Learn, The network folder specified is currently mapped using a different user name and password error. On the error that occurs when trying to establish multiple connections to the same server with different credentials being by design, and on the workarounds being connecting by IP address or creating a separate DNS alias.  2 3

  10. Microsoft Learn, System Error Codes (1000-1299). On the definition and message text for error 1219 (ERROR_SESSION_CREDENTIAL_CONFLICT).  2

  11. Microsoft Learn, Mapped drive connection to network share may be lost. On an idle connection being disconnected after a default 15-minute timeout (autodisconnect), and on the drive icon in Explorer showing a red X while reconnecting promptly on the next access.  2

  12. Microsoft Learn, File.Exists(String) Method. On the method returning false without throwing when read permission is missing, and returning false as well if any error occurs while checking for existence (an invalid path, a disk failure, insufficient permissions, and so on).  2

  13. Microsoft Learn, FileSystemWatcher Class. On support for watching files on the local computer, a network drive, and a remote computer, on events being possibly dropped when the buffer size is exceeded, and on the maximum InternalBufferSize being 64 KB when watching over the network.  2 3 4 5

  14. Microsoft Learn, WNet Functions. On WNetGetUniversalName being the function that retrieves a universal (UNC-form) name from a drive-based path. 

  15. Microsoft Learn, Secure group managed service accounts. On a gMSA’s password being a randomly generated 240 bytes, automatically rotated by the OS every 30 days, eliminating the need for administrators to plan password changes or service downtime.  2

  16. Microsoft Learn, Service Accounts and BITS. On LocalSystem/NetworkService authenticating on the network with computer credentials while LocalService uses anonymous credentials, on access being denied when an ACL is restricted to a user account, and on system accounts not being meant to use mapped drives. 

  17. Microsoft Learn, cmdkey. On the cmdkey command being able to create, list, and delete saved user names and passwords (credentials). 

  18. Microsoft Learn, Credentials processes in Windows authentication. On Credential Manager storing credentials in the Windows Credential container and presenting them automatically at subsequent authentication. 

  19. Microsoft Learn, Client Access to Network Resources. On establishing a connection via WNetAddConnection2 with specified client credentials being listed as one strategy a server process can use to access network resources. 

  20. Microsoft Learn, SMB file server share access is unsuccessful through DNS CNAME alias. On a missing SPN registration for the alias being one cause of SMB access failing over a CNAME, and on the recommendation to define the alias using the netdom computername command rather than a DNS CNAME. 

  21. Microsoft Learn, Windows Networking Operations. On a persistent connection being a network connection the system automatically restores at the user’s logon. 

  22. Microsoft Learn, System Error Codes (0-499). On the definitions of ERROR_BAD_NETPATH (53), ERROR_UNEXP_NET_ERR (59), ERROR_NETNAME_DELETED (64), and ERROR_SEM_TIMEOUT (121). 

Recent articles sharing the same tags. Deepen your understanding with closely related topics.

These topic pages place the article in a broader service and decision context.

This article connects naturally to the following service pages.

Frequently Asked Questions

Common questions about the topic of this article.

Why can't a Windows service access a mapped network drive (Z:)?
Because a drive letter is not a system-wide resource — it belongs to a single logon session. A Z: drive that a user maps in Explorer is nothing more than a symbol that belongs to that user's logon session, and it is invisible to a service running under a different logon session. Even when a service runs under a user account, the system creates a fresh logon session for the service, so a desktop-side mapping for that same account is not carried over. The correct approach from a service is to access the resource via its UNC path, \\server\share.
How can a service running as LocalSystem access a shared folder?
On the network, LocalSystem authenticates using the computer's own credentials. In a domain environment, you can grant the machine's computer account (DOMAIN\MACHINE$) permission on the share (both the share permissions and the NTFS ACL) to make this work. However, that setup is awkward to operate — replacing the machine means redoing the permissions — so in practice we recommend running the service under a domain account or a gMSA (group managed service account) and granting that account permission on the share instead.
Is it safe to watch files on a shared folder with FileSystemWatcher?
You can use it, but do not trust it on its own. FileSystemWatcher does support watching network drives and remote computers, but change notifications arrive through an internal buffer, and if notifications arrive in a burst, the buffer can overflow and events get dropped. Worse, when watching over the network, the buffer size is capped at 64 KB. Treat notifications purely as a trigger to rescan, and always pair them with a full scan (polling) on startup, on error, and on a schedule.
How do I design file exchange to be resilient against network disconnects?
Design around 'the share is slow, drops connections, and is sometimes unreachable' as the normal case, not an edge case. Concretely: write under a temporary filename and rename it into place only after the file handle is closed (temp -> rename), wrap reads and writes in retry logic, and distinguish transient network errors from genuine business errors. Note that File.Exists returns false even when the file cannot be reached, so it cannot distinguish 'the file doesn't exist' from 'the server is unreachable' — and as a last line of defense, make sure processing stays idempotent so that reprocessing never causes corruption.

Author Profile

Profile page for the article author.

Go Komura

Representative of KomuraSoft LLC

Focused on Windows software development, technical consulting, and investigations into failures that are difficult to reproduce.

Back to the Blog