Update (13/12/2007): The contents of this post have since been largely superseded by the release of PowerShell cmdlets for WebSphere MQ.
PowerShell is Microsoft’s new command line. Released last year, it introduced a number of enhancements over the traditional Windows Command Prompt, including a novel object-oriented approach.
I won’t go into the background about PowerShell – if you’re interested, a quick search will turn up masses of information, everything from detailed guides to the first impressions of obscure bloggers!
One of the more interesting features is the ability to access the .NET API – directly from the command line. So I thought it would be interesting to point out that with PowerShell, the .NET bindings available for WebSphere MQ means that you can interact with queue managers from the command line.
It means that pretty much anything that you could do with WMQ from a .NET application can now be done from the command line.
For example, putting a message to a queue on a local queue manager…
The first (and only tricky) thing you need to do is load the WebSphere MQ DLL into PowerShell:
[System.Reflection.Assembly]::LoadFrom("C:\\Program Files\\IBM\\WebSphere MQ\\bin\\amqmdnet.dll")
If you do this right, it prints out an entry showing the registered DLL.
From then on, it’s much like typical C# programming, with slightly different syntax for object constructors:
$qmgr = new-object IBM.WMQ.MQQueueManager("DALES_QMGR")
$queue = $qmgr.AccessQueue("QUEUE_1", 49)
$mymessage = new-object IBM.WMQ.MQMessage
$mymessage.WriteUTF("Hello Dale. I was sent from the PowerShell")
$queue.Put($mymessage)
(The more observant of you might notice that I cheated slightly – using ’49’ for the queue’s open options. This was made up from: MQOO_INPUT_AS_Q_DEF (0x00000001), MQOO_OUTPUT (0x00000010), and MQOO_INQUIRE (0x00000020). I’m sure that there is a way to get these constants in the Shell as well, but at first glance I haven’t spotted how.)
You could then get the message back, like this:
$my2ndmessage = new-object IBM.WMQ.MQMessage
$queue.Get($my2ndmessage)
$msgstring = $my2ndmessage.ReadUTF()
echo $msgstring
I’ve kept to the smallest API calls to keep the example as simple as possible. But you could make them as complicated as you want. For example, you could add get-options so that the MQGET call blocks until a message arrives, giving you something like this:
[System.Reflection.Assembly]::LoadFrom("C:\\Program Files\\IBM\\WebSphere MQ\\bin\\amqmdnet.dll")
$qmgr = new-object IBM.WMQ.MQQueueManager("DALES_QMGR")
$queue = $qmgr.AccessQueue("QUEUE_1", 49)
$mymessage = new-object IBM.WMQ.MQMessage
$mygetoptions = new-object IBM.WMQ.MQGetMessageOptions
$mygetoptions.Options = 1
$mygetoptions.WaitInterval = -1
$queue.Get($mymessage, $mygetoptions)
And the last Get
call will block until a message is available on the queue.
When a message arrives, the call completes and a prompt appears on the next line, letting you display the message as before:
echo $mymessage.ReadUTF()
(As before, I’ve cheated again with the constants, using 1 to indicate a get option with wait, and 1 to indicate an unlimited wait.)
This opens up the chance for some very powerful scripting in WebSphere MQ environments, without needing applications that need compiling and so on. For simple tasks, it could be a useful alternative to writing applications that need re-compiling after changes.
I’m not sure if there will be a big demand for this, but I thought it was pretty cool anyway! 🙂
14 comments
Comments feed for this article
February 12, 2007 at 9:27 am
Andy Piper
Very funky.
I think the syntax is a little too longhand – why wouldn’t you just compile yourself the equivalent C# program?
Nevertheless, a very useful tip.
February 12, 2007 at 7:29 pm
Jeffrey Snover
> I think the syntax is a little too longhand – why wouldn’t you just compile yourself the equivalent C# program?
There are a ton of things you can do from PowerShell like leverage its object utilities and formatting. The point about the syntax being longhand is right except that what you would actually do is to write a function which gave you access to this function in a shorthand way and then this could would be the implementation code for that function. e.g.
PS> Read-MQMessage DALES_QMGR QUEUE_1
Jeffrey Snover [MSFT]
Windows PowerShell/Aspen Architect
Visit the Windows PowerShell Team blog at: http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at: http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx
February 13, 2007 at 7:33 am
People Over Process » Blog Archive » links for 2007-02-13
[…] WebSphere MQ scripting using PowerShell Using PowerShell as a CLI to MQ. (tags: powershell websphere mq ibm msft via:JamesGovernor scripting redmonkclients .net windows cli) […]
February 13, 2007 at 12:18 pm
protocol7 » Blog Archive » links for 2007-02-13
[…] WebSphere MQ scripting using PowerShell (tags: wmq .net powershell by:dale_lane) […]
February 14, 2007 at 6:27 pm
Ian Edwards
Just reading through your update, aren’t those constants available in:
IBM.WMQ.MQC.MQOO_INPUT_AS_Q_DEF,
IBM.WMQ.MQC.MQOO_OUTPUT and
IBM.WMQ.MQC.MQOO_INQUIRE
Also, to reduce the size of this script, does it PowerShell allow for a ‘using’ keyword, so ‘using IBM.WMQ’ would mean the removal of IBM.WMQ throughout the rest of the script… Never played with it, just thinking out loud.
February 15, 2007 at 9:18 am
Ian Edwards
Just noticed, your PowerShell link is broken, try:
http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx
February 15, 2007 at 9:46 am
Dale Lane
Fixed it – thanks!
February 16, 2007 at 1:03 am
Dale Lane
Jeffrey – thanks, it’s a good point.
For completeness, this could give me:
function Put-WMQMessage
{
$myMsgText = $args[0]
$myQueue = $args[1]
$myQueueManager = $args[2]
[System.Reflection.Assembly]::LoadFrom("C:\Program Files\IBM\WebSphere MQ\bin\amqmdnet.dll")
$qmgr = new-object IBM.WMQ.MQQueueManager($myQueueManager)
$myoptions = 49
$queue = $qmgr.AccessQueue($myQueue, $myoptions)
$mymessage = new-object IBM.WMQ.MQMessage
$mymessage.WriteUTF($myMsgText)
$queue.Put($mymessage)
}
function Get-WMQMessage
{
$myQueue = $args[0]
$myQueueManager = $args[1]
[System.Reflection.Assembly]::LoadFrom("C:\Program Files\IBM\WebSphere MQ\bin\amqmdnet.dll")
$qmgr = new-object IBM.WMQ.MQQueueManager($myQueueManager)
$myoptions = 49
$queue = $qmgr.AccessQueue($myQueue, $myoptions)
if ($queue.CurrentDepth -gt 0)
{
$mygetoptions = new-object IBM.WMQ.MQGetMessageOptions
$mygetoptions.Options = 1
$mygetoptions.WaitInterval = -1
$mymessage = new-object IBM.WMQ.MQMessage
$queue.Get($mymessage, $mygetoptions)
echo $mymessage.ReadUTF()
}
else
{
echo "Queue is empty."
}
}
Put-WMQMessage "Hello Dale" SYSTEM.DEFAULT.LOCAL.QUEUE TESTQMGR
Get-WMQMessage SYSTEM.DEFAULT.LOCAL.QUEUE TESTQMGR
February 16, 2007 at 1:13 am
Dale Lane
Ian – yeah, I saw the constants like IBM.WMQ.MQC.MQOO_INPUT_AS_Q_DEF, except I can’t figure out how to get them into PowerShell
Same with ‘using’ – I’m sure it’s possible, but I haven’t quite worked out the syntax yet.
If anyone else works it out first, please let me know!
February 17, 2007 at 7:16 am
Jeffrey Snover
That is MUCH better! Here are a couple of ideas you might use. You can certainly use $args – there is nothing wrong with that but you can also name the parameters like this:
function Put-WMQMessage($myMsgText, $myQueue, $myQueueManager)
{
[System.Reflection.Assembly]::LoadFrom(“C:\Program Files\IBM\WebSphere MQ\bin\amqmdnet.dll”)
$qmgr = new-object IBM.WMQ.MQQueueManager $myQueueManager
$myoptions = 49
$queue = $qmgr.AccessQueue($myQueue, $myoptions)
$mymessage = new-object IBM.WMQ.MQMessage
$mymessage.WriteUTF($myMsgText)
$queue.Put($mymessage)
}
Declaring the parameters gives you 2 benefits:
1) You can declare a TYPE of the parameter and we’ll do the type validation and/or coercion for you.
2) you can support positional or NAMED parameters. for instance, all of the following are the same:
ps> Put-WMQMessage “hello Dale” SYSTEM.DEFAULT.LOCAL.QUEUE TESTQMGR
ps> Put-WMQMessage -MyMsgText “hello Dale” -MyQueue SYSTEM.DEFAULT.LOCAL.QUEUE -MyQueueManager TESTQMGR
ps> Put-WMQMessage -MyQueueManager TESTQMGR -MyQueue SYSTEM.DEFAULT.LOCAL.QUEUE -MyMsgText “hello Dale”
Also – be aware that NEW-OBJECT is a command not a function so the correct usage is:
$qmgr = new-object IBM.WMQ.MQQueueManager $myQueueManager
Cheers!
BTW – I’m happy to see you guys kicking the tires on PowerShell. I became a huge fan of the MQ team when I was in the CTO office at Tivoli. I’d love to hear any ideas you have to make things better.
Jeffrey Snover [MSFT]
Windows PowerShell/MMC Architect
Visit the Windows PowerShell Team blog at: http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at: http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx
February 19, 2007 at 2:58 pm
Dale Lane
Thanks Jeffrey, that’s useful
I saw a comment on the All About Interop blog which talks about the benefits of a powershell library for WMQ. I guess this would be a good way to ease new users into simple administration without needing to get too into the WMQ .NET API.
I think I’ve got my head around commands now – and want to try playing with the different ways PowerShell lets me play with output produced. Even just giving an object reference and getting a dump of all of it’s variables is a nice start:
$qmgr = new-object IBM.WMQ.MQQueueManager $qmgrName
$queue = $qmgr.AccessQueue($queueName, $myoptions)
$queue
AlterationDateTime : 18/02/2007 17:24:07
BackoutRequeueName :
BackoutThreshold : 0
BaseQueueName :
ClusterName :
ClusterNamelistName :
CreationDateTime : 18/02/2007 17:24:07
CurrentDepth : 0
DefaultBind : 0
DefaultInputOpenOption : 2
DefaultPersistence : 0
DefaultPriority : 0
DefinitionType : 1
DepthHighEvent : 0
DepthHighLimit : 80
DepthLowEvent : 0
DepthLowLimit : 20
DepthMaximumEvent : 1
Description :
DistributionLists : 0
DynamicQueueName : AMQ.*
.
.
.
And I just found that by accident. I’ll have to have a go at creating some queries for common tasks.
April 17, 2007 at 12:20 pm
WebSphere MQ scripting using PowerShell - part 2 « a Hursley view on WebSphere MQ
[…] – the new Windows command shell and scripting language. It was a useful reminder that I had said that I was going to look into writing some useful PowerShell functions for WebSphere MQ, so last night I had a quick play to see what I could do with […]
April 17, 2007 at 12:27 pm
Dale Lane
Many of the questions still unanswered in this post (such as how to access constants like IBM.WMQ.MQC.MQOO_INPUT_AS_Q_DEF) are addressed in my follow-up post.
Dale
October 22, 2007 at 12:34 am
learning something new » Blog Archive » An introduction to Windows PowerShell
[…] be good to address some of the misunderstandings I had about PowerShell when I wrote about it before. In the presentation, I will be giving an introduction to Windows PowerShell – what is it, […]