2012-09-16 22 views
3

我正在使用Powershell中的添加類型進行試驗。我正在使用netapi32.dll使用NetSessionEnum函數。 這幾乎有效,但不完全。當用零級查詢時,我可以得到結果。查詢其他選項時,嘗試對PtrToStructure進行簡化時,IDE或PowerShell會話崩潰。我完全卡住了?在PowerShell中使用intPtr和使用添加類型封送處理

我認爲這與結構尺寸有關,但並不確定。 如果有人能指出我正確的方向或提供一些奇妙的提示。

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 

回答

0

我這一點發揮四周,好像你忘了做的唯一一件大事是$ QueryLevel變量傳遞到函數的「級別」參數,當你把它叫做。目前,當您調用該函數時,該參數會靜態地設置爲0。因此,當你將$ Querylevel設置爲0以外的任何值時,0級返回的結構和數據不匹配,腳本崩潰......或類似的東西。

這是你有什麼:

#調用函數
$結果= [pinvoke.Win32Util] :: NetSessionEnum($計算機名,$ ComputerSession,$用戶名,0,[參考] $ ptrInfo ,-1,[參考] $ EntriesRed,[參考] $ TotalRead,[參考] $ ResumeHandle)

這是什麼似乎工作:

#調用函數 $結果= [PInvoke的。 Win32Util] :: NetSessionEnum($有限公司我有一個新的先進的技術,它是一個新的先進的技術,我有點新的先進的技術, PowerShellery。所以如果我離開我的搖桿讓我知道,但希望這有助於。

1

我早已放棄了上述觀點,轉移到其他方面,直到有人再次提起我的興趣。

http://support.microsoft.com/kb/2909958

上面的代碼工作(沒有拋出錯誤)在添加了這個非常小的修改: $信息= [system.runtime.interopservices.marshal] ::累得PtrToStructure($ newintptr,$類型) 到 $信息= [system.runtime.interopservices.marshal] ::累得PtrToStructure($ newintptr,[System.Type的] $型)

如果您有興趣使用Windows API this人都有一些有趣的工作,鏈接到其他一些偉大的資源。

感謝NullBind爲您的迴應,非常感謝。

+0

這是非常有用的,並讓我深入瞭解如何進行以下工作:[System.Runtime.InteropServices.Marshal] :: SizeOf([int]) (它會在我的機器上引發錯誤) 替換爲[System.Runtime.InteropServices.Marshal] :: SizeOf([System.Type] [int])然後成功。 –

相關問題