ps1.soapyfrog.com https://ps1.soapyfrog.com doing inappropriate things with powershell Wed, 13 May 2015 08:27:10 +0000 en-US hourly 1 https://wordpress.org/?v=4.5.2 Google bullying, new style https://ps1.soapyfrog.com/2015/05/13/google-bullying-new-style/ Wed, 13 May 2015 08:27:10 +0000 https://ps1.soapyfrog.com/?p=84 So I ended this blog some time ago (August 2007), but, being the WWW, thought it would be nice to keep it out there in case anyone was interested.

However, Google has decided that it would be downgraded in rankings because of its presentation.

Now reactive, responsive web design was in its infancy back when this content was created and small screens were rare and Android didn’t really exist, but Google now says I have to have a presentation that looks good on mobile devices.

So I switched to a modern, yet generic WordPress theme. I don’t like it much.

I wonder if Google will start down-ranking museums because the content doesn’t meet its modern standards?

 

]]>
All source code now on Github https://ps1.soapyfrog.com/2014/06/05/grrr-source-code-now-on-github/ Thu, 05 Jun 2014 21:57:21 +0000 https://ps1.soapyfrog.com/?p=67 Gosh, it’s been a long time since I’ve thought about this, but recently I was playing around with svn2git and moved my repository.

Grr is now at http://github.com/soapyfrog/grrr and other misc scripts are at http://github.com/soapyfrog/miscps1 – feel free to do what you will with them, but note the CC license.

 

 

]]>
Grrr source code, including Invaders https://ps1.soapyfrog.com/2007/08/26/grrr-source-code-including-invaders/ https://ps1.soapyfrog.com/2007/08/26/grrr-source-code-including-invaders/#comments Sun, 26 Aug 2007 16:24:46 +0000 https://ps1.soapyfrog.com/2007/08/26/grrr-source-code-including-invaders/ As you may have noticed, there has been very little activity here from me in recent months.

This is partly because my full time work does not use nor need PowerShell and my free time has become more precious.

Playing with PS1 has been fun and I’ve learned a lot, but ultimately, it’s just a toy to me, and there comes a time when you must put your toys away — one might argue that, at nearly 40, I should have put my toys away long ago 🙂

Now, I’ve been inundated with literally 3 requests for the source code to Grrr, the snapin-based framework behind Big Invaders, so here it is:

Grrr source code

Like the rest of the stuff here, it’s released under the creative commons license.

So long, and thanks for all the fish.

]]>
https://ps1.soapyfrog.com/2007/08/26/grrr-source-code-including-invaders/feed/ 3
Google going down the pan https://ps1.soapyfrog.com/2007/04/01/google-going-down-the-pan/ Sun, 01 Apr 2007 07:36:16 +0000 https://ps1.soapyfrog.com/2007/04/01/google-going-down-the-pan/ Not PowerShell related in any way (unless you can think of something) but this did make me laugh.

http://www.google.com/tisp/

I especially like the FAQ on why it’s free 🙂

]]>
Cmdlet clashes https://ps1.soapyfrog.com/2007/03/06/cmdlet-clashes/ https://ps1.soapyfrog.com/2007/03/06/cmdlet-clashes/#comments Tue, 06 Mar 2007 09:56:22 +0000 https://ps1.soapyfrog.com/2007/03/06/cmdlet-clashes/ One of the things that struck me whilst developing Grrr as a snapin is: what do you do when you have a cmdlet with the same verb-noun pair as an existing cmdlet?

If someone else had a cmdlet called, say, out-banner, and that cmdlet was already loaded in a snap-in (perhaps mandated by site policy), would I be able to register and add the Grrr snapin, which also defines it?

I’ve scanned the available documentation and the language grammar, used introspection in the shell and so on, but could not find anything to deal with this problem.

With projects like PowerShell Community Extensions seemingly laying claim to hundreds of common nouns and verbs, I was concerned that the scope for writing unique cmdlets would dry up real fast.

To determine what would happen, I registered and added Soapyfrog.Grrr, then wrote a new snapin, Soapyfrog.Conflict, with a single cmdlet, out-banner, conflicting with the one in Grrr.

I registered and added this, and was surprised that no warning of a conflict was given. To see if both were added, I tried this:

PS> get-command out-banner

CommandType     Name                        Definition
-----------     ----                        ----------
Cmdlet          Out-Banner                  Out-Banner [-Text] <Str...
Cmdlet          Out-Banner                  Out-Banner [-Text] <Str...

Interesting. Both are available, so what happens when I try to invoke it?

PS> out-banner hello
The term 'out-banner' resolved to a cmdlet name that is ambiguous. Pos
sible matches include: Soapyfrog.Grrr\Out-Banner soapyfrog.conflict\Ou
t-Banner.
At line:1 char:11
+ out-banner  <<<< hello

OK, so at this point, we know it’s possible to break existing PowerShell scripts by simply registering and adding a new snapin with a same-named cmdlet. Not good. Is there a work-around?

PS> Soapyfrog.Grrr\out-banner hello -fg 'o'
o   o ooooo o     o      ooo
o   o o     o     o     o   o
ooooo ooo   o     o     o   o
o   o o     o     o     o   o
o   o ooooo ooooo ooooo  ooo

Yes! We can fully qualify the cmdlet name with the snapin name and a backslash.

So, it’s not as bad as I first feared, but as I noted above, you need to be very careful about how you code and run scripts in environments where you can’t predict what snapins are registered and installed.

I suppose you can create the correct shell environment with Export-Console and run your script with:

powershell -psconsolefile xxx.psc1 -noprofile -command myscript.ps1

Or if your script requires a snapin, add the snapin in the script and fully qualify each cmdlet you use.

]]>
https://ps1.soapyfrog.com/2007/03/06/cmdlet-clashes/feed/ 6
Grrr 1.1 and Big Invaders https://ps1.soapyfrog.com/2007/02/26/grrr-11-and-big-invaders/ https://ps1.soapyfrog.com/2007/02/26/grrr-11-and-big-invaders/#comments Mon, 26 Feb 2007 16:29:41 +0000 https://ps1.soapyfrog.com/2007/02/22/grrr-11-and-big-invaders/ So I’ve been spending a bit of time getting to grips with Cmdlets and resurrecting interest in PSInvaders using Grrr and now have something to post.

Grrr 1.1 is now Cmdlet based and comes as a Snap-In. The most obvious benefit from this is performance, as I can now present a playable version of PowerShell Big Invaders.

BigInvaders 1.1 in play

BigInvaders is one of the demo PowerShell scripts that makes use of the Grrr.

Download this prerelease version 1.1 of the Grrr snap-in.

Update: this should now install on Vista – thanks to Chris Warwick for pointing out some issues

There’s no installer (yet) so to get going, follow this instructions:

Unzip the archive where you want to use it and CD to the top level director where the README file is.

Type: ./installgrrr.ps1 -r

The -r switch forces it to re-register the snap-in if a (possibly) older version exists. It then adds the snap-in to the current shell.

From here you can CD into the demos directory and run any of the scripts. Each one shows a feature of Grrr, but perhaps the most interesting is in the biginvaders directory.

To run BigInvaders, you need to have a very large console. To achieve this you probably need to set the font size of your console window to 6×8.

If you want sound, you need to install DirectX DirectSound. More on why later.

It should work without, silently, but this hasn’t had much testing as all my XP boxes have it installed 🙂 If there are exceptions, start it with the -nosound switch.

Assuming all is well, type ./biginvaders.ps1 and you should see this title screen:

BigInvaders 1.1 intro screen

Hit ESC to quit or Space to play. In play, Space fires a missile and arrow keys move left and right. Hit F to toggle FPS display in the top-righthand corner.

The target FPS is 33. I achieve this easily on my MacPro, and my wife’s Dell (a core 1 duo, 1.66ghz) also just manages.

There are still a few snags to iron out here and I want to add proper PowerShell help and an installer, but it is functional.

I’ve learned a lot about C#, PowerShell SDK and .NET these last weeks and will write about my findings over the next days. It’s not all been rosy.

I’ll also be writing about the features of Grrr, and where I want to go with it.

That’s it for now.

]]>
https://ps1.soapyfrog.com/2007/02/26/grrr-11-and-big-invaders/feed/ 11
Grrr, Cmdlets and PSInvaders revival https://ps1.soapyfrog.com/2007/02/15/grrr-cmdlets-and-psinvaders-revival/ Thu, 15 Feb 2007 16:09:53 +0000 https://ps1.soapyfrog.com/2007/02/15/grrr-cmdlets-and-psinvaders-revival/ Still not much happening here, again partly due to being busy with other things, and also the final arrival of my Wii.

Anyways, I’ve almost completed the transition of Grrr to Cmdlets and it’s looking very promising as this screen shot shows (I get 50fps with only 20% cpu load doing this):

Big Invaders

I intend to redo the original PSInvaders using Grrr, with more authentic gameplay and original graphics.

The scrolling tilemap support is looking good, so games like Gauntlet, Scramble and Super Mario Brothers should be possible… all scripted in PowerShell.

So apologies for the low post volume recently and please do watch this space.

]]>
Slow week https://ps1.soapyfrog.com/2007/02/09/slow-week/ https://ps1.soapyfrog.com/2007/02/09/slow-week/#comments Fri, 09 Feb 2007 09:45:27 +0000 https://ps1.soapyfrog.com/2007/02/09/slow-week/ Not much happening here on the blog this week as I’ve been a bit busy with other things and also on some non-trivial PowerShell projects:

  • A snap-in version of Grrr – I realised that PowerShell alone is just too slow for it to be useful, so thought I’d have a go at doing it all as cmdlets in a snap-in. It’s fairly easy, but I’m not there yet.
  • In trying to understand the grammar of PowerShell better (the documentation is not so great, and Bruce hasn’t printed his book yet), I’ve started to write an interpreter in Java. I’ve got a more or less complete AST, and a prototype interpreter, but it’s slow going (well, I only started 4 days ago, and it’s in my spare time).

Watch this space.

]]>
https://ps1.soapyfrog.com/2007/02/09/slow-week/feed/ 2
IRC chat bot and monitor https://ps1.soapyfrog.com/2007/01/31/irc-chat-bot-and-monitor/ Wed, 31 Jan 2007 14:52:16 +0000 https://ps1.soapyfrog.com/2007/01/31/irc-chat-bot-and-monitor/ Last weekend, I asked my wife if she could think of anything inappropriate or unusual to do with PowerShell. She came up with some good ideas and one of them was to write a chat/IM client.

A full client takes time, so with a nod toward PowerShell’s administrative uses, I wrote a script that forms the basis of an IRC chat bot.

This script can be used to pipe messages to a chat channel and/or join a set of channels, returning all messages posted there.

I’ve sure most of you out there use Microsoft MSN Windows Live Messenger, or even Yahoo! or AOL, so this may just serve as an example of synchronous TCP/IP messaging in PowerShell.

You can download the script here: chat-irc.ps1.

You may need to unblock it according the the instructions in help about_signing.

Summary of use

This script operates in two modes, sender, or monitor (or both).

Regardless, you need to set up connection info in a hash, eg:

$coninfo = @{
  server="chat.freenode.net"
  port=6667
  nick="mynick"
  user="myuser"
  pwd="my password if required"
  realname="This is my real name"
  hostname"This is my host name, but is generally ignored"
}

💡 I’ve been using chat.freenode.net and my own local hybrid irc server for testing.

To send a message to the #test channel and quit:

chat-irc -coninfo $coninfo -sendto "#test" -message "Hello, world"

To send output from the pipeline, eg a file:

gc file.txt | chat-irc -coninfo $coninfo

To monitor a channel for messages:

chat-irc -coninfo $coninfo -monitor "#test"

This will stay connected until you ctrl+C, are killed by the server, etc, or if chat-irc is sent the message “stopstopstop”.

The output is formatted strings containing from/to/message, however these strings are annotated with noteproperties, so you can do:

chat-irc -coninfo $coninfo -monitor "#test" select *

The properties include sender info (user,host,nick,full), date, to and message.

These two modes can be used together, and the monitor parameter can take
more than one channel, so for example:

chat-irc -coninfo $coninfo -monitor "#foo","#bar" -sendto "#test" -message "hello"

will send “hello” to #test then monitor #foo,#bar and #test for messages.

By default, only messages sent to the monitored channel(s) are output, but you can include private messages with the switch -incprivate, the message of the day with -incmotd, notices with -incnotice and other with -incother.

You can see debug info with -debug and verbose output (all messages)
with -verbose. These latter switches just set the $DebugPreference and $VerbosePreference variables to “Continue” in the script’s scope See Debug and Verbose Colouring for more information on that.

Examples

Here we get chat-irc to monitor the channel #test2 whilst I (millinad) chat to it in a normal IRC chat client.

PS> chat-irc -coninfo $coninfo -monitor "#test2" | select date,nick,message|ft -wrap

date                         nick                        message
----                         ----                        -------
31/01/2007 14:21:20          millinad                    hello soapybot
31/01/2007 14:21:30          millinad                    nice to see you here
31/01/2007 14:21:38          millinad                    time for you to go now
31/01/2007 14:21:40          millinad                    stopstopstop

and in the chat client:

 * soapybot (n=soapybot@*******) has joined #test2
  hello soapybot
  nice to see you here
  time for you to go now
  stopstopstop
 * soapybot (n=soapybot@*******) has left #test2

Now lets do the same thing again, but with debug switched on and private messages enabled. We’ll turn off the pipeline formatting.

PS> chat-irc -coninfo $coninfo -monitor "#test2" -incprivate -debug
DEBUG: Using connection info:
DEBUG: server: chat.freenode.net
DEBUG: port: 6667
DEBUG: user: soapybot
DEBUG: nick: soapybot
DEBUG: pwd: ************
DEBUG: realname: powershell bot using soapyfrog inout-irc.ps1
DEBUG: hostname: localhost
freenode-connect : soapybot : ☺VERSION☺
DEBUG: I *may* have joined channel #test2
millinad : #test2 : hello again
millinad : #test2 : i see you received a ctcp message above. pity you don't understa
nd them.
millinad : #test2 : time to go again
millinad : soapybot : stopstopstop

In the last line, I sent soapybot a direct message to stopstopstop rather than to the channel. Without -incprivate this message would not have been output.

How it works

The script connects to the chat server using System.Net.Sockets.TcpClient. Messages are sent using a System.IO.StreamWriter with ASCII encoding. .NET doesn’t seem to mind of non ASCII chars are translated in this way.

Reading messages is done differently. We can’t use a System.IO.StreamReader, because ReadLine blocks if there isn’t a full line available.

We can’t use asynchronous reading because it’s quite hard to use scriptblocks as delegates (although that might change in future versions of PowerShell), and threading is a bit of an unknown quantity in PowerShell.

Instead I use the Net.Sockets.NetworkStream with its DataAvailable and ReadByte. This means I can check if data is available, and if not, idle or send messages, then check again. Reading byte by byte makes the code easier to read, and it’s not too big a performance hit, we’re bound by the network and the speed of people typing 🙂

Lines are processed in the process-line function where the line is parsed and checked for known numeric responses and commands.

The default handling of a message is in the function _onprivmsg where the message is just formatted and decorated and place into the output pipeline.

💡 If you wanted to have this bot do something else, you would do it here.

A good chat citizen

This script tries to be a good citizen by throttling it’s message sending with 1 second delays between messages. This is set with the -throttledelay parameter (milliseconds). The amount of time the script idles when there is no data from the server is 2 seconds, set with the -idledelay parameter.

Even with these values, it’s still possibly to be killed by a server for flooding. You may want to ask server admin to reduce the flood spec for your bot, or increase the throttledelay.

For example, at chat.freenode.net, piping the output from a directory listing would still cause a flood.

Enjoy 🙂

]]>
Debug and Verbose colouring https://ps1.soapyfrog.com/2007/01/29/debug-and-verbose-colouring/ https://ps1.soapyfrog.com/2007/01/29/debug-and-verbose-colouring/#comments Mon, 29 Jan 2007 17:59:05 +0000 https://ps1.soapyfrog.com/2007/01/29/debug-and-verbose-colouring/ Over the weekend, I set about writing an IRC chat client/channel monitoring tool in PowerShell (more on that in a day or so) and one of the things I was doing a lot was writing verbose and debug information to the console.

By default, Write-Verbose and Write-Debug cmdlets write nothing to the console, because the the value of the variables $VerbosePreference and $DebugPreference respectively are “SilentlyContinue”.

If you set them both to “Continue” the text is written to the console, but both in bright yellow on black (I wonder why?), like this:

PS> $DebugPreference="continue"
PS> $VerbosePreference="continue"
PS> write-debug "debug msg"
DEBUG: debug msg
PS> write-verbose "verbose msg"
VERBOSE: verbose msg

These colours can be changed so you can more easily distinguish between debug and verbose messages, and also not have the real output swamped.

The trick is to change the values of the colours in $host.privatedata, and I do this:

$defbg="darkmagenta"
$deffg="darkyellow"

# normal colours
$r=$host.ui.rawui
$r.BackgroundColor=$defbg
$r.foregroundColor=$deffg

$p=$host.privatedata
# error colours
$p.ErrorBackgroundColor=$defbg
$p.ErrorForegroundColor="red"

# warning colours
$p.WarningBackgroundColor=$defbg
$p.WarningForegroundColor="yellow"

# debug colours
$p.DebugBackgroundColor=$defbg
$p.DebugForegroundColor="darkgray"

# verbose colours
$p.VerboseBackgroundColor=$defbg
$p.VerboseForegroundColor="darkcyan"

# progress colours
$p.ProgressBackgroundColor="darkcyan"
$p.ProgressForegroundColor="yellow"

Now, the IRC app I’m working on, when I run with debug/verbose switched on, yields an output like this:

PS> test
DEBUG: Using connection info:
DEBUG: port: 6667
DEBUG: nick: soapybot
DEBUG: server: chat.freenode.net
DEBUG: hostname: localhost
DEBUG: user: soapybot
DEBUG: realname: inout-irc as soapybot
VERBOSE: >> NICK soapybot
VERBOSE: >> USER soapybot localhost chat.freenode.net :inout-irc as soapybot
VERBOSE: << NOTICE AUTH :*** Looking up your hostname...
VERBOSE: << NOTICE AUTH :*** Found your hostname, welcome back
VERBOSE: << NOTICE AUTH :*** Checking ident
VERBOSE: << NOTICE AUTH :*** No identd (auth) response
VERBOSE: << :brown.freenode.net 001 soapybot :Welcome to the freenode IRC Network 
soapybot
VERBOSE: << :brown.freenode.net 002 soapybot :Your host is 
brown.freenode.net[brown.freenode.net/6667], running version hyperion-1.0.2b
VERBOSE: << NOTICE soapybot :*** Your host is 
brown.freenode.net[brown.freenode.net/6667], running version hyperion-1.0.2b
VERBOSE: << :brown.freenode.net 003 soapybot :This server was created Fri Dec 22 
00:07:52 UTC 2006
VERBOSE: << :brown.freenode.net 004 soapybot brown.freenode.net hyperion-1.0.2b 
aAbBcCdDeEfFGhHiIjkKlLmMnNopPQrRsStTuUvVwWxXyYzZ01234569*@ bcdefFhiIklmnoPqstv
VERBOSE: << :brown.freenode.net 005 soapybot IRCD=dancer CAPAB CHANTYPES=# EXCEPTS INVEX
 CHANMODES=bdeIq,k,lfJD,cgijLmnPQrRstz CHANLIMIT=#:20 PREFIX=(ov)@+ MAXLIST=bdeI:50 
MODES=4 STATUSMSG=@ KNOCK NICKLEN=16 :are supported by this server
VERBOSE: << :brown.freenode.net 005 soapybot SAFELIST CASEMAPPING=ascii CHANNELLEN=30 
TOPICLEN=450 KICKLEN=450 KEYLEN=23 USERLEN=10 HOSTLEN=63 SILENCE=50 :are supported by 
this server
VERBOSE: << :brown.freenode.net 251 soapybot :There are 18601 listed and 16168 unlisted 
users on 24 servers
VERBOSE: << :brown.freenode.net 375 soapybot :- brown.freenode.net Message of the Day - 
VERBOSE: << :brown.freenode.net 372 soapybot :- Freenode is a service of Peer-Directed 
Projects Center, an
VERBOSE: << :brown.freenode.net 372 soapybot :- IRS 501(c)(3) not-for-profit 
organization.  Our yearly
VERBOSE: << :brown.freenode.net 372 soapybot :- fundraiser will begin soon; if you'd 
like to donate early,
VERBOSE: << :brown.freenode.net 372 soapybot :- please see 
http://freenode.net/pdpc_donations.shtml for more
VERBOSE: << :brown.freenode.net 372 soapybot :- information.  Thank you for using 
freenode!
VERBOSE: << :brown.freenode.net 372 soapybot :- 
VERBOSE: << :brown.freenode.net 376 soapybot :End of /MOTD command.
VERBOSE: >> JOIN #test,#test2,#archlinux
VERBOSE: << :freenode-connect!freenode@freenode/bot/connect PRIVMSG soapybot :☺VERSION☺
freenode-connect : soapybot : VERSION
VERBOSE: << :soapybot!n=soapybot@*********** JOIN :#test
DEBUG: We may have joined channel #test
VERBOSE: << :brown.freenode.net 332 soapybot #test :Welcome to #test - This channel is 
for testing only. Don't harass or annoy other users here. Don't paste senceless crap 
here. If you need a response for tests type '#say foobar' or '#moo' - Have a nice time 
in here... RIP lilo aka rob levin :'(
DEBUG: We have joined channel #test
VERBOSE: << :soapybot!n=soapybot@*************** JOIN :#test2
DEBUG: We may have joined channel #test2
VERBOSE: >> PRIVMSG #test2 :hello
VERBOSE: << :soapybot!n=soapybot@*************** JOIN :#archlinux
DEBUG: We may have joined channel #archlinux
VERBOSE: << :brown.freenode.net 332 soapybot #archlinux :[ Welcome to #archlinux! 
(!rules) || main: archlinux.org || forums: bbs.archlinux.org || wiki: wiki.archlinux.org
 || bugs: bugs.archlinux.org || AUR: aur.archlinux.org || iso: 
ftp://ftp.archlinux.org/other/0.8 ]
DEBUG: We have joined channel #archlinux
VERBOSE: << :schnappi!n=joy@debiancenter/user/schnappi PRIVMSG #test :Good after-noon, 
soapybot. It's 17:28h.GMT
schnappi : #test : Good after-noon, soapybot. It's 17:28h.GMT
VERBOSE: << :Danny|!n=Danny@89-172-171-230.adsl.net.t-com.hr PART #archlinux :"So Say We
 All."
VERBOSE: << :millinad!n=millinad@*************** PRIVMSG #test2 :hello 
soapybot
millinad : #test2 : hello soapybot
VERBOSE: << :millinad!n=millinad@*************** PRIVMSG #test2 :go now
millinad : #test2 : go now
VERBOSE: << :millinad!n=millinad@*************** PRIVMSG #test2 :wibble
millinad : #test2 : wibble
VERBOSE: >> PART #test2
VERBOSE: >> PART #archlinux
VERBOSE: >> PART #test
VERBOSE: >> QUIT :bye bye

(some of the above has been trimmed for clarity and privacy).

The brighter white output is the normal output from the script, the grey is debug messages and cyan, verbose. It gives me all the output I want, without making it too hard to pick out the real information.

Once I’m happy that all is well, I can revert the $VerbosePreference and $DebugPreference variables back to “SilentlyContinue” and all you get is the default white output.

]]>
https://ps1.soapyfrog.com/2007/01/29/debug-and-verbose-colouring/feed/ 2
Making functions *really* read-only https://ps1.soapyfrog.com/2007/01/26/making-functions-really-read-only/ https://ps1.soapyfrog.com/2007/01/26/making-functions-really-read-only/#comments Fri, 26 Jan 2007 10:24:34 +0000 https://ps1.soapyfrog.com/2007/01/26/making-functions-really-read-only/ Over at the excellent PowerShell Team Blog, Bruce Payette wrote about Controlling PowerShell Function (Re)Definition.

However, making a function constant does not prevent it from being shadowed in child scopes. Given that a child scope is created in any script, new function definition or script block, this makes it very unconstant.

Consider this:

# define a constant function, one that cannot be replaced
set-item function:/funca -option constant {
  write-host "this is the outer funca"
  # redefine the function in this new scope
  function funca {
    write-host "this is the inner funca"
  }
  # call this new funca
  funca 
}

# call the outer one
funca

If you run it, you will see that the inner funca is defined and executed. So much for being constant.

You can, however, make it a bit more permanent by adding the allscope option to the outer function, like this:

# define a constant function, one that cannot be replaced
set-item function:/funca -option constant,allscope {
  write-host "this is the outer funca"
  # redefine the function in this new scope - this will fail!
  function funca {
    write-host "this is the inner funca"
  }
}

# call the outer one
funca

When we run this, we get an error:

PS> funcs
this is the outer funca
Cannot write to function funca because it is read-only or constant.
At C:/Documents and Settings/adrian/My Documents/proj/ps1/funcs.ps1:5 char:17
+   function funca  <<<< {

Why? Because allscope copies the function to all child scopes that are created. The default behaviour, when finding a function (or variable) is to look in the current scope, then the parent, and so on up to global. By automatically copying the constant function to all scopes, you can prevent the function from ever being redefined.

So to make a function as constant as possible, define it with constant,allscope in your $profile.

PS. It appears that you can use scope modifiers with test-path. These two commands do seem to work, although I’ve not seen any documentation regarding it:

test-path function:/funca
test-path function:/script:funca

However, get-childitem function: only shows one.

]]>
https://ps1.soapyfrog.com/2007/01/26/making-functions-really-read-only/feed/ 2
Updated get-bufferhtml https://ps1.soapyfrog.com/2007/01/25/updated-get-bufferhtml/ https://ps1.soapyfrog.com/2007/01/25/updated-get-bufferhtml/#comments Thu, 25 Jan 2007 14:52:11 +0000 https://ps1.soapyfrog.com/2007/01/25/updated-get-bufferhtml/ A while back, I posted an article: Console screen grabs in html.

I fixed some bugs and added a couple of new features to the script get-bufferhtml.ps1, and have updated the article with examples.

Enjoy!

]]>
https://ps1.soapyfrog.com/2007/01/25/updated-get-bufferhtml/feed/ 2
Webserver and RSH in PowerShell https://ps1.soapyfrog.com/2007/01/24/webserver-and-rsh-in-powershell/ https://ps1.soapyfrog.com/2007/01/24/webserver-and-rsh-in-powershell/#comments Wed, 24 Jan 2007 12:57:45 +0000 https://ps1.soapyfrog.com/2007/01/24/webserver-and-rsh-in-powershell/ Ever wanted to control a PowerShell session from a web browser or curl/wget on another machine?

Yes? Well it surprisingly simple using PowerShell to script the System.Net.HttpListener. Here’s a working example with some genuine uses (well useful for me).

I’ll leave all the security and risk concerns as an exercise for the reader 🙂

What we have here is a small PowerShell script, httpd.ps1, that listens on a port of your choosing (default 8888) using the HTTP protocol, executes supplied PowerShell expressions, the returns the pipeline output to the caller.

To use it, type this in a PowerShell window:

./httpd

This will set the web server listening on http://yourhostname:8888/. You can change this to be something else by supplying a prefix as a parameter, eg:

./httpd http://192.168.0.28:8888/

or safer (in case it crashes)

powershell -command ./httpd http://192.168.0.28:8888/

This parameter must end in a slash.

You’ll need to open the appropriate port in your firewall, if you intend to try to use this from a different machine.

Once running (and using that example above) you can enter that url into your web browser, and the response you’ll get should be something like:

No command supplied.

Syntax is: http://server/?cmd=xxxx

Where xxxx is 'quit' to tell the server to quit
or any PowerShell command.

Eg:  http://server/?cmd=get-process

You can see from this that you need to supply a command. Try this:

http://192.168.0.28:8888/?cmd=get-process

What you get back is a process listing for the host machine.

I use this mostly with the command line tool curl to get command output on my Mac, eg:

macpro:~ adrian$ curl -g 'http://192.168.0.21:8888/?cmd=ps|where%20{$_.ws%20-gt%2010mb}'

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    836      15    42864      55092   236     8.58   3440 dexplore
    512      14    15736      27316    94    17.20   1512 explorer
    192       6    16092      11160   126     0.12   2748 httpd.vshost
    657      17    20224      31776   112    10.32   3792 iexplore
    419      14     6680      11564    75     9.12   1412 KService
   1004       6    45232      43740   156     2.93   3324 powershell
    185       5    22108      28624   126     0.54   3368 powershell
    163       7    35812      34668   138     1.74   3640 powershell
   1588      57    45812      54516   231   495.46    808 svchost

You have to escape the URL for curl, but this executed ps|where {$_.ws -gt 10mb} (all processes with a working set greater than 10mb).

Note that this script does not show you the output from write-host or any errors, but if you ask for $Error you will get the recent errors returned.

An alternative would be to modify the script to use get-bufferhtml to return a full copy of the PowerShell buffer.

Anyways, I learned how easy it is to write a mini web server in .NET and PowerShell, so I’m happy 🙂

Oh, one last thing. To stop the script, send it a cmd=quit. You could just ctrl+break in the PowerShell window, but I find that causes the whole host to disappear.

]]>
https://ps1.soapyfrog.com/2007/01/24/webserver-and-rsh-in-powershell/feed/ 1
Running pipelines in the background https://ps1.soapyfrog.com/2007/01/22/running-pipelines-in-the-background/ Mon, 22 Jan 2007 14:34:18 +0000 https://ps1.soapyfrog.com/2007/01/22/running-pipelines-in-the-background/ In the unix world, we’re used to being able to run the different commands in a pipeline in different threads/processes. This is usually a lot more efficient when the producer/consumer rates vary, and makes use of multiple cores/cpus.

For example, cmd1 | cmd2 will run the two commands in separate processes.

PowerShell doesn’t do this. Everything runs in one thread, and pipelined objects are processed in batches, one bit at a time. You can control the batch size with the -outBuffer parameter, but things are still done sequentially, with one command in the pipe being busy whilst all others are sitting idle.

Even the venerable CMD.exe will put these two commands tree | more into separate processes.

This aside, what about simply running an arbitrary command (or scriptblock) in the background whilst doing something else?

PowerShell doesn’t have any obvious way to do this, but it is possible with runspaces. You can create a new runspace and then invoke a pipeline asynchronously.

Here is an example script, but lets go through it step by step.

$rscfg = [management.automation.runspaces.runspaceconfiguration]::Create()
$rs=[management.automation.runspaces.runspacefactory]::CreateRunspace($rscfg)
$rs.Open()

Here, we create a runspace with a default configuration. There is an overloaded version of CreateRunspace that takes a PSHost object, so we could pass in $host. In this case we just use the default. We then open the runspace.

$block = {
  $sum=0
  "adding numbers in background!"
  foreach($i in $input) {
    $sum+=$i 
    start-sleep 1 # pretent it takes ages to compute this
    "adding number $i"
  }
  "that's it, sum is $sum"
}
$pipe=$rs.CreatePipeline($block)

Here we create the scriptblock $block that we want to run in the background and create a pipeline $pipe for it. The block itself simply takes it time adding up numbers passed to it, yielding textual information to the pipe, ending with the result.

$writer = $pipe.Input
$pipe.InvokeAsync()

Here we simply grab hold of the pipe’s input then invoke it asynchronously.

$numwritten = $writer.Write(1..5,$true)
$writer.Close()

This is where we give the background pipe some data to play with. Write(1..5,$true) means write the numbers 1 through 5 into the pipeline ($true means send the numbers one at a time instead of all at once).

1..3 | foreach { start-sleep 1; "busy in foreground $_" }

The whole purpose of this example is to show how two different things can be done at once, so here we simply spend 3 seconds pretending to be busy 🙂

$reader = $pipe.Output
while (-not $reader.EndOfPipeline) {
  $o = $reader.Read()
  write-host "$o"
}

Here we get the output $reader from the pipeline and whilst there is data, read an object and display it.

We didn’t have to do it this way; we could have read the whole thing in one go like this: $out = $reader.ReadToEnd(). The latter might be better if the background work produces a single result, but the line-by-line version may suit something with a lot of output. Although we simple do a write-host "$o" here, this could be a lengthy operation that would run whilst the background operation continues to do work.

$pipe.Error.ReadToEnd()
$pipe.Dispose()
$rs.Close()

Finally we consume any error output and clean up.

If you run the example script, you will see something like this:

busy in foreground 1
busy in foreground 2
busy in foreground 3
adding numbers in background!
adding number 1
adding number 2
adding number 3
adding number 4
adding number 5
that's it, sum is 15

This is great, but why is this post categorised as a rant? Well, it’s very long-winded and in my mind, async job scheduling is something that all shells should do.

It’s a pity PowerShell doesn’t let you do something like this:

{ foo | bar ; wibble}.InvokeAsync()

or

invoke-command -async { foo | bar ; wibble }

You can do this, however:

{ foo | bar ; wibble}.Invoke()

So how would all this be used? Would it make space invaders any quicker on a core duo pc? Only a profiler would know.

A single runspace can only have one asynchronous pipeline running and the pipeline cannot be reused. The setup costs are quite high, so you’d probably have to mess about with a single background pipeline reading work requests and writing them back.

]]>
Banners https://ps1.soapyfrog.com/2007/01/19/banners/ Fri, 19 Jan 2007 14:37:46 +0000 https://ps1.soapyfrog.com/2007/01/19/banners/ In the old days, when you printed something out, you’d have to wander down to the print room and find your output in a stack of fanfold with the job name printed as a large banner on the top. I miss those days so I wrote a banner script to do this:

banner screenshot

It’s a script, so execute it directly. It takes a string (or array of strings) as the first argument and two optional parameters, -fg char to set the foreground character and -bg char for the background character. The defaults are a solid block and a space. For example:

PS> banner "hello","world" -fg "/"
/   / ///// /     /      ///
/   / /     /     /     /   /
///// ///   /     /     /   /
/   / /     /     /     /   /
/   / ///// ///// /////  ///

/   /  ///  ////  /     ////
/   / /   / /   / /     /   /
/ / / /   / ////  /     /   /
// // /   / /   / /     /   /
/   /  ///  /   / ///// ////

PS>

You can download the script here: banner.ps1.

Don’t copy/paste this – save it directly from the above link. It contains formatted text that may get corrupted.

Enjoy!

[Update] The script will also take input from the pipeline so you can do things like:

[enum]::getnames([consolecolor]) | where { $_ -notlike "dark*"} | banner -fg "#"

to get this:

               
####  #      ###   ###  #   #                                                                             
#   # #     #   # #   # #  #                                                                              
####  #     ##### #     ###                                                                               
#   # #     #   # #   # #  #                                                                              
####  ##### #   #  ###  #   #                                                                             
                                                                                                          
 ###  ####   ###  #   #                                                                                   
#     #   # #   #  # #                                                                                    
#  ## ####  #####   #                                                                                     
#   # #   # #   #   #                                                                                     
 ###  #   # #   #   #                                                                                     
                                                                                                          
####  #     #   # #####                                                                                   
#   # #     #   # #                                                                                       
####  #     #   # ###                                                                                     
#   # #     #   # #                                                                                       
####  #####  ###  #####                                                                                   
                                                                                                          
 ###  ####  ##### ##### #   #                                                                             
#     #   # #     #     ##  #                                                                             
#  ## ####  ###   ###   # # #                                                                             
#   # #   # #     #     #  ##                                                                             
 ###  #   # ##### ##### #   #                                                                             
                                                                                                          
 ###  #   #  ###  #   #                                                                                   
#   #  # #  #   # ##  #                                                                                   
#       #   ##### # # #                                                                                   
#   #   #   #   # #  ##                                                                                   
 ###    #   #   # #   #                                                                                   
                                                                                                          
####  ##### ####                                                                                          
#   # #     #   #                                                                                         
####  ###   #   #                                                                                         
#   # #     #   #                                                                                         
#   # ##### ####                                                                                          
                                                                                                          
#   #  ###   ###  ##### #   # #####  ###                                                                  
## ## #   # #     #     ##  #   #   #   #                                                                 
# # # ##### #  ## ###   # # #   #   #####                                                                 
#   # #   # #   # #     #  ##   #   #   #                                                                 
#   # #   #  ###  ##### #   #   #   #   #                                                                 
                                                                                                          
#   # ##### #     #      ###  #   #                                                                       
 # #  #     #     #     #   # #   #                                                                       
  #   ###   #     #     #   # # # #                                                                       
  #   #     #     #     #   # ## ##                                                                       
  #   ##### ##### #####  ###  #   #                                                                       
                                                                                                          
#   # #   #  ###  ##### #####                                                                             
#   # #   #   #     #   #                                                                                 
# # # #####   #     #   ###                                                                               
## ## #   #   #     #   #                                                                                 
#   # #   #  ###    #   #####                                                                             
                                                                                                                                                                        
]]>