Skip to content

Instantly share code, notes, and snippets.

@IISResetMe
Created September 16, 2015 21:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IISResetMe/3c3e9408129af6a928f5 to your computer and use it in GitHub Desktop.
Save IISResetMe/3c3e9408129af6a928f5 to your computer and use it in GitHub Desktop.
Offline comments for Richard Siddaway's Objective: Objects talk @ PSHSummit
#region new()
# new() works not only on PS Classes, but wraps existing .NET ctors as well:
[System.Net.WebProxy]::new("proxyserver.contoso.com",3128)
#endregion
#region Add-Type
#region Access modifiers
# Add-Type and C# type and member defitions are not only useful for controlling accessibility levels:
$Definition = @'
public class MyClass {
public string param1 { get; set; }
private string param2 { get; set; }
public MyClass() {
this.param2 = "Not accessible from outside the class";
}
}
'@
Add-Type -TypeDefinition $Definition
#endregion
#region property accessors
# But for defining custom accessors ("getters" and "setters") as well:
$Definition = @'
public class MyMathClass {
private int square;
public int Square
{
get { return this.square; }
set { this.square = value * value; }
}
}
'@
Add-Type -TypeDefinition $Definition
# What black magic is this?!
PS C:\> $myInstance = [MyMathClass]::new()
PS C:\> $myInstance.Square = 3
PS C:\> $myInstance.Square
9
#endregion
#region DllImport
# and finally: marshalling native code!
# PowerShell + the DllImport attribute + pinvoke.net = magic
$PingUtilityDefinition = @'
using System;
using System.Net;
using System.Runtime.InteropServices;
public class IcmpPing
{
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
private struct ICMP_OPTIONS
{
public byte Ttl;
public byte Tos;
public byte Flags;
public byte OptionsSize;
public IntPtr OptionsData;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
private struct ICMP_ECHO_REPLY
{
public int Address;
public int Status;
public int RoundTripTime;
public short DataSize;
public short Reserved;
public IntPtr DataPtr;
public ICMP_OPTIONS Options;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=250)]
public string Data;
}
[DllImport("icmp.dll", SetLastError=true)]
private static extern IntPtr IcmpCreateFile();
[DllImport("icmp.dll", SetLastError=true)]
private static extern bool IcmpCloseHandle(IntPtr handle);
[DllImport("icmp.dll", SetLastError=true)]
private static extern int IcmpSendEcho(IntPtr icmpHandle, int destinationAddress, string requestData, short requestSize, ref ICMP_OPTIONS requestOptions, ref ICMP_ECHO_REPLY replyBuffer, int replySize, int timeout);
public bool Ping(IPAddress ip)
{
IntPtr icmpHandle = IcmpCreateFile();
ICMP_OPTIONS icmpOptions = new ICMP_OPTIONS();
icmpOptions.Ttl = 255;
ICMP_ECHO_REPLY icmpReply = new ICMP_ECHO_REPLY();
string sData = "x";
int iReplies = IcmpSendEcho(icmpHandle, BitConverter.ToInt32(ip.GetAddressBytes(), 0), sData, (short)sData.Length, ref icmpOptions, ref icmpReply, Marshal.SizeOf(icmpReply), 30);
IcmpCloseHandle(icmpHandle);
if (icmpReply.Status == 0)
return true;
return false;
}
}
'@
Add-Type -TypeDefinition $PingUtilityDefinition
# Now you can have the OS send an ICMP echo for you, just like ping.exe - incredibly low overhead:
PS C:\> [IcmpPing]::new().Ping("127.0.0.1")
True
# Example above is from http://pinvoke.net/default.aspx/icmp.IcmpSendEcho
#endregion
#endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment