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
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!