Saturday, October 30, 2010

Perl action indicator using Term::Cap

If you are wondering how to make one of those whirling "I'm doing something" indicator on a screen in Perl, here is some code that will get you going. There are many libraries out there, but for those of you in companies where they won't let you use just any old CPAN library, here is a Termcap version which is standard with all Unix/Linux distributions of Perl.

use Term::Cap;
use POSIX;

# Load terminal IO library
my $termios = new POSIX::Termios;
# Get terminal settings
$termios->getattr;
# Get terminal speed
my $ospeed = $termios->getospeed;

$|=1;
$terminal = Tgetent Term::Cap { TERM => undef, OSPEED => $ospeed };
$terminal->Trequire(qw/ce ku kd/);

# Array for spinning thingy
my @seq=qw(| / - | \ -);
my $count=0;

# Position on the screen left to right (0 being left of screen)
my $x = 0;
# Position on the screen top to bottom (0 being top of screen)
my $y = 10;

while (1)
{
$terminal->Tputs('cl',1,*STDOUT); # Clear screen
$terminal->Tputs('cd',1,*STDOUT); # Clear data

# Set cursor position on screen
$terminal->Tgoto('cm',$x,$y,*STDOUT);
# Print one of the chars | / - \
print "$seq[$count++]";
sleep 1;
if ( $count > 5 )
{
$count = 0;
}
}

Friday, October 29, 2010

Interactive Password on Console app with C#

If you've ever used C# for application development and needed to get a password into your program but don't want to display it to the screen, you'll realise that you will need to use some COM objects and kernel functionality.
This simple example provides you with a template to get the password from a user without displaying on the screen what they typed, and also accepting the backspace key when they press it.
The code;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace FirstOne
{
class Program
{
// Get the kernel function for setting console modes
[System.Runtime.InteropServices.DllImport("kernel32 ")]
private static extern int SetConsoleMode(IntPtr hConsoleHandle, int dwMode);
// Get the kernel function for getting console modes
[System.Runtime.InteropServices.DllImport("kernel32 ")]
private static extern int GetConsoleMode(IntPtr hConsoleHandle, ref int dwMode);

// Some useful constants for the console values
private const int ENABLE_LINE_INPUT = 2;
private const int ENABLE_ECHO_INPUT = 4;
// Standard input file handle
private const int CONIN = 3;

// Ensure that our process is single threaded as we as using COM and need to ensure communication
[STAThread]
static void Main(string[] args)
{
IntPtr hStdIn = new IntPtr(CONIN);
int myMode=0;
char inputChar;
string password = "";
Console.Write("Password: ");
// Get the current console settings
GetConsoleMode(hStdIn, ref myMode);
// Turn off echo
myMode = (myMode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT));
SetConsoleMode(hStdIn, myMode);

do
{
inputChar = (char)Console.Read();
if (inputChar == '\b') // Can also use 8 instead of '\b'
{
// Delete character if user has pressed backspace
password=password.Remove(password.Length-1);
}
if (inputChar >= 32)
{
// Store password characters
password += inputChar;
}
} while (inputChar != '\r');

// Reset terminal echo
myMode = (myMode | (ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT));
SetConsoleMode(hStdIn, myMode);
Console.WriteLine("");
Console.WriteLine("Password was: {0}", password);
}
}
}

Tracing a Web Reference

  1. First you will need SvcTraceViewer.exe which should be some where similar to;
    C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SvcTraceViewer.exe
  2. Add your Web Reference to the project and code as normal
  3. To trace the service you will need to modify your app.Config file
The essential parts required to get a trace that can be viewed with SvcTraceViewer are;
  • <diagnostics> section which should be added after the <system.servicemodel> tag and before the <bindings> tag

<diagnostics>messagelogging logentiremessage="true"
logmalformedmessages="true" logmessagesatservicelevel="true"
logmessagesattransportlevel="true" maxmessagestolog="100"
maxsizeofmessagetolog="10000000"</diagnostics>

  • After the </system.serviceModel> tag you should then add the following <system.Diagnostics> section

<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Information,ActivityTracing" propagateActivity="true">
<listeners>
<add name="xml" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging" switchValue="All" propagateActivity="true">
<listeners>
<add name="xml" />
</listeners>
</source>
</sources>
<sharedListeners>
<add initializeData="c:\abc.svclog" type="System.Diagnostics.XmlWriterTraceListener" name="xml" />
</sharedListeners>
<trace autoflush="true" />
</system.diagnostics>

  • Run your application and then locate your c:\abc.svclog file
  • Note that you should name and locate the initializeData attribute in a sensible location and a meaning full name.

Wednesday, October 27, 2010

Dynamic Perl Subroutines

You've got a set of subroutines that take similar numbers of parameters, but need to call a different constructor from different modules which use OO Perl. Here is an example of how that can be done using dynamic Perl subroutines.


---------- mod1.pm ----------
package mod1;

sub new
{
my ($modname,$a,$b) = @_;
print "In module 1\n";
return bless {'a'=>"$a","b"=>"$b"};
}

1;

---------- mod2.pm ----------
package mod2;

sub new
{
my ($modname,$a,$b) = @_;
print "In Module 2\n";
return bless {'a'=>"$a","b"=>"$b"};
}

1;


---------- main program -----
#!/usr/bin/perl

use mod1;
use mod2;

sub declared
{
my $module = shift;
# $cmd contains the code which will be the body of our subroutine
$cmd="my (\$name, \$fullname) = \@_; $module(\$name, \$fullname);";
# perform and evaluation on $cmd so that it becomes an anonymous subroutine reference
$cmd = eval("sub { $cmd };");
# return the subroutine reference (a normal Perl thing)
return $cmd;
};

# Create a subroutine reference that calls the new method from mod1
my $campus=declared("new mod1");
# Create a subroutine reference that calls the new method from mod2
my $camp=declared("new mod2");
# Now call the 2 subroutines from the different modules
my $f=&$campus("Module 1","blah blah");
my $g=&$camp("Module 2","more blah");
# Show that we did get different results from the 2 methods
print "f: ",$f->{a}," and ",$f->{b},"\n";
print "g: ",$g->{a}," and ",$g->{b},"\n";


What fun was that. Now you are all going to want to go away and reduce your code :-)

Monday, October 25, 2010

Temporarily closing STDERR in Perl

Someone asked me how to get rid of a STDERR message being printed from a Perl module as it was being annoying to the program that they were writing. But also what a pain that the module was writing the errors!

Anyway, the simple emulation of the module was to make it print to STDERR. Here's the module code (module called p.pm);

---------------- p.pm ---------------------------
package p;

sub dothis
{
print STDERR "There's a problem";
return 2;
}

1;
---------------- p.pm ---------------------------


The program code that temporarily prevents the STDERR from being displayed is as follows;

---------------- stopstderr ---------------------------
#!/usr/bin/perl
# using perl 5.8

use p;

# Open a new file handle to remember where STDERR really points to
open (OLDER, ">&", \*STDERR) || die "Can't dup stderr";
close STDERR;
# Repoint STDERR to null
open (STDERR, ">/dev/null") || die "Can't remap STDERR";
print "No message here: ";
# No message printed from the module
my $s=p->dothis();
print "\n";
print "Return value is $s\n";
print "Trying to print to STDERR directly: ";
# No output printed to STDERR so next line goes to /dev/null
print STDERR "Can you see this?\n";
print "\n";
close STDERR;
# Repoint STDERR to where it normally goes
open (STDERR, ">&", \*OLDER) || die "Can't repoint STDERR";
close OLDER;
# Ensure that everything prints out when expected
select STDERR; $| = 1;
select STDOUT; $| = 1;
# Everything is happy again
print "Now STDERR is back, message here: ";
print STDERR "Cool :-)\n";

---------------- stopstderr ---------------------------

What fun :-)

Perl writing STDERR to a variable

Further to the problem of preventing STDERR from being displayed we wanted to capture the error message in a variable.

---------------- p.pm ---------------------------
package p;

sub dothis
{
print STDERR "There's a problem";
return 2;
}

1;
---------------- p.pm ---------------------------


The program code that temporarily prevents the STDERR from being displayed is as follows;

---------------- stopstderr ---------------------------
#!/usr/bin/perl
# using perl 5.8

use p;

# Open a new file handle to remember where STDERR really points to
open (OLDER, ">&", \*STDERR) || die "Can't dup stderr";
close STDERR;
# Repoint STDERR to a memory location so that we can capture the error message
open (STDERR, ">", \$var) || die "Can't remap STDERR";
print "No message here: ";
# No message printed from the module
my $s=p->dothis();
print "\n";
print "Return value is $s\n";
print "Trying to print to STDERR directly: ";
# No output printed to STDERR so next line goes to /dev/null
print STDERR "Can you see this?\n";
print "\n";
close STDERR;
# Let's print our the message captured in the variable $var even though we closed STDERR
print "The captured error message: $var\n";
# Repoint STDERR to where it normally goes
open (STDERR, ">&", \*OLDER) || die "Can't repoint STDERR";
close OLDER;
# Ensure that everything prints out when expected
select STDERR; $| = 1;
select STDOUT; $| = 1;
# Everything is happy again
print "Now STDERR is back, message here: ";
print STDERR "Cool :-)\n";

---------------- stopstderr ---------------------------


What fun :-)

Example of querying an object from WMI in C#

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Data;
using System.Net;
using System.Net.NetworkInformation;
// These next 2 lines can only be used if you have included a Project --> Reference to System.Management
using System.Management;
using System.Management.Instrumentation;

namespace Test1 {
class Program {
static void Main(string[] args) {
Console.Write("Please enter your name: ");
string name = Console.ReadLine();
Console.WriteLine("Hello {0}", name);
Console.ReadLine();

// Set up the connection to the host
ConnectionOptions oConn = new ConnectionOptions();
//oConn.Username = "";
//oConn.Password = "";
System.Management.ManagementScope oMs = new System.Management.ManagementScope("\\\\WIN-V31ZRUWURFW\\root\\cimv2", oConn);

// Set the query to run
System.Management.ObjectQuery oQuery = new System.Management.ObjectQuery("SELECT * FROM Win32_Desktop");

ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(oMs, oQuery);

// Get results
ManagementObjectCollection oReturnCollection = oSearcher.Get();

foreach (ManagementObject oReturn in oReturnCollection)
{
if ( oReturn["Name"].ToString() == "WIN-V31ZRUWURFW\\Administrator" )
{
Console.WriteLine("Name: {0}", oReturn["Name"].ToString());
Console.WriteLine("ScreenSaver: {0}", oReturn["ScreenSaverExecutable"].ToString());
try {
Console.WriteLine("Wallpaper: {0}", oReturn["Wallpaper"].ToString());
} catch (NullReferenceException e) {
Console.WriteLine("Wallpaper: None installed");
}
}
}
Console.Read();
}
}
}