Pages

Monday, August 3, 2015

Select a List of Column Names in SQL Server

This gives a list of all the tables and columns in the tables in your database.  The TABLES table was included to exclude views.
Select
    COLUMNS.TABLE_SCHEMA, 
    COLUMNS.TABLE_NAME,
    COLUMNS.COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
inner join
    INFORMATION_SCHEMA.TABLES
    on Tables.TABLE_CATALOG = Columns.TABLE_CATALOG
        and Tables.TABLE_SCHEMA = Columns.TABLE_SCHEMA
        and Tables.TABLE_NAME = COLUMNS.TABLE_NAME
        and Tables.TABLE_TYPE = 'BASE TABLE'
 


...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Sunday, June 1, 2014

Easy Linq Example



Linq is a great tool to introduce the power of SQL to the C# environment.  I have found lots of uses for Linq, but this is just a quick sample to get you started.


 //Create a list of random integers
            List<int> myList = new List<int>();
            Random random = new Random();
            for (int i = 0; i < 1000; i++)
            {
                myList.Add(random.Next(0, 500));
            }

            //list is loaded
            //find the values > 10, eliminate dups, and sort.
            //now watch Linq in action

            List<int> filteredList = myList
                .Where<int>(r => r > 10)
                .Distinct()
                .OrderBy(r => (int)r).ToList();

            int fullList = myList.Count();
            int distinctList = filteredList.Count();

            //pop up the counts
            MessageBox.Show(string.Format("{0} records, {1} unique values.", fullList, distinctList));

            //pop up the list
            MessageBox.Show(string.Join(", ",filteredList.ToList()));







...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Saturday, May 24, 2014

State

I have heard it a thousand times.  Web pages are stateless.  That means that - unlike desktop apps where you load a form with data and it stays loaded as long as the app is running - a web page loads. renders, and the webserver immediately forgets everything.

At least that's the way it was.

In the bad old days, web designers would put hidden fields on the form, and hide data there, sometimes raw data, and sometimes just a handle to session data being stored on the webserver, or in a database.

But these days, our frameworks have built-in storage for state information, and some components save their state data by default. Note the differences:

Create an HTML form (even in an ASP.NET site) and put this code in it.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
    <form id="thisform" action="HtmlPage.html" method="get">
        <input id="Text1" type="text" />
        <input id="Button1" type="submit" value="Post" />
    </form>
</body>
</html>


This is the oldschool way of doing form posts.  Note that if you click the submit button, the text you put in the text box will disappear.  That's because it's state (value) is not being stored.  Now create an asp.net form.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
            <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
            <asp:Button ID="Button1" runat="server" Text="Button" />
    </div>
    </form>
</body>
</html>

Note that this asp.net example remembers the values typed in its boxes on a postback.  Now, in the browser, do a view page source.

Notice that there is a line in there that looks like this:

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="E+wH9na5ksRkcpEtk56HJ50O8S2k8vu5dqruZeQtCdLxTdF9WHAcmxUsqAeaxzlLld9hLgv6LIwp+KFpLzzJEdyW2AOL2gz/b2NZ2SOhfx0=" />
That's the automatic way ASP.NET stores state information on the web page.  If you pick the textbox and look at its properties, you'll notice one called EnableViewstate and another called ViewstateMode.  Saving state is enabled by default.

So this gets us to the two ways to store state information on an ASP.NET page.
  • Viewstate
  • Session

ViewState

As discussed, viewstate stores the status of all viewstate-enabled controls.  But you can also add stuff to Viewstate, and read it out again, even complex objects.
            //add a key
            ViewState.Add("myKey", "myValue");

            //store complex objects
            DataSet myData = new DataSet();
            ViewState.Add("data", myData);

            //change a key
            ViewState["myKey"] = "myNewValue";

            //read a key
            string data = (string)ViewState["myKey"];

            //delete a key
            ViewState.Remove("myKey");
            ViewState.Remove("data");

Note the following:
  1. ViewState lives in the page.  It does not flow from page to page. 
  2. Multiple users (like different computers and even 2 different browsers on the same computer do not share ViewState).
  3. ViewState is only read on a POSTBACK, not on an initial load of the page.
  4. I have found that storing things in ViewState can result in hard-to-debug errors that make your development life a living hell.
learn more

Session

Session is like ViewState, in that it is created automatically whether you want it or not. Session is linked to the user, not the page.  When someone browses to your page and there is no session ID, a new session is created.  Some features of sessions are:
  • Sessions time out after a period of inactivity.
  • Session data persists for that user until the session times out
  • Sessions can store complex items like ViewState
  • Sessions are unique, not shared if more than one browser is opened
Using sessions is easy, and since regular objects do not do anything with sessions, it's not likely to get you trapped into the impossible-to-diagnose error loop you get with ViewState.

            //add a key
            Session.Add("myKey", "myValue");

            //store complex objects
            DataSet mySessionData = new DataSet();
            Session.Add("data", mySessionData);

            //change a key
            Session["myKey"] = "myNewValue";

            //read a key
            string data2 = (string)Session["myKey"];

            //delete a key
            Session.Remove("myKey");
            Session.Remove("data");

            //Special session methods
            Session.Abandon();
            Session.Clear();
            if (Session.IsNewSession) { }
            string s = Session.SessionID;

Take care when using sessions. Note that the values are available to all pages on the site.  For instance, let's say you put a SortedBy value in multiple pages.  If the user travels from Customers sorted by LastName to the Orders page, the "SortedBy" key still says "LastName".
learn more


...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Thursday, January 9, 2014

Dramatically Speed Up Stored Procedures using Temp Tables

If you're wondering how to create a list, or temp table in a SQL Server Stored Procedure, look here.

But what if you're joining to an in-memory table and you experience performance issues?  I had a multiple join against such a table, and found that the query was taking over 12 seconds to complete - causing a timeout ocassionally.  Here was the temp table declaration:

    declare @tempIDs TABLE
    (
        pick_list_id integer
    )
Simple enough, right? Just a long list of integers.  But like I said the entire stored procedure was taking over 12 seconds to execute.  In a database table, my first approach would be to make an index on the column.  So that's what I did in my stored procedure.  It turned out to be incredibly simple and improved performance from 12 seconds to 30 milliseconds.  Looky!

    declare @tempIDs TABLE
    (
        pick_list_id integer not null PRIMARY KEY
    )
That's it! The rest of the stored procedure is exactly the same.  That's a 40000% speed boost!  Not bad for one modified line of code!


...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Tuesday, January 7, 2014

Column Modification Checklist

This is one of those things that I always forget part of, so because I just went through this, I thought I would document what needs to be done to sync your application whenever you modify any column in your database.

This tutorial is designed for:
  • MS SQL Server
  • Visual Studio (for web or desktop)
Quick Checklist:
  1. In SQL Server Management Studio (SSMS)
    1. Check for source and destination columns (for instance if widening "Address1" from 40 to 50, make sure all the columns in the order table, address book, Shipping and Billing etc are all the same)
    2. Update All Views that depend on this column. (SQL Server does not do this automatically)
    3. Update all stored procedures that operate on this column (for instance in and out parameters that access the changed column)
  2. In your Desktop App:
    1. Check all dataset xsd files to ensure the result column maxlengths are updated.
    2. Check all dataset xsd files to ensure the query parameter maxlengths are updated.
    3. Ensure all databound textboxes are set to the correct MaxLength.
    4. Ensure all DataGridView Columns are set to the correct MaxInputLength.
Updating Views:

There is actually a stored procedure for updating views.  Once you have found a dependent view, just run...

EXECUTE sp_refreshview 'dbo.v_myViewName';

That will take care of it.  Of course if your view is no longer valid because of the change, you'll get an appropriately misleading error message from Microsoft.

Updating Stored Procs:

Your stored procs have a header much like this:

ALTER PROCEDURE [dbo].[StoredProcName]
    -- Add the parameters for the stored procedure here
    @customer varchar(10),
    @PurchaseOrder varchar(15),
    @Address1 varchar(40)
AS

These header parameters and any internally declared variables must be changed to match any column changes.



...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Thursday, January 2, 2014

How to access your Main Form from a Static Method

Of course the right way is to pass a handle to the form if it is needed in the static method.

public static void Import(MainForm parent)
{
    parent.whatever();
}
But in my case I just didn't want to pass that handle around - and my application only had one form, so...

Application.OpenForms[0].Refresh();


...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Friday, December 27, 2013

Windows 8 is Costing You Money

Your Money is Being Sucked Down a Hole
I have a client that I have designed a desktop app for.  It's a Winforms app designed in Visual Studio 2010 and uses the barely functional DataGridView object to edit data.  It's been working forever in Windows XP, Vista, and 7.  Though as stated, the DataGridView gives constant headaches.  Now the boss has upgraded his tablet to Win 8 and the app has stopped functioning once again, crashing while trying to automatically calculate column widths during a paint event.

This function of the DataGridView has been spotty at best even on the other versions of Windows, and I have had to code around problems with it before.  Basically, the thing is just a nightmare to configure and use. I constantly find myself writing 200 lines of code to get the damn thing to stop crashing, when in my humble opinion, the damned thing ought to just work out of the box.  Now, I can see there might be problems if I were trying to shoehorn grids into grids, or streaming media into 20,000 rows of data... but really I am doing nothing out of the ordinary here.

Now I have to stop ongoing development, and retrofit this whole app (at the client's expense) to an operating system that - say it with me - ought to just work out of the box!

Meanwhile the client is wondering if I am really all that sharp, because Microsoft muffed up their OS with backward compatibility problems.  Thanks, Microsoft!
...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Monday, December 16, 2013

Refresh All Views on SQL Server

Whenever you make a change to a table - say, to modify a column - you need to update all the views that depend on that column.  This script will find and update all your views. 

-- Back Up All Databases
-- by Bryan Valencia

--create temp table
declare @temp table(commands varchar(500), completed bit)

--load it with backup commands
insert into @temp (commands, completed)
(
    SELECT DISTINCT 'EXEC sp_refreshview ''' + name + '''',0
    FROM sys.objects AS so
    INNER JOIN sys.sql_expression_dependencies AS sed
        ON so.object_id = sed.referencing_id
    WHERE so.type = 'V'
    and is_schema_bound_reference = 0
)

--variable for the current command
declare @thisCommand varchar(500);

--loop through the table
while (select count(1) from @temp where completed=0)>0
begin
    --find the first row that has not already been executed
    select top 1 @thisCommand = commands from @temp where completed=0

    --show the command in the "mesage" output window.
    print @thisCommand

    --execute the command
    EXEC (@thisCommand);

    --flag this row as completed.
    update @temp set completed=1 where commands=@thisCommand
end

--show the user the rows that have been found.
select * from @temp


Of course if a view is now no longer correct, you'll see on your messages tab in SQL Server Management Studio.

...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Friday, December 13, 2013

Integratederatederatedratedrated

This is not about Visual Studio.  In fact it's from 1982 when I was in tech school in Phoenix, Arizona.   We were using a Radio Shack Model 100 computer with 4K of RAM and a blazing fast cassette drive to store our programs.  Marc was using BASIC to create a simple keyboard-to-printer program so that he could type a page of text, edit, and print the text on the Epson dot matrix printer.

Basically he created an array to hold all the characters typed, and used that array to draw the text onscreen AND to print it when he was done. 

There was one small thing though.

The backspace character was a character like any other in the array, it (correctly) backed the cursor up on the screen, but did absolutely nothing to the printer. So Marc was typing a paper about integrated circuits, and his edits - which looked fine onscreen, printed out as Integratederatederatedratedrated Circuits.

The moral of this story is:  There's always more to a program than you thought up front.


...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Thursday, December 5, 2013

Selecting scalar values from a stored procedure

The easy and obvious answer is to use a function, not a procedure.   Then you can use it like any built-in T-SQL function.

select 1, dbo.Function() But alas, functions do not allow us to store (insert, update, delete) any data to the database and my stored procedure needs to do exactly that. 

In a moment of brilliant engineering, SQL Server does not allow the return value of a stored procedure to appear as a column in a query (select, insert, update, where clause),  so you can't just say...

select orderID, dbo.StoredProcedure() from... In my task, I had to insert the results of a stored procedure into a column in a table.  The code example I show below creates a temporary lookup table, and uses it later for a list of inserts.  try to follow this...

--creates a temp table for later use in joining (not shown)
declare @PickListNo table(OrderID varchar(20), PickListNo int, done bit);

--loads the temp table, except the column from the stored procedure
insert into @PickListNo (OrderID, done)
(
    Select distinct AOO.[order number], 0 from uploads.open_orders AOO
)

--vars the stored procedure needs
declare @A int
declare @NextVal int   

--while there are unprocessed rows...
while exists (select 1 from @PickListNo where PickListNo is null)
BEGIN
    --execute the procedure and capture the return value
    exec @A=dbo.NextPickListNo @NextVal OUTPUT
   
    --update one row in the table
    --I used Max(ID) to find a single row, but I might have used MIN, or Select top 1 as well.
    update @PickListNo set PicklistNo = @A where OrderID=(select MAX(orderID) from @PickListNo where PickListNo is null)
END
This use of the while loop is my way of cheating and not using cursors.  Cursors are nicely powerful but demand a lot of babysitting and resources (so I am told).

...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Tuesday, December 3, 2013

Conditional Output with the ? Operator in C#

I needed to ensure that column data was trimmed to the correct lengths in a SQL insert.  Normally I would expect that this code...

string toobig="This string is exactly 37 characters.";
string nottoobig = "13 characters";


//attempt to trim both to 20

string s;
s = toobig.Substring(0, 20);
Console.WriteLine(s);

s = nottoobig.Substring(0, 20);
Console.WriteLine(s);

 ...would do the trick.

 Sadly, if you use substring with a length greater than your string, you don't get the whole string as you might expect, you get this.

System.ArgumentOutOfRangeException was unhandled
  Message=Index and length must refer to a location within the string.
Parameter name: length
  Source=mscorlib
  ParamName=length
So we need a way to trim a string only if it's needed, i.e. a conditional trim.  Normally this is written like this:

if (nottoobig.Length > 20) { s = nottoobig.Substring(0, 20); } else { s = nottoobig; };
This works, and so does this...

s = nottoobig.Substring(0, Math.Min(20, nottoobig.Length)); where we substring to the min of the actual length and the desired length.

But there is also this:

s = nottoobig.Length > 20 ? nottoobig.Substring(0, 20) : nottoobig; This works just like excel iif():
condition ? first_expression : second_expression;
Condition must be true or false. If true, the first_expression is used, if false, the second_expression is.


 

So I have written a clip() function that acts the way I expected substring() to:

        static void Main(string[] args)
        {
            string toobig = "This string is exactly 37 characters.";
            string nottoobig = "13 characters";
           
            //attempt to trim both to 20
            string s;
            s = clip(toobig,20);
            Console.WriteLine(s);

            s = clip(nottoobig, 20);
            Console.WriteLine(s);
        }

        private static string clip(string s, int max)
        {
            if (max < 0) max = 0;
            return s.Length > max ? s.Substring(0, max) : s;
        }



...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Wednesday, November 13, 2013

The type or namespace name 'OfficeOpenXml' could not be found

Error Message:
The type or namespace name 'OfficeOpenXml' could not be found (are you missing a using directive or an assembly reference?)

You need to change your app config to use .NET Framework 4 not .NET Framework 4 (Client Profile).

Project - <Project> Properties - Application tab

Target Framework

As it turns out, EPPlus needs the System.Web namespace, which is not in the client profile.



...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Thursday, October 31, 2013

Auto Close and why you want it OFF

So I was perusing my SQL Server Error Logs on my web server and found all my databases restarting. 

All night. 

Every 2 seconds.  

It turns out that the reason for this is that the database is set to automatically shut down whenever there are no more connections.  In a web environment, that means every single time there is a page hit.

We need to turn this off.  Now.

Open SQL Server Management Studio and log in.
From the Object Explorer select

  • Server
    • Databases
      • DatabaseName → Properties


Make sure Auto Close is set to False.


...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Monday, September 2, 2013

Labor Day

Isn't it great to live in a country where we can celebrate Labor by taking the day off work?

Thursday, August 29, 2013

MailMessage to Text

This simple class exposes a static method to take a MailMessage object and represent it as a block of text.  I ran into this because when an emailer program I wrote started getting error messages, the only thing I got in the error log was

Failure sending mail. 

 So - to track the problem, I wanted to quickly see what the mailmessage looked like and include it in my error notifications.

Here is the class

using System.Collections.Generic;
using System.Net.Mail;
using System.Text;

namespace mailmessage_to_text
{
    class MailtoText
    {
        private static string MailAddresstoString(MailAddress addy)
        {
            //"Russ Jansen" <RussJ@prosourceinc.com>
            string answer = "";
            if (addy != null)
            {
                if (string.IsNullOrEmpty(addy.DisplayName))
                {
                    answer = string.Format("<{0}>", addy.Address);
                }
                else
                {
                    answer = string.Format("\"{1}\" <{0}>", addy.Address, addy.DisplayName);
                }
            }
            return answer;
        }

        private static string MailAddressCollectionToString(MailAddressCollection mc)
        {
            List<string> addies = new List<string>();
            foreach (MailAddress addy in mc)
            {
                addies.Add(MailAddresstoString(addy));
            }
            return string.Join(", ", addies.ToArray());
        }

        /// <summary>
        /// Convert a MailMesage to a string
        /// </summary>
        /// <param name="msg">the MailMessage to convert</param>
        /// <returns>the MailMessage as a string</returns>
        public static string MessageToString(MailMessage msg)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("FROM: {0}", MailAddresstoString(msg.From)).AppendLine();
            sb.AppendFormat("TO: {0}", MailAddressCollectionToString(msg.To)).AppendLine();
            sb.AppendFormat("CC: {0}", MailAddressCollectionToString(msg.CC)).AppendLine();
            sb.AppendFormat("BCC: {0}", MailAddressCollectionToString(msg.Bcc)).AppendLine();
            sb.AppendFormat("SUBJECT: {0}", msg.Subject).AppendLine();
            sb.AppendFormat("BODY: {0}", msg.Body).AppendLine();

            foreach (Attachment att in msg.Attachments)
            {
                sb.AppendFormat("Attachment: {0}", att.Name);
            }

            return sb.ToString();
        }

    }
}
 This class exposes a single static function MessageToString() that will convert a MailMessage object to a readable string.  Perfect for logging or sending in a notification email.

The output looks like this:
FROM: "Bryan" <bryan@gmail.com>
TO: "Bob" <bob@gmail.com>, "Bill" <bill@gmail.com>, <some@yahoo.com>
CC: <bossman@cap.com>
BCC:
SUBJECT: New WebSite Contact
BODY: Blah has submitted the following on the CONCACT.ASPX page.
   Name: Ruby
   Email: Ruby@rails.com

...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Friday, August 23, 2013

Visual Studio Grrr 1



This video illustrates the horrible gyrations you have to go through to create event handlers for components that are embedded into tables.  Clearly a fix is needed to the Visual Studio for Web interface, but they have added a feature that - while not a good solution - is at least a usable workaround.
...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Thursday, August 22, 2013

Dear Job Poster

Your recent job posting really gave me a good chuckle.  You want a "Programmer Analyst" - which is a junior programmer title - with the following:

Master's Degree or foreign equiv. in CS,Comp.Engng,Computer App.,or related field, plus 2 yrs of exp.in job offered,S/W consultant, engnr or related

an expert in...
HTML, DHTML, CSS, PHP, XML PERL, CORBA,  C, C++, and JAVA;

and then
Oracle, SQL, and MS Access

So, overall expert in DOS/Windows and Linux technologies.

I'm not sure why you think someone with a masters in CS will want a junior programmer job, or what you gained by shortening engineer to engnr.  I also don't know what you mean by SQL, there are MySQL, MSSQL, Sybase SQL Server - or do you just mean the general concept of the structured query language? 

This is what happens when HR people try to write job postings with no understanding of what any of it means.  In reality, this looks like a Java web programmer position.  I'm not sure why anyone with a masters degree would be interested in this for more than an afternoon, as this kind of work is very mundane and repetitive. 

I may be unemployed, but I do enjoy a good chuckle.

...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Sunday, July 28, 2013

Executing an Unmanaged (COM) DLL from an ASP.NET web page.

 I had a regular old DLL that needed to accept parameters, and spit out a string as an answer.  It is a 64 bit DLL running on a 64 bit server under .NET Framework 4.5.

Here is a quick tutorial on how I got it to work.

First, I had to add this to my main <Configuration> section of my web.config


 <system.codedom>
  <compilers>
   <compiler
     language="c#;cs;csharp"
     extension=".cs"
     compilerOptions="/unsafe"
     type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  </compilers>
 </system.codedom>



The /unsafe option is the big thing we needed here, as any call from managed code (.NET is all managed code) to unmanaged code, is considered unsafe.

Next, the dll must be wrapped in its own class.  So add a class to your web site.  Mine looks like this.
using System;
using System.Runtime.InteropServices;

namespace CodeGenerator
{

 internal class NativeMethods
 {
  [DllImport("kernel32.dll", SetLastError = true)]
  public static extern IntPtr LoadLibrary(string dllToLoad);

  [DllImport("kernel32.dll", SetLastError = true)]
  public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

  [DllImport("kernel32.dll")]
  public static extern bool FreeLibrary(IntPtr hModule);
 }

 public class unlocker
 {
  [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  private delegate IntPtr CreateCode2A(
   int level,
   string name,
   string encrypt_template,
   UInt32 hardwareID,
   UInt16 otherinfo1,
   UInt16 otherinfo2,
   UInt16 otherinfo3,
   UInt16 otherinfo4,
   UInt16 otherinfo5
   );


  public static unsafe string CreateUnlockingCode(string regname, string encrypt_template, string HardwareID, string pathtoDLL)
  {
   string unlockingcode = "";
   string sfp = HardwareID.Remove(4, 1);
   UInt32 lfingerprint = Convert.ToUInt32(sfp, 16);

   IntPtr pDll = NativeMethods.LoadLibrary(pathtoDLL);  //attempt to load the library
   int err1 = Marshal.GetLastWin32Error();
   try
   {
    IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "CreateCode2A");
    int err2 = Marshal.GetLastWin32Error();
    CreateCode2A createCode2 = (CreateCode2A)Marshal.GetDelegateForFunctionPointer(
      pAddressOfFunctionToCall,
      typeof(CreateCode2A));

    if (err1 == 0 && err2 == 0)
    {
     IntPtr unlockingcodeptr = createCode2(1, regname, encrypt_template, lfingerprint, 0, 0, 0, 0, 0);
     unlockingcode = Marshal.PtrToStringAnsi(unlockingcodeptr);
    }
    else
    {
     unlockingcode = string.Format("Error Codes: {0} and {1}", err1, err2);
    }
   }
   finally
   {
    bool result = NativeMethods.FreeLibrary(pDll);
   }
   return unlockingcode.ToString();
  }

 }
}

Now all we need is to call our CreateUnlockingCode function from the main page, which calls the DLL function, and marshals the result back to a C# string for us.


unlockingcode = CodeGenerator.unlocker.CreateUnlockingCode(regname, encrypt_template, fingerprint, pathtoDLL);

...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Sunday, July 7, 2013

DLL HELL

I have a 64 bit COM DLL that generates unlocking codes for a client.  I cannot edit this DLL.  It works SOMETIMES.

[DllImport(@"codegen64.dll")]
 public static extern string CreateCode2(
  int level,
  string name,
  string encrypt_template,
  Int64 hardwareID,
  int otherinfo1,
  int otherinfo2,
  int otherinfo3,
  int otherinfo4,
  int otherinfo5
  );
 
There is the page global DLLImport function... and when I try to use it...

try
  {
    unlockingcode = CreateCode2(1, regname, encrypt_template, lfp, 0, 0, 0, 0, 0);
  }
  catch (Exception ex)
  {
    unlockingcode = "";
  }

I get this pop-up dialog on my IIS server...
[Window Title]
Visual Studio Just-In-Time Debugger

[Main Instruction]
An unhandled win32 exception occurred in w3wp.exe [11016].

The Just-In-Time debugger was launched without necessary security permissions. To debug this process, the Just-In-Time debugger must be run as an Administrator. Would you like to debug this process?

[^] Hide process details  [Yes, debug w3wp.exe] [No, cancel debugging]

[Expanded Information]
Process Name: w3wp.exe
User Name: NETWORK SERVICE

Trying to invoke the debugger gives...


NOTE: I have enclosed the call to the DLL in a TRY block and it still fails, killing my WHOLE WEBSITE.
There MUST be a way to load, use, and unload a single DLL in a web page SAFELY, so that I don't get these HORIBLE crashes.

I have a feeling that the DLL is failing to unload, as it seems to work once, then fail until I restart the app pool and web site.
BUT I don't really know because I CANT DEBUG THE PROBLEM.
Sorry for the yelling, but this is like the ninth time I have told the client this is fixed, only to have it recur EVERY TIME a client orders from the web site!
Oh, it should be noted that I have NEVER installed Visual Studio on this web server.
Also, it's IIS8
.NET framework 4
Windows Server Essentials 2012....

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Saturday, July 6, 2013

Quick Question about Speech Recognition

***From my Android Galaxy 2 with ZERO Training***
How come my android phone can understand everything that I say, yet windows 7 voice recognition can't get it after hours of training?


***From Windows (after many hours training)***
Up to my android phone can understand everything that I say, At 107 voice recognition can't get it after hours of training?

***I typed the rest.***
It seems to me that Microsoft should scrap the whole speech recognition project and just buy whatever Android did.   Because clearly they have failed.

To all my subscriber (yes there's only one), Use Windows Speech Recognition to comment below.

Share This!

Contact Us

Name

Email *

Message *