May 2009 - Blake Niemyjski

  • CodeSmith CSLA templates - Part 2: The quick start

    In Part 1: The introduction was an overview of the CodeSmith CSLA templates we are developing at CodeSmith. In this post, I am going to go over how to use the CSLA quick start and the new improvements resulting from customer feedback (Keep the feedback coming!).

    First launch CodeSmith Studio and under the Frameworks node open CodeSmith.CSLA. The CSLA.NET folder will eventually be going away and replaced with our in house CSLA templates (CodeSmith.CSLA).

    CodeSmith Studio 

    There are a couple of folders in the CodeSmith.CSLA folder

    Folder Name

    Description

    Common Contains the supporting CSLA assemblies and the Visual Studio templates to create the project.
    CSharp Contains the C# templates.
    Source Contains the source code to the quick start and the API that the templates use.
    VB Doesn’t exist yet but will contain the VB.NET templates.

    Now double click on the quick start template, the property grid should now be populated with the quick start properties.

    CodeSmith Studio (4)

    Next select “” button for the Source Database property and select your database you wish to generate against. In this example I will select the PetShop database. The quick start will now populate the property grid most common settings. From here configure the settings to your liking and click generate. Microsoft Visual Studio should now launch unless you set Launch Visual Studio property to false.

    PetShop - Microsoft Visual Studio (Administrator)

    Next right click the PetShop.UI project and select Set as Startup Project

    PetShop - Microsoft Visual Studio (Administrator) (3)

    Now when you select build or debug your project will start generating.

    PetShop - Microsoft Visual Studio (Administrator) (4)

    The UI Project is a place holder project for you to start building your application. So now that you have the general idea on getting up and running quickly with the quick start lets see what it takes to customize the type of each entity. Lets right click the Entities.csp template and select Manage Outputs.

    PetShop - Microsoft Visual Studio (Administrator) (5)

    After the manage outputs dialog comes up double click on the Entities.cst item.

    Edit Output - Entities.csp (2)

    Earlier in the CSLA beta we had 14 different outputs instead of one. Now all the settings are in one output (Entities.cst). Say you wanted to change the types of your entities from an EditableRoot to a EditableRootChild object. Just use the familiar table picker and change it. It will check to make sure there is no conflict and that any child lists are populated. For example if you had no entities selected and you added a table to EditiableChild it would look through all the lists and if a list entity was not found it would add the table to the EditableChildList. This makes it extremely easy to configure your Business objects.

    Please give us your feedback on the new CSLA templates!

  • A fix for the Microsoft .Net Framework 3.5 SP1 Fatal Execution Error (VS Silent Death Bug).

    We released CodeSmith 5.1 with the new requirements of the Microsoft .Net Framework 3.5. One of our experiences in upgrading to the .Net Framework 3.5 is issues we have run into like our customers reporting Visual Studio disapearing or closing extremely quick when they try to generate code using CodeSmith's Visual Studio Integration. The following link (Tools - Part 11 - Add-ins - Attempting to work around the “VS Silent Death” bug) describes this issue in detail. Since his blog content is currently offline I’ll quote his content.

    One very annoying and elusive problem that sometimes slam down on VS2008 / .net 3.5 SP1 developers is the “VS Silent Death” bug. It manifests itself by simply making the Visual Studio IDE ‘disappear’ at a random point such as when opening a project or when opening a certain type of file in Visual Studio.

    The annoying part is the lack of feedback from VS that leaves many baffled. The VS IDE just “disappears” without any feedback, although there is always an entry in the Windows event log (app log) for each crash stating something along the lines of “.NET Runtime version 2.0.50727.1434 - Fatal Execution Engine Error (79FEC5F0) (80131506)” or “.NET Runtime version 2.0.50727.3053 - Fatal Execution Engine Error (7A035E00) (80131506)“.

    The elusive part of the problem is that for some users it happens only on rare occasions, while for others it can occur with relatively high frequency. It can happen for a specific project or solution on one machine while the same project/solution works fine on an identical machine next to it (and vice versa). This makes it tricky to reproduce and troubleshoot “on demand”.

    A mitigating factor is if any tools or add-ins used reference the .net 3.5 framework, so it can happen more frequently when VS add-ins are installed but also when using certain features in VS2008/.net 3.5 such as asp.net MVC, Entity Framework, Linq-to-SQL, WPF, etc. The fact that third party add-ins are commonly affected has made it easy to put the blame on the add-ins; Microsoft’s PowerCommands, Huagati DBML/EDMX Tools, Jetbrains Resharper, Ankh, Gallio, and many other third party add-ins have been affected and sometimes blamed for causing the crashes. So has the WPF designer, L2S designer, MVC libraries etc. However, debugging* and research* points to corrupt NGen images and assembly load problems.

    Finally Microsoft wakes up

    There have been numerous reports* to Microsoft on this issue through Microsoft Connect but despite the reporting party supplying crash dump files for several of the reports they have all been closed with “not reproducible”. In fact, until very recently I have not found a single acknowledgement from Microsoft of this bug, even when actively pursuing an answer (i.e. asking them directly). A few days ago a Microsoft blogger, Jim Nakashima, wrote in his msdn blog that they have reproduced it when working with MVC in Azure projects and that the CLR team is working on a fix:

    http://blogs.msdn.com/jnak/archive/2009/02/15/potential-crash-in-vs-when-using-the-mvc-rc-on-windows-azure.aspx

    Fantastic. Great. Terrific.

    So far there’s no “official” acknowledgement from MSFT of this bug or ETA for a hot fix on msdn.microsoft.com, or connect.microsoft.com. Not even Microsoft’s primary communication channels to the developer community (a.k.a. Scottgu or Scottha’s blogs) mention the problem except in user comments.

    Update: Microsoft has a patch, KB963676 that addresses this issue. After installing it on my repro-system it looks promising; I have not yet been able to trigger the ‘VS death’ after applying the patch. No word (yet) on when it will be publicly available, but I assume that affected parties can request this hot patch through MS Support by referring to the MSKB #.

    Update 2: The patch is now available for download from Microsoft connect. See Jim Nakashima’s announcement at http://blogs.msdn.com/jnak/archive/2009/02/26/fix-available-asp-net-mvc-rc-crash-in-a-windows-azure-cloud-service-project.aspx

    Source  (Tools - Part 11 - Add-ins - Attempting to work around the “VS Silent Death” bug).

    The Fix.

    A current workaround for this issue is to apply the following Microsoft patch and reboot your computer.

  • How to register a keyboard shortcut (hot key) in a .NET Windows Forms Application.

    There may come a time when you want to implement some extra features or maybe an Easter egg into your application using keyboard shortcuts. I was recently tasked with creating an Easter egg so we could test some functionality in CodeSmith. After countless searches looking for an elegant solution (I found a few ugly solutions and some nicer ones) I came across Method #3. I’ll First touch on the one I didn’t choose to go with.

    Method #1

    The following code block will make an unmanaged call to the user32.dll to register the hotkey. I would never go this approach, but if you were like me and couldn’t find anything in the time frame allotted then you might end up implementing this.

    First you will need to update your using block.

    using System.Runtime.InteropServices;

    Then add the following code to your form.

    /// <summary> The RegisterHotKey function defines a system-wide hot key </summary>
    /// <param name="hWnd">Handle to the window that will receive WM_HOTKEY messages
    /// generated by the hot key.</param>
    /// <param name="id">Specifies the identifier of the hot key.</param>
    /// <param name="fsModifiers">Specifies keys that must be pressed in combination with the key
    /// specified by the 'virtualKey' parameter in order to generate the WM_HOTKEY message.</param>
    /// <param name="virtualKey">Specifies the virtual-key code of the hot key</param>
    /// <returns><c>true</c> if the function succeeds, otherwise <c>false</c></returns>
    /// <seealso cref="http://msdn.microsoft.com/en-us/library/ms646309(VS.85).aspx"/>
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint virtualKey);
     
    [DllImport("user32.dll")]
    private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
     
    public static int MOD_CONTROL = 0x2;
    public static int MOD_SHIFT = 0x4;
    public static int WM_HOTKEY = 0x312;
     
    private static int keyId;
    public static void RegisterHotKey(Form f, Keys key)
    {
       int modifiers = 0;
     
       if ((key & Keys.Control) == Keys.Control)
           modifiers = modifiers | MOD_CONTROL;
     
       if ((key & Keys.Shift) == Keys.Shift)
           modifiers = modifiers | MOD_SHIFT;
     
       Keys k = key & ~Keys.Control & ~Keys.Shift;
     
       Func<bool> ff = () =>
                           {
                               keyId = f.GetHashCode();
                               RegisterHotKey(f.Handle, keyId, (uint) modifiers, (uint) k);
     
                               return true;
                           };
     
       if (f.InvokeRequired)
           f.Invoke(ff);
       else
           ff();
    }
     
    public static void UnregisterHotKey(Form f)
    {
       try
       {
           Func<bool> ff = () =>
                               {
                                   UnregisterHotKey(f.Handle, keyId);
     
                                   return true;
                               };
     
           if (f.InvokeRequired)
               f.Invoke(ff);
           else
               ff();
       }
       catch (Exception ex)
       {
           Debug.WriteLine(ex.ToString());
       }
    }
     
    protected override void WndProc(ref Message m)
    {
       base.WndProc(ref m);
     
       if (m.Msg == WM_HOTKEY)
           throw new Exception("You found an Easter Egg.");
    }

    Then in your Form Load event add the following code.

    Keys k = Keys.F2 | Keys.Control;
    RegisterHotKey(this, k);

    I found this example here, Please note that I did some refactoring to it.

    Method #2

    I also found this WPF solution that I haven’t tried but should work. This looks like the best approach for implementing this functionality in WPF as I have seen people use the first method.

    public WindowMain()
    {  
       InitializeComponent();     
       
       this.InputBindings.Add(new InputBinding(MyAppCommands.SaveAll, new KeyGesture(Key.F2, ModifierKeys.Control)););
       
       CommandBinding cb = new CommandBinding(MyAppCommands.SaveAll);
       cb.Executed += SaveAllDocuments;
       
       this.CommandBindings.Add(cb );
    }
     
    private void SaveAllDocuments(object obSender, ExecutedRoutedEventArgs e)
    {
    }

    Method #3

    The approach I went I thought was the best way as it is small and elegant piece of code. It is completely safe to implement as it doesn’t have any hooks into native windows dlls. The initial idea came from here, to implement this code just place it anywhere in your Form.

    protected override bool ProcessCmdKey(ref Message message, Keys keys)
    {
        switch (keys)
        {
            case Keys.F2 | Keys.Control:
                //Process action here.
                return false;
        }
     
        return false;
    }

    Method #4

    A friend recently sent me this example right before publishing this. I have never seen this approach but never the less it is an example of how to implement this functionality.

    C#
    public class MyMainForm : System.Windows.Forms.Form, IMessageFilter
    {
         const int WM_KEYDOWN = 0x100;
         const int WM_KEYUP = 0x101;
     
         public bool PreFilterMessage(ref Message m)
         {
              Keys keyCode = (Keys)(int)m.WParam & Keys.KeyCode;
              if(m.Msg == WM_KEYDOWN && keyCode == Keys.Escape)
              {
                   Console.WriteLine("Ignoring Escape...");
                   return true;
              }
              return false;
         }
     
         private void MyMainForm_Load(object sender, System.EventArgs e)
         {
              Application.AddMessageFilter(this);
         }
    }
    VB.NET
    Public Class MyMainForm
         Inherits System.Windows.Forms.Form
         Implements IMessageFilter
     
         Private WM_KEYDOWN As Integer = &H100
         Private WM_KEYUP As Integer = &H101
     
         Public Function PreFilterMessage(ByRef m As Message) As Boolean
              Dim keyCode As Keys = CType(CInt(m.WParam), Keys) And Keys.KeyCode
              If m.Msg = WM_KEYDOWN And keyCode = Keys.Escape Then
                   Console.WriteLine("Ignoring Escape...")
                   Return True
              End If
              Return False
         End Function 'PreFilterMessage
     
         Private Sub MyMainForm_Load(sender As Object, e As System.EventArgs)
              Application.AddMessageFilter(Me)
         End Sub 'MyMainForm_Load
    End Class 'MyMainForm

    Please let me know if you find any issues in the sample code above.

  • How to clear cached contacts from Microsoft Outlook.

    A long time ago we needed a script to remove the cached contacts in Microsoft Outlook. After some research we found that these were stored in a NK2 file in the user profile directory. To run the script please close Outlook and create a new batch file (text file with the extension of .bat), or download the file below. Please not this will create a backup of the NK2 file so everything can be reverted.

    @ECHO off
     
    TITLE Clear the nickname automatic completion caches in Outlook
    CLS
     
    ECHO Clearing the nickname automatic completion caches in OutLook...
    ECHO Created by Blake Niemyjski (http://windowscoding.com)
    ECHO.
     
    CD %userprofile%\Application Data\Microsoft\Outlook
     
    RENAME *.NK2 *.NK2.BAK
     
    ECHO.
    ECHO The operation has now completed.
    ECHO.
     
    PAUSE
    EXIT

    Download is attached to this post.

  • Microsoft Visual Studio 2010 Beta 1 is coming to MSDN on May 18th.

    So far I have been very impressed with the CTP builds of Visual studio 2010. There are some really welcoming changes that are apart of Visual Studio 2010 like UI Unit tests and a completely new IDE written in WPF. The only area where I thought was lacking was the responsiveness of the application. Last night a few members of the Visual Studio team announced that one of there main goals for Beta 1 and RTM is on Performance. I am very excited to hear this.

    "During these last weeks we’ve made a lot of progress, I’m sure you’re going to feel the product is a lot snappier than the builds we provided at the PDC. But of course I’m never satisfied – there are even more wins coming later. I worked with many different teams to help us with our startup, with UI transitions, with memory usage, with threading issues – especially with how WPF and our main thread synchronize” Rico Mariani.

    Jihad Dannawi from Microsoft Australia reports that MSDN will have the latest bits of Visual Studio 2010 on May 18th, So keep an eye open.

     

    MSDN download Link.

  • How to protect your Community Server site from spammers

    One should always be aware that your site could be attacked by spam bots if you don’t take the proper precautions. The easiest and quickest way to help prevent 500+ spam users from joining your site is to configure the default options to make it harder for spam bots to create accounts. Please note that this can also reduce the number of registrations on your site due to the extra steps it takes to register.

    1. Navigate to the Account Settings tab in the control panel (/controlpanel/membership/AccountSettings.aspx).
    2. In the Registration Settings tab Set Account Activation to Email.Email Settings
    3. If you have a full time moderator then you can also set New user Moderation Level to User is Moderated.
    4. Navigate to the Post Settings in the control panel (/controlpanel/Settings/AdvancedConfiguration.aspx).
    5. Make sure Enable Anonymous Posting is set to No.
    6. Navigate to the Username Filters in the control panel (/controlpanel/tools/UsernameFilter.aspx).
    7. Add any words you think are necessary, like offensive words. I would also add words of medication, payment or buying keywords, and health.
    8. Navigate to the Manage Spam Blocker in the control panel (controlpanel/tools/ManageSpamRules.aspx).
    9. Enable User Creation IP Frequency and configure the minutes to be 1440. This will stop all the spammers from joining from the same IP.
    10. Enable any rules you think would benefit your community.
    11. Click Save.

    If you came to this article because you already had your site taken over by spam users created by bots, then continue reading. Please note: before continuing please create a database backup and continue at your own risk. I am not liable for any harm that comes to your database or community after running the following query.

    1. Navigate to Manage Users in the control panel (controlpanel/membership/membersearch.aspx?SelectedNavItem=BrowseMembers).
    2. Next if you know the email address of the spam account in question then enter *aspamdomain.com (replacing the domain name with the email domain in question). Now if this returns only the spam accounts in question continue, otherwise you will need to modify the search criteria until you see the list of spam accounts.
    3. Open SQL Server Management Studio and connect to your community server database.
    4. Now backup your community server database. Here is a how to guide.
    5. Run the following query and make sure it returns the list of user accounts you want to remove.  You may need to update this query and change the domain name from step 2.
         1: SELECT * FROM cs_users WHERE Email LIKE '%@aspamdomain.com'
    6. If you notice that you had a bunch of users join your site all from a certain domain then this TSQL script will work for you out of the box. Also if your spam bots have created posts, you may want to create a new user of which you want to assign the spam posts to. All you need to do is to create a new user account and change line 18 from Anonymous to the case sensitive user name you created.  I modified the following query quite a bit to fit this scenario. Please note: you will need to update line 10 to match the like query in step 5 and also change the domain name.
         1: declare @Proc nvarchar(50)
         2: declare @RowCnt int
         3: declare @MaxRows int
         4: declare @ExecSql nvarchar(255)
         5: declare @user_id int
         6:  
         7: select @RowCnt = 1
         8:  
         9: declare @Import table (rownum int IDENTITY (1, 1) Primary key NOT NULL , UserID int NOT NULL)
        10: insert into @Import (UserID) select UserID from cs_users where Email like '%@aspamdomain.com'
        11:  
        12: select @MaxRows = count(*) from @Import
        13:  
        14: while @RowCnt <= @MaxRows
        15: begin
        16:     select @user_id = UserID from @Import where rownum = @RowCnt
        17:  
        18:     execute [dbo].[cs_User_Delete] @user_id, 'Anonymous'
        19:  
        20:     Set @RowCnt = @RowCnt + 1
        21: end
    7. Go back and run the query from step 5, If it returns no results then all the spam accounts have been removed.
  • How to protect your Community Server site from rouge spiders with a robots text file.

    Over the course of the past two years, I have worked on a number of Community Server sites. The goal of these tips are to share useful information about Telligent's Community Server platform. There are a few ways you can protect yourself from rouge search bots from stealing your content and bringing down your site. 

    The easiest way is to setup a robots text file, which will tell search engines to ignore certain files or directories. I found this guide which was very helpful on setting up a robots.txt file in the root directory of your website. There are a few disadvantages to this approach.

    • It isn’t guaranteed to work. There are companies out there who don’t care what safe guards you have setup. They are just concerned with indexing or stealing your content.
    • People do list there private directories in the robots file thus opening themselves for making public any documents they think are hidden.

    If this doesn’t work, and trust me sometimes it doesn’t always work as I learned a few months ago, then you need to go to the extra step. If you take a look at your exception log in community server by navigating to (/controlpanel/Tools/Reports/ExceptionsReport.aspx) or by running the following SQL Query:

       1: SELECT [Frequency], [IPAddress], [UserAgent], [HttpReferrer], [HttpVerb], [PathAndQuery], [Exception], [ExceptionMessage], [DateLastOccurred] FROM [dbo].[cs_Exceptions] ORDER BY DateLastOccurred DESC

    You will see the IP Address and the name of the spider that's bringing down your site. From here you need to open up Internet Information Services (IIS) Manager. Once open you need to navigate to the site you want to block the IP or IP Range from accessing and then click on IP Address and Domain Restrictions

    Internet Information Services (IIS) Manager (2)

    Next right click and click Add Allow Entry or Add Deny Entry and fill in the information.

    Add Allow Restriction Rule 

    The spider has now been blocked. I’d suggest keeping an eye on this and blocking the IP Range of the spider. The last step is to contact the owner of the spider and ask them to stop. You can get this information by looking up the IP Address through Network Solutions.

1 2 Next >
windowscoding.com;
Copyright © 2008 Windows Coding
Microsoft and Microsoft logo's are trademarks of Microsoft Corporation.