How to add helpstring in tlb generate from VB.NET or C# class

25. January 2012 11:34 by Mrojas in COM Interop  //  Tags: , , , , ,   //   Comments (0)

In IDL you can have a helpstring attribute that adds descriptions to your interfaces.
To be able to generated those helpstring tags in a VB.NET  class you should use the Description tag

For example see this example taken from:http://stackoverflow.com/questions/6668500/getting-the-helpstring-attribute-applied-to-c-sharp-properties-exposed-via-com-i

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;



namespace ClassLibrary1 {
    [ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface IFoo {
        int property {
            [Description("prop")]
            get;
            [Description("prop")]
            set;
        }
    }
}

NOTE: remenber that in some cases you have to apply the description attribute to both get and set.

ADITIONAL NODE:

After some test, I found that there are some differences with the helpstring behaviour in VB.NET. For example the helpstring attribute is not generated for methods. More on C#/VB.NET Interop Differences http://mheironimus.blogspot.com/2006/10/vbnet-com-interface-issues.html

Quick replacement for the VB6 OLE Container Control in .NET

23. January 2012 13:09 by Mrojas in COM Interop  //  Tags: , , , , ,   //   Comments (0)

I have developed a very quick replacement for the OLE Container Control that you had in VB6.
I just did it in rush so it just supports basic properties as DisplayType Icon or Content
The content functionality is performed using the Vista feature for content preview. I would have tried using a 
WebBrowser control but in new versions of Office, the default is not showing the document on the Browser and
it might be difficult to change the registry in some vista or Win7 environments.

 The following picture show the OLEContainer inside a Windows Form.

This is the container with the Display set to content:

 

And the container with display set to icon:

 

You can call the CreateLink and you can also use the DoVerb Open.

I have attached the example source code in this post.

ReplaceOLEContainer.zip (100.69 kb)

UPDATE

 NOTE: I friend also sent me a link to this article in CodeProject which is very similar: http://www.codeproject.com/Tips/487566/OLE-container-surrogate-for-NET

 

NOTE: This solution only applies for read-only. If you wan to edit your files, then you need a real ActiveX container. MS used to have a sample OCX called DSOFramer that allows you to do that. Warning: this sample is no longer supported by MS becuase it said to have issues However I have used it in the past and it worked fine in some simple scenarios. I have added the control and its source to this post. There is a commercial product from Edraw http://www.edrawsoft.com/edword.php that is supported by them and has samples for C# and VB.NET

 

 NOTE: Another approach, embed the application in your windows form.

In general what you should do is use the SetParent, SetWindowLong and MoveWindow APIs to embed the application. Something like this:

var filename = openFileDialog1.FileName;
                var officeApplicationProgID = "Excel.Application";
                var officeApplicationType = Type.GetTypeFromProgID(officeApplicationProgID, false);
                dynamic officeApplication = Activator.CreateInstance(officeApplicationType);
                officeApplication.Workbooks.Open(filename);
                int pid = 0;
                GetWindowThreadProcessId(officeApplication.HWnd, out pid);
                officeApplication.Visible = true;
                //officeApplication.Visible = false;
                var process = Process.GetProcessById(pid);
                var panel = new Panel();
                panel.Location = new Point(0, 0);
                panel.Size = new Size(this.Size.Width, this.Size.Height);
                var processHandle = process.MainWindowHandle;
                SetParent(processHandle, panel.Handle);
                SetWindowLong(processHandle, GWL_STYLE, WS_VISIBLE + WS_MAXIMIZE + WS_CHILD);
                MoveWindow(processHandle, 0, 0, panel.Width, panel.Height, true);
                this.mainBody.Controls.Add(panel);
 
Figure: Example of technique of hosting Excel inside a Windows Form Application

I have attached a sample project. (Remember to free your resources, and close the excel App before closing your application, I skipped that from this sample)

DsoFramer.zip (463.42 kb)

ExampleOfEmbeddingExcelInWindowsForm.zip (53.76 kb)

Migration of Point of Sale (POS) Applications to Mobile/Tablet Devices

22. January 2012 23:54 by Mrojas in HTML5  //  Tags: , , , , , , , , , , , , ,   //   Comments (0)

A long time ago, I had the idea of writing a series of posts about the issues
related to the migration of Point Of Sale applications developed in VB6.
(http://blogs.artinsoft.net/Mrojas/archive/2007/05/07/Migration-of-VB6-POS.aspx)

 A lot of companies developed this kind of software in VB6, and they faced a lot of
of similar issues specially when dealing with POS devices.

 

It's nice that the industry has made the effort of developing standards as the UPOS or
Unified POS (http://en.wikipedia.org/wiki/UnifiedPOS) and Microsoft also did a great work
by providing the COM and .NET implementations.

 

It was nice to move VB6 applications to POS for .NET, but times have change and so
has the UPOS grown to interesting proposals like WS-POS.

 

"The fundamental benefit of WS-POS is the ability to provision POS peripherals as
services that can be accessed by remote POS applications, including mobile POS
solutions. Retailers can then use the power of Service-Oriented Architecture (SOA)
to allow access to their existing peripherals anywhere in the store through these
services. WS-POS holds potential benefits for all members of the retail ecosystem." from http://www.ibm.com/developerworks/webservices/library/ws-pos-retail/index.html 

 

So you can now think about leveraring your VB6 POS to Silverlight or HTML5 and
consume WS-POS services to provide for example tablet-based implementations.
Imagine your POS application running in Silverlight or WinFX on a Windows 8 Tablet
or in HTML5 in iPads or Androids. Does it sound appealing? Well that is exactly the
kind of experience that our migration solution brings to the table.

 

 

 

You can download a working implementation of WS-POS from the  Association for Retail
Technology Standards (ARTS) web site.
Go to http://www.nrf-arts.org/arts_download/schema-non-member
Download the UnifiedPOS 1.13 pdfs and reference implementation from the
WS-POS Addendum link (http://www.nrf-arts.org/download/file?f=http://www.nrf.com/Attachments.asp?id=30476&rid=227810) There are Java and WCF implementations. It is also very easy to modify the WCF
implementation so it can receive and respond JSON and work with your HTML5 implementations.

I always appreciate feedback, so if you have any more toughts or questions about HTML5 or Windows 8 POS implementations just let me know.

 

Printing BarCodes in Silverlight

19. January 2012 10:32 by Mrojas in Silverlight  //  Tags: , , , ,   //   Comments (0)

Well I tought this was gonna be more difficult, but no. The Silverlight community is great and there are tons of
of  code out there.

So I found a great project in codeplex called obviously http://silverlightbarcode.codeplex.com/

And printing barcode with that library is a peace of cake.

Just do something like this:

 

private void button1_Click(object sender, RoutedEventArgs e)
{
    var p = new PrintDocument();
    p.PrintPage += new EventHandler<PrintPageEventArgs>(p_PrintPage);
    p.Print("NuevoDocument");
}

void p_PrintPage(object sender, PrintPageEventArgs e)
{
    Canvas canvasBarCode = new Canvas();
    canvasBarCode.Width = 200;
    canvasBarCode.Height = 200;
    Me.BarcodeSoftware.Barcode.Barcodes barcode = 
           new Me.BarcodeSoftware.Barcode.Barcodes();
    barcode.BarcodeType =        
                  Me.BarcodeSoftware.Barcode.Barcodes.BarcodeEnum.Code39;
    barcode.Data = "123456";
    barcode.encode();
    string encodedData = barcode.EncodedData;
    //if you want to put the barcode number 
        // add a label to canvas and set text to barcode.HumanText;

    int encodedLength = 0;
    for (int x = 0; x < encodedData.Length; x++)
    {
        if (encodedData[x] == 't')
            encodedLength++;
        else if (encodedData[x] == 'w')
            encodedLength = encodedLength + 3;
    }

    float barWidth = (float)(canvasBarCode.Width / encodedLength);

    if (barWidth < 1) barWidth = 1;
    float thickWidth = barWidth * 3;
    double incrementWidth = 0;

    int swing = 0;
    for (int x = 0; x < encodedData.Length; x++)
    {
        Brush brush;
        if (swing == 0)
            brush = new SolidColorBrush(Colors.Black);
        else
            brush = new SolidColorBrush(Colors.White);

        if (encodedData[x] == 't')
        {
            Rectangle r = new Rectangle();
            r.Fill = brush;
            r.Width = barWidth;
            r.Height = canvasBarCode.Height;
            r.SetValue(Canvas.LeftProperty, incrementWidth);
            r.SetValue(Canvas.TopProperty, 0.0);
            canvasBarCode.Children.Add(r);
            incrementWidth = incrementWidth + ((barWidth));
        }
        else if (encodedData[x] == 'w')
        {
            Rectangle r = new Rectangle();
            r.Fill = brush;
            r.Width = 3 * barWidth;
            r.Height = canvasBarCode.Height;
            r.SetValue(Canvas.LeftProperty, incrementWidth);
            r.SetValue(Canvas.TopProperty, 0.0);
            canvasBarCode.Children.Add(r);
            incrementWidth = incrementWidth + (3 * (barWidth));
        }

        if (swing == 0)
           swing = 1;
        else
           swing = 0;
    }
    e.PageVisual = canvasBarCode;
    e.HasMorePages = false;

}

Printing BarCodes in Silverlight

19. January 2012 10:32 by Mrojas in Silverlight  //  Tags: , , , ,   //   Comments (0)

Well I tought this was gonna be more difficult, but no. The Silverlight community is great and there are tons of
of  code out there.

So I found a great project in codeplex called obviously http://silverlightbarcode.codeplex.com/

And printing barcode with that library is a peace of cake.

Just do something like this:

 

private void button1_Click(object sender, RoutedEventArgs e)
{
    var p = new PrintDocument();
    p.PrintPage += new EventHandler<PrintPageEventArgs>(p_PrintPage);
    p.Print("NuevoDocument");
}

void p_PrintPage(object sender, PrintPageEventArgs e)
{
    Canvas canvasBarCode = new Canvas();
    canvasBarCode.Width = 200;
    canvasBarCode.Height = 200;
    Me.BarcodeSoftware.Barcode.Barcodes barcode = 
           new Me.BarcodeSoftware.Barcode.Barcodes();
    barcode.BarcodeType =        
                  Me.BarcodeSoftware.Barcode.Barcodes.BarcodeEnum.Code39;
    barcode.Data = "123456";
    barcode.encode();
    string encodedData = barcode.EncodedData;
    //if you want to put the barcode number 
        // add a label to canvas and set text to barcode.HumanText;

    int encodedLength = 0;
    for (int x = 0; x < encodedData.Length; x++)
    {
        if (encodedData[x] == 't')
            encodedLength++;
        else if (encodedData[x] == 'w')
            encodedLength = encodedLength + 3;
    }

    float barWidth = (float)(canvasBarCode.Width / encodedLength);

    if (barWidth < 1) barWidth = 1;
    float thickWidth = barWidth * 3;
    double incrementWidth = 0;

    int swing = 0;
    for (int x = 0; x < encodedData.Length; x++)
    {
        Brush brush;
        if (swing == 0)
            brush = new SolidColorBrush(Colors.Black);
        else
            brush = new SolidColorBrush(Colors.White);

        if (encodedData[x] == 't')
        {
            Rectangle r = new Rectangle();
            r.Fill = brush;
            r.Width = barWidth;
            r.Height = canvasBarCode.Height;
            r.SetValue(Canvas.LeftProperty, incrementWidth);
            r.SetValue(Canvas.TopProperty, 0.0);
            canvasBarCode.Children.Add(r);
            incrementWidth = incrementWidth + ((barWidth));
        }
        else if (encodedData[x] == 'w')
        {
            Rectangle r = new Rectangle();
            r.Fill = brush;
            r.Width = 3 * barWidth;
            r.Height = canvasBarCode.Height;
            r.SetValue(Canvas.LeftProperty, incrementWidth);
            r.SetValue(Canvas.TopProperty, 0.0);
            canvasBarCode.Children.Add(r);
            incrementWidth = incrementWidth + (3 * (barWidth));
        }

        if (swing == 0)
           swing = 1;
        else
           swing = 0;
    }
    e.PageVisual = canvasBarCode;
    e.HasMorePages = false;

}

Printing BarCodes in Silverlight

19. January 2012 10:32 by Mrojas in   //  Tags: , , , ,   //   Comments (0)

Well I tought this was gonna be more difficult, but no. The Silverlight community is great and there are tons of
of  code out there.

So I found a great project in codeplex called obviously http://silverlightbarcode.codeplex.com/

And printing barcode with that library is a peace of cake.

Just do something like this:

 

private void button1_Click(object sender, RoutedEventArgs e)
{
    var p = new PrintDocument();
    p.PrintPage += new EventHandler<PrintPageEventArgs>(p_PrintPage);
    p.Print("NuevoDocument");
}

void p_PrintPage(object sender, PrintPageEventArgs e)
{
    Canvas canvasBarCode = new Canvas();
    canvasBarCode.Width = 200;
    canvasBarCode.Height = 200;
    Me.BarcodeSoftware.Barcode.Barcodes barcode = 
           new Me.BarcodeSoftware.Barcode.Barcodes();
    barcode.BarcodeType =        
                  Me.BarcodeSoftware.Barcode.Barcodes.BarcodeEnum.Code39;
    barcode.Data = "123456";
    barcode.encode();
    string encodedData = barcode.EncodedData;
    //if you want to put the barcode number 
        // add a label to canvas and set text to barcode.HumanText;

    int encodedLength = 0;
    for (int x = 0; x < encodedData.Length; x++)
    {
        if (encodedData[x] == 't')
            encodedLength++;
        else if (encodedData[x] == 'w')
            encodedLength = encodedLength + 3;
    }

    float barWidth = (float)(canvasBarCode.Width / encodedLength);

    if (barWidth < 1) barWidth = 1;
    float thickWidth = barWidth * 3;
    double incrementWidth = 0;

    int swing = 0;
    for (int x = 0; x < encodedData.Length; x++)
    {
        Brush brush;
        if (swing == 0)
            brush = new SolidColorBrush(Colors.Black);
        else
            brush = new SolidColorBrush(Colors.White);

        if (encodedData[x] == 't')
        {
            Rectangle r = new Rectangle();
            r.Fill = brush;
            r.Width = barWidth;
            r.Height = canvasBarCode.Height;
            r.SetValue(Canvas.LeftProperty, incrementWidth);
            r.SetValue(Canvas.TopProperty, 0.0);
            canvasBarCode.Children.Add(r);
            incrementWidth = incrementWidth + ((barWidth));
        }
        else if (encodedData[x] == 'w')
        {
            Rectangle r = new Rectangle();
            r.Fill = brush;
            r.Width = 3 * barWidth;
            r.Height = canvasBarCode.Height;
            r.SetValue(Canvas.LeftProperty, incrementWidth);
            r.SetValue(Canvas.TopProperty, 0.0);
            canvasBarCode.Children.Add(r);
            incrementWidth = incrementWidth + (3 * (barWidth));
        }

        if (swing == 0)
           swing = 1;
        else
           swing = 0;
    }
    e.PageVisual = canvasBarCode;
    e.HasMorePages = false;

}

List users in Active Directory with C#

10. January 2012 15:07 by Mrojas in   //  Tags: , ,   //   Comments (0)
If you ever need to list the user in a domain. For example Artinsoft.com this is code might be helpful

public static void Main()
    {
        var ctx = new PrincipalContext(ContextType.Domain,"Artinsoft",
                                            "DC=artinsoft,DC=com");
        UserPrincipal userPrin = new UserPrincipal(ctx);
        userPrin.Name = "*";
        var searcher = new System.DirectoryServices.AccountManagement.PrincipalSearcher();
        searcher.QueryFilter = userPrin;
        var results = searcher.FindAll();
        foreach (Principal p in results)
        {
            Console.WriteLine("Name:{0},Account={1},DisplayName={2},Distinguish={3}",
p.Name,
p.SamAccountName,
p.DisplayName,
p.DistinguishedName); } }

Can I Install Roslyn in Windows XP?

4. January 2012 14:26 by Mrojas in   //  Tags: ,   //   Comments (0)

Yes, you can.

The only thing that you will need is to copy the sqmapi.dll file that you can find in either: C:\Program Files\Microsoft Visual Studio 10.0\Microsoft Visual Studio 2010 Ultimate - ENU or C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE. as quoted in: http://social.msdn.microsoft.com/Forums/en-US/roslyn/thread/dd38cd0a-eb6e-401c-bec5-28ca2b9b4a5d

Also make sure to have installed Visual Studio 2010 SP1 ans VS SDK SP1

 

Using MARS or There is already an open DataReader associated with this Command which must be closed first.

14. December 2011 10:11 by Mrojas in SQL Server  //  Tags: , , , , ,   //   Comments (0)

 

This is a very strange error that you can find sometimes when working with ADO.NET.

David McKean from MSFT says:

This occurs when you have multiple DataReaders open concurrently on the same connection,
ie you call SqlCommand.ExecuteReader but don't close the SqlDataReader returned by this
method before calling it again (either on the same command or another command on the same connection).

It requires a feature called MultipleActiveResultSets which is not available in all providers.

For example SQL2000 does not support it, it was implemented starting from SQL2005.

Also .NET 2.0 must be used.

For more information about enabling Multiple Active Result Sets see: http://msdn.microsoft.com/en-us/library/h32h3abf(v=vs.80).aspx

A good recommendation to make sure that the the readers are closed is to put them inside a using statement, in that case,
no matter if an exception happened they will be closed and disposed.

If you are using SQL Server 2000, MARS is not available so you can create two different connection objects.

Another good article about this issue is: http://blogs.msdn.com/b/spike/archive/2009/08/20/there-is-already-an-open-datareader-associated-with-this-command-which-must-be-closed-first-explained.aspx

 

But in general to use it is just a change in the connection string:

<connectionStrings>
    <clear />
      <add name="VasquezDB" 
         connectionString="Data Source=rvasquez;Initial Catalog=VasquezDB;
                 Integrated Security=True;MultipleActiveResultSets=Yes" />
 </connectionStrings>

 

Good Luck

 

NOTE: a good link with more details about MARS is:

http://blog.typps.com/2011/04/mars-multiple-active-result-sets.html

Web Standards Update not working after install

25. November 2011 03:12 by Mrojas in General  //  Tags: , , ,   //   Comments (0)

If you were looking for HTML5 and CSS3 support, web standards update is a great choice.

However this install tool does not work if you installation is not in the defualt Visual Studio directory:
C:\Program Files\Microsoft Visual Studio 10.0\Common7

One way to fix it is to run the Web Standard update and after the update look for the default dir:

C:\Program Files\Microsoft Visual Studio 10.0\Common7

and copy and merge its contents in your current instalation directory