首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Powershell、PInvoke和GetLastError

Powershell、PInvoke和GetLastError
EN

Stack Overflow用户
提问于 2013-08-13 15:50:54
回答 2查看 3.6K关注 0票数 4

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

作为一个快速测试,我创建了一个等价的C程序,GetLastError在那里返回预期值(122个== ERROR_INSUFFICIENT_BUFFER)。

请注意,我对Powershell和.NET一般都是新手,所以请原谅任何明显的失礼。

代码语言:javascript
复制
$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()
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-08-13 16:37:57

相反,我将直接调用,创建一个包装器C#类,进行GetFileSecurity调用,然后获取错误。PowerShell在GetFileSecurity() pinvoke调用和GetLastWin32Error() pinvoke调用之间调用Win32 API的任何调用都有可能重置Win32错误号。

票数 3
EN

Stack Overflow用户

发布于 2022-08-17 23:22:05

您可以将其保存在PowerShell中,只要您阻止PowerShell将GetFileSecurity()的结果直接写入控制台。如Keith所说,对GetLastWin32Error()的调用必须在调用GetFileSecurity()之后立即,没有控制台写入或其他Win32 API调用。

您可以通过将调用转换为void来使调用保持沉默。

代码语言:javascript
复制
[void]([Win32.API]::GetFileSecurity("c:\temp", $info, $sec, $sec.Length, [ref] $len))
[System.Runtime.InteropServices.Marshal]::GetLastWin32Error()

或者您可以将其结果保存到一个变量中,并在以后打印它:

代码语言:javascript
复制
$result = [Win32.API]::GetFileSecurity("c:\temp", $info, $sec, $sec.Length, [ref] $len)
[System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
Write-Output $result
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18213687

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档