::::::::: PowerShell :::::::::
Sunday, December 11, 2005
  Strange "Get-Member" behavior(Title borrowed from Mow's blog)
Ok, it was weird that whenever I was trying to see if a returned value if of a type array or a scalar.

I have been frusted to see foreach or .length property of output to see if the returned value is an array or not.

But I don't think I would have to worry about it no more.

Strangely enough,

MSH>((get-help get-childitem)."#comment") | gm

would result in displaying type information for type of stored information in the result array object instead of displaying the type of actual array.

But apparently there was at least one another person who was having the similiar problem.

Mow gave me the answer on Usenet newsgroup post and
Here is the answer he posted.


MSH>,((get-help get-childitem)."#comment") | gm

TypeName: System.Management.Automation.MshObject[]


Note that, only difference here was that "," is used to before piping the output to "gm".


For more extensive coverage and answer for this behavior, I recommend
/\/\o\/\/ on MSH (Monad): Create System Variable From MSH (Part2)

If you read through his blog, there is another way to retrieve type information of the array.

gm -input ((get-help get-childitem)."#comment")

Apparently this latter solution works as well.
But why?

Thanks /\/\o\/\/ for another tip there :)
 
Sunday, December 04, 2005
  Calling Win32 API functions through MSH
I have always been wondering if there is a native(in terms of MSH context) way to call Win32 API functions inside MSH. There isn't a built-in way to call Win32 API functions directly.

Oh, don't be disappointed, though. There is a work-around; Dynamic in-memory compilation of C#/VB.net code does the trick.

Well, another day and another day at UseNet newsgroup, I have found the answer.
Solutions were provided by /\/\o\/\/(with VB.net solution) and Jeffery Snover for in-memory compilation of C# code snippet.

My next project will be creating a utility MSH function to ease the pain of declaring and using Win32 API functions

e.g.) new-win32_function declaration [[-ns namespace] [-cn classname]]
new-win32_function "public static extern int puts(string c)" -ns TestNs -cl TestApp
Would let me use "puts" function like the following
MSH> [TestNs.TestApp]::puts("test")


/\/\o\/\/'s VB.NET solution
$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()




and here is the C# solution(Modified a bit to fix syntax error)
Jeffery's C# solution


##################################################### 
# 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.xm­l.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!")




Has anyone ever noticed that "Solution" sounds better than simply referring it as "answer"?
 
Let's get lazy with PowerShell!

Name:
Location: Flushing, NY, United States

Experimenting with a different format of blogs...

Links
ARCHIVES
10/01/2005 - 11/01/2005 / 11/01/2005 - 12/01/2005 / 12/01/2005 - 01/01/2006 / 01/01/2006 - 02/01/2006 / 02/01/2006 - 03/01/2006 / 03/01/2006 - 04/01/2006 / 04/01/2006 - 05/01/2006 / 05/01/2006 - 06/01/2006 / 06/01/2006 - 07/01/2006 / 07/01/2006 - 08/01/2006 / 08/01/2006 - 09/01/2006 / 10/01/2006 - 11/01/2006 / 11/01/2006 - 12/01/2006 /


Powered by Blogger