Ohhh Glorious Silverlight Theming!!

27. September 2011 03:14 by Mrojas in General  //  Tags: , , , , ,   //   Comments (0)

I’m very fond of one of our newest products www.silverlightmigration.com Smile

It provides a way to refresh your applications to take full advantage of XAML,
solves deployment issues, runs in Windows, Mac OSX and in some Linux with
MoonLight

And we are event tuning it up for the next jump: Windows 8… keep tuned for that.

One of the things a like most about this solution is XAML theming.

In general there are good themes but today I would like to recommend the SystemColors theme
from http://blogs.msdn.com/b/corrinab/archive/2010/04/12/9994045.aspx

You can download it from here.
This theme allows you to style all core, sdk and toolkit controls so they will use the theme that
you currently have in Windows. These might be very useful for some LOB applications,
so the applications can see more like native applications, and with the advent of Silverlight 5 and more
native integration, better Out-of-Browser execution I think it is just fine.

See some screen shots:

ORA-01843 NOT A VALID MONTH

21. September 2011 09:06 by Mrojas in General  //  Tags: , , ,   //   Comments (0)

Out of the blue, I just started getting this obnoxious exception. Why?? Why meeeeeee!!

Another weird thing is that is was only from my test server. Again Why?>>> Why Meeee!!!

In general when I executed some stored procedures or performed select staments againts the
Oracle database I just got that exception.

ORA-01843: not a valid month

CAUSE:

The source of the problem is that when a table has a date stored in a format that the client is not able
to understand due to format differentes it will throw this message.

For example, if the table is storing dates like ‘DD-MM-YY’, (that is day-month-year european format)
and the client tries to read the date as ‘MM-DD-YY’ or viceversa. In this case we can see that the
month number is confused with the day and it is very likely that there will be dates with a month value
bigger that 12.

SOLUTION:

The solution to this problem is to tell the client the right format to use for dates. This is part of the session values
in oralce. Part of those values can be queries with the following statement:

select * from nls_session_parameters

In the query results, we can see the value of the NLS_DATE_FORMAT that is being used by the client.

You can take several actions.

1. If you are just performing a query on SQL PLUS and is just an isolated query you can just change that value for
your current session by executing:

alter session set NLS_DATE_FORMAT=’DD-MM-RR’

This will take effect ONLY for the actual session. In this example we can see that the format is being changed to
‘day-month-year’. The RR, indicates the year.

2. If you want a more permanent change or at least something that applies to all your session. You can:

2.1. Create an After Logon Trigger something like:

CREATE OR REPLACE TRIGGER LOGINTRG AFTER LOGON ON DATABASE

BEGIN EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT=''DD-MM-RR'''; END LOGINTRG;

2.2. Option 2. Go to the Registry and locate

\\HKEY_LOCAL_ MACHINE\SOFTWARE\ORACLE\KEY_HOMENAME\

For example in my case it was

\\HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOME0

And create an String Key called NLS_DATE_FORMAT and set it to DD-MM-RR

How to call an stored procedure defined in an Oracle Package?

21. September 2011 08:55 by Mrojas in General  //  Tags: , , , , ,   //   Comments (0)

Today I had an stored procedure defined in a package and I didn’t know how to call it.
And my stored procedure returned a cursor and I needed to see the results.

So after some tests this is the way to perform this. You can use code like the following:

variable r refcursor -- use this if you have an out parameter that is an out cursor

DECLARE 

  -- Declare a variable for each of your stored procedure arguments

  VAR_IN_1 VARCHAR2(32767);

  VAR_IN_2 VARCHAR2(32767);

  VAR_IN_3 VARCHAR2(32767);

  INFO sys_refcursor;

BEGIN 

  -- Init the variables with the parameter you want to use to test the stored procedure

  VAR_IN_1 := 'Param1';

  VAR_IN_2 := 'Param2';

  VAR_IN_3 := 'Param3';



-- Call the stored procedure. You should write something like schema.package.storedprocedure( param1, param2, ..., paramN);

MYSCHEMA.PKG_TEST.TEST_STORED_PROC ( VAR_IN_1, VAR_IN_2, VAR_IN_3, INFO );

-- If one of the parameters was an out cursor assign it to the r variable to be able to see the results

  :r := PC_INFO;

  COMMIT; 

END; 

-- Execute this code in SQL PLUS

And after executing it just call in the SQL PLUS prompt

PRINT r to see cursor results

Property Pages in VB.NET and C#

13. September 2011 02:20 by Mrojas in General  //  Tags: , , , , , ,   //   Comments (0)

Visual Basic 6.0 property pages allow you to work around the
limitations of the Visual Basic Property Browser. For example,
you can use property pages to give users a way to add a collections of
colors to a color list user control.

In the property page you would write code that manages the collection,
something beyond the capabilities of the Visual Basic Property Browser.
In contrast, the Visual Basic .NET Property Browser can be used
to edit any .NET variable type or class. Property Pages are no longer needed.

The Upgrade Wizard and the VBUC do not automatically upgrade your
Visual Basic 6.0 property pages but they can sure be of help.
What if you really what to keep those property pages? Is there any workaround.
mmmm Sure there is.

You can follow these steps.

1. Before migrating your Visual Basic 6.0 project with the VBUC
modify your property pages (.pag) files to resemble common Visual Basic 6.0 forms.
For example a property page looks like this:

VERSION 5.00
Begin VB.PropertyPage PropertyPage1 
   Caption         =   "PropertyPage1"
   ClientHeight    =   3600
   ClientLeft      =   0
   ClientTop       =   0
   ClientWidth     =   4800
   PaletteMode     =   0  'Halftone
   ScaleHeight     =   3600
   ScaleWidth      =   4800
   Begin VB.TextBox Text1 
      Height          =   495
      Left            =   480
      TabIndex        =   1
      Text            =   "Text1"
      Top             =   1200
      Width           =   2175
   End
   Begin VB.CommandButton Command1 
      Caption         =   "Command1"
      Height          =   615
      Left            =   3120
      TabIndex        =   0
      Top             =   480
      Width           =   1455
   End
   Begin VB.Label Label1 
      Caption         =   "Label1"
      Height          =   375
      Left            =   240
      TabIndex        =   2
      Top             =   600
      Width           =   1815
   End
End
Attribute VB_Name = "PropertyPage1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False

Can be turned into a Form, to ease migration with simple changes:

VERSION 5.00
Begin VB.Form  PropertyPage1 
   Caption         =   "PropertyPage1"
   ClientHeight    =   3600
   ClientLeft      =   0
   ClientTop       =   0
   ClientWidth     =   4800
   PaletteMode     =   0  'Halftone
   ScaleHeight     =   3600
   ScaleWidth      =   4800
   Begin VB.TextBox Text1 
      Height          =   495
      Left            =   480
      TabIndex        =   1
      Text            =   "Text1"
      Top             =   1200
      Width           =   2175
   End
   Begin VB.CommandButton Command1 
      Caption         =   "Command1"
      Height          =   615
      Left            =   3120
      TabIndex        =   0
      Top             =   480
      Width           =   1455
   End
   Begin VB.Label Label1 
      Caption         =   "Label1"
      Height          =   375
      Left            =   240
      TabIndex        =   2
      Top             =   600
      Width           =   1815
   End
End
Attribute VB_Name = "PropertyPage1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False

If the form had a event like:

Private Sub PropertyPage_Initialize()

End Sub

Change that to Form_Load()

2. Rename the file from .pag to .frm.
3. Remove the .pag from the VB6 project
4. Add the .frm file to the VB6 project
5. Run the VBUC tool.

Once migrated you have a close migration of your original Property Page.
Remember however that some things change in .NET and you will need to manually finish some details.
For example, you need to review code in the
PropertyPage_ApplyChanges(),
PropertyPage_EditProperty(PropertyName As String)
PropertyPage_SelectionChanged().

Ok. Once you take your Property Page to .NET how do you integrate it with your control.
Well that’s easy. There you could create a ControlDesigner or just use an UITypeEditor.

Let’s see the UITypeEditor aproach.

The general idea with this aproach is to provide an UITypeEditor (this is just a way to provide an
editor in the property Browser that is not supported by default. And taking advantage of that editor
we will show the form that was produced after migrating out Property Pages. If you want an interface
more similar to what you had on Visual Basic 6.0 you can modify the property page and add a TabControl.

Ok. So these are the steps to follow:

1. First you need to create a type for which you will provide a Type Editor. We will call this type CustomData

 

namespace CustomEditor
{
    public class CustomData
    {
    }
}

2.Now we will add a property to our control.

        public CustomData Custom
        {
            get;
            set;
        }

3. Now add attributes to associate an editor

        [Description("Custom"), Editor(typeof(CustomDataEditor), typeof(UITypeEditor))]
        public CustomData Custom
        {
            get;
            set;
        }

4. And now lets implement the CustomDataEditor

using System.Windows.Forms.Design;

namespace CustomEditor
{
    public class CustomDataEditor : UITypeEditor
    {
        public CustomDataEditor() {}

        public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
        {

            return UITypeEditorEditStyle.Modal;
        }

        public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            IWindowsFormsEditorService frmsvr = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
            if (frmsvr == null) return null;
            PropertyPageForm propPage = new PropertyPageForm();
            propPage.control = (MyControl)context.Instance;
            frmsvr.ShowDialog(f);
            return null;
        }

    }
}

5. In the previous put attention to the highlighted details. What we are doing is getting a reference
to the WindowsFormEditor service so we property open the PropertyPage that has now been turned into a form.
It is important that you add a public property to the migrated PropertyPage like:

public MyControl control { get; set; };

because that will give you a reference to the actual control that is on the form. The property page is just an interface
you will need to set the values into properties on your control, in order for them to be serialized.

6. Once you do that, when you see the property editor for your control you will see something like:

When you press the … button it will show up your property page form.

You could also add other visual elements like:

Or

But that is maybe for another post.

Regards

Fixing memory Leaks, Finalizer and other ugly problems in your .NET code

8. September 2011 07:48 by Mrojas in General  //  Tags: , , , ,   //   Comments (0)

Fixing memory leaks is sometimes hard. Because even if you track which is the instance
that is being retained, is difficult to determine WHERE was it created.

Another problem I have found difficult to tackle is when you get an exception because of
code that was put in a finalizer (yes I know that putting code in a Finalizer doesn’t sound like the
best programming practice but sometime I just have to give maintenance to code that does that).

So, my friend Jose de Jesus showed me a nice tip to identify where are those objects being created.

He told me to do the following:

1. Add an instance variable like:

 

public System.Diagnostics.StackTrace myClassStackTrace = new System.Diagnostics.StackTrace();

2. Just by doing that I can inspect that field and identify where was this particular instance created!.

Cheers

Things to consider for Internationalization of a .NET Application

23. August 2011 04:56 by Mrojas in General  //  Tags: , , ,   //   Comments (0)

Here is a list of some things that you should consider for Internationalization of Applications.

1. CurrentUICulture and CurrentCulture.

Is is better if you don’t change CurrentUICulture form the the Operating System

2. Windows Forms Layout

Forms must be set Localizable property to true.
This will allow you to define different layouts for your forms depending on the current culture.

 

3. Strongly Typed Resources.

Instead of something like MessageBox.Show(“Invalid code”) use something like:

MessageBox.Show(resourceManager.GetString(“InvalidCode”)) or even better if you strongly type it:
MessageBox.Show(Form1Resources.InvalidCode);

4. Localize Exceptions messages.

If you include messages in your exceptions that will be shown somehow
on the user interface it is better if your localize those strings also.
If exceptions messages are only for developers then you might not need this.

5.Relate Internationalization sensitive values to the Culture Info

For example

a) Extension methods something like:

CurrentCulture.GetPostalCode();

static class CultureInforExtensions
{

  public static string GetPostalCode(this CultureInfo cultureInfo)
  {
      return new PostalCode(cultureInfo.Name).ToString();

  }

}

and then use it like:
maskedTextBox1.Mask = CultureInfo.CurrentCulture.GetPostalCode()

b) Customized CultureInfo it can be helpful for

  • Change inappropiate Culture Information
  • Supplementary Cultures
  • New Combinations of Existing Languages and Regios (for example: Spanish (United States))

6. Right To Left

In some languages Right to Left is important and is an important aspect to consider.
In your forms you have to set the RightToLeftLayout to true and RightToLeft to Yes.

However some controls do not have rtl layoout when RightToLeft=yes: Panel, GroupBos, TabPages and SplitContainerPanels.
You need to rearrange the items in these controls to flow from RightToLeft manually.
This is an example of rearranging the layout of the controls programmatically at runtime, without changing the Form at design-time:

int NumberOfControls = ParentPanel.Controls.Count;
for ( int i=0; i<NumberOfControls;i++)
{
      ParentPanel.Controls[i].Left = ParentPanel.Width -
      (ParentPanel.Controls[i].Left + ParentPanel.Controls[i].Width);
}

This code iterates into all the controls in the ParentPanel and changes their location to be rtl oriented.

Other problematic controls are: MainMenu, ToolBar, StatusBar MenuStrip, ToolStrip, StatusStrip and ContextMenuString

Other advises:

When you develop multi-lingual application you are bound to change your Forms direction to rtl programmatically at runtime.

There are several techniques to detect the OS language and display your application with the appropriate language and rtl settings, here are some ideas:

The old technique, you would need to detect your UIculture and change the RightToLeft value accordingly.

public static bool CultureInfoIsRightToLeft()
{
string cultureInfoLanguage = System.Globalization.CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
return
cultureInfoLanguage == "ar" ||
cultureInfoLanguage == "div" ||
cultureInfoLanguage == "fa" ||
cultureInfoLanguage == "syr" ||
cultureInfoLanguage == " ur " ;
}

In Visual Studio 2005, you have a new property TextInfo.IsRightToLeft that indicates the direction of each culture. This is a simple code snippet to detect the culture direction.

private static bool CultureInfoIsRightToLeft()
{
return System.Globalization.CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft;
}

 

GDI+

In case you implement your own drawing, you need to specify how your digits would appear in your DrawString. This is achieved using the StringFormat.SetDigitSubstitution. For more info to this method please refer to the documentation . Below is a code snippet that shows how to display digits using the different enums.

private void IndicDigits_Paint( object sender, PaintEventArgs e)
{
StringFormat StrFormat = new StringFormat ();
int AraLCID = new System.Globalization. CultureInfo ( "ar-eg" ).LCID;
StrFormat.SetDigitSubstitution(AraLCID, StringDigitSubstitute .National);
e.Graphics.DrawString( "Digit Substitution National 0,1,2,3,4,5,6,7,8,9" , this .Font, newSolidBrush ( this .ForeColor), new PointF (10, 10), StrFormat);
StrFormat.SetDigitSubstitution(AraLCID, StringDigitSubstitute .Traditional);
e.Graphics.DrawString( "Digit Substitution Traditional 0,1,2,3,4,5,6,7,8,9" , this .Font, newSolidBrush ( this .ForeColor), new PointF (10, 30), StrFormat);
StrFormat.SetDigitSubstitution(AraLCID, StringDigitSubstitute .None);
e.Graphics.DrawString( "Digit Substitution None 0,1,2,3,4,5,6,7,8,9" , this .Font, newSolidBrush ( this .ForeColor), new PointF (10, 50), StrFormat);
StrFormat.SetDigitSubstitution(AraLCID, StringDigitSubstitute .User);
e.Graphics.DrawString( "Digit Substitution User 0,1,2,3,4,5,6,7,8,9" , this .Font, newSolidBrush ( this .ForeColor), new PointF (10, 70), StrFormat);
}

Making a form bigger than the Screen Resolution

11. August 2011 02:55 by Mrojas in General  //  Tags: , , , , ,   //   Comments (0)

 

A friend at work asked me how do I make my form bigger that the screen resolution. I was not able to do it, but
he google it and found a solution from: http://social.msdn.microsoft.com/Forums/en/vblanguage/thread/65c48eea-408a-45ed-a1cc-ea0336047798

This is just the transliteration of that code in C# just as a reference
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class Form1 : Form { [DllImport("User32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int w, int h, bool Repaint); private void Form1_Load(System.Object sender, System.EventArgs e) { this.MaximumSize = new Size(5000, 800); bool Result = MoveWindow(this.Handle, this.Left, this.Top, 5000, 500, true); } public Form1() { Load += Form1_Load; } }

Setting the Default Printer in .NET

 
The following C# code shows how to use WMI to query printers information, set and get default printer.
public bool SetDefaultPrinter()
{
    System.Management.ManagementObjectSearcher search = 
default(System.Management.ManagementObjectSearcher); System.Management.ManagementObjectCollection results =
default(System.Management.ManagementObjectCollection); System.Management.ManagementObject printer =
default(System.Management.ManagementObject); search =
new System.Management.ManagementObjectSearcher("select * from win32_printer"); results = search.Get(); //Get Default Printer System.Management.ManagementObject defaultPrinter = null; foreach (System.Management.ManagementObject foundPrinter in results) { System.Management.PropertyDataCollection
propertyDataCollection = foundPrinter.Properties; if ((bool)foundPrinter["Default"]) // DEFAULT PRINTER { System.Diagnostics.Debug.WriteLine(foundPrinter["Name"]); System.Diagnostics.Debug.WriteLine(foundPrinter["Location"]); } } //Sets new default Printer foreach (System.Management.ManagementObject foundPrinter in results) { System.Diagnostics.Debug.Print(foundPrinter["Name"].ToString()); if (foundPrinter["Name"].Equals("PDFCreator")) { System.Management.ManagementBaseObject outParams =
foundPrinter.InvokeMethod("SetDefaultPrinter", null, null); if (outParams == null) System.Diagnostics.Debug.WriteLine("Unable to set default printer"); Int32 retVal = (int)(uint)outParams.Properties["ReturnValue"].Value; if (retVal == 0) return true; else return false; } } return false; }

Tracing Database Connection Leaks

19. July 2011 06:15 by Mrojas in General  //  Tags:   //   Comments (0)

Complex applications are difficult too debug. You might have lots of components, some exposed
thru COM, some managed, some called from an ASP page, some used from a VB6 application that instanciates
a ServicedComponent.

And this complex applications will use databases. And one complex bug to track in applications
is when you have Connection Leaks.

Connection leaks are those situations where the application is not releasing connections to the ConnectionPool.

How can you detect the problems and their origins? One possibility could be use ADO.NET
and ODBC tracing (but that is for another post).

Now I will show an easier approach. Use extension methods!!!
What? you would say, what do extension methods have to do with this?

Well you can use an extension method to intercept all database connection. The way we do this is the following:

First create an extension method like:

public static class DBTrace
{
      private static string LogDBTrace = @"C:\DBTrace.txt";
      /// <summary>
      /// 
      /// </summary>
      /// <param name="conn"></param>
      public static void OpenWithTrace(this DbConnection conn)
      {
            conn.ConnectionString = NewConnectionstring(conn.ConnectionString);
#if DBTrace
            File.AppendAllText(LogDBTrace, 
"Opening connection [" + conn.ConnectionString + "] " +
new System.Diagnostics.StackTrace().ToString()); #endif conn.Open(); } /// <summary> /// /// </summary> /// <param name="factory"></param> /// <returns></returns> public static DbConnection CreateConnectionWithTrace(this DbProviderFactory factory) { #if DBTrace File.AppendAllText(LogDBTrace, "Creating connection " +
new System.Diagnostics.StackTrace().ToString()); #endif return factory.CreateConnection(); } public static string NewConnectionstring(String connectionString) { #if ConnectionPoolOff if (!connectionString.Contains("Pooling=")) { if (connectionString.EndsWith(";")) { connectionString += "Pooling=false;"; } else { connectionString += ";Pooling=false;"; } } return connectionString; #else return connectionString; #endif } }

This will allow you to use compilation directives like: ConnectionPoolOff, and DBTrace which will
help you to turn on and off the database tracing and connection pooling in order to be able to detect connection leaks.

Second,

Look for any calls to Connection.Open() and change them to Connection.OpenWithTrace()
(A simple Find and Replace or regular expression should work).

This is a simple mechanism to implement database connection tracing.

Monitor open connections in oracle

13. July 2011 04:08 by Mrojas in General  //  Tags: , , ,   //   Comments (0)

 

This is an useful script taken from: http://dbaforums.org/oracle/index.php?showtopic=16834 which provides a list of the currently
open sessions.

To track if you application is having problems releasing connection you can open the SQLPlusW and run this script
a couple of times while you exercise your application.

set line 150;
ttitle "dbname Database|UNIX/Oracle Sessions";

set heading off;

select 'Sessions on database '||substr(name,1,8) from v$database;

set heading on;

select
       substr(a.spid,1,9) pid,
       substr(b.sid,1,5) sid,
       substr(b.serial#,1,5) ser#,
       substr(b.machine,1,20) computer,
       substr(b.username,1,10) username,
--       b.server,
       substr(b.osuser,1,8) os_user,
       substr(b.program,1,30) program
from v$session b, v$process a
where
b.paddr = a.addr
and type='USER'
order by spid;

ttitle off;

spool off;

This will provide an output like: