diff --git a/DevDrive.csproj b/DevDrive.csproj index 3fa004f..b94b7ed 100644 --- a/DevDrive.csproj +++ b/DevDrive.csproj @@ -1,7 +1,7 @@ - Exe + WinExe net8.0-windows enable enable @@ -21,4 +21,13 @@ + + + PreserveNewest + + + PreserveNewest + + + diff --git a/Program.cs b/Program.cs index 9583344..ee0730c 100644 --- a/Program.cs +++ b/Program.cs @@ -8,7 +8,6 @@ namespace DevDrive; /// /// Entry point for the virtual drive application. -/// Monitors a config drive via WMI events and creates symlinks based on index.json. /// [SupportedOSPlatform("windows")] public static class Program diff --git a/README.md b/README.md new file mode 100644 index 0000000..08b9973 --- /dev/null +++ b/README.md @@ -0,0 +1,118 @@ +# DevDrive + +A lightweight virtual drive for Windows built with Dokan. DevDrive mounts a user-defined filesystem at a drive letter (default: `A:`) and exposes folders from your machine as symlinks. Configuration lives in `C:\PhysicalDrive\index.json`. + +## Requirements +- Windows 10/11 x64 +- .NET 8 SDK +- Dokan Library (driver/runtime) + - Install the latest Dokan release (driver + library) from the official site. + https://github.com/dokan-dev/dokany + +## Setup +1. Install Dokan. +2. Create the config folder and file: + - Folder: `C:\PhysicalDrive\` + - File: `C:\PhysicalDrive\index.json` +3. Populate `index.json` using the schema below. + +### About `C:\PhysicalDrive` +- This path is a remapped physical drive root. It can point to a USB stick or a legacy floppy that you mount to the folder `C:\PhysicalDrive\`. +- Disk Management: Right-click the device → Change Drive Letter and Paths → Add → Mount in the empty NTFS folder `C:\PhysicalDrive\`. + +- DevDrive just watches `C:\PhysicalDrive\index.json`; the backing device can be any removable media. + +### index.json schema +```json +{ + "driveName": "Dev Disk", + "driveIcon": "%SystemRoot%\\System32\\shell32.dll,6", + "driveTotalMB": 100, + "driveFreeMB": 50, + "paths": [ + { "name": "Projects", "path": "C:\\DEV\\Projects" }, + { "name": "Tools", "path": "C:\\Tools" } + ] +} +``` +- `driveName`: Label shown in Explorer. +- `driveIcon`: Optional custom icon. Supports file paths (e.g., `C:\\Icons\\dev.ico`) or resource references (e.g., `%SystemRoot%\\System32\\shell32.dll,6`). +- `driveTotalMB`: Total capacity reported to Explorer. +- `driveFreeMB`: Free space reported to Explorer. +- `paths`: Symlinks created at the root of the mounted drive. Each entry becomes a folder that points to the real location. + +## Build +```powershell +Push-Location "C:\DEV\devDrive" +dotnet build +Pop-Location +``` +- Output: `bin\Debug\net8.0-windows\DevDrive.dll` and `DevDrive.exe`. + +## Run (Console) +```powershell +Push-Location "C:\DEV\devDrive\bin\Debug\net8.0-windows" +./DevDrive.exe +Pop-Location +``` +- Defaults: Mounts at `A:\` and reads config from `C:\PhysicalDrive\index.json`. +- Arguments: `DevDrive.exe ` + - Example: + ```powershell + ./DevDrive.exe Z:\ C:\PhysicalDrive\ + ``` + +## Run (Windows Service) +DevDrive can run as a Windows service that starts automatically on boot. + +### Install Service +Right-click `install-service.bat` and select **Run as administrator**. +- Creates a service named `DevDrive`. +- Sets it to start automatically on boot. +- Configures automatic restart on failure. + +### Uninstall Service +Right-click `uninstall-service.bat` and select **Run as administrator**. +- Stops and removes the `DevDrive` service. + +### Manual Service Commands +```powershell +# Start +sc start DevDrive + +# Stop +sc stop DevDrive + +# Query status +sc query DevDrive +``` + +### Service Notes +- Service logs go to the Windows Event Log (Application). +- The service mounts to `A:\` with config from `C:\PhysicalDrive\index.json` (no command-line args in service mode). +- To change mount point or config path when running as a service, edit `DevDriveService.cs` and rebuild. + +## Behavior +- Mount options: Uses Mount Manager and current session; not flagged as removable. +- Volume label: Taken from `driveName`. +- Icon: Applied per-user via registry under `HKCU\Software\Classes\Applications\Explorer.exe\Drives`. +- Space reporting: `driveTotalMB` and `driveFreeMB` control what Explorer shows. +- Symlinks: Entries in `paths` are exposed as directories at the root; contents come from the target paths. + +## Hotplug and Config Detection +- If `ConfigPath` is a drive letter (e.g., `E:\`): WMI `Win32_LogicalDisk` events detect insert/remove. +- If `ConfigPath` is a folder (e.g., the remapped physical `C:\PhysicalDrive\`): WMI `Win32_Volume` events are used; unplugging the backing device makes the folder inaccessible, which triggers unmount. + +## Troubleshooting +- Build errors due to locked executable: + - Stop any running `DevDrive.exe` before rebuilding. +- Mount fails or requires elevation: + - Mounting `A:` may require admin privileges depending on system policies. +- Icon not updating immediately: + - The app requests a shell refresh; if the icon still doesn’t change, sign out/in or restart Explorer. +- Dokan not installed: + - Ensure the Dokan driver and library are installed and loaded; reboot after installation if needed. + +## Notes +- By default, DevDrive mounts to `A:` with a FAT-style label, but it is not a physical floppy or removable device. +- Registry icon changes are per-user and cleaned up on unmount. diff --git a/delete b/delete new file mode 100644 index 0000000..f43aaba --- /dev/null +++ b/delete @@ -0,0 +1 @@ +DevDrive diff --git a/install-service.bat b/install-service.bat new file mode 100644 index 0000000..ce5a720 --- /dev/null +++ b/install-service.bat @@ -0,0 +1,61 @@ +@echo off +:: DevDrive Startup Task Installer +:: Run as Administrator + +setlocal + +set TASK_NAME=DevDrive +set EXE_PATH=%~dp0DevDrive.exe + +echo Installing %TASK_NAME% startup task... +echo. + +:: Check for admin privileges +net session >nul 2>&1 +if %errorlevel% neq 0 ( + echo ERROR: This script requires Administrator privileges. + echo Right-click and select "Run as administrator". + pause + exit /b 1 +) + +:: Check if executable exists +if not exist "%EXE_PATH%" ( + echo ERROR: DevDrive.exe not found at: + echo %EXE_PATH% + echo. + echo Please build the project first: + echo dotnet build + pause + exit /b 1 +) + +:: Remove existing task if present +schtasks /query /tn "%TASK_NAME%" >nul 2>&1 +if %errorlevel% equ 0 ( + echo Removing existing task... + schtasks /delete /tn "%TASK_NAME%" /f >nul 2>&1 +) + +:: Create scheduled task to run at logon (hidden, no console window) +echo Creating startup task... +schtasks /create /tn "%TASK_NAME%" /tr "\"%EXE_PATH%\"" /sc onlogon /rl highest /f +if %errorlevel% neq 0 ( + echo ERROR: Failed to create task. + pause + exit /b 1 +) + +:: Start it now +echo Starting DevDrive... +schtasks /run /tn "%TASK_NAME%" + +echo. +echo %TASK_NAME% installed successfully! +echo. +echo DevDrive will: +echo - Start automatically when you log in +echo - Mount the virtual drive at A:\ +echo - Watch C:\PhysicalDrive\index.json for config +echo. +pause diff --git a/stop b/stop new file mode 100644 index 0000000..f43aaba --- /dev/null +++ b/stop @@ -0,0 +1 @@ +DevDrive diff --git a/uninstall-service.bat b/uninstall-service.bat new file mode 100644 index 0000000..dc12cb4 --- /dev/null +++ b/uninstall-service.bat @@ -0,0 +1,45 @@ +@echo off +:: DevDrive Startup Task Uninstaller +:: Run as Administrator + +setlocal + +set TASK_NAME=DevDrive + +echo Uninstalling %TASK_NAME%... +echo. + +:: Check for admin privileges +net session >nul 2>&1 +if %errorlevel% neq 0 ( + echo ERROR: This script requires Administrator privileges. + echo Right-click and select "Run as administrator". + pause + exit /b 1 +) + +:: Check if task exists +schtasks /query /tn "%TASK_NAME%" >nul 2>&1 +if %errorlevel% neq 0 ( + echo Task %TASK_NAME% is not installed. + pause + exit /b 0 +) + +:: Kill running process +echo Stopping DevDrive... +taskkill /im DevDrive.exe /f >nul 2>&1 + +:: Delete task +echo Removing startup task... +schtasks /delete /tn "%TASK_NAME%" /f +if %errorlevel% neq 0 ( + echo ERROR: Failed to remove task. + pause + exit /b 1 +) + +echo. +echo %TASK_NAME% uninstalled successfully! +echo. +pause