dirs-dev / dirs-rs

a low-level library that provides config/cache/data paths, following the respective conventions on Linux, macOS and Windows

Home Page:https://dirs.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Windows: Add fallback for nanoserver Windows containers

lippertmarkus opened this issue · comments

Getting directories via shlobj::SHGetKnownFolderPath works fine on Windows and Windows Server containers, but not in Nanoserver containers.

Simple program to output all dirs:

extern crate dirs;

fn main() {
    println!("audio_dir: {}", dirs::audio_dir().unwrap_or_default().to_string_lossy());
    println!("cache_dir: {}", dirs::cache_dir().unwrap_or_default().to_string_lossy());
    println!("config_dir: {}", dirs::config_dir().unwrap_or_default().to_string_lossy());
    println!("data_dir: {}", dirs::data_dir().unwrap_or_default().to_string_lossy());
    println!("data_local_dir: {}", dirs::data_local_dir().unwrap_or_default().to_string_lossy());
    println!("desktop_dir: {}", dirs::desktop_dir().unwrap_or_default().to_string_lossy());
    println!("document_dir: {}", dirs::document_dir().unwrap_or_default().to_string_lossy());
    println!("download_dir: {}", dirs::download_dir().unwrap_or_default().to_string_lossy());
    println!("executable_dir: {}", dirs::executable_dir().unwrap_or_default().to_string_lossy());
    println!("font_dir: {}", dirs::font_dir().unwrap_or_default().to_string_lossy());
    println!("home_dir: {}", dirs::home_dir().unwrap_or_default().to_string_lossy());
    println!("preference_dir: {}", dirs::preference_dir().unwrap_or_default().to_string_lossy());
    println!("public_dir: {}", dirs::public_dir().unwrap_or_default().to_string_lossy());
    println!("picture_dir: {}", dirs::picture_dir().unwrap_or_default().to_string_lossy());
    println!("runtime_dir: {}", dirs::runtime_dir().unwrap_or_default().to_string_lossy());
    println!("template_dir: {}", dirs::template_dir().unwrap_or_default().to_string_lossy());
    println!("video_dir: {}", dirs::video_dir().unwrap_or_default().to_string_lossy());
}

Dockerfile:

ARG version=servercore:1809
FROM mcr.microsoft.com/windows/$version
COPY target/release/rust-test.exe .
ENTRYPOINT ["rust-test.exe"]

Outputs

  • Win 10 (no containers):

    audio_dir: C:\Users\myuser\Music
    cache_dir: C:\Users\myuser\AppData\Local
    config_dir: C:\Users\myuser\AppData\Roaming
    data_dir: C:\Users\myuser\AppData\Roaming
    data_local_dir: C:\Users\myuser\AppData\Local
    desktop_dir: C:\Users\myuser\Desktop
    document_dir: C:\Users\myuser\Documents
    download_dir: C:\Users\myuser\Downloads
    executable_dir:
    font_dir:
    home_dir: C:\Users\myuser
    preference_dir: C:\Users\myuser\AppData\Roaming
    public_dir: C:\Users\Public
    picture_dir: C:\Users\myuser\Pictures
    runtime_dir:
    template_dir: C:\Users\myuser\AppData\Roaming\Microsoft\Windows\Templates
    video_dir: C:\Users\myuser\Videos
    
  • Windows ServerCore 1809 Container:

    PS C:\dev\repos\rust-test> docker run --rm $(docker build --build-arg version=servercore:1809 -q .)
    audio_dir: C:\Users\ContainerAdministrator\Music
    cache_dir: C:\Users\ContainerAdministrator\AppData\Local
    config_dir: C:\Users\ContainerAdministrator\AppData\Roaming
    data_dir: C:\Users\ContainerAdministrator\AppData\Roaming
    data_local_dir: C:\Users\ContainerAdministrator\AppData\Local
    desktop_dir: C:\Users\ContainerAdministrator\Desktop
    document_dir: C:\Users\ContainerAdministrator\Documents
    download_dir: C:\Users\ContainerAdministrator\Downloads
    executable_dir:
    font_dir:
    home_dir: C:\Users\ContainerAdministrator
    preference_dir: C:\Users\ContainerAdministrator\AppData\Roaming
    public_dir: C:\Users\Public
    picture_dir: C:\Users\ContainerAdministrator\Pictures
    runtime_dir:
    template_dir: C:\Users\ContainerAdministrator\AppData\Roaming\Microsoft\Windows\Templates
    video_dir: C:\Users\ContainerAdministrator\Videos
    
  • Windows Nanoserver 1809 Container:

    PS C:\dev\repos\rust-test> docker run --rm $(docker build --build-arg version=nanoserver:1809 -q .)
    audio_dir:
    cache_dir:
    config_dir:
    data_dir:
    data_local_dir:
    desktop_dir:
    document_dir:
    download_dir:
    executable_dir:
    font_dir:
    home_dir:
    preference_dir:
    public_dir:
    picture_dir:
    runtime_dir:
    template_dir:
    video_dir:
    
  • Windows Nanoserver 20H2 Container (newest version):

    PS C:\dev\repos\rust-test> docker run --rm $(docker build --build-arg version=nanoserver:20H2 -q .)
    audio_dir:
    cache_dir:
    config_dir:
    data_dir:
    data_local_dir:
    desktop_dir:
    document_dir:
    download_dir:
    executable_dir:
    font_dir:
    home_dir:
    preference_dir:
    public_dir:
    picture_dir:
    runtime_dir:
    template_dir:
    video_dir:
    

This is a known issue (or maybe even intended) in nanoserver according to dotnet/runtime#21430 (comment)

To work around this we could use environment variables on nanoserver, although only for some:

USERPROFILE for home_dir
APPDATA for data_dir
LOCALAPPDATA for data_local_dir
PUBLIC for public_dir

To find out if running on nanoserver, the easiest would be to check the registry:

  • Windows Nanoserver container:
    C:\>reg query "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels"
    
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels
        NanoServer    REG_DWORD    0x1
    
  • Windows Server Core container:
    C:\>reg query "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels"
    
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels
        ServerCore    REG_DWORD    0x1
    
  • Windows Server 2019 (without containers)
    C:\>reg query "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels"
    
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels
        Server-Gui-Mgmt    REG_DWORD    0x1
        Server-Gui-Shell    REG_DWORD    0x1
        ServerCore    REG_DWORD    0x1
        ServerCoreExtended    REG_DWORD    0x1
    
  • Windows 10 (without containrs): registry key doesn't exist
commented

Hi @lippertmarkus,

sadly env vars are not a substitute to the Win API calls; see the discussion about this in dirs-dev/directories-jvm#43 (comment).

If the API doesn't return anything, there is not much we can do here as a library. I think this is something that should be taken up with the operating system vendor:

Either it is a bug, then the vendor should fix it, or it is intentional, then we shouldn't pretend otherwise.

Alright, thanks for clarifying!