Sunday, February 05, 2012 Register  Login

This site uses DNS Made Easy. Use it for reliable and professional DNS services.

RSS Feeds
Categories
  
Blog Archives
  
Blog

Code

    Apr
    27

    I've been working a lot more with LINQ2SQL and LINQ2Entities lately, and I ran into my first issue at the end of last week. I couldn't figure out why null parameters were causing the query to return strange results.

    The original query looked like this:

       List<MenuLayoutDataEntity> ret = (from c in _Context.tblMenuLayouts
                                         where c.ConceptID == entity.ConceptID
                                         && c.ItemID == entity.ItemID
                                         && c.MarketID == entity.MarketID
                                         && c.DepartmentID == entity.DepartmentID
                                         orderby c.SortOrder
                                         select new MenuLayoutDataEntity()
                                         {
                                             MenuID = c.MenuID,
                                             ItemNamePOS = c.ItemNamePOS,
                                             ItemID = c.ItemID.HasValue ? c.ItemID.Value : -1
                                         }).ToList();

    Sometimes, the MarketID and DepartmentID would be null, and that's what was causing the problem. After some Googling, I found that I need to enclose the equality using the Equals method in the object class. Here's the query using Equals:

       List<MenuLayoutDataEntity> ret = (from c in _Context.tblMenuLayouts
                                         where c.ConceptID == entity.ConceptID
                                         && c.ItemID == entity.ItemID
                                         && Equals(c.MarketID, entity.MarketID)
                                         && Equals(c.DepartmentID, entity.DepartmentID)
                                         orderby c.SortOrder
                                         select new MenuLayoutDataEntity()
                                         {
                                             MenuID = c.MenuID,
                                             ItemNamePOS = c.ItemNamePOS,
                                             ItemID = c.ItemID.HasValue ? c.ItemID.Value : -1
                                         }).ToList();

    Unfortunately, this only works for LINQ2SQL, and this query is actually a LINQ2Entities query. So back to Googling. I finally found a hint in a post over at StackOverflow. Apparently, there's is a bug in the LINQ2Entities parser when trying to use IS NULL functionality in the where clause. The solution was to check the value on the entity class, and then select a specific query. Here's the results that actually gave me the results that I wanted:

                List<MenuLayoutDataEntity> ret = null;
                // Check if this is a store item, i.e. Departmental
                if (entity.MarketID.HasValue && entity.DepartmentID.HasValue)
                {
                    ret = (from c in _Context.tblMenuLayouts
                           where c.ConceptID == entity.ConceptID
                                 && c.ItemID == entity.ItemID
                                 && c.MarketID == entity.MarketID
                                 && c.DepartmentID == entity.DepartmentID
                           orderby c.SortOrder
                           select new MenuLayoutDataEntity()
                           {
                               MenuID = c.MenuID,
                               ItemNamePOS = c.ItemNamePOS,
                               ItemID = c.ItemID.HasValue ? c.ItemID.Value : -1
                           }).Distinct().ToList();
                }
                // Check if this is a market item, i.e. MarketID is not null
                if (entity.MarketID.HasValue && !entity.DepartmentID.HasValue)
                {
                    ret = (from c in _Context.tblMenuLayouts
                           where c.ConceptID == entity.ConceptID
                                 && c.ItemID == entity.ItemID
                                 && c.MarketID == entity.MarketID
                                 && c.DepartmentID == null
                           orderby c.SortOrder
                           select new MenuLayoutDataEntity()
                           {
                               MenuID = c.MenuID,
                               ItemNamePOS = c.ItemNamePOS,
                               ItemID = c.ItemID.HasValue ? c.ItemID.Value : -1
                           }).Distinct().ToList();
                }
                // Check if this is a global item, i.e. both MarketID and DepartmentID are null
                if (!entity.MarketID.HasValue && !entity.DepartmentID.HasValue)
                {
                    ret = (from c in _Context.tblMenuLayouts
                           where c.ConceptID == entity.ConceptID
                                 && c.ItemID == entity.ItemID
                                 && c.MarketID == null
                                 && c.DepartmentID == null
                           orderby c.SortOrder
                           select new MenuLayoutDataEntity()
                           {
                               MenuID = c.MenuID,
                               ItemNamePOS = c.ItemNamePOS,
                               ItemID = c.ItemID.HasValue ? c.ItemID.Value : -1
                           }).Distinct().ToList();
                }

    Very annoying, but at least I know how to handle this. Hopefully this will help another soul out there.

    posted @ Wednesday, April 27, 2011 11:32 AM by Hector Sosa, Jr

    Posted in: Code, Databases

    Actions:Tweet This Share on Facebook Share on LinkedIn Emakl Permalink del.icio.us
    Jan
    27
     518 Views ::  1 Comments RSS comment feed

    I got tired of having to hand-copy file paths into the InnoSetup script for PainlessSVN. I'm specifically referring to the Subversion server files. There's something like 278 files, that are in nested folders. I had just finished pasting in all the paths for Subversion 1.6.13, when 1.6.15 was released and I was seriously dreading repeating this whole excersise again.

    I needed something that would recurse through both files and folders. It's easy doing one or the other, but not both at the same time (at least for me). I spent about 3 hours last night working on this. The good thing about this code is that I needed something similar for the new DeleteDevCrumbs utility that I'm polishing for release.

    As it currently stands, this code will create a list of files from the directory that is passed in through a command-line argument, scan the child directories, and create a text file for you. The file will contain a ready made list that can be pasted right in the [Files] section of an InnoSetup script.

    Here's a console app with this code: 

    using System.Collections.Generic;
    using System.IO;

    namespace ScanFilesTest {     class Program     {         private static List<string>  _tree = new List<string>();         static void Main(string[] args)         {             string rootDirectory = args[0];             var rootInfo = new DirectoryInfo(rootDirectory);             if (!rootInfo.Exists)             {                 throw new DirectoryNotFoundException(string.Format("{0} does not exist!", rootInfo.FullName));             }             FileInfo[] files = rootInfo.GetFiles();             if (files.Length > 0)             {                 ScanFolders(files);             }             else             {                 DirectoryInfo[] folders = rootInfo.GetDirectories();                 ScanFolders(folders);             }             TextWriter subversionList = new StreamWriter("D:\\subversionfilelist.txt");             foreach (var file in _tree)             {                 var currInfo = new FileInfo(file);                 string currDir = currInfo.FullName.Replace(rootDirectory, string.Empty);                 subversionList.WriteLine(string.Format("Source: {0}; DestDir: {{pf}}\\Subversion{1}; Components: Subversion", file, currDir));                 subversionList.Flush();             }             subversionList.Close();         }         private static void ScanFolders(FileInfo[] files)         {             foreach (var file in files)             {                 if (file != null && !string.IsNullOrEmpty(file.FullName))                 {                     _tree.Add(file.FullName);                  }             }             if (files.Length > 0)             {                 string root = files[0].DirectoryName;                 var rootInfo = new DirectoryInfo(root);                 DirectoryInfo[] folders = rootInfo.GetDirectories();                 if (folders.Length > 0)                 {                     ScanFolders(folders);                  }              }         }         private static void ScanFolders(IEnumerable<DirectoryInfo> folders)         {             foreach (var folder in folders)             {                 if (folder.GetFiles().Length > 0)                 {                     ScanFolders(folder.GetFiles());                 }                 else                 {                     if (folder.GetDirectories().Length > 0)                     {                         ScanFolders(folder.GetDirectories());                     }                     else                     {                         if (folder != null && !string.IsNullOrEmpty(folder.FullName))                         {                             _tree.Add(folder.FullName);                         }                     }                 }             }         }     } }

    posted @ Thursday, January 27, 2011 10:18 AM by Hector Sosa, Jr

    Actions:Tweet This Share on Facebook Share on LinkedIn Emakl Permalink del.icio.us
    Oct
    09
     947 Views ::  13 Comments RSS comment feed

    I'm involved in creating a COM interface from a C# 4.0 library. This took a lot of hair-pulling and banging-head-against-the-wall moments. This skillset appears to be quickly disappearing; sad, but quite understandable. I wanted to store how this is done, because I found many little slivers across the Intertubes, but nowhere did I find the slivers put into a coherent picture.

    I'm going to use a simple class that I'm calling ComDog. Here is the definition:

    using System;

    using System.Runtime.InteropServices;

    namespace ComDog

    {

        [ComVisible(false)]

        public delegatevoid DogEventHandler();

        [ComVisible(true)]

        [Guid("2406DD50-A3CE-43A6-9F20-112B621CB784")]

        [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]

        public interfaceIDogEvents

       {

            [DispId(1)]

            void Bark(); 

            [DispId(2)]

            void Howl(); 

            [DispId(3)]

            void Eat();

        }

        [ComVisible(true)]

        [Guid("8C6DAD17-0612-4166-AD35-3A55DDEAF62E")]

        [ClassInterface(ClassInterfaceType.AutoDual)]

        [ComSourceInterfaces(typeof(IDogEvents))]

        public class Dog : MarshalByRefObject

       {

            public event DogEventHandler Bark;

            public event DogEventHandler Howl;

            public event DogEventHandler Eat;

     

            public void MakeDogBark()

           {

                if (Bark != null)

               {

                   Bark();

               }

           }

     

            public void MakeDogHowl()

           {

                if (Howl != null)

               {

                   Howl();

               }

           }

     

            public void MakeDogEat()

           {

                if (Eat != null)

               {

                   Eat();

               }

           }

       }

    Now let's get this compiled and registered. To get this registered with COM, well need to issue this command, in an elevated command prompt:

    C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm comdog.dll /tlb:ComDog.tlb

    Now on to Delphi 7...

    Copy both the ComDog.dll and ComDog.tlb to the same folder as your Delphi project. I'm doing this, because I don't want to mess with the GAC.

    In the Delphi IDE, select Project --> Import Type Library. It will look like this:

    This in turn, should show the Import Type Library dialog, that looks like this:

    If you registered the assembly (dll in .NET parlance), you should see an entry for ComDog, like the selected one in the dialog above. Click on the "Create Unit" button. This will add a "ComDog_TLB.pas" file to your Delphi project.

    One important section that I want to direct your attention to:

    // *********************************************************************//
    // OLE Server Proxy class declaration
    // Server Object    : TDog
    // Help String      :
    // Default Interface: _Dog
    // Def. Intf. DISP? : No
    // Event   Interface: IDogEvents
    // TypeFlags        : (2) CanCreate
    // *********************************************************************//
    {$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
      TDogProperties= class;
    {$ENDIF}
      TDog = class(TOleServer)
      private
        FOnBark: TNotifyEvent;
        FOnHowl: TNotifyEvent;
        FOnEat: TNotifyEvent;
        FIntf:        _Dog;

    The events are of type TNotifyEvent, because they do not have parameters. This comes from the IDogEvents. Delphi will ALWAYS use the definition in your event interface, instead of the events listed in the main class. Make absolutely sure that the signature in the event interface match the signature of the events in your main C# class.

    Here is what the definition of the events will look like in your Delphi main form/unit:

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ActiveX, ComObj, ComDog_TLB, StdCtrls, OleServer;

    type
      TForm1 = class(TForm)
        btnBark: TButton;
        btnHowl: TButton;
        btnEat: TButton;
        Memo1: TMemo;
        procedure FormCreate(Sender: TObject);
        procedure btnBarkClick(Sender: TObject);
        procedure btnHowlClick(Sender: TObject);
        procedure btnEatClick(Sender: TObject);
      private
        { Private declarations }
      protected
        procedure Barked(Sender: TObject);
        procedure Howled(Sender: TObject);
        procedure Ate(Sender: TObject);
      public
        { Public declarations }
      end;

    var
      Form1: TForm1;
      TestDog: TDog;

    The proctected section above defines the events. This you will have to type manually. Make sure that your _TLB file is listed in the uses section above.

    Now to actually have the events handled, you will have to create a procedure that matches the signature of event. Like so:

    procedure TForm1.Barked(Sender: TObject);
    begin
      Memo1.Lines.Add('Dog Barked');
    end;

    procedure TForm1.Howled(Sender: TObject);
    begin
      Memo1.Lines.Add('Dog Howled');
    end;

    procedure TForm1.Ate(Sender: TObject);
    begin
      Memo1.Lines.Add('Dog ate something');
    end;

    This is how you wire up C# COM events up to a Delphi COM client app.

    The next question is how to deal with events that have parameters. It's basically the same thing. You'll just have to make sure that the signatures for event definitions and event handlers in Delphi, match what's in the _TLB file.

    I did a lot of hair-pulling in order to get this working. I wanted to post this in my blog, for the next time I'm doing this. Please feel free to comment here, if you need more help.

    posted @ Saturday, October 09, 2010 6:34 AM by Hector Sosa, Jr

    Actions:Tweet This Share on Facebook Share on LinkedIn Emakl Permalink del.icio.us
    Feb
    10

    I just finished creating a new release on CodePlex for SVNManagerLib 0.5.6. Here is a list of what is new:

    NEW - Upgraded the solution to Visual Studio 2008.
    NEW - Started introducing interfaces
    NEW - Introduced lazy loading of anything below repository level
    NEW - Deprecated SVNController for SubversionServerController
    NEW - Deprecated SVNRepository for ISubversionRepository, SubversionRepositoryBase, and SvnServeRepository. This will open the way for eventually adding Apache support.
    NEW - Broke out RepositoryRootDirectoryDoesNotExistException into a file
    NEW - Added support for using a global configuration file.
    NEW - Added support for Subversion Realms.
    NEW - Finished the code for loading dump files. Hasn't been tested yet!
    NEW - Added RepositoryRootDirectoryDoesNotExistException.cs to help deal with the issue of disconnected mapped drives in Vista.
    NEW - Many little code refactorings to help readability

    http://www.codeplex.com/svnmanagerlib

    posted @ Tuesday, February 10, 2009 1:58 AM by Hector Sosa, Jr

    Actions:Tweet This Share on Facebook Share on LinkedIn Emakl Permalink del.icio.us
    Jan
    11

    I was installing one of my new 1 tb drives on my system at home. I went ahead and moved all my virtual machines to this new drive. While doing this, I found that I had downloaded a VMWare image from the Mono Project. This has Mono 2.0.1 and Suse 11.0. Since I was wide awake from my migraine medication, I decided to see if could still compile SVNManagerLib on Linux. To my delight, MonoDevelop compiled it fine, without any errors. Here's a screeshot fo SVNManagerLib compiled in MonoDevelop 1.0 running in Suse 11.0:

    svnmanagerlib compiled in MonoDevelop 1.0

    And here is a screenshot of the TestHarness winform app compiled successfully as well:

    And here is the TestHarness running from MonoDevelop:

    This is soooo cool! I just downloaded the zip file from the CodePlex page at www.codeplex.com/svnmanagerlib I clicked on the Source tab, then downloaded the last changeset. It worked without any changes to the source. This is the library that powers PainlessSVN and SVN Backup Widget.

    Now I just need to find a good tutorial on how to install Subversion in Suse 11. I'm a total n00b when it comes to Linux, and none of the How-To docs out there have helped me here. Anybody has a good resource for installing Subversion in Suse 11?

    posted @ Sunday, January 11, 2009 2:02 AM by Hector Sosa, Jr

    Actions:Tweet This Share on Facebook Share on LinkedIn Emakl Permalink del.icio.us
    Nov
    24
     1458 Views ::  1 Comments RSS comment feed

    The integration that I had with my ecommerce DNN module (ActivePurchase) broke when I moved the site to PowerDNN. I have been fighting with this for a couple weeks now.

    Here's what happened:
    The part that sends the serial number did not work anymore, because the SMTP server was not on the same network. Changing the settings did not work at first. I went googling for sending emails from DNN. I got some good hits for sending email from inside DNN modules.

    The API for this is fairly simple (relatively). You first make a reference to DotNetNuke.Services.Mail. Then you make a call to the Mail.SendMail() method, with the appropriate parameters. There are 5 overloads. The call from a module would look like this:

    DotNetNuke.Services.Mail.Mail.SendMail(FromAddress, SendTo, "", Subject, Body, "", "", "", "", "", "")

    Well, that didn't work. So now I was scratching my head.

    I am using a special type of integration called a custom step, which is just an assembly in the bin directory for the DotNetNuke install. I had to go and dig into the event log that DNN keeps. There were several exceptions there. The message was that the SMTP connection needed to be authenticated. WTF??

    Custom DNN modules use the SMTP settings that the administrator has setup. However, the custom step does not get treated as a module. So I had to do this:

    DotNetNuke.Services.Mail.Mail.SendMail(FromAddress, SendTo, "", Subject, Body, "", "", "", "", UserName, Password)

    Once I did that, the custom step started sending emails like before. YES!

    Now that this is fixed, I can get my undivided attention back to PainlessSVN and SVN Backup Widget stuff.

    posted @ Monday, November 24, 2008 10:29 PM by Hector Sosa, Jr

    Actions:Tweet This Share on Facebook Share on LinkedIn Emakl Permalink del.icio.us
    Sep
    07

    I finally got PainlessSVN to read the icons that are associated with files in the Windows shell. That took some Win32 API hacking though.

    Here's a screenshot of the left hand side treeview:

    Here is a screenshot of the details pane:

     

    I got the base code for doing this from this Microsoft link:

    www.microsoft.com/downloads/details.aspx

    This code is VB.NET, but it's fairly easy to convert to C#. Ok, I cheated. I pasted the VB.NET code into SharpDevelop 3.0, and let it convert it to C#. Didn't have to change anything. Visual Studio took the code without complaining.

     

    posted @ Sunday, September 07, 2008 4:18 PM by Hector Sosa, Jr

    Actions:Tweet This Share on Facebook Share on LinkedIn Emakl Permalink del.icio.us
    Jun
    16

     


    Well, I had a hair pulling session trying to recover the passwords on my hobby site. Both my admin and host paswords got hosed, so I couldn't just login and fix them.
    I first went Googling to find a winform app to help with this problem. Well, all the solutions were just modules to install on your DotNetNuke installation. Since I can't even login as host, this approach is just totally useless. Thankfully, DNN uses the ASP.NET 2.0 Membership Providers.
    So, I started with Membership.Provider.RetrievePassword(). Oops, "Bad Data". Crap! I tried other account passwords with the same result. Double-Crap! I modified my little winform app, to now reset passwords. This time I used Membership.Provider.ResetPassword(). Got a new password for host, and I was able to login now. YES! I'm using .NET 2.0 for this winform app.
    So if you want to get this working, here is what you need to do:
    Make sure that you include the following sections from your DNN's website web.config file:
    connectionStrings
    system.web
    You only need the membership and machineKey sections inside system.web.
    Import System.Configuration and System.Web into your project. All of the needed API calls will be under Membership.Provider namespace. You'll find a lot of samples on how to use on Google.


    Anyways, I wanted to put it somewhere, so that I can find it later, WHEN I would need to do this again.

    posted @ Monday, June 16, 2008 11:09 AM by Hector Sosa, Jr

    Actions:Tweet This Share on Facebook Share on LinkedIn Emakl Permalink del.icio.us
    Apr
    02

    I have several Subversion servers on my network, so I'm registering new servers in PainlessSVN fairly often. I got tired of trying to figure out what server I was hooked to, so I added a little visual tweak on the server node.

    Server node has server name and drive

    So now, I can tell exactly what server I'm working with at a glance. I will probably end up adding the ability to keep several servers registered, a la Enterprise Manager and SQL Server Management Studio.

    I had to mess with Win32 APIs in order to get this working correctly. Here are the API calls that I used:


    public
    const uint DRIVE_UNKNOWN = 0; // unknow drive type
    public
    const uint DRIVE_NO_ROOT_DIR = 1; // invalid root path was given to the function
    public
    const uint DRIVE_REMOVABLE = 2; // removeable drive like a floppy
    public
    const uint DRIVE_FIXED = 3; // a fixed drive like a hard disk
    public
    const uint DRIVE_REMOTE = 4; // a network drive
    public
    const uint DRIVE_CDROM = 5; // a cd-rom drive
    public
    const uint DRIVE_RAMDISK = 6; // a ram disk
     
    [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public
    static extern uint GetDriveType(string lpRootPathName);

    [DllImport("mpr.dll")]
    [return: MarshalAs(UnmanagedType.U4)]
    public
    static extern int WNetGetUniversalName(
    string
    lpLocalPath,
    [MarshalAs(UnmanagedType.U4)] int dwInfoLevel,
    IntPtr
    lpBuffer,
    [MarshalAs(UnmanagedType.U4)] ref int lpBufferSize);

    posted @ Wednesday, April 02, 2008 10:22 PM by Hector Sosa, Jr

    Posted in: PainlessSVN, Code

    Actions:Tweet This Share on Facebook Share on LinkedIn Emakl Permalink del.icio.us
    Oct
    31
     754 Views ::  5 Comments RSS comment feed

    After some more testing I found that the URIBuilder class does not work correctly with UNC path. Here's the updated code: 

    public static string PathToFileUrl( string pathToConvert )
    {
        string fileURL = "";
        bool isUNC;
        UriBuilder fileURI = null;
     
        // This is to capture whether the incoming path is
        // an UNC path or not.
        if ( pathToConvert.StartsWith( @"\\" ) )
        {
            isUNC = true;
        }
        else
        {
            isUNC = false;
        }
     
        try
        {
            fileURI = new UriBuilder( pathToConvert );
        }
        catch( UriFormatException ex )
        {
            // This is for debugging
            string msg = ex.Message;
        }
     
        if ( isUNC )
        {
            if ( fileURI != null ) fileURL = fileURI.ToString();
        }
        else
        {
       if ( fileURI != null ) fileURL = fileURI.ToString().Replace( "file://", "file:///" );
        }
     
        return fileURL;
    }

    posted @ Wednesday, October 31, 2007 12:33 AM by Hector Sosa, Jr

    Posted in: Code

    Actions:Tweet This Share on Facebook Share on LinkedIn Emakl Permalink del.icio.us
    Page 1 of 2First   Previous   [1]  2  Next   Last   
    Terms Of Use | Privacy Statement | SystemWidgets
    Copyright 2002-2012 by SystemWidgets
    Google Analytics Alternative