MSH>((get-help get-childitem)."#comment") | gm
MSH>,((get-help get-childitem)."#comment") | gm
TypeName: System.Management.Automation.MshObject[]
gm -input ((get-help get-childitem)."#comment")
$provider = new-object Microsoft.VisualBasic.VBCodeProvider
$params = new-object System.CodeDom.Compiler.CompilerParameters
$params.GenerateInMemory = $True
$refs = "System.dll","Microsoft.VisualBasic.dll"
$params.ReferencedAssemblies.AddRange($refs)
# VB.NET EXAMPLE
$txtCode = @'
Class mow
Declare Auto Function MyMessageBox Lib “user32.dll” Alias _
“MessageBox” (ByVal hWnd as Integer, ByVal msg as String, _
ByVal Caption as String, ByVal Tpe as Integer) As Integer
Sub Main()
MyMessageBox(0, "Hello World !!!", "Project Title", 0)
End Sub
end class
'@
$results = $provider.CompileAssemblyFromSource($params, $txtCode)
$mAssembly = $results.CompiledAssembly
$i = $mAssembly.CreateInstance("mow")
$r = $i.main()
#####################################################
# This is a general purpose routine that I put into a file called
# LibraryCodeGen.msh and then dot-source when I need it.
#####################################################
function Compile-Csharp ([string] $code, $FrameworkVersion="v2.0.50727",
[Array]$References)
{
#
# Get an instance of the CSharp code provider
#
$cp = new-object Microsoft.CSharp.CSharpCodeProvider
#
# Build up a compiler params object...
#
"${framework}\System.Data.dll,${framework}\System.dll,${framework}\system.xml.dll"
$framework = Combine-Path $env:windir "Microsoft.NET\Framework\$FrameWorkVersion"
$refs = new-object Collections.ArrayList
$refs.AddRange( @("${framework}\System.dll",
"${mshhome}\System.Management.Automation.dll",
"${mshhome}\System.Management.Automation.ConsoleHost.dll",
"${framework}\system.windows.forms.dll",
"${framework}\System.data.dll",
"${framework}\System.Drawing.dll",
"${framework}\System.Xml.dll"))
if ($references.Count -ge 1)
{
$refs.AddRange($References)
}
$cpar = New-Object System.CodeDom.Compiler.CompilerParameters
$cpar.GenerateInMemory = $true
$cpar.GenerateExecutable = $false
$cpar.OutputAssembly = "custom"
$cpar.ReferencedAssemblies.AddRange($refs)
$cr = $cp.CompileAssemblyFromSource($cpar, $code)
if ( $cr.Errors.Count)
{
$codeLines = $code.Split("`n");
foreach ($ce in $cr.Errors)
{
write-host "Error: $($codeLines[$($ce.Line - 1)])"
$ce out-default
}
Throw "INVALID DATA: Errors encountered while compiling code"
}
}
#########################################################
# Here I leverage one of my favorite features (here-strings) to define
# the C# code I want to run. Remember - if you use single quotes - the
# string is taken literally but if you use double-quotes, we'll do variable
# expansion. This can be VERY useful.
#########################################################
$code = '
using System;
using System.Runtime.InteropServices;
namespace test
{
public class Testclass
{
[DllImport("msvcrt.dll")]
public static extern int puts(string c);
[DllImport("msvcrt.dll")]
internal static extern int _flushall();
public static void Run(string message)
{
puts(message);
_flushall();
}
}
}
'
########################################################
# So now we compile the code and use .NET object access to run it.
########################################################
compile-CSharp $code
[Test.TestClass]::Run("Monad ROCKS!")
Experimenting with a different format of blogs...