Немедленное исправление имеет два аспекта:
[DllImport("shell32.dll")]
->
[DllImport("Shell32.dll", CharSet = CharSet.Unicode)]
Поскольку вы явно указали цель ShellExecuteW
- версия API-функции Unicode - вы должны объявить этот факт через поле CharSet
в атрибуте. [1]
Хотя это и не обязательно, int hwnd
должно быть IntPtr hwnd
.
$exec::ShellExecuteW(0, "open", "notepad.exe", 0, 0, 1)
->
$exec::ShellExecute(0, "open", "notepad.exe", [NullString]::Value, [NullString]::Value, 1)
- Обратите внимание на использование
[NullString]::Value
для передачи null
в string
-типированные параметры; по умолчанию PowerShell обрабатывает $null
в строковом контексте как пустую строку вместо null
; в этом конкретном случае, однако, пустая строка (и, следовательно, $null
) тоже будет работать.
Чтобы сложить все вместе:
$exec = Add-Type -name "win" -namespace Win32Functions -passThru -memberDefinition @'
[DllImport("shell32.dll", CharSet=CharSet.Unicode)]
public static extern int ShellExecuteW(
IntPtr hwnd,
string lpOperation,
string lpFile,
string lpParameters,
string lpDirectory,
int nShowCmd
);
'@
$exec::ShellExecuteW(
0,
'open',
'notepad.exe',
[NullString]::Value,
[NullString]::Value,
1
)
Шаг назад: командлет Start-Process
позволяет сделать то же самое без необходимости скомпилированных объявлений P / Invoke по запросу:
# Use -WorkingDirectory, if needed.
Start-Process Notepad.Exe -Verb Open -WindowStyle Normal
[1] Пропуск суффикса W
(ShellExecute
), в то время как не , указание значения CharSet
тоже работает на практике, хотя документы подразумевает, что тогда вызывается версия ANSI . Однако на практике я этого не вижу: даже при явной передаче аргументов с символами за пределами диапазона ANSI (например, 'file€§ü.txt'
) в версию функции ANSI они, похоже, правильно передаются в Блокнот. Однако, наоборот, передача такой строки в приложение console never , кажется, передает их правильно, даже при явной ориентации на версию Unicode.