Environment
Wails provides comprehensive environment information through the EnvironmentManager API. This allows your application to detect system properties, theme preferences, and integrate with the operating system’s file manager.
Accessing the Environment Manager
Section titled “Accessing the Environment Manager”The environment manager is accessed through the Env property on your application instance:
app := application.New(application.Options{ Name: "Environment Demo",})
// Access the environment managerenv := app.EnvSystem Information
Section titled “System Information”Get Environment Information
Section titled “Get Environment Information”Retrieve comprehensive information about the runtime environment:
envInfo := app.Env.Info()
app.Logger.Info("Environment information", "os", envInfo.OS, // "windows", "darwin", "linux" "arch", envInfo.Arch, // "amd64", "arm64", etc. "debug", envInfo.Debug, // Debug mode flag)
// Operating system detailsif envInfo.OSInfo != nil { app.Logger.Info("OS details", "name", envInfo.OSInfo.Name, "version", envInfo.OSInfo.Version, )}
// Platform-specific informationfor key, value := range envInfo.PlatformInfo { app.Logger.Info("Platform info", "key", key, "value", value)}Environment Structure
Section titled “Environment Structure”The environment information includes several important fields:
type EnvironmentInfo struct { OS string // Operating system: "windows", "darwin", "linux" Arch string // Architecture: "amd64", "arm64", "386", etc. Debug bool // Whether running in debug mode OSInfo *operatingsystem.OS // Detailed OS information PlatformInfo map[string]any // Platform-specific details}Theme Detection
Section titled “Theme Detection”Dark Mode Detection
Section titled “Dark Mode Detection”Detect whether the system is using dark mode:
if app.Env.IsDarkMode() { app.Logger.Info("System is in dark mode") // Apply dark theme to your application applyDarkTheme()} else { app.Logger.Info("System is in light mode") // Apply light theme to your application applyLightTheme()}Theme Change Monitoring
Section titled “Theme Change Monitoring”Listen for theme changes to update your application dynamically:
import "github.com/wailsapp/wails/v3/pkg/events"
// Listen for theme changesapp.Event.OnApplicationEvent(events.Common.ThemeChanged, func(event *application.ApplicationEvent) { if app.Env.IsDarkMode() { app.Logger.Info("Switched to dark mode") updateApplicationTheme("dark") } else { app.Logger.Info("Switched to light mode") updateApplicationTheme("light") }})
func updateApplicationTheme(theme string) { // Update your application's theme // This could emit an event to the frontend app.Event.Emit("theme:changed", theme)}File Manager Integration
Section titled “File Manager Integration”Open File Manager
Section titled “Open File Manager”Open the system’s file manager at a specific location:
// Open file manager at a directoryerr := app.Env.OpenFileManager("/Users/username/Documents", false)if err != nil { app.Logger.Error("Failed to open file manager", "error", err)}
// Open file manager and select a specific fileerr = app.Env.OpenFileManager("/Users/username/Documents/report.pdf", true)if err != nil { app.Logger.Error("Failed to open file manager with selection", "error", err)}Common Use Cases
Section titled “Common Use Cases”Show files or folders in the file manager from your application:
func showInFileManager(app *application.App, path string) { err := app.Env.OpenFileManager(path, true) if err != nil { // Fallback: try opening just the directory dir := filepath.Dir(path) err = app.Env.OpenFileManager(dir, false) if err != nil { app.Logger.Error("Could not open file manager", "path", path, "error", err)
// Show error to user app.Dialog.Error(). SetTitle("File Manager Error"). SetMessage("Could not open file manager"). Show() } }}
// Usage examplesfunc setupFileMenu(app *application.App) { menu := app.Menu.New() fileMenu := menu.AddSubmenu("File")
fileMenu.Add("Show Downloads Folder").OnClick(func(ctx *application.Context) { homeDir, _ := os.UserHomeDir() downloadsDir := filepath.Join(homeDir, "Downloads") showInFileManager(app, downloadsDir) })
fileMenu.Add("Show Application Data").OnClick(func(ctx *application.Context) { configDir, _ := os.UserConfigDir() appDir := filepath.Join(configDir, "MyApp") showInFileManager(app, appDir) })}Platform-Specific Behavior
Section titled “Platform-Specific Behavior”Adaptive Application Behavior
Section titled “Adaptive Application Behavior”Use environment information to adapt your application’s behavior:
func configureForPlatform(app *application.App) { envInfo := app.Env.Info()
switch envInfo.OS { case "darwin": configureMacOS(app) case "windows": configureWindows(app) case "linux": configureLinux(app) }
// Adapt to architecture if envInfo.Arch == "arm64" { app.Logger.Info("Running on ARM architecture") // Potentially optimize for ARM }}
func configureMacOS(app *application.App) { app.Logger.Info("Configuring for macOS")
// macOS-specific configuration menu := app.Menu.New() menu.AddRole(application.AppMenu) // Add standard macOS app menu
// Handle dark mode if app.Env.IsDarkMode() { setMacOSDarkTheme() }}
func configureWindows(app *application.App) { app.Logger.Info("Configuring for Windows")
// Windows-specific configuration // Set up Windows-style menus, key bindings, etc.}
func configureLinux(app *application.App) { app.Logger.Info("Configuring for Linux")
// Linux-specific configuration // Adapt to different desktop environments}Debug Mode Handling
Section titled “Debug Mode Handling”Development vs Production
Section titled “Development vs Production”Use debug mode information to enable development features:
func setupApplicationMode(app *application.App) { envInfo := app.Env.Info()
if envInfo.Debug { app.Logger.Info("Running in debug mode") setupDevelopmentFeatures(app) } else { app.Logger.Info("Running in production mode") setupProductionFeatures(app) }}
func setupDevelopmentFeatures(app *application.App) { // Enable development-only features menu := app.Menu.New()
// Add development menu devMenu := menu.AddSubmenu("Development") devMenu.Add("Reload Application").OnClick(func(ctx *application.Context) { // Reload the application window := app.Window.Current() if window != nil { window.Reload() } })
devMenu.Add("Open DevTools").OnClick(func(ctx *application.Context) { window := app.Window.Current() if window != nil { window.OpenDevTools() } })
devMenu.Add("Show Environment").OnClick(func(ctx *application.Context) { showEnvironmentDialog(app) })}
func setupProductionFeatures(app *application.App) { // Production-only features // Disable debug logging, enable analytics, etc.}Environment Information Dialog
Section titled “Environment Information Dialog”Display System Information
Section titled “Display System Information”Create a dialog showing environment information:
func showEnvironmentDialog(app *application.App) { envInfo := app.Env.Info()
details := fmt.Sprintf(`Environment Information:
Operating System: %sArchitecture: %sDebug Mode: %t
Dark Mode: %t
Platform Information:`, envInfo.OS, envInfo.Arch, envInfo.Debug, app.Env.IsDarkMode())
// Add platform-specific details for key, value := range envInfo.PlatformInfo { details += fmt.Sprintf("\n%s: %v", key, value) }
if envInfo.OSInfo != nil { details += fmt.Sprintf("\n\nOS Details:\nName: %s\nVersion: %s", envInfo.OSInfo.Name, envInfo.OSInfo.Version) }
dialog := app.Dialog.Info() dialog.SetTitle("Environment Information") dialog.SetMessage(details) dialog.Show()}Platform Considerations
Section titled “Platform Considerations”On macOS:
- Dark mode detection uses system appearance settings
- File manager operations use Finder
- Platform info includes macOS version details
- Architecture may be “arm64” on Apple Silicon Macs
if envInfo.OS == "darwin" { // macOS-specific handling if envInfo.Arch == "arm64" { app.Logger.Info("Running on Apple Silicon") }}On Windows:
- Dark mode detection uses Windows theme settings
- File manager operations use Windows Explorer
- Platform info includes Windows version details
- May include additional Windows-specific information
if envInfo.OS == "windows" { // Windows-specific handling for key, value := range envInfo.PlatformInfo { if key == "windows_version" { app.Logger.Info("Windows version", "version", value) } }}On Linux:
- Dark mode detection varies by desktop environment
- File manager operations use system default file manager
- Platform info includes distribution details
- Behavior may vary between different Linux distributions
if envInfo.OS == "linux" { // Linux-specific handling if distro, ok := envInfo.PlatformInfo["distribution"]; ok { app.Logger.Info("Linux distribution", "distro", distro) }}Best Practices
Section titled “Best Practices”-
Cache Environment Information: Environment info rarely changes during runtime:
type App struct {envInfo *application.EnvironmentInfo}func (a *App) getEnvInfo() application.EnvironmentInfo {if a.envInfo == nil {info := a.app.Env.Info()a.envInfo = &info}return *a.envInfo} -
Handle Theme Changes: Listen for system theme changes:
app.Event.OnApplicationEvent(events.Common.ThemeChanged, func(event *application.ApplicationEvent) {updateTheme(app.Env.IsDarkMode())}) -
Graceful File Manager Failures: Always handle file manager errors:
func openFileManagerSafely(app *application.App, path string) {err := app.Env.OpenFileManager(path, false)if err != nil {// Provide fallback or user notificationapp.Logger.Warn("Could not open file manager", "path", path)}} -
Platform-Specific Features: Use environment info to enable platform features:
envInfo := app.Env.Info()if envInfo.OS == "darwin" {// Enable macOS-specific features}
Complete Example
Section titled “Complete Example”Here’s a complete example demonstrating environment management:
package main
import ( "fmt" "os" "path/filepath" "runtime" "github.com/wailsapp/wails/v3/pkg/application" "github.com/wailsapp/wails/v3/pkg/events")
func main() { app := application.New(application.Options{ Name: "Environment Demo", })
// Setup application based on environment setupForEnvironment(app)
// Monitor theme changes monitorThemeChanges(app)
// Create menu with environment features setupEnvironmentMenu(app)
// Create main window window := app.Window.New() window.SetTitle("Environment Demo")
err := app.Run() if err != nil { panic(err) }}
func setupForEnvironment(app *application.App) { envInfo := app.Env.Info()
app.Logger.Info("Application environment", "os", envInfo.OS, "arch", envInfo.Arch, "debug", envInfo.Debug, "darkMode", app.Env.IsDarkMode(), )
// Configure for platform switch envInfo.OS { case "darwin": app.Logger.Info("Configuring for macOS") // macOS-specific setup case "windows": app.Logger.Info("Configuring for Windows") // Windows-specific setup case "linux": app.Logger.Info("Configuring for Linux") // Linux-specific setup }
// Apply initial theme if app.Env.IsDarkMode() { applyDarkTheme(app) } else { applyLightTheme(app) }}
func monitorThemeChanges(app *application.App) { app.Event.OnApplicationEvent(events.Common.ThemeChanged, func(event *application.ApplicationEvent) { if app.Env.IsDarkMode() { app.Logger.Info("System switched to dark mode") applyDarkTheme(app) } else { app.Logger.Info("System switched to light mode") applyLightTheme(app) } })}
func setupEnvironmentMenu(app *application.App) { menu := app.Menu.New()
// Add platform-specific app menu if runtime.GOOS == "darwin" { menu.AddRole(application.AppMenu) }
// Tools menu toolsMenu := menu.AddSubmenu("Tools")
toolsMenu.Add("Show Environment Info").OnClick(func(ctx *application.Context) { showEnvironmentInfo(app) })
toolsMenu.Add("Open Downloads Folder").OnClick(func(ctx *application.Context) { openDownloadsFolder(app) })
toolsMenu.Add("Toggle Theme").OnClick(func(ctx *application.Context) { // This would typically be handled by the system // but shown here for demonstration toggleTheme(app) })
app.Menu.Set(menu)}
func showEnvironmentInfo(app *application.App) { envInfo := app.Env.Info()
message := fmt.Sprintf(`Environment Information:
Operating System: %sArchitecture: %sDebug Mode: %tDark Mode: %t
Platform Details:`, envInfo.OS, envInfo.Arch, envInfo.Debug, app.Env.IsDarkMode())
for key, value := range envInfo.PlatformInfo { message += fmt.Sprintf("\n%s: %v", key, value) }
if envInfo.OSInfo != nil { message += fmt.Sprintf("\n\nOS Information:\nName: %s\nVersion: %s", envInfo.OSInfo.Name, envInfo.OSInfo.Version) }
dialog := app.Dialog.Info() dialog.SetTitle("Environment Information") dialog.SetMessage(message) dialog.Show()}
func openDownloadsFolder(app *application.App) { homeDir, err := os.UserHomeDir() if err != nil { app.Logger.Error("Could not get home directory", "error", err) return }
downloadsDir := filepath.Join(homeDir, "Downloads") err = app.Env.OpenFileManager(downloadsDir, false) if err != nil { app.Logger.Error("Could not open Downloads folder", "error", err)
app.Dialog.Error(). SetTitle("File Manager Error"). SetMessage("Could not open Downloads folder"). Show() }}
func applyDarkTheme(app *application.App) { app.Logger.Info("Applying dark theme") // Emit theme change to frontend app.Event.Emit("theme:apply", "dark")}
func applyLightTheme(app *application.App) { app.Logger.Info("Applying light theme") // Emit theme change to frontend app.Event.Emit("theme:apply", "light")}
func toggleTheme(app *application.App) { // This is just for demonstration // Real theme changes should come from the system currentlyDark := app.Env.IsDarkMode() if currentlyDark { applyLightTheme(app) } else { applyDarkTheme(app) }}