.net - Powershell、PInvoke 和 GetLastError

标签 .net powershell error-handling pinvoke getlasterror

我正在尝试通过 PInvoke 从 Powershell 使用 GetFileSecurity。调用本身有效,但 System.Runtime.InteropServices.Marshal.GetLastWin32Error 和 GetLastError (我导入用于测试)都返回错误的错误代码。看来 PInvoke 签名中的 SetLastError = true 根本没有任何效果,因为在启动新的 Powershell 实例后第一次运行脚本时,两者都返回 203 (ERROR_ENVVAR_NOT_FOUND),但是如果我再次调用同一个脚本,都返回 0。

作为快速测试,我编写了一个等效的 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# 类来进行 GetFileSecurity 调用,然后获取错误,而不是直接 pinvoking。 PowerShell 在 GetFileSecurity() pinvoke 调用和 GetLastWin32Error() pinvoke 调用之间对 Win32 API 进行的任何调用都可能会重置 Win32 错误号。

关于.net - Powershell、PInvoke 和 GetLastError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18213687/

相关文章:

c# - 将 cookie 从 CookieContainer 写入 IE cookie 存储

c# - 使用两个具有相同命名空间的 .NET 库

javascript - 何时会在 window.onError 函数上提供适当的堆栈跟踪?

.net - Vb.Net 属性语法

powershell - |%在PowerShell中是什么意思

windows - 使用 PowerShell 在表中格式化三个数据列表

powershell - 使用 PowerShell 计算文件夹深度

java - 安卓错误: Unable To Start Activity

jakarta-ee - Java.lang.throwable和错误代码

.net - 检查内存转储中所有实例的字段