2013-08-13 3 views
3

Я пытаюсь использовать 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() 

ответ

2

Скорее, что непосредственно pinvoking, я хотел бы создать класс # обертка C, что делает вызов GetFileSecurity, а затем получает ошибку. Возможно, что любые вызовы PowerShell делают Win32 API между вашим вызовом pinvoke GetFileSecurity(), а вызов pinvoke GetLastWin32Error() сбрасывает номер ошибки Win32.

+0

Спасибо, что сработало. Я закончил тем, что написал все на C#, кажется намного менее сумасшедшим и более читаемым. – leromarinvit