DllImport в powershell для доступа к 32-разрядному API в стиле C с использованием относительного пути

#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.