#powershell #dllimport #32-bit
#powershell #dllimport #32-разрядный
Вопрос:
Я хочу импортировать dll с относительным путем в powershell. Ниже приведен фрагмент кода, который я пытаюсь импортировать dll.
$dirpath = split-path $MyInvocation.MyCommand.Definition
$testDllPath = "$dirpath..Test1Test.dll"
$signatureGet = @'
[DllImport(@"$testDllPath",EntryPoint="TestMethod",ExactSpelling=false)]
public static extern bool TestMethod([MarshalAs(UnmanagedType.LPWStr)]string args1, [MarshalAs(UnmanagedType.LPWStr)]string args2);
'@
$typeFunc = Add-Type -MemberDefinition $signatureGet -Name "TestMethod" -PassThru
$ret = $typeFunc::TestMethod($args1, $args2)
Когда я пытаюсь проделать то же самое с жестко заданным путем, он может загрузить dll. То же самое и с относительным путем, он не работает. Выдает ошибку из-за неправильного формата.
Пожалуйста, дайте мне знать, как этого добиться.
Ответ №1:
Полагаться на текущий каталог (используя относительный путь) в PowerShell опасно при взаимодействии с Windows. Например, если вы когда-нибудь выполните это:
[environment]::CurrentDirectory
Вы увидите, что понятие текущего каталога в PowerShell не всегда соответствует понятию текущего каталога в Windows. Это связано с тем, что в одном процессе PowerShell может одновременно выполняться несколько сценариев, и каждый из них может изменять текущий каталог по мере необходимости. Кроме того, я не думаю, что атрибут DllImportAttribute принимает относительный путь для начала. Обычно указывается только имя, а затем Windows выполняет поиск в том же каталоге, что и exe (PowerShell.exe ) затем пути в переменной окружения PATH.
Что вы можете сделать, так это изменить переменную $env:PATH env непосредственно перед попыткой вызвать скрипт, который импортирует dll, например:
$dirpath = split-path $MyInvocation.MyCommand.Definition
$env:PATH = ";$dirpath....Test1"
$signatureGet = @'
[DllImport(@"Test.dll",EntryPoint="TestMethod",ExactSpelling=false)]
public static extern bool TestMethod([MarshalAs(UnmanagedType.LPWStr)]string args1, [MarshalAs(UnmanagedType.LPWStr)]string args2);
'@
$typeFunc = Add-Type -MemberDefinition $signatureGet -Name "TestMethod" -PassThru
$ret = $typeFunc::TestMethod($args1, $args2)
Ответ №2:
На самом деле переменные не раскрываются в @' '@
строках (только в @" "@
единицах), поэтому путь к DLL не разрешается при указании ссылки на переменную.
Ответ №3:
Еще одна причина, по которой вы используете 64-разрядную ОС (Seven, Windows 8 …)
Когда вы запускаете командную строку PowerShell или запускаете PowerShell в командной строке, по умолчанию вы запускаете 64-разрядный PowerShell, в этом cas вы не можете загрузить 32-разрядную DLL в 64-разрядный процесс.
В этом случае попробуйте запустить свой скрипт, используя 32-разрядный PowerShell :
%SystemRoot%syswow64WindowsPowerShellv1.0powershell.exe
Комментарии:
1. Спасибо за ответ. Я запускаю powershell из указанного самого 32-разрядного пути exe.