Я пытаюсь использовать GetFileSecurity из Powershell через PInvoke. Сам вызов работает, но как System.Runtime.InteropServices.Marshal.GetLastWin32Error, так и GetLastError (который я импортировал для тестирования) возвращают неправильный код ошибки. Похоже, что SetLastError = true
в сигнатуре PInvoke вообще не имеет никакого эффекта, так как первый раз, когда скрипт запускается после запуска нового экземпляра Powershell, оба возвращают 203 (ERROR_ENVVAR_NOT_FOUND), но если я снова вызову тот же скрипт, оба возвращаются 0.Powershell, PInvoke и GetLastError
В качестве быстрого теста я взломал эквивалентную программу на C, и GetLastError возвращает ожидаемое значение (122 == ERROR_INSUFFICIENT_BUFFER).
Обратите внимание, что я новичок в Powershell и .NET в целом, поэтому, пожалуйста, извините за любые очевидные ошибки.
$signature = @'
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetFileSecurity(
string lpFileName,
int RequestedInformation,
byte [] pSecurityDescriptor,
uint nLength,
out int lpnLengthNeeded
);
[DllImport("Kernel32.dll")]
public static extern uint GetLastError();
'@
$enum = @'
namespace Win32 {
public enum SECURITY_INFORMATION : uint
{
OWNER_SECURITY_INFORMATION = 0x00000001,
GROUP_SECURITY_INFORMATION = 0x00000002,
DACL_SECURITY_INFORMATION = 0x00000004,
SACL_SECURITY_INFORMATION = 0x00000008,
UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000,
UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000,
PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000,
PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000
}
}
'@
Add-Type -TypeDefinition $enum
Add-Type -MemberDefinition $signature -Name API -Namespace Win32
$len = 0
$sec = New-Object byte[] 0
$info = new-object Win32.SECURITY_INFORMATION
$info = [Win32.SECURITY_INFORMATION]::OWNER_SECURITY_INFORMATION -bor
[Win32.SECURITY_INFORMATION]::GROUP_SECURITY_INFORMATION -bor
[Win32.SECURITY_INFORMATION]::DACL_SECURITY_INFORMATION
[Win32.API]::GetFileSecurity("c:\temp", $info, $sec, $sec.Length, [ref] $len)
[System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
[Win32.API]::GetLastError()
Спасибо, что сработало. Я закончил тем, что написал все на C#, кажется намного менее сумасшедшим и более читаемым. – leromarinvit