enums之在 powershell 中使用 add-type 处理 intPtr 和编码

cyq1162 阅读:13 2024-06-03 14:00:57 评论:0

我正在尝试在 Powershell 中添加类型。我正在使用 netapi32.dll 使用 NetSessionEnum 函数。
这几乎有效,但不完全有效。当以零级查询时,我可以获得结果。当使用任何其他选项查询时,IDE 或 powershell session 在尝试对 PtrToStructure 进行编码时只会崩溃。我完全卡住了?

我认为这与结构尺寸有关,但不确定。
如果有人能指出我正确的方向或提供一些技巧,那就太棒了。

NetSessionEnum function

function Get-NetSessions { 
 
param( 
[string]$ComputerName = "", 
[string]$ComputerSession = "", 
[string]$UserName = "", 
[int]$QueryLevel 
 
) 
 
$DebugPreference = 'continue' 
 
$signature = @' 
[DllImport("netapi32.dll", SetLastError=true)] 
public static extern int NetSessionEnum( 
        [In,MarshalAs(UnmanagedType.LPWStr)] string ServerName, 
        [In,MarshalAs(UnmanagedType.LPWStr)] string UncClientName, 
        [In,MarshalAs(UnmanagedType.LPWStr)] string UserName, 
        Int32 Level, 
        out IntPtr bufptr, 
        int prefmaxlen, 
        ref Int32 entriesread, 
        ref Int32 totalentries, 
        ref Int32 resume_handle); 
'@ 
 
 
 
 
$SessionInfoStructures = @' 
namespace pinvoke { 
using System; 
using System.Runtime.InteropServices; 
 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
    public struct SESSION_INFO_0 
    { 
    [MarshalAs(UnmanagedType.LPWStr)] 
    public String sesi0_cname; 
    } 
 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
    public struct SESSION_INFO_1 
    { 
    [MarshalAs(UnmanagedType.LPWStr)] 
    public string sesi1_cname; 
    [MarshalAs(UnmanagedType.LPWStr)] 
    public string sesi1_username; 
    public uint sesi1_num_opens; 
    public uint sesi1_time; 
    public uint sesi1_idle_time; 
    public uint sesi1_user_flag; 
    } 
 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
    public struct SESSION_INFO_2 
    { 
    [MarshalAs(UnmanagedType.LPWStr)] 
    public string sesi2_cname; 
    [MarshalAs(UnmanagedType.LPWStr)] 
    public string sesi2_username; 
    public uint  sesi2_num_opens; 
    public uint  sesi2_time; 
    public uint  sesi2_idle_time; 
    public uint  sesi2_user_flags; 
    [MarshalAs(UnmanagedType.LPWStr)] 
    public string sesi2_cltype_name; 
    } 
 
 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
    public struct SESSION_INFO_10 
    { 
    [MarshalAs(UnmanagedType.LPWStr)] 
    public string sesi10_cname; 
    [MarshalAs(UnmanagedType.LPWStr)] 
    public string sesi10_username; 
    public uint sesi10_time; 
    public uint sesi10_idle_time; 
    } 
 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
    public struct SESSION_INFO_502 
    { 
    [MarshalAs(UnmanagedType.LPWStr)] 
    public string sesi502_cname; 
    [MarshalAs(UnmanagedType.LPWStr)] 
    public string sesi502_username; 
    public uint sesi502_num_opens; 
    public uint sesi502_time; 
    public uint sesi502_idle_time; 
    public uint sesi502_user_flags; 
    [MarshalAs(UnmanagedType.LPWStr)] 
    public string sesi502_cltype_name; 
    [MarshalAs(UnmanagedType.LPWStr)] 
    public string sesi502_transport; 
    } 
 
    public enum NERR 
    { 
    /// <summary> 
    /// Operation was a success. 
    /// </summary> 
    NERR_Success = 0, 
    /// <summary> 
    /// More data available to read. dderror getting all data. 
    /// </summary> 
    ERROR_MORE_DATA = 234, 
    /// <summary> 
    /// Network browsers not available. 
    /// </summary> 
    ERROR_NO_BROWSER_SERVERS_FOUND = 6118, 
    /// <summary> 
    /// LEVEL specified is not valid for this call. 
    /// </summary> 
    ERROR_INVALID_LEVEL = 124, 
    /// <summary> 
    /// Security context does not have permission to make this call. 
    /// </summary> 
    ERROR_ACCESS_DENIED = 5, 
    /// <summary> 
    /// Parameter was incorrect. 
    /// </summary> 
    ERROR_INVALID_PARAMETER = 87, 
    /// <summary> 
    /// Out of memory. 
    /// </summary> 
    ERROR_NOT_ENOUGH_MEMORY = 8, 
    /// <summary> 
    /// Unable to contact resource. Connection timed out. 
    /// </summary> 
    ERROR_NETWORK_BUSY = 54, 
    /// <summary> 
    /// Network Path not found. 
    /// </summary> 
    ERROR_BAD_NETPATH = 53, 
    /// <summary> 
    /// No available network connection to make call. 
    /// </summary> 
    ERROR_NO_NETWORK = 1222, 
    /// <summary> 
    /// Pointer is not valid. 
    /// </summary> 
    ERROR_INVALID_HANDLE_STATE = 1609, 
    /// <summary> 
    /// Extended Error. 
    /// </summary> 
    ERROR_EXTENDED_ERROR= 1208, 
    /// <summary> 
    /// Base. 
    /// </summary> 
    NERR_BASE = 2100, 
    /// <summary> 
    /// Unknown Directory. 
    /// </summary> 
    NERR_UnknownDevDir = (NERR_BASE + 16), 
    /// <summary> 
    /// Duplicate Share already exists on server. 
    /// </summary> 
    NERR_DuplicateShare = (NERR_BASE + 18), 
    /// <summary> 
    /// Memory allocation was to small. 
    /// </summary> 
    NERR_BufTooSmall = (NERR_BASE + 23) 
    } 
 
    public enum SESSION_LEVEL 
    { 
    /// <summary> 
    /// ZERO 
    /// </summary> 
    LEVEL_0 = 0, 
    /// <summary> 
    /// ONE 
    /// </summary> 
    LEVEL_1 = 1, 
    /// <summary> 
    /// TWO 
    /// </summary> 
    LEVEL_2 = 2, 
    /// <summary> 
    /// TEN 
    /// </summary> 
    LEVEL_10 = 10, 
    /// <summary> 
    /// FIVE HUNDRED AND TWO 
    /// </summary> 
    LEVEL_502 = 502 
    } 
} 
'@ 
 
 
 
# Add the custom structures and enums 
Add-Type $SessionInfoStructures 
 
 
# Add the function definition 
Add-Type -MemberDefinition $signature -Name Win32Util -Namespace Pinvoke -Using Pinvoke 
 
 
if ([Pinvoke.SESSION_LEVEL]::LEVEL_0 -eq $QueryLevel) {$x = New-Object pinvoke.SESSION_INFO_0} 
if ([Pinvoke.SESSION_LEVEL]::LEVEL_1 -eq $QueryLevel) {$x = New-Object pinvoke.SESSION_INFO_1} 
if ([Pinvoke.SESSION_LEVEL]::LEVEL_2 -eq $QueryLevel) {$x = New-Object pinvoke.SESSION_INFO_2} 
if ([Pinvoke.SESSION_LEVEL]::LEVEL_10 -eq $QueryLevel) {$x = New-Object pinvoke.SESSION_INFO_10} 
if ([Pinvoke.SESSION_LEVEL]::LEVEL_502 -eq $QueryLevel) {$x = New-Object pinvoke.SESSION_INFO_502} 
 
# Declare the reference variables 
$type = $x.gettype() 
Write-Debug "$type.tostring()" 
 
$ptrInfo = 0  
$EntriesRed = 0 
$TotalRead = 0 
$ResumeHandle = 0 
 
# Call the function 
$Result = [pinvoke.Win32Util]::NetSessionEnum($ComputerName,$ComputerSession,$UserName,0,[ref]$ptrInfo,-1,[ref]$EntriesRed,[ref]$TotalRead,[ref]$ResumeHandle) 
 
$Result 
 
 
if ($Result -eq ([pinvoke.NERR]::NERR_Success)){ 
 
    Write-Debug 'Result is success' 
    Write-Debug "IntPtr $ptrInfo" 
    Write-Debug "Entries read $EntriesRed" 
    Write-Debug "Total Read $TotalRead" 
 
 
    # Locate the offset of the initial intPtr 
    $offset = $ptrInfo.ToInt64() 
    Write-Debug "Starting Offset $offset" 
 
    # Work out how mutch to increment the pointer by finding out the size of the structure 
    $Increment = [System.Runtime.Interopservices.Marshal]::SizeOf($x) 
    Write-Debug "Increment $Increment" 
 
 
    for ($i = 0; ($i -lt $EntriesRed); $i++){ 
 
        $newintptr = New-Object system.Intptr -ArgumentList $offset 
        Write-Debug "Newintptr `[$i`] $newintptr" 
        $Info = [system.runtime.interopservices.marshal]::PtrToStructure($newintptr,$type) 
        $Info | Select-Object * 
        $offset = $newintptr.ToInt64() 
        $offset += $increment 
    } 
 
} 
else  
{ 
    #       switch ($Result) 
    #           { 
    #           ([Pinvoke.NERR]::ERROR_ACCESS_DENIED)       {Write-Host "The user does not have access to the requested information."} 
    #           ([Pinvoke.NERR]::ERROR_INVALID_LEVEL)       {Write-Host "The value specified for the level parameter is not valid."} 
    #           ([Pinvoke.NERR]::ERROR_INVALID_PARAMETER)   {Write-Host 'The specified parameter is not valid.'} 
    #           ([Pinvoke.NERR]::ERROR_MORE_DATA)           {Write-Host 'More entries are available. Specify a large enough buffer to receive all entries.'} 
    #           ([Pinvoke.NERR]::ERROR_NOT_ENOUGH_MEMORY)   {Write-Host 'Insufficient memory is available.'} 
    #           ([Pinvoke.NERR]::NERR_ClientNameNotFound)   {Write-Host 'A session does not exist with the computer name.'} 
    #           ([Pinvoke.NERR]::NERR_InvalidComputer)      {Write-Host 'The computer name is not valid.'} 
    #           ([Pinvoke.NERR]::NERR_ClientNameNotFound)   {Write-Host 'The user name could not be found.'}                 
    #           } 
} 
} 
 
 
Get-NetSessions -QueryLevel 0 

请您参考如下方法:

我早就放弃了上述内容并转向其他事情,直到某件事再次引起了我的兴趣。
https://support.microsoft.com/en-us/help/2909958/exceptions-in-windows-powershell-other-dynamic-languages-and-dynamical
添加这个非常小的修改时,上面的代码工作(没有抛出错误):

$Info = [system.runtime.interopservices.marshal]::PtrToStructure($newintptr,$type) 
$Info = [system.runtime.interopservices.marshal]::PtrToStructure($newintptr,[System.Type]$type) 
如果您有兴趣使用 Windows API this person 有一些有趣的工作,并链接到其他一些很棒的资源。
感谢 NullBind 的回复,非常感谢。


标签:Shell
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号