Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[MSH] is it possible to run Win32 API functions from MSH?

23 views
Skip to first unread message

DontBotherMeWithSpam

unread,
Dec 2, 2005, 3:46:04 PM12/2/05
to
I am wondering if it is possible to run Win32 API functions such as
"SendMessage"(from "user32") or "Sleep"(from "kernel32"), etc.

I am wondering if there is something like [DllImport(...)] equivalent
in MSH.

Jon Davis

unread,
Dec 4, 2005, 4:13:29 AM12/4/05
to

"DontBotherMeWithSpam" <DontBother...@gmail.com> wrote in message
news:1133556364.3...@g47g2000cwa.googlegroups.com...

Not automatic. You can always drum up some C# solution that does on-the-fly
compilation and execution for such a thing.

ActiveX is--or was and will be--supported, though.

Jon


/\/\o\/\/

unread,
Dec 4, 2005, 5:25:17 AM12/4/05
to

this MSH script one does it in Visual Basic.NET but you can switch the
compiler for a C# version :

$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()

gr /\/\o\/\/

DontBotherMeWithSpam

unread,
Dec 4, 2005, 1:21:33 PM12/4/05
to
Ok, Thanks guys for the help. I will be looking into encapsulating
C#/VB.net(C# preferably :)) code to call Win32 API.
I have been trying to get "Balloontips" working but AFAIK, it is easily
supported only by Tray Icons so been trying to use Win32 calls instead.

Jeffrey Snover [MSFT]

unread,
Dec 4, 2005, 2:07:14 PM12/4/05
to
Here is the way that I do it using C#:
#####################################################
# 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 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!")

--
Jeffrey Snover [MSFT]
Monad Architect
Microsoft Corporation
This posting is provided "AS IS" with no warranties, no confers rights.


"DontBotherMeWithSpam" <DontBother...@gmail.com> wrote in message

news:1133720493.1...@f14g2000cwb.googlegroups.com...


/\/\o\/\/

unread,
Dec 4, 2005, 2:52:57 PM12/4/05
to
Jeffrey Snover [MSFT] wrote:
> Here is the way that I do it using C#:
> #####################################################
> # 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"
>


that last line is to much,
and throw an error as $framework is not yet declared, it gets declared
below, and also there are these refs again.

if you delete it it works as expected, pasting error I presume.

thanks for the addition to my toolbox, it's good for the "glide-path"

gr /\/\o\/\/

PS if you change this line,

$cpar.GenerateInMemory = $False

you can use it to make CMDlets

make-shell -out mowSH -namespace mow -reference ShowFileDialog.dll
mowSH

DontBotherMeWithSpam

unread,
Dec 4, 2005, 3:40:42 PM12/4/05
to
Well, Hullo. That was more than I have expected :)

This has been great of a help. I guess now this opens up a new
area(Win32API) I could explore with Msh :)

DontBotherMeWithSpam

unread,
Dec 4, 2005, 3:55:53 PM12/4/05
to
I have forgotten that C# isn't case-insensitive so I kept on getting
errors with C# code i assigned to "$code" :)
Man, case-insensitive nature of MSH did get me big time :)

/\/\o\/\/

unread,
Dec 4, 2005, 4:59:11 PM12/4/05
to

You might want to try VS 2005 C# express.

http://msdn.microsoft.com/vstudio/express/visualcsharp/download/

that will help a Lot ;-)

and its free !!

if you want to distribute, you can past it in the MSH wrapper.

anonymous

unread,
Dec 5, 2005, 10:09:36 AM12/5/05
to
Are there examples doing expansions with here-strings?

Can you do?

file test.txt:
@"Hello $name"@

MSH >$name = "monad"
MSH >gc test.txt


Jouko Kynsijärvi

unread,
Dec 5, 2005, 10:23:51 AM12/5/05
to

Here-strings are only usable in MSH script files:

test.msh:

$name = "monad"
$msg1 = @"
Hello
$name
"@
$msg2 = @'
Hello
$name
'@
$msg1
$msg2

MSH> .\test.msh
Hello
monad
Hello
$name


Jeffrey Snover [MSFT]

unread,
Dec 5, 2005, 10:34:28 AM12/5/05
to
Exactly correct!

you can also run any command by putting in $() e.g.
@"
Top 10 Handlecounts:
$(get-process |sort handlecount |select -last 10|out-string)
"@


Here strings are awesome tools for creating XML/HTML/any files.


--
Jeffrey Snover [MSFT]
Monad Architect
Microsoft Corporation
This posting is provided "AS IS" with no warranties, no confers rights.

<anonymous> wrote in message
news:%23Y0wo3a%23FHA...@TK2MSFTNGP14.phx.gbl...

Keith Hill

unread,
Dec 5, 2005, 12:01:26 PM12/5/05
to
"Jeffrey Snover [MSFT]" <jsn...@microsoft.com> wrote in message
news:%230kyjFb%23FHA...@TK2MSFTNGP09.phx.gbl...

> Here strings are awesome tools for creating XML/HTML/any files.

I agree. These are very handy. Although, just out of curiousity, what's
with the name "here string"? From a "glidescope to C#" point of view,
aren't these very similar to C# verbatim strings sans the issue of optional
variable expansion? Which also begs the question, why the funky syntax?
What not just use:

MSH > $s1 = @"Some string with an expanded var $PID"
MSH > $s2 = @'Some string with an unexpanded var $PID and a
>> newline with some more text'
>>
MSH >

If I want a simple string just to prevent escaping, I have to do this over
three lines of text with MSH:

MSH $s1 = @"
>> Some string with an expanded var $PID
>> "@
>>

BTW, why aren't the escapes `r`n etc escaped in "here" strings? I guess
this might explain why "here" strings are not the same as C# verbatim
strings?

--
Keith


/\/\o\/\/

unread,
Dec 5, 2005, 5:10:04 PM12/5/05
to
Marcel Ortiz [MSFT] wrote:
> Someone posted an example of how to call Win32 API's from MSH some time ago.

I think Jouko posted an Emit example some time ago
(was to much for me, so I went the Compile way ;-) )

> Anyway, I needed to do this for one of my scripts so I came up with the
> attached script. It creates a scriptblock that calls a win32 api. For
> example:
>

WOW cool.
thx.

Jeffrey Snover [MSFT]

unread,
Dec 5, 2005, 11:06:23 PM12/5/05
to
The conceptually closest concept to a HERE-STRING is a UNIX HERE-DOC.
$ cat << EOF
now I
can type anything
until I encounter an EOF
by itself
EOF

now I
can type anything
until I encounter an EOF
by itself
$

--
Jeffrey Snover [MSFT]
Monad Architect
Microsoft Corporation
This posting is provided "AS IS" with no warranties, no confers rights.

"Keith Hill" <r_keit...@no.spam.thank.u.hotmail.com> wrote in message
news:%23XjgI2b%23FHA...@TK2MSFTNGP15.phx.gbl...

0 new messages