Pages

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.

Monday, June 17, 2013

SQL Server: Friendly Time Differences

Ok, so I always like the Facebook smart date displays, like
posted by Bob Loblaw about 12 minutes ago
So I set about recreating this on my own sites in SQL Server.  Here is a fairly easy way to produce this kind of friendly time differences.

Select *
,iif(
datediff(DAY, errdate, getdate()) >0 ,
cast(datediff(DAY, errdate, getdate()) as varchar(90))+' days  ',
''
)+
iif(
datediff(HOUR, errdate, getdate()) >0 ,
cast(datediff(HOUR, errdate, getdate()) % 24 as varchar(90))+' hours  ',
''
)+
iif(
datediff(MINUTE, errdate, getdate()) >0 ,
cast(datediff(MINUTE, errdate, getdate()) % 60 as varchar(90))+' minutes  ',
''
)+
iif(
datediff(SECOND, errdate, getdate()) >0 ,
cast(datediff(SECOND, errdate, getdate()) % 60 as varchar(90))+' seconds ago.',
''
)
[friendlytime]
from errorlog
--where errdate > DATEADD(HOUR, -1, GETDATE())
order by errdate


This produces a nice, friendly time difference that is better than a list of raw dates for human interpretation.


errdatepageerrmessagefriendlytime
1961-06-17 11:07:21.820TESTTHIS IS A TEST ERROR MESSAGE18993 days  0 hours  20 minutes  36 seconds ago.
2010-06-17 11:06:05.470TESTTHIS IS A TEST ERROR MESSAGE1096 days  0 hours  21 minutes  52 seconds ago.
2012-06-17 11:04:41.123TESTTHIS IS A TEST ERRORMESSAGE365 days  0 hours  23 minutes  16 seconds ago.
2013-06-17 11:07:59.197TESTTHIS IS A TEST ERROR MESSAGE20 minutes  58 seconds ago.

Alternately, if you don't care to display all the way down to seconds when the time span is many days, you can nest it like this to only show the most relevant time gap.

iif(
datediff(DAY, errdate, getdate()) >0 ,
cast(datediff(DAY, errdate, getdate()) as varchar(90))+' days ago',
iif(
datediff(HOUR, errdate, getdate()) >0 ,
cast(datediff(HOUR, errdate, getdate()) as varchar(90))+' hours ago',
iif(
datediff(MINUTE, errdate, getdate()) >0 ,
cast(datediff(MINUTE, errdate, getdate()) as varchar(90))+' minutes ago',
iif(
datediff(SECOND, errdate, getdate()) >0 ,
cast(datediff(SECOND, errdate, getdate()) as varchar(90))+' seconds ago.',
'now'
)
)
)
) [friendlytime2]

This produces a result as follows:

18993 days ago
1096 days ago
365 days ago
38 minutes ago
...

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, May 12, 2013

Best SQL Server Backup Script Evah

-- 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
    'BACKUP DATABASE ['+name+
    '] TO  DISK = N''J:\Backups\'+name+
    '.bak'' WITH  COPY_ONLY, NOFORMAT, NOINIT,  NAME = N'''+name+
    '-Full Database Backup'', SKIP, NOREWIND, NOUNLOAD,  STATS = 10',
    0
from
    master.sys.databases
where
    owner_sid <> 0x01 and state_desc='ONLINE'
)

--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


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, April 25, 2013

Min (n) must be less than or equal to max (-1) in a Range object.

This happened to me when I would read an XML file into a Dataset, as follows:

string sort = "";
string where = string.Format("userID={0}", EmployeeID);
DataSet ds = new DataSet();
ds.ReadXml(XMLFilename);
DataRow[] rows = ds.Tables[0].Select(where, sort, DataViewRowState.CurrentRows);

The userID column is numeric, yet I found that I could make this error dissappear by single-quoting the parameter like this.

string where = string.Format("userID='{0}'", EmployeeID);

...

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, April 13, 2013

The "SendUsing" configuration value is invalid.

I am moving a asp classic app from Windows SBS 2003 IIS 7 to Windows Server 2012 IIS 8.
After spending all day figuring out a dozen different things, the site finds itself unable to send emails.  So I constructed a simple email sender to test it out.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <title> Email Test </title>
 </head>

 <body>
<%
    Set myMail=CreateObject("CDO.Message")
    myMail.Subject="Sending email with CDO"
    myMail.From="doNotReply@myserver.com"
    myMail.To="myemail@gmail.com"
    myMail.TextBody="This is a message."
    myMail.Send
    set myMail=nothing
%>

The message has been sent.
 </body>
</html>
 That's literally the whole thing.  it gives...

CDO.Message.1 error '80040220'
The "SendUsing" configuration value is invalid.
/cgi-bin/testemail.asp, line 14
So I googled.  First I changed the app pool user from ApplicationPoolIdentity to NetworkService, as many bloggers suggest.



No change.

Then I found some code that looks like this:

schema = "http://schemas.microsoft.com/cdo/configuration/"
  Set objFlds = objConf.Fields
  with objFlds
    .Item(schema & "sendusing") = 2
    .Item(schema & "smtpserver") = "smtp.gmail.com"
    .Item(schema & "smtpserverport") = 465
    .Item(schema & "smtpauthenticate") = 1
    .Item(schema & "sendusername") = "abc@def.com"
    .Item(schema & "sendpassword") = "qwerty"
    .Item(schema & "smtpusessl") = 1
    .Update
  End with
 and... no such luck.  Same Error.




...

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, March 9, 2013

Setting Up WebDAV in IIS 8 for Site Publishing

This complete tutorial will tell you how to enable WebDav for publishing internet sites on your IIS8 server.

DONT.

Instead download FileZilla Server, install, and add an exception to your firewall.

I took 2 days trying to get WebDav to allow me to remote in and upload files to my site, and could not get past the "you are not authorized" message.

I had FileZilla running in 10 minutes. 


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, March 5, 2013

Propertybinding Combobox Values

 Ok, you have a search dialog box and you'd like to store the user's last choice for use the next time he launches your program.

So you go into "PropertyBinding" and there is no way to bind this value.


SelectedIndex and SelectedText are not in the list.  Text will not work if your box is a DropDownList, it will only work if your Combobox is a Dropdown.
So here's what you have to do.

First, from your project, Select Project and <projectname> Properties.
Then add a user scoped string setting for your Combobox.
Don't save the SelectedIndex as an integer, because whenever the list changes, you'll be restoring the wrong item in the list.

private void FindDropDownValue(ComboBox ddl, string value, int defaultvalue)
{
    int selectedListItem = ddl.Items.IndexOf(value);
    if (selectedListItem == -1)
    {
        selectedListItem = defaultvalue;
    }
    ddl.SelectedIndex = selectedListItem;
}

private void Load_Dropdowns()
{
//reload user settings
    FindDropDownValue(cbCustomer, Properties.Settings.Default.Quote_Customer, 0);
}
This will load the values from the user settings store.   I suggest calling Load_Dropdowns from your FORM_LOAD() method.

Now all we need is to save the settings on Form_Closing() of the form.

Private void SaveUserSettings()
{
    Properties.Settings.Default.Quote_Customer = cbCustomer.Text;
}

private void QuoteForm_FormClosing(object sender, FormClosingEventArgs e)
{
    SaveUserSettings();
}




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, February 12, 2013

Temp Tables in SQL Server

We all know you can create variables in SQL Server...
declare @customer varchar(20)
set @customer='a customer'

...but what if there is a need to store more complex data?
As it turns out, there is an easy way to accomplish that as well.

declare @csrlist Table(customer varchar(20), CSR varchar(25), counts int)

--get the counts of customer service reps orders for each customer.
insert into @csrlist (customer, csr, counts)
(
select distinct customer, Csr, COUNT(1) counts
from Purchase_Order
where Csr is not null
group by customer, csr
) 

The resulting in-memory table can be inserted to, deleted from, updated, just like any real data table.
--find the CSR with the most orders for each customer
insert into @csrlist2 (customer, CSR)
    (select customer, Csr from @csrlist A where counts=(select MAX(counts) from @csrlist B where a.customer=b.customer))


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.

DropdownList: SelectedValue does nothing.

 I have a ComboBox set as a DropDownList, and the SelectedValue property, which ostensibly will find and select the selected value, does not.

cbSalesman.SelectedValue = salesman;  This is probably because you would need to give it not just a string to look for, but an actual object that is a member of the Items list.  That would require ugly gyrations along the lines of the following.
  1. get the string to look for
  2. get the index of that string in the dropdown (using Items.IndexOf)
  3. grab the item at that index
  4. feed it to the "SelectedValue" property.
Instead of all that, why not just do this.

cbSalesman.SelectedIndex = cbSalesman.Items.IndexOf(salesman);


...

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, January 18, 2013

DBNulls: the Bane of my Existence

So yes, a DataGridViewCell.value is an object.  But it seems there should be a way to tell it "hey, in this case, when I ask for a value and you have a null, just hand me an empty string".

So I wrote this (for use until I figure out how to default a null cell to string.empty).

        /// <summary>
        /// Converts an object value to a string.
        /// (usually from a DataGridViewCell.Value;
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public string Val2Str(object value)
        {
            if (value == DBNull.Value)
            {
                return string.Empty;
            }
            return value.ToString();
        }

        /// <summary>
        /// Converts a DataGridViewCell value to a string.
        /// </summary>
        /// <param name="Cell">The cell.</param>
        /// <returns></returns>
        public string Val2Str(DataGridViewCell Cell)
        {
            return Val2Str(Cell.Value);
        }

These overloaded routines can be passed either a DataGridViewCell itself, or just the Value property.  Kinda like this:

string customer = Val2Str(dataGridView1.CurrentRow.Cells["Customer"]);
string customer = Val2Str(dataGridView1.CurrentRow.Cells["Customer"].Value);

...

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, January 14, 2013

Cannot execute as the database principal.

Cannot execute as the database principal because the principal "username" does not exist, this type of principal cannot be impersonated, or you do not have permission.
I am going to read your mind now.

  1. You recently backed up your database copy-only and moved it to another server or development box. 
  2. You're attempting to perform an  "Execute As..." command.
  3. Your software has been running for some time and this new error just started cropping up after you "refreshed" your copy of the database (from production?).
  4. You looked at the server logins, and the database users, and they seem to match (there is a login with the same name as the user).
What happened is that the SIDs (Security IDs) from the server login does not match the database user of the same name.  Remember that LOGINS are stored at the server level and USERS are in the databases.

What you need to do is re-create the user in the database (and reassign any roles and permissions).

USE [myDB]
GO

/****** Object:  User [myUser]    Script Date: 01/14/2013 18:21:22 ******/
IF  EXISTS (SELECT * FROM sys.database_principals WHERE name = N'myUser')
DROP USER [myUser]
GO

USE [myDB]
GO

/****** Object:  User [myUser]    Script Date: 01/14/2013 18:21:22 ******/
GO

CREATE USER [myUser] FOR LOGIN [myUser] WITH DEFAULT_SCHEMA=[dbo]
GO




...

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 11, 2012

SQL Server Matching on NULL parameter

So I have this query where I am trying to select on customer, unless the user doesn't enter a parameter for customer.  When they leave it blank, we want to see all customers.

So normally I would do it like this:

Select * from Orders where Customer=@customer And then to handle the null parameter I would change it like this:

Select * from Orders where ((Customer = @customer) OR (@customer is null))  This works great but then I came across this way of making it simpler.

Select * from Orders where Customer = isnull(@customer, Customer) The isnull()  effectively handles the case where the parameter (@customer) is null by replacing it with the content of the [Customer] data column, matching to itself!  Problem solved!


...

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 4, 2012

Operation is not valid due to the current state of the object.

App Details:

Visual Studio 2010
Desktop Winforms App
MDI Child form with a Datagridview connected to SQL Server 2008

Error details:
When closing the form, debugger jumps to this line in form.designer.cs (one of the files you are not supposed to edit).

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
    if (disposing && (components != null))
    {
        components.Dispose();  //<<<---error points here
    }
    base.Dispose(disposing);
}
and here is the massive error...

System.InvalidOperationException was unhandled
  Message=Operation is not valid due to the current state of the object.
  Source=System.Windows.Forms
  StackTrace:
       at System.Windows.Forms.DataGridViewCell.GetInheritedStyle(DataGridViewCellStyle inheritedCellStyle, Int32 rowIndex, Boolean includeColors)
       at System.Windows.Forms.DataGridViewCell.GetPreferredWidth(Int32 rowIndex, Int32 height)
       at System.Windows.Forms.DataGridViewColumn.GetPreferredWidth(DataGridViewAutoSizeColumnMode autoSizeColumnMode, Boolean fixedHeight)
       at System.Windows.Forms.DataGridView.AutoResizeColumnInternal(Int32 columnIndex, DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal, Boolean fixedHeight)
       at System.Windows.Forms.DataGridView.OnColumnGlobalAutoSize(Int32 columnIndex)
       at System.Windows.Forms.DataGridView.OnColumnCommonChange(Int32 columnIndex)
       at System.Windows.Forms.DataGridViewCell.OnCommonChange()
       at System.Windows.Forms.DataGridViewComboBoxCell.set_DataSource(Object value)
       at System.Windows.Forms.DataGridViewComboBoxCell.DataSource_Disposed(Object sender, EventArgs e)
       at System.EventHandler.Invoke(Object sender, EventArgs e)
       at System.ComponentModel.Component.Dispose(Boolean disposing)
       at System.Windows.Forms.BindingSource.Dispose(Boolean disposing)
       at System.ComponentModel.Component.Dispose()
       at System.ComponentModel.Container.Dispose(Boolean disposing)
       at System.ComponentModel.Container.Dispose()
       at Onesource.MaterialReceiptsEntry.Dispose(Boolean disposing) in P:\Projects\myproject\sample\MaterialReceiptsEntry.Designer.cs:line 18
       at System.Windows.Forms.Form.WmClose(Message& m)
       at System.Windows.Forms.Form.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DefMDIChildProc(IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
       at System.Windows.Forms.Form.DefWndProc(Message& m)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
       at System.Windows.Forms.Form.WmSysCommand(Message& m)
       at System.Windows.Forms.Form.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DefMDIChildProc(IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
       at System.Windows.Forms.Form.DefWndProc(Message& m)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
       at System.Windows.Forms.ContainerControl.WndProc(Message& m)
       at System.Windows.Forms.Form.WmNcButtonDown(Message& m)
       at System.Windows.Forms.Form.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at Onesource.Program.Main() in P:\Projects\myproject\sample\Program.cs:line 19
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException:
The solution:
I was looking through the ugly error stack above and found a lot of references to stuff like GetPreferredWidth. Having previously dealt with numerous problems involving AutoSizeColumnsMode and DataGridViewComboboxColumns,   I decided to try testing the form with AutoSizeColumnsMode set to None.  The layout did suck, but the form stopped crashing...

This means that the datagridview is trying to resize its columns during a form close!  Here is what I did to solve the problem.

I set the AutoSizeColumnsMode to AllCells and added a FormClose event as follows...




private void MaterialReceiptsEntry_FormClosing(object sender, FormClosingEventArgs e)

{

myDataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;

}

This ensures that the grid will not be updating its column sizes as the form is closing.



...

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, November 29, 2012

Case Schizophrenia and the DataGridViewComboboxColumn

So by default SQL Server (Microsoft) creates indices* and  does searches that are case insensitive.

Select * from orders where salesrep='bob' Will find BOB, bob, bOb, etc. (but not Robert)

So I have a DataGridViewComboboxColumn for that field, but since the data all comes from Paradox, where anything goes, I have a mixture of case scenarios.

As it turns out, even though your database cares not what capitalization you use, the combobox does.  It WILL NOT MATCH a field that has an alternate capitalization of whats in your data.

Example: if you have DONNA in the lookup list, and Donna in the orders table, the dropdown will display SOME RANDOM OTHER NAME.

It also throws a dataerror that looks like...

Order Entry [OrdersGrid]: Row 2 Column 16 Context Formatting, PreferredSize... System.Windows.Forms.DataGridViewDataErrorEventArgs DATA: TONYA 

...and it throws this error for each and every row you attempt to display on the screen.

The solution?

All I did was load the Purchase Orders table using the salesman as its own lookup.  like this

update Purchase_Order set Salesman=(select Salesman from Salesman S where S.Salesman=Purchase_Order.Salesman)

So, we're looking up the salesman, say "Bob" in the Salesman lookup table (finding, say "BOB") and writing that back over the Bob in the row, essentially updating the names in such a way as to match exactly what's in the lookup table.

Now our DataGridViewComboboxColumns work, and we didn't even have to edit the program!




...
* I still can't make myself use the word indexes.

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, November 17, 2012

Easy Tabbed CSS3 Menus

Look no further than here http://cssmenumaker.com/menu/grey-tabbed-menu for an easy CSS guide to making awesome menus.

This works in ASP.NET and pretty much anything else.

Enjoy!

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, October 14, 2012

Input string was not in a correct format.Couldn't store <>

I got this error after simply adding a column to the SQL Server database, then the XSD Dataset, and lastly a Datagridview.

Here is how I fixed it (it was simple, and Visual Studio misled me, causing this error).

 I added the column here, and clicked Finish.  DO NOT DO THAT.  Instead click Next, then Next. 

Only when you see this screen is the column correctly added.


...

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, September 27, 2012

Microsoft Lies

Ok, I joined the Microsoft Partner network so I could get Visual Studio 2010 (back when that was a new thing).  It was a good deal, but before I signed I called in and asked specifically if I could continue to use the software if I decided not to renew my partner network membership.

The answer was yes.  My memory is not fuzzy on this because that was the key upon which my decision to join depended.  So I signed up.

Fast forward to this morning.  I need to move my Visual Studio to a new machine.  The machine is up and running and all I need is...
  1. a link to re-download the installer
  2. my product key (which I may have somewhere in my 2010 tax box).
You'd think all this info would be readily available in my records.  So I log into my msdn account, click "My Product Keys" and...

So I called in again and got a really helpful guy named Ozzie.  And as it turns out, Ozzie will not help me move my Visual Studio to my new machine unless I shell out for a new partner membership membership for $149 or something - I couldn't quite hear the price over the call center chatter.

Now those of you who know me know that I am struggling mightily in this economy.  And now apparently - even though I got a valid microsoft product without cheating, they want MONEY just to move it to a new machine!  Apparently, they want money just for me to continue using the software at all!  So apparently, when you buy something, it is not really yours!  It's theirs, you're just renting it!  They should stop calling it sales, and call it what it is.  Rentals!  They are not GM, they are Netflix!  You don't get to keep what you buy!

So now I am faced with an ethical dilemma.  Do I (apparently illegally) keep using "my" software to try and eke out a living?  Or (even though I was lied to twice) should I deactivate it and basically starve to death?

I have about -$32,000 right now, and am struggling to keep food on the table.  I CANNOT just pay them and take the hit.  Especially after they misled me!

Please, if you are considering signing up for the Microsoft Partner Network to get your hands on discount software, RECONSIDER!  That or understand exactly what you will be DENIED access to after your subscription ends.


...

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, September 23, 2012

Getting the Identity Of Inserted Row in Visual C#

This works to return the identity of an inserted row.  The highlighted portions are the important parts.

 private int insertnew()
        {
            int newtix = 0;
            string SQL1 = "insert into delivery (date) values (GETDATE()); SELECT CAST(scope_identity() AS int)";
            SqlCommand myCommand = new SqlCommand(SQL1, myConnection);

            try
            {
                newtix = Convert.ToInt32(myCommand.ExecuteScalar());
            }
            finally
            {
                myReader.Close();
            }

            return newtix;
        }
Note that
  1. there are 2 SQL commands in the one SQL string.
  2. I had to cast the Scope_Identity as an int in the SQL or it would not read.
  3. ExecuteScalar reads the FIRST column in the FIRST row only, but if there were a compound key, or multiple rows inserted, ExecuteReader can be used instead.



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.

Share This!

Contact Us

Name

Email *

Message *