Posts Tagged ‘Programming’

How do I – Validate user input is numeric from Powershell?

Written by Cornelius J. van Dyk on . Posted in Blog

As the level of complexity and power of our Powershell scripts increase, it is inevitable that we reach a point where we need to interact with the user and prompt them for some information.  In this case we were building a script to automate the creation and scaling of Search so we needed to know how many servers would be configured as Crawl servers.  We all know the Read-Host cmdlet can provide us with the input, but how do we know that the user actually entered numeric only data?  The easiest way is to simply use a try/catch block and attempt to convert the input to an int value.  Here’s how we do that:

$numberOfCrawl = 0
$inputOK = $false
do
{
  try
  {
    [int]$numberOfCrawl = Read-Host -ForegroundColor red "Please enter the number of servers you wish to configure as Crawl servers."
    $inputOK = $true
  }
  catch
  {
    Write-Host -ForegroundColor red "INVALID INPUT!  Please enter a numeric value."
  } 
}
until ($inputOK)
Write-Host –ForegroundColor green "You chose to configure [$numberOfCrawl] Crawl servers."

We start by defining the $inputOK variable as false and then wrap the entire piece of code in a do/until loop that repeats until the user enters a valid numeric only value.  Inside of this loop, we have a try/catch block.  Inside the try, we attempt to assign the entered value from Read-Host to the $numberofCrawl variable which we cast as an int.  If the user enters a non-numeric value, the cast will fail and will be caught by the catch.  In the catch we output an error message in red text and simply allow the loop to restart from the top.  If however, the user entered a valid numeric value, the cast will succeed afterwich we set the $inputOK variable to true thus allowing the loop to end gracefully.  As a final step, we display the entered value to the user.



Cheers
C




image

How do I – Sort a list of custom class objects in descending order in C#?

Written by Cornelius J. van Dyk on . Posted in Blog, How Do I...

Suppose we have a custom class defined thus:

    class CustomClass
    {
        public string String1 { get; set; }
        public string String2 { get; set; }
        public string String3 { get; set; }
        public int Int1 { get; set; }
        public int Int2 { get; set; }

        public CustomClass()
        {
            String1 = "";
            String2 = "";
            String3 = "";
            Int1 = 0;
            Int2 = 0;
        }

        public int Calculate()
        {
            return Int1 + Int2;
        }
    }
As we can see, the class initializes it’s variables and has a Calculate() method that simply returns the added value of the two int variables of the class. Now suppose we have a list of these class objects in our app with varying values thus:
    CustomClass MyClass = new CustomClass();
    MyClass.Int1 = 10;
    MyClass.Int2 = 5;
    CustomClass My2ndClass = new CustomClass();
    My2ndClass.Int1 = 7;
    CustomClass My3rdClass = new CustomClass();

    List lst = new List();
    lst.Add(My2ndClass); 
    lst.Add(MyClass);
    lst.Add(My3rdClass);
We now have a list containing 3 of our custom class objects. The first object in the list has an Int1 value of 10. The second has an Int1 value of 5 and the third, given the class’ initialization method, will have an Int1 value of 0. Given the order that we added the class objects to our list, the list, when looking at the Int1 field would look thus: 7, 10, 0 How do we go about sorting this list by any one of the variable fields of the custom class, say Int1 in our case? The built in support for Linq in Visual C# and the .NET Framework, actually makes this very easy. Using a Lambda expression, the task becomes a one liner thus:
  lst = lst.OrderByDescending(x => x.Int1).ToList();
We start with the OrderByDescending() method and then pass the Lambda expression to reference back to the object itself. The x => part of the expression tells C# to reference back to the calling object which in our case is lst. C# will reference back to lst as x which is where the x.Int1 then instructs the OrderByDescending method to use the Int1 field as the value by which to sort, in descending order, the x object which translates to lst. By appending the ToList() method to the back of the statement, C# will take the sorted result and generate a new List<> object which we simply assign back to the original lst variable. If we needed to sort in ascending order we would use the OrderBy() method instead thus making the statement:
 lst = lst.OrderBy(x => x.Int1).ToList();


Cheers
C




image

How do I – Play the TNG Red Alert (or any audio file for that matter) in my WinForms C# app

Written by Cornelius J. van Dyk on . Posted in Blog, How Do I...

Out of the box, C# and .NET supports the playing of any .WAV file.  The code is pretty straight forward.  We simply need to reference the system media class to create a SoundPlayer{} object thus:

System.Media.SoundPlayer p = new System.Media.SoundPlayer(@"C:\Media\MySoundEffect.wav");
Once we have the object, we simply invoke the Play() method thus:
p.Play();

So in two simple lines of code, we are able to play any .wav file from our application.  There are some more embedded problems that may not immediately be obvious.  Allow me to explain.

Suppose I’m trying to add the Star Trek TNG Red Alert sound to my app for an emergency notification.  I begin by locating the sound in question.  A quick web search takes me to the http://www.trekcore.com/audio/ site where the Red Alert section has several samples to choose from.  Once I locate the sound sample that I wish to use, I click the link and download the file.

image

PROBLEM #1:  The file is in the .mp3 audio format.  Attempting to use it in the instantiation of the SoundPlayer() method fails with the message that only .wav files are supported.

RESOLUTION We could use a custom media player class, or we could just let the internet do some work for us.  A quick search pointed me to the http://media.io/ online audio conversion web site.  The simple interface couldn’t be cleaner or more straight forward:

image

Simply take the .mp3 file we previously downloaded and upload and convert it on this site.  Now we finally have a .wav file that we can use in our project.  Now we would like the alert sound to be played 3 times and a popup window present the error notification.  That’s easy, right?  We simply use a for() loop that looks like this:

for (int i = 0; i <= 2; i++)
{
    System.Media.SoundPlayer p = new System.Media.SoundPlayer(@"TNG-Red-Alert.wav");
    p.Play();
}
MessageBox.Show("There is an error!", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);

We compile and run the app and expect the alert sound to play 3 times… only… it doesn’t.  So why doesn’t it play our audio?  It seems the problem is related to the fact that the asynchronous .Play() method, being spun from the current executing thread, does not have enough time to execute before the modal .Show() method is executed.  As you know, the MessageBox.Show() method will block the existing thread from executing any further until user action is taken on the window.  As such, the Play() method is queued really quickly given present computer CPU speeds, and once the.Show() method is invoked, it aborts the asynchronous threads to the .Play() method.  To solve the problem we have to allow the .Play() method some time to begin execution.  The easiest way to do that is to simply .Sleep() the current thread.  By injecting this line of code:

System.Threading.Thread.Sleep(1500);

right after the .Play() call, the currently executing thread will pause for 1.5 seconds.  Depending on what audio you’re playing, you can tweak this value (in milliseconds) to match accordingly.

At this point, the alert message and audio work correctly… but the OCD in me still isn’t happy with the effect we get.  When the error condition is generated, the audio alert is played three times, per our code, and then the error alert is popped up.  The problem I have with that is that the audio warning gets my attention, but then I have to wait for it to finish playing three times before the error message with useful information pops up.  That should be easy to fix, right?  Why not just simply move the .Show() method call to before the for() loop containing the .Play() call?

Unfortunately, this doesn’t work as you’d expect.  Because of the fact that the .Show() call actually freezes the current thread, the message box is displayed and then awaits user interaction before it allows the audio code to execute.  What we need is for the .Show() code to be spun off in another thread so as to allow the audio alert to play while the message is displayed.  To do this, we create a new method thus:

public void ShowAlert()
{
    System.Threading.Thread t = new System.Threading.Thread(() =>
    {
        MessageBox.Show("There is an error!", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
    });
    t.Start();
}

Once we have the message box contained in a separate thread, we simply make that call prior to playing our audio thus:

ShowAlert();
for (int i = 0; i <= 2; i++)
{
    System.Media.SoundPlayer p = new System.Media.SoundPlayer(@"TNG-Red-Alert.wav");
    p.Play();
    System.Threading.Thread.Sleep(1500);
}

Once the user interacts with the message box, the thread (t) will terminate gracefully.  In the mean time our main app is free to continue execution of our loop to play the alert sound.



Cheers
C




image

How do I – Scroll the Telerik RadGridView to the top after a data refresh?

Written by Cornelius J. van Dyk on . Posted in How Do I...

What seems like a very simple thing to do, and quite frankly it should be, turned out to be a little more tricky than I thought. Setting the Scene The app has a RadGridView control that displays information from a SQL database. The data is presented to the control via a simple Linq2SQL DataSet. Given that the RadGridView control has a .CurrentRow property which is updatable, logic dictates that a simple statement such as this:

 1:  grdContentSources.CurrentRow = grdContentSources.Rows[0];
would take care of moving the cursor to the top after the data refresh. Alas, it doesn’t. Next I experimented with disconnecting the data source, filling the table adapter and then reconnecting the data source to the grid, but that didn’t work either. Internet searches, especially the very helpful Telerik support site, indicated that we should be using the .IsCurrent() method of the row instead. So this should solve the problem, right?
 1:  grdContentSources.Rows[0].IsCurrent = true;
Unfortunately, that didn’t solve the problem either. Then I found an obscure comment from “Jack”, and Admin on the Telerik team, that pointed me towards the .ChildRows collection for sorted data instead. Since I did have some sorting on the grid, I tried it and it worked! Here’s the complete code:
 1:  Cursor.Current = Cursors.WaitCursor;
   2:  this.crawlManDBDataSet.vwContentSourceCrawlHistory.Clear();
   3:  this.vwContentSourceCrawlHistoryTableAdapter.Fill(
   4:    this.crawlManDBDataSet.vwContentSourceCrawlHistory);
   5:  grdContentSources.ChildRows[0].IsCurrent = true;
   6:  Cursor.Current = Cursors.Default;
Since the operation takes some time, in line 1 we set the cursor to the hour glass. In line 2 we clear the source table for the grid. In line 3 we refill the table to get refreshed data. This reflects back onto the grid as it triggers a .Changed() event to refresh the grid view. Line 5 is where the magic happens as we simply set the .IsCurrent property of the .ChildRows[0] row to be true. Using zero takes the grid back to the top. We could set this to any value within the range of the grid e.g. we could have used:
 1:  grdContentSources.ChildRows[
   2:    grdContentSources.ChildRows.Count - 1].IsCurrent = true;
in order to scroll the grid to the bottom instead.

Cheers
C




image

InfoPath AND OR logic with boolean types and bit values in C based languages – Why your checkboxes are not working as expected

Written by Cornelius J. van Dyk on . Posted in Annoyances

OK, that’s a massive title for this blog post. 🙂 Nevertheless, if you’re having trouble with your InfoPath check boxes not having the desired effect in rules, then read on.

To simplify this explanation, I’m going to use a simple form with two check boxes and a button. The form looks like this:

image[8]

As you can see, it’s a pretty simple form. The two check boxes simply bind to two fields and our data structure looks like this:

image[16]

When we right click on each of the check boxes thus:

image[23]

and then click “Check Box Properties” on the popup menu, we’d see the properties as expected thus:

image[37]

As expected, the default state of the check box is “Cleared” and the value corresponding to that state is “FALSE”. The inverse is true of the Checked state having the value TRUE. This is all as it should be thus far.

Now let’s suppose that we want to hid the Button if either of the two check boxes are unchecked i.e. set to FALSE. We do this via the Rules on the Button control. If we look at the rule defined in this case, we see it looks like this:

image[30]


image[47]

As we can see, the rule is pretty simple and straight forward. Given that both check box controls have a default value of Cleared i.e. FALSE, we would expect the form, when loaded, to hide the button, correct?

This is unfortunately, not the case however, as you can see from here:

image[54]

Check checking the first box, the button is still there:

image[58]

When we uncheck the first box, the button disappears, as we expect it to.

image[62]

Rechecking the box, shows the button again, even though it shouldn’t since the second box is unchecked. The same behavior is found when dealing with the second check box.

So what could possibly be the problem here?

The issue here is the way in which InfoPath deals with the Boolean data type. Keep in mind that InfoPath was developed with C# and C++. All C based derivative languages share the same common handling for null values. In C based languages, a boolean value is defined thus:

bool myValue;

The thing to note is that a boolean value is represented by a single bit in the data stream which is either turned off i.e. false or turned on i.e. true. In C based languages however, the declaration of a variable such as the above, does NOT assign any value to the variable and the value is considered to be unknown or NULL until assigned.

We can debate the merits of null values all day long, but the short of it is that a boolean value could actually have 3 values per se.

We have already looked at our Check Box control in detail and we have found that it can either have a Checked or Cleared value representing TRUE or FALSE. The control itself does not have any way to represent a null value, but we must remember that the control is almost certainly bound to a data value somewhere. The data value is a distinctly different object value that is synched with the value of the check box. As such, it’s governed by a separate set of rules so let’s take a look at the data field properties.

When we locate field1 and right click it, and click “Properties” on the popup menu we see this:

image[71]

The fact that the Default Value property of the data field allows a value of “(Blank)” to be assigned means that the data field can represent null values. This is where state comes into play. If we consider the fact that the check box control can only have TRUE or FALSE values (Checked or Cleared), and we keep in mind that the data field value is synched with the control value, then what is happening here?

The answer lies in the timing of synchronization between the check box control and the data field. In order to preserve resources and cut down traffic, most controls are event driven. That means that the control doesn’t actually update it’s underlying data field value unless the value of the control itself changes. As such, when the form is first loaded, the check box has a value of Cleared i.e. FALSE while the data field does not have any value and as a result, InfoPath assigns the “(Blank)” or null value to the field. This results in a mismatch of state i.e. the data field value does not represent the visual value displayed in the check box.

Due to the fact that InfoPath rules operate on the underlying data field values rather than their bound control values, the formatting rule we had defined for the Button would be checking if the check boxes had a FALSE value. Since upon first load their value is in fact null rather than false, the rule fails the check and does not hid the button as we expected.

When the check box is checked, the TRUE value is synched with the data field and when it is unchecked, the FALSE value from the check box is synched back to the data field. That is why after checking and then unchecking the check box, the button is hidden as expected.

Though I believe allowing “(Blank)” to be a valid value for the data field is a design flaw, the reality is that it’s unlikely to change so we need to be aware of this kind of behavior when designing InfoPath forms.

Special thanks to Chuck for working through this logic with me until we were able to identify what was causing this odd behavior.



Cheers
C




image