SmbSharp 1.1.2

dotnet add package SmbSharp --version 1.1.2
                    
NuGet\Install-Package SmbSharp -Version 1.1.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SmbSharp" Version="1.1.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SmbSharp" Version="1.1.2" />
                    
Directory.Packages.props
<PackageReference Include="SmbSharp" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SmbSharp --version 1.1.2
                    
#r "nuget: SmbSharp, 1.1.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SmbSharp@1.1.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SmbSharp&version=1.1.2
                    
Install as a Cake Addin
#tool nuget:?package=SmbSharp&version=1.1.2
                    
Install as a Cake Tool

SmbSharp

A cross-platform .NET library for SMB/CIFS file operations. Works seamlessly on Windows using native UNC paths (or smbclient via WSL), and on Linux/macOS using smbclient.

NuGet License: MIT

Features

  • Cross-Platform: Windows (native UNC), Linux (smbclient), and macOS (smbclient)
  • WSL Support: Optionally use smbclient via WSL on Windows
  • Dual Authentication: Kerberos and username/password authentication
  • Stream-Based API: Efficient, memory-friendly file operations
  • Async/Await: Full async support with cancellation tokens
  • Dependency Injection: Built-in ASP.NET Core DI integration
  • Health Checks: Monitor SMB share connectivity with ASP.NET Core health checks
  • Multiple .NET Versions: Supports .NET Core 3.1, .NET 6, .NET 8, and .NET 10
  • Secure: Passwords passed via environment variables, not command-line arguments
  • Well-Documented: Comprehensive XML documentation with IntelliSense support

Installation

NuGet Package Manager

Install-Package SmbSharp

.NET CLI

dotnet add package SmbSharp

Package Reference

<PackageReference Include="SmbSharp" Version="1.1.0" />

Platform Requirements

Windows

  • No additional requirements - uses native UNC path support
  • Optional WSL support: If you want to use smbclient via WSL instead of native UNC paths, install WSL and smbclient inside your distribution:
    wsl apt-get install smbclient
    

Linux

  • Requires smbclient to be installed:
    # Debian/Ubuntu
    sudo apt-get install smbclient
    
    # RHEL/CentOS
    sudo yum install samba-client
    
    # Alpine Linux
    apk add samba-client
    

macOS

  • Requires smbclient to be installed:
    brew install samba
    

Docker

Add smbclient to your Dockerfile:

Debian/Ubuntu-based images:

FROM mcr.microsoft.com/dotnet/aspnet:8.0
RUN apt-get update && apt-get install -y smbclient && rm -rf /var/lib/apt/lists/*

Alpine-based images:

FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine
RUN apk add --no-cache samba-client

RHEL/CentOS-based images:

FROM mcr.microsoft.com/dotnet/aspnet:8.0-rhel
RUN yum install -y samba-client && yum clean all

Quick Start

Kerberos Authentication (Default)
// Program.cs
builder.Services.AddSmbSharp();

// Usage in a controller/service
public class MyService
{
    private readonly IFileHandler _fileHandler;

    public MyService(IFileHandler fileHandler)
    {
        _fileHandler = fileHandler;
    }

    public async Task<IEnumerable<string>> GetFiles()
    {
        return await _fileHandler.EnumerateFilesAsync("//server/share/folder");
    }
}
Username/Password Authentication
// Program.cs - Direct credentials
builder.Services.AddSmbSharp("username", "password", "DOMAIN");

// Or using configuration
builder.Services.AddSmbSharp(options =>
{
    options.UseKerberos = false;
    options.Username = "username";
    options.Password = "password";
    options.Domain = "DOMAIN";
});

// Or from appsettings.json
builder.Services.AddSmbSharp(options =>
{
    builder.Configuration.GetSection("SmbSharp").Bind(options);
});
Using smbclient via WSL on Windows
// Use smbclient through WSL instead of native UNC paths
builder.Services.AddSmbSharp(options =>
{
    options.UseWsl = true; // Enable WSL smbclient on Windows
    options.UseKerberos = false;
    options.Username = "username";
    options.Password = "password";
    options.Domain = "DOMAIN";
});

Direct Instantiation (Without Dependency Injection)

using Microsoft.Extensions.Logging;
using SmbSharp.Business;

// Without logging
var handler = FileHandler.CreateWithKerberos();
var handler = FileHandler.CreateWithCredentials("username", "password", "DOMAIN");

// With console logging (for debugging)
using var loggerFactory = LoggerFactory.Create(builder =>
{
    builder
        .SetMinimumLevel(LogLevel.Debug)
        .AddConsole();
});

var handler = FileHandler.CreateWithKerberos(loggerFactory);
var handler = FileHandler.CreateWithCredentials("username", "password", "DOMAIN", loggerFactory);

// Using smbclient via WSL on Windows
var handler = FileHandler.CreateWithKerberos(useWsl: true);
var handler = FileHandler.CreateWithCredentials("username", "password", "DOMAIN", loggerFactory, useWsl: true);

// Usage
var files = await handler.EnumerateFilesAsync("//server/share/folder");

Note: To use console logging, you need to add the Microsoft.Extensions.Logging.Console package:

dotnet add package Microsoft.Extensions.Logging.Console

Path Format

SmbSharp accepts SMB paths in multiple formats for flexibility:

// Forward slashes (recommended for cross-platform code)
await fileHandler.EnumerateFilesAsync("//server/share/folder");

// Backslashes (Windows UNC format)
await fileHandler.EnumerateFilesAsync("\\\\server\\share\\folder");

// Mixed (automatically normalized)
await fileHandler.EnumerateFilesAsync("//server/share\\folder");

Note: All path formats are automatically normalized internally. Forward slashes (/) are recommended for cross-platform compatibility, but backslashes (\) are fully supported for Windows-style UNC paths.

Usage Examples

List Files in a Directory

var files = await fileHandler.EnumerateFilesAsync("//server/share/folder");
foreach (var file in files)
{
    Console.WriteLine(file);
}

Read a File

await using var stream = await fileHandler.ReadFileAsync("//server/share/folder", "file.txt");
using var reader = new StreamReader(stream);
var content = await reader.ReadToEndAsync();

Write a File (String Content)

await fileHandler.WriteFileAsync("//server/share/folder/file.txt", "Hello, World!");

Write a File (Stream)

await using var fileStream = File.OpenRead("local-file.txt");
await fileHandler.WriteFileAsync("//server/share/folder/file.txt", fileStream);

Write with Different Modes

// Overwrite existing file (default)
await fileHandler.WriteFileAsync("//server/share/file.txt", stream, FileWriteMode.Overwrite);

// Create only if doesn't exist (fails if exists)
await fileHandler.WriteFileAsync("//server/share/file.txt", stream, FileWriteMode.CreateNew);

// Append to existing file
await fileHandler.WriteFileAsync("//server/share/file.txt", stream, FileWriteMode.Append);

Delete a File

await fileHandler.DeleteFileAsync("//server/share/folder/file.txt");

Move a File

await fileHandler.MoveFileAsync(
    "//server/share/folder/old.txt",
    "//server/share/folder/new.txt"
);

Note: On Linux/macOS (and Windows with WSL), move operations download and re-upload the file, which can be slow for large files. The operation is atomic with automatic retry logic - if the source deletion fails after copying, it retries once before rolling back the destination to maintain consistency.

Create a Directory

await fileHandler.CreateDirectoryAsync("//server/share/newfolder");

Test Connectivity

bool canConnect = await fileHandler.CanConnectAsync("//server/share");
if (canConnect)
{
    Console.WriteLine("Successfully connected!");
}

Using Cancellation Tokens

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));

try
{
    var files = await fileHandler.EnumerateFilesAsync(
        "//server/share/folder",
        cts.Token
    );
}
catch (OperationCanceledException)
{
    Console.WriteLine("Operation timed out!");
}

Authentication

Kerberos Authentication

On Linux, ensure you have a valid Kerberos ticket before using the library:

kinit username@DOMAIN.COM

Verify your ticket:

klist

Username/Password Authentication

Credentials are securely passed to smbclient via environment variables, not command-line arguments, preventing exposure in process listings.

Health Checks

SmbSharp includes built-in health check support for ASP.NET Core applications to monitor SMB share connectivity.

Single Share Health Check

// Program.cs
builder.Services.AddSmbSharp();
builder.Services.AddHealthChecks()
    .AddSmbShareCheck("//server/share/folder");

Named Health Check with Options

builder.Services.AddHealthChecks()
    .AddSmbShareCheck(
        directoryPath: "//server/share/folder",
        name: "primary_smb_share",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "smb", "storage" },
        timeout: TimeSpan.FromSeconds(10)
    );

Multiple Share Health Checks

var shares = new Dictionary<string, string>
{
    { "primary", "//server1/share1" },
    { "backup", "//server2/share2" },
    { "archive", "//server3/share3" }
};

builder.Services.AddHealthChecks()
    .AddSmbShareChecks(shares, tags: new[] { "smb" });

Health Check Endpoint

// Program.cs
var app = builder.Build();

app.MapHealthChecks("/health");
// Or with detailed response
app.MapHealthChecks("/health", new HealthCheckOptions
{
    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});

Example Response

Healthy:

{
  "status": "Healthy",
  "results": {
    "smb_share": {
      "status": "Healthy",
      "description": "Successfully connected to SMB share: //server/share/folder"
    }
  }
}

Unhealthy:

{
  "status": "Unhealthy",
  "results": {
    "smb_share": {
      "status": "Unhealthy",
      "description": "Unable to connect to SMB share: //server/share/folder"
    }
  }
}

Health Check Logging

When health checks fail, error logs are automatically generated to help troubleshoot connectivity issues:

// Enable logging in your appsettings.json
{
  "Logging": {
    "LogLevel": {
      "SmbSharp.HealthChecks.SmbShareHealthCheck": "Error"
    }
  }
}

Example error log:

[Error] Health check failed: Unable to connect to SMB share: //server/share/folder
[Error] Health check failed for SMB share //server/share/folder: Access denied

API Reference

IFileHandler Interface

Method Description
EnumerateFilesAsync(directory, cancellationToken) Lists all files in a directory
ReadFileAsync(directory, fileName, cancellationToken) Opens a file for reading as a stream
WriteFileAsync(filePath, content, cancellationToken) Writes a string to a file
WriteFileAsync(filePath, stream, cancellationToken) Writes a stream to a file
WriteFileAsync(filePath, stream, writeMode, cancellationToken) Writes a stream with specific write mode
DeleteFileAsync(filePath, cancellationToken) Deletes a file
MoveFileAsync(sourcePath, destPath, cancellationToken) Moves a file
CreateDirectoryAsync(directoryPath, cancellationToken) Creates a directory
CanConnectAsync(directoryPath, cancellationToken) Tests connectivity to a share

FileWriteMode Enum

Value Description
Overwrite Creates a new file or overwrites existing (default)
CreateNew Creates only if file doesn't exist (throws if exists)
Append Appends to existing file or creates new

Error Handling

The library throws specific exceptions for different error scenarios:

try
{
    await fileHandler.ReadFileAsync("//server/share", "file.txt");
}
catch (FileNotFoundException ex)
{
    // File or path doesn't exist
}
catch (UnauthorizedAccessException ex)
{
    // Access denied or authentication failed
}
catch (DirectoryNotFoundException ex)
{
    // Network path not found
}
catch (IOException ex)
{
    // Other SMB/network errors
}
catch (PlatformNotSupportedException ex)
{
    // Running on unsupported platform (not Windows/Linux/macOS)
}

Debugging

To troubleshoot authentication issues or see exactly what commands are being sent to smbclient, enable debug logging:

// In Program.cs or appsettings.json
builder.Logging.SetMinimumLevel(LogLevel.Debug);

// Or configure specific loggers
builder.Logging.AddFilter("SmbSharp.Infrastructure.ProcessWrapper", LogLevel.Debug);

Example debug output:

Executing process: smbclient //server/share -U "username" -c "ls folder/*"
Environment variables set: PASSWD
Process exited with code: 0

Note: Passwords are never logged. Only environment variable names (like PASSWD) are shown, not their values.

Performance Considerations

Windows

  • Uses native UNC paths - very efficient
  • All operations are direct file system calls
  • Move operations are atomic and instant (metadata-only)

Linux / macOS / Windows (WSL)

  • Uses smbclient subprocess - some overhead
  • Read operations download to temp file (auto-cleaned)
  • Write operations upload from temp file
  • Move operations = download + upload + delete (can be slow for large files)
  • For large files, consider alternative approaches or be aware of 2x disk space + network transfer

Security Features

  • ✅ Passwords passed via environment variables (not visible in process listings)
  • ✅ Command injection protection (input escaping)
  • ✅ Comprehensive input validation
  • ✅ Path traversal protection

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

Acknowledgments

Built with ❤️ for the .NET community.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.1 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.2 81 2/10/2026
1.1.1 77 2/10/2026 1.1.1 is deprecated because it has critical bugs.
1.1.0 63 2/7/2026 1.1.0 is deprecated because it has critical bugs.
1.0.16 112 2/4/2026
1.0.15 55 2/4/2026
1.0.14 66 2/4/2026
1.0.13 53 2/4/2026
1.0.12 58 2/4/2026
1.0.11 57 2/3/2026
1.0.10 50 2/3/2026
1.0.9 53 2/3/2026
1.0.8 52 2/3/2026
1.0.7 50 2/3/2026
1.0.6 48 2/3/2026
1.0.5 59 2/3/2026
1.0.4 54 2/2/2026
1.0.3 48 2/2/2026
1.0.2 50 2/2/2026
1.0.1 57 1/30/2026
1.0.0 58 1/29/2026

v1.1.2: Repackage of v1.1.1 fixes with clean build (previous package contained stale binaries). Fix EnumerateFilesAsync on smbclient path: include files with any attribute (not just Archive), correctly parse filenames containing spaces, return empty list for empty directories instead of throwing, and include hidden dot-files. v1.1.0: Add macOS support (smbclient), WSL smbclient support on Windows (opt-in), and sample console app.