63 lines
1.8 KiB
Go
63 lines
1.8 KiB
Go
//go:build windows
|
|||
|
|
|
||
|
|
package files
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"fmt"
|
||
|
|
"os/exec"
|
||
|
|
"path/filepath"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
var ErrSelectionCanceled = context.Canceled
|
||
|
|
|
||
|
|
type commandRunner interface {
|
||
|
|
Run(context.Context, string, ...string) ([]byte, error)
|
||
|
|
}
|
||
|
|
|
||
|
|
type execRunner struct{}
|
||
|
|
|
||
|
|
func (execRunner) Run(ctx context.Context, name string, args ...string) ([]byte, error) {
|
||
|
|
return exec.CommandContext(ctx, name, args...).Output()
|
||
|
|
}
|
||
|
|
|
||
|
|
type windowsDirectoryPicker struct{ runner commandRunner }
|
||
|
|
|
||
|
|
func NewDirectoryPicker() DirectoryPicker { return windowsDirectoryPicker{runner: execRunner{}} }
|
||
|
|
|
||
|
|
func newDirectoryPickerWithRunner(runner commandRunner) windowsDirectoryPicker {
|
||
|
|
return windowsDirectoryPicker{runner: runner}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (p windowsDirectoryPicker) ChooseDirectory(ctx context.Context) (string, error) {
|
||
|
|
if err := ctx.Err(); err != nil {
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
output, err := p.runner.Run(ctx, "powershell.exe",
|
||
|
|
"-NoProfile", "-NonInteractive", "-STA", "-WindowStyle", "Hidden", "-Command", folderDialogScript)
|
||
|
|
if err != nil {
|
||
|
|
if ctxErr := ctx.Err(); ctxErr != nil {
|
||
|
|
return "", ctxErr
|
||
|
|
}
|
||
|
|
return "", fmt.Errorf("open directory picker: %w", err)
|
||
|
|
}
|
||
|
|
selected := strings.TrimSpace(string(output))
|
||
|
|
if selected == "" {
|
||
|
|
return "", ErrSelectionCanceled
|
||
|
|
}
|
||
|
|
if !filepath.IsAbs(selected) {
|
||
|
|
return "", fmt.Errorf("directory picker returned a non-absolute path")
|
||
|
|
}
|
||
|
|
return filepath.Clean(selected), nil
|
||
|
|
}
|
||
|
|
|
||
|
|
const folderDialogScript = `[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
|
||
|
|
Add-Type -AssemblyName System.Windows.Forms
|
||
|
|
$dialog = New-Object System.Windows.Forms.FolderBrowserDialog
|
||
|
|
$dialog.Description = '选择浏览器 User Data Dir'
|
||
|
|
$dialog.ShowNewFolderButton = $true
|
||
|
|
if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
|
||
|
|
[Console]::Out.Write($dialog.SelectedPath)
|
||
|
|
}`
|