Visual Studio Build Action Copy to Output Directory Not Working

net_logo

February 9, 2019 | Posted in .Net

So here’s an interesting one. I have been working on other systems and it has been a while since I’ve worked on the particular system i’m on now. I add a new library, and needed to have an xsl file copy itself to the main application bin folder – there is a dependency on it to render some XML which then displays a simple report style invoice in a standard .Net web browser control.

Anyway, even though I had the file set to:

Build Action: Content

Copy to Output Directory: Copy always

I couldn’t understand why the file wasn’t being copied to the main bin folder where it needed to be. There was a very simple explanation and something I had completely overlooked, so perhaps this may help someone else in the same situation. You just need to make sure the project that hosts the file you want in the main bin folder is reference from the main application library, that’s it.

Leave a comment in the comments section if this helped you.

Read More →

System.Data.DataRelation: These columns don’t currently have unique values.

net_logo

December 10, 2018 | Posted in .Net

So, this is a very short article about creating a relationship between two data tables in a dataset.

In my case, I was returning a dataset, with two data tables and I needed to add a relationship between the tables for the purposes of displaying that data in a nested fashion in a grid control (rough example – not complete code):

DataSet dataSource;

………..

DataRelation newRelation = new DataRelation(
“RelationshipName”,
headers.Columns["ParentID"],
lines.Columns["ChildID"]);

dataSource.Relations.Add(newRelation);

At the point of adding the DataRelation to the dataset, an error would bubble up as per the title of this blog post, “These columns don’t currently have unique values.”. Having gone through the data returned from the stored procedure I did in fact find ParentID in there twice which caused this error, however I found that I could overcome the error by passing in false on the next DataRelation param called bool createConstraints which may be something you want to do:

DataRelation newRelation = new DataRelation(
“Line”,
headers.Columns["RecId"],
lines.Columns["RecID"],
false);

In my case I didn’t end up doing this as I wanted to see the error and find the data issues (it might be an good idea to add a unique constraint in your database if this does not follow the required database design and duplicates should not exist). A join in the stored procedure was my problem, returning the same record twice.

“Notice that when the DataRelation is created for the Customers and Orders tables, no value is specified for the createConstraints flag (the default is true). This assumes that all the rows in the Orders table have a CustomerID value that exists in the parent Customers table. If a CustomerID exists in the Orders table that does not exist in the Customers table, a ForeignKeyConstraint causes an exception to be thrown.
When the child column might contain values that the parent column does not contain, set the createConstraints flag to false when adding the DataRelation. In the example, the createConstraints flag is set to false for the DataRelation between the Orders table and the OrderDetails table. This enables the application to return all the records from the OrderDetails table and only a subset of records from the Orders table without generating a run-time exception.”

Source: https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/dataset-datatable-dataview/navigating-datarelations

 

Read More →

Calling Stored Procedures Via Entity Framework

net_logo

August 30, 2018 | Posted in .Net

If you want to call stored procedures via EF, there is a way, which allows you to keep the entities aspect, and in particular, allows for the transposing of table rows to your own custom DTO’s, which will end up being your entites. Or, if you want a simple conversion from a list of entities to something like a dataset that is also possible. In simplistic terms you need to:

1) Create a new model (edmx) from your database, and when it asks which database schema you want to inject i.e. tables, stored procedures etc, choose none (it will ask you if you are sure, say yes)

2) Copy the new connection string in to your main application configuration file otherwise an exception will get raised when opening the connection

3) Create a DAL and to call your stored procedure

Here is an example:

public class SystemWarningsDTO
{
public string WarningType { get; set; }

public string Supplier { get; set; }

public int Count { get; set; }

public string SuggestedFix { get; set; }
}

public sealed class Adhoc : IDisposable
{
#region class declarations

private bool _disposed = false;

private AdhocQueriesEntities _objectContext = null;

#endregion

#region “constructors”

public Adhoc()
{
this._objectContext = new AdhocQueriesEntities();
}

#endregion

#region “destructor”

~Adhoc()
{
this.Dispose(false);
}

#region IDisposable

public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}

#endregion

private void Dispose(bool disposing)
{
if (!this._disposed)
{
if (disposing)
{
//// TODO: dispose managed resources
}

//// TODO: Call the appropriate methods to clean up unmanaged resources here

this._disposed = true;
}
}

#endregion

#region “properties”
#endregion

#region “methods”
#endregion

#region “functions”

private static DataTable ConvertToDatatable<T>(IList<T> data)
{
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
for (int i = 0; i < props.Count; i++)
{
PropertyDescriptor prop = props[i];
if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
table.Columns.Add(prop.Name, prop.PropertyType.GetGenericArguments()[0]);
else
table.Columns.Add(prop.Name, prop.PropertyType);
}

object[] values = new object[props.Count];
foreach (T item in data)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = props[i].GetValue(item);
}
table.Rows.Add(values);
}
return table;
}

public DataSet DoSomething()
{
DataSet dataSource = new DataSet();

try
{
var cmd = this._objectContext.Database.Connection.CreateCommand();
cmd.CommandText = “dbo.usp_MySproc”;
cmd.CommandType = CommandType.StoredProcedure;

if (this._objectContext.Database.Connection.State != ConnectionState.Open)
this._objectContext.Database.Connection.Open();

// get first result set of invoice headers
DbDataReader reader = cmd.ExecuteReader();

IList<SystemWarningsDTO> systemWarnings =
((IObjectContextAdapter)this._objectContext).ObjectContext.Translate<SystemWarningsDTO>(reader).ToList();

DataTable warnings = ConvertToDatatable(systemWarnings);

dataSource.Tables.Add(warnings);
}
catch (Exception)
{
throw;
}

return dataSource;
}

#endregion

#region “base overrides”

#region “properties”
#endregion
#region “methods”
#endregion
#region “functions”
#endregion

#endregion

#region “events”
#endregion
}

 

That accounts for the get side of things, but what if you want to update via a stored procedure? Well that is also a straight forward operation, below is an example function that would achieve this:

public bool DoSomething(string invoiceLineIds,
string creditOrderNumber,
string creditNotes,
string resolvedBy,
DateTime resolvedOn)
{
bool returnVal = false;

try
{
var cmd = this._objectContext.Database.Connection.CreateCommand();
cmd.CommandText = “dbo.usp_MySproc”;
cmd.CommandType = CommandType.StoredProcedure;

DbParameter invoiceLineIdsSqlParam = cmd.CreateParameter();
invoiceLineIdsSqlParam.ParameterName = “@invoiceLineIds”;
invoiceLineIdsSqlParam.Value = invoiceLineIds;
cmd.Parameters.Add(invoiceLineIdsSqlParam);

DbParameter creditOrderNumberSqlParam = cmd.CreateParameter();
creditOrderNumberSqlParam.ParameterName = “@creditOrderNumber”;
creditOrderNumberSqlParam.Value = creditOrderNumber;
cmd.Parameters.Add(creditOrderNumberSqlParam);

DbParameter creditNotesSqlParam = cmd.CreateParameter();
creditNotesSqlParam.ParameterName = “@creditNotes”;
creditNotesSqlParam.Value = creditNotes;
cmd.Parameters.Add(creditNotesSqlParam);

DbParameter resolvedBySqlParam = cmd.CreateParameter();
resolvedBySqlParam.ParameterName = “@resolvedBy”;
resolvedBySqlParam.Value = resolvedBy;
cmd.Parameters.Add(resolvedBySqlParam);

DbParameter resolvedOnSqlParam = cmd.CreateParameter();
resolvedOnSqlParam.ParameterName = “@resolvedOn”;
resolvedOnSqlParam.Value = resolvedOn;
cmd.Parameters.Add(resolvedOnSqlParam);

DbParameter returnSqlParam = cmd.CreateParameter();
returnSqlParam.ParameterName = “@result_value”;
returnSqlParam.DbType = DbType.Int32;
returnSqlParam.Direction = ParameterDirection.Output;
cmd.Parameters.Add(returnSqlParam);

if (this._objectContext.Database.Connection.State != ConnectionState.Open)
this._objectContext.Database.Connection.Open();

// get first result set of invoice headers
cmd.ExecuteNonQuery();

int result = (int)cmd.Parameters["@result_value"].Value;

if (result > 0)
returnVal = true;
}
catch (Exception)
{
throw;
}

return returnVal;
}

 

And finally, what if there are multiple rowsets being returned from our stored procedure, they have a parent/child relationship and you want to display them in some type of grid control? Well that is also straightforward enough, here is an example of how to achieve that by trasposing, in this example, invoice headers and invoice lines:

public DataSet DoSomething(string supplierCode,
string poNumber,
string invoiceNumber,
DateTime? invoicesFrom,
DateTime? invoicesTo,
string fileName,
bool includeDiscrepancyResolved,
bool includeNoDiscrepancy)
{
DataSet dataSource = new DataSet();

try
{
var cmd = this._objectContext.Database.Connection.CreateCommand();
cmd.CommandText = “dbo.usp_MySproc”;
cmd.CommandType = CommandType.StoredProcedure;

DbParameter supplierCodeSqlParam = cmd.CreateParameter();
supplierCodeSqlParam.ParameterName = “@supplierCode”;
supplierCodeSqlParam.Value = string.IsNullOrWhiteSpace(supplierCode) ? (object)DBNull.Value : supplierCode;
supplierCodeSqlParam.IsNullable = true;
cmd.Parameters.Add(supplierCodeSqlParam);

DbParameter poNumberSqlParam = cmd.CreateParameter();
poNumberSqlParam.ParameterName = “@poNumber”;
poNumberSqlParam.Value = string.IsNullOrWhiteSpace(poNumber) ? (object)DBNull.Value : poNumber;
poNumberSqlParam.IsNullable = true;
cmd.Parameters.Add(poNumberSqlParam);

DbParameter invoiceNumberSqlParam = cmd.CreateParameter();
invoiceNumberSqlParam.ParameterName = “@invoiceNumber”;
invoiceNumberSqlParam.Value = string.IsNullOrWhiteSpace(invoiceNumber) ? (object)DBNull.Value : invoiceNumber;
invoiceNumberSqlParam.IsNullable = true;
cmd.Parameters.Add(invoiceNumberSqlParam);

DbParameter invoiceDateFromSqlParam = cmd.CreateParameter();
invoiceDateFromSqlParam.ParameterName = “@invoiceDateFrom”;
invoiceDateFromSqlParam.Value = invoicesFrom ?? (object)DBNull.Value;
invoiceDateFromSqlParam.IsNullable = true;
cmd.Parameters.Add(invoiceDateFromSqlParam);

DbParameter invoiceDateToSqlParam = cmd.CreateParameter();
invoiceDateToSqlParam.ParameterName = “@invoiceDateTo”;
invoiceDateToSqlParam.Value = invoicesTo ?? (object)DBNull.Value;
invoiceDateToSqlParam.IsNullable = true;
cmd.Parameters.Add(invoiceDateToSqlParam);

DbParameter fileNameSqlParam = cmd.CreateParameter();
fileNameSqlParam.ParameterName = “@fileName”;
fileNameSqlParam.Value = string.IsNullOrWhiteSpace(fileName) ? (object)DBNull.Value : fileName;
fileNameSqlParam.IsNullable = true;
cmd.Parameters.Add(fileNameSqlParam);

DbParameter includeDiscrepancyResolvedSqlParam = cmd.CreateParameter();
includeDiscrepancyResolvedSqlParam.ParameterName = “@includeDiscrepancyResolved”;
includeDiscrepancyResolvedSqlParam.Value = includeDiscrepancyResolved;
includeDiscrepancyResolvedSqlParam.IsNullable = true;
cmd.Parameters.Add(includeDiscrepancyResolvedSqlParam);

DbParameter includeNoDiscrepancySqlParam = cmd.CreateParameter();
includeNoDiscrepancySqlParam.ParameterName = “@includeNoDiscrepancy”;
includeNoDiscrepancySqlParam.Value = includeNoDiscrepancy;
includeNoDiscrepancySqlParam.IsNullable = true;
cmd.Parameters.Add(includeNoDiscrepancySqlParam);

if (this._objectContext.Database.Connection.State != ConnectionState.Open)
this._objectContext.Database.Connection.Open();

// get first result set of invoice headers
DbDataReader reader = cmd.ExecuteReader();

IList<InvoiceDiscrepancyHeaderDTO> invoiceHeaders =
((IObjectContextAdapter)this._objectContext).ObjectContext.Translate<InvoiceDiscrepancyHeaderDTO>(reader).ToList();

// move to invoice lines
reader.NextResult();

IList<InvoiceDiscrepancyLineDTO> invoiceLines =
((IObjectContextAdapter)this._objectContext).ObjectContext.Translate<InvoiceDiscrepancyLineDTO>(reader).ToList();

DataTable headers = ConvertToDatatable(invoiceHeaders);
DataTable lines = ConvertToDatatable(invoiceLines);

dataSource.Tables.Add(headers);
dataSource.Tables.Add(lines);

DataRelation newRelation = new DataRelation(“PK_RecID”, headers.Columns["RecID"], lines.Columns["RecID"]);
dataSource.Relations.Add(newRelation);
}
catch (Exception)
{
throw;
}

return dataSource;
}

 

Read More →

How To Quickly Test A WCF Service

net_logo

January 15, 2018 | Posted in .Net

A nice way to be able to test a WCF service without the need to spend time creating your own test harness if you want something quick and dirty is to use the Microsoft “WcfTestClient.exe” utility which can be found in a path similar to C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\WcfTestClient.exe. All you have to do is copy your service url and paste it to the utility where you can double click on whichever method you’d like to invoke, drop down he message type and complete the requested info and there you have it, a quick a easy way to test a WCF service.

On the left you sill see the available methods, to the right of that you will see the request and below the request you will see the response from the service.

Read More →

The value of EntityCommand.CommandText is not valid for a StoredProcedure command. The EntityCommand.CommandText value must be of the form ‘ContainerName.FunctionImportName’.

net_logo

January 7, 2016 | Posted in .Net

If you are seeing this exception when trying to call a stored procedure through Entityframework version 5 or greater, there is a known issue with the model tt files.

Open the tt file for your model and search for public string ExecuteFunction(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption) and change edmFunction.Name to edmFunction.FullName.

This should fix the problem for you.

Read More →

MSXML2.XMLHTTP30Class and MSXML2.DOMDocument30Class Deprecated

net_logo

August 5, 2015 | Posted in .Net

We have a .Net Windows Forms application that uses RoboHelp to serve up help files. However, since moving our Team Foundation Server to TFS 2013 on Windows Server 2012 R2 compilation issues arose with errors suggesting that XMLHTTP30Class couldn’t be found in the MSXML2 namespace. The same story was true for DOMDocument30Class.

To resolve this simply use XMLHTTP60Class and DOMDocument60Class instead, in RoboHelp_CSH.cs which is supplied by Adobe for .Net incorporation.

I could find no documentation on this either on MSDN or on the Adobe website so hopefully this will help someone else in the same situation.

It’s important to point out that we had the latest version of MSXML Core Service on the server and infact on my machine (the error wasn’t present on my Windows 7 x64 machine however it was present on the new Windows Server 2012 R2 / TFS 2013 machine). The version used was MSXML 6 SP3.

Read More →

Using Extension Methods And A Custom Attribute To Extend System.Windows.Form.Control

net_logo

June 18, 2015 | Posted in .Net

I needed a way to mark any control in the system so that I could check if I needed to perform some action on it. Ideally it needed to be on the base class System.Windows.Forms.Control so that this could be done on anything that inherits from it.

I used two separate extension methods to add and check for the custom attribute using the TypeDescriptor class, and then:

To add the attribute to the control with the ignoreAction value:

YourControl.IgnoreAction(True)

To check for the attribute on the control elsewhere in the system:

if (Not YourControl.IgnoreAction) or (!YourControl.IgnoreAction) if using c#

The extension methods:

Public Module Extensions
Private ReadOnly attr As New IgnoreActionAttribute(True)

<System.Runtime.CompilerServices.Extension()>
Public Sub IgnoreAction(ByVal value As System.Windows.Forms.Control, ignore As Boolean)

Try
Dim params() As Attribute = {New IgnoreActionAttribute(ignore)}

System.ComponentModel.TypeDescriptor.AddAttributes(value, params)

Catch ex As Exception
‘Handle Error
End Try

End Sub

<System.Runtime.CompilerServices.Extension()>
Public Function IgnoreAction(ByVal value As System.Windows.Forms.Control) As Boolean

Dim ignore As Boolean = False

Dim attribs As System.ComponentModel.AttributeCollection = Nothing

Try
attribs = System.ComponentModel.TypeDescriptor.GetAttributes(value)

If attribs.Contains(attr) Then
ignore = True
End If

Catch ex As Exception
‘Handle Error
End Try

Return ignore

End Function

End Module

The custom attribute:

Public Class IgnoreActionAttribute
Inherits Attribute

”’ <summary>
”’ The ignore action value.
”’ </summary>
”’ <remarks></remarks>
Private _ignoreAction As Boolean

”’ <summary>
”’ Main constructor for the ignore action attribute.
”’ </summary>
”’ <param name=”ignoreAction”></param>
”’ <remarks></remarks>
Public Sub New(ignoreAction As Boolean)
Me._ignoreAction = ignoreAction
End Sub

”’ <summary>
”’ The ignore action value.
”’ </summary>
”’ <returns>True if the action should be ignored.</returns>
”’ <remarks></remarks>
Public Property IgnoreAction() As Boolean
Get
Return Me._ignoreAction
End Get
Set(value As Boolean)
Me._ignoreAction = value
End Set
End Property

End Class

I’ve seen other implementations which are far more convoluted than this. Here you can quickly and easily add your attribute to a control, or you could extend it to add any custom attribute to any object you like and then use the TypeDescriptor to check for it.

Read More →

toolstripcombobox.count = 0

net_logo

March 27, 2015 | Posted in .Net

Having used a toolstripcombobox hosted in a Toolstrip, although having bound a list of objects to the combo using a new bindingsource the items wouldn’t show until the form had displayed and validated. To fix this (if some actuib such as validation is to be performed before the form loads) set the toolstripcombobox.combobox.bindingcontext to the forms bindingcontext which will force the binding to happen.

toolstripcombobox.combobox.bindingcontext = this.bindingcontext;

For more information see https://msdn.microsoft.com/en-us/library/system.windows.forms.control.bindingcontext%28v=vs.100%29.aspx

Read More →

Can’t DragDrop Items to Custom Windows Explorer or Windows Control in Visual Studio 2012

net_logo

July 15, 2014 | Posted in .Net

Are you running Visual Studio as “Administrator”? This could very well be your problem.

On windows Vista and later, windows explorer runs with medium integrity. If you run Visual Studio as “Administrator” it runs with high integrity which means the OS will disable DragDrop operatins based on a WIM, literally (Windows Integration Mechanism).

For some light reading, head over to the following URL..

http://msdn.microsoft.com/en-us/library/bb625957.aspx

“The Windows integrity mechanism is a core component of the Windows security architecture that restricts the access permissions of applications that are running under the same user account and that are less trustworthy..”

Read More →

Flooring And Truncating Decimals

net_logo

April 16, 2014 | Posted in .Net

There may be legitimate circumstances where you want to store a specific decimal value and you don’t want SQL Server to round that precision off which would give you incorrect results when multiplying by large numbers.

Example 10.73085 stored in a SQL Server decimal 18,4 will round up and be stored as 10.7309. If like me you wanted to keep the 4 decimal place precision without round up there is a way.

(Math.Floor(value * 10000) / 10000)

Just specify a zero for each decimal place you wish to keep i.e. * 1000 for 3dp, * 100 for 2 dp and so on.

Read More →

Locating User In Active Directory Using System.DirectoryServices.DirectorySearcher

net_logo

April 11, 2014 | Posted in .Net

DirectorySearcher.FindAll() is very slow. Instead search for the specific AD user, much faster:

Dim windowsLogin As String
Dim currentIdentity As System.Security.Principal.WindowsIdentity
Dim slashIndex As Integer = 0

Try
currentIdentity = System.Security.Principal.WindowsIdentity.GetCurrent()
slashIndex = currentIdentity.Name.IndexOf(“\”)
windowsLogin = currentIdentity.Name.Substring(slashIndex + 1)
Catch
Throw
End Try

Dim searcher As New DirectorySearcher(“”)
Dim result As SearchResult = Nothing
With searcher
.Filter = String.Format(“(&(objectCategory=person)(SAMAccountName={0}))”, windowsLogin)
result = .FindOne()
End With

If ((result IsNot Nothing) AndAlso
(result.Properties.Item(“SAMAccountName”) IsNot Nothing) AndAlso
(result.Properties.Item(“SAMAccountName”).Item(0) IsNot Nothing) AndAlso
(CStr(result.Properties.Item(“SAMAccountName”).Item(0)).ToUpper() = windowsLogin.ToUpper())) Then

MessageBox.Show(String.Format(“User {0}”, windowsLogin) + ” found”)

End If

Read More →

Visual Studio Treat Warnings As Errors

net_logo

April 9, 2014 | Posted in .Net

I spent a considerable amount of time trying to find all of the VB.Net and C# check id’s so that I could treat a select few warnings as errors. The truth of it is, that the Visual Basic compiler is a lot less picky than the C# compiler. As an example, the default behaviour of the C# compiler is to tell you that a function has no return value (as an error), whereas in the land of Visual Basic you need to specify this under VB Project -> Compile -> Warning Configurations (Condition “Unused local variable” = “Error”). This instructs the Visual Basic compiler to treat these warnings as errors and as you would expect, they then show up in your errors list.

There seem to be very few options for Visual Basic projects to achieve this for many of the desired warnings as errors, but the following should get you started:

http://msdn.microsoft.com/en-us/library/3y20cc1z.aspx

I’ve also managed to find the C# equivilent URL which lists the check id’s here:

http://msdn.microsoft.com/en-us/library/dd380629.aspx

NOTE: If you exceed the maximum number of warnings in Visual Studio and you are treating them as errors, the errors will not show if they are out of scope and will effectively be hidden!! Watch out for this.

Read More →

Bing Geocode Service Returns The remote server returned an unexpected response: (417) Expectation Failed.

net_logo

October 4, 2013 | Posted in .Net

I’d been using the geocode SOAP service for a while and all of a sudden I started to run in to the following error:

The remote server returned an unexpected response: (417) Expectation Failed.

To get around the around the issue, I added a simple setting before making the request to the service (in bold):

 private void GeocodeAddress(string address)
 {
     try
     {
         string key = Properties.Settings.Default.BingMapsKey;
         GeocodeRequest geocodeRequest = new GeocodeRequest();

         // Set the credentials using a valid Bing Maps key
         geocodeRequest.Credentials = new GeocodeService.Credentials();
         geocodeRequest.Credentials.ApplicationId = key;

         // Set the full address query
         geocodeRequest.Query = address;

         // Set the options to only return high confidence results 
         ConfidenceFilter[] filters = new ConfidenceFilter[1];
         filters[0] = new ConfidenceFilter();
         filters[0].MinimumConfidence = GeocodeService.Confidence.High;

         // Add the filters to the options
         GeocodeOptions geocodeOptions = new GeocodeOptions();
         geocodeOptions.Filters = filters;
         geocodeRequest.Options = geocodeOptions;

         // Switch off 100 continue expectation
         System.Net.ServicePointManager.Expect100Continue = false;

         // Make the geocode request
         GeocodeServiceClient geocodeService = new GeocodeServiceClient();
         GeocodeResponse geocodeResponse = geocodeService.Geocode(geocodeRequest);

         if (geocodeResponse.Results.Length > 0)
         {
             this._addressLatitude = Convert.ToString(geocodeResponse.Results[0].Locations[0].Latitude);
             this._addressLongitude = Convert.ToString(geocodeResponse.Results[0].Locations[0].Longitude);
         }
     }
     catch
     {
         throw;
     }
 }

Read More →

Creating An Entity Framework Connection String

net_logo

October 3, 2013 | Posted in .Net

Not quite the same as the conventional ADO.Net connection string. Quick function to return the required format by Entity Framework:

Public Shared Function EntityFrameworkConnectionString() As String
Dim efConnectionString As String = New System.Data.EntityClient.EntityConnectionStringBuilder() _
With {.Metadata = “res://*”, _
.Provider = “System.Data.SqlClient”, _
.ProviderConnectionString = New System.Data.SqlClient.SqlConnectionStringBuilder() _
With {.InitialCatalog = “DatabaseName”, _
.DataSource = “ServerName”, _
.IntegratedSecurity = True
}.ConnectionString
}.ConnectionString
Return efConnectionString
End Function

Read More →

Parsing/Displaying XML with XmlReader and XmlWriter

net_logo

October 3, 2013 | Posted in .Net

Imports System.Drawing
Imports System.IO
Imports System.Text
Imports System.Windows.Forms
Imports System.Xml

 

Public NotInheritable Class XMLViewer

Public Shared Sub ViewXML(ByVal parentForm As Form, ByVal xml As String)

If ((parentForm IsNot Nothing) AndAlso (Not String.IsNullOrEmpty(xml))) Then

Dim xmlDisplay As New System.Windows.Forms.Form
Dim brokerXML As New RichTextBox()
Dim output As StringBuilder = New StringBuilder()
Dim ws As XmlWriterSettings = New XmlWriterSettings()

Dim formSize As New Size(CInt(parentForm.Width / 2), (parentForm.Height – CInt(parentForm.Height / 6)))

brokerXML.Multiline = True
brokerXML.Dock = DockStyle.Fill

xmlDisplay.Size = formSize
xmlDisplay.MinimumSize = formSize
xmlDisplay.Text = “XML Viewer”
xmlDisplay.StartPosition = FormStartPosition.CenterParent
xmlDisplay.Controls.Add(brokerXML)

ws.Indent = True

Try
Using reader As XmlReader = XmlReader.Create(New StringReader(xml))

Using writer As XmlWriter = XmlWriter.Create(output, ws)

While reader.Read()

Select Case reader.NodeType
Case XmlNodeType.Element
writer.WriteStartElement(reader.Name)
Case XmlNodeType.Text
writer.WriteString(reader.Value)
Case XmlNodeType.XmlDeclaration
Case XmlNodeType.ProcessingInstruction
writer.WriteProcessingInstruction(reader.Name, reader.Value)
Case XmlNodeType.Comment
writer.WriteComment(reader.Value)
Case XmlNodeType.EndElement
writer.WriteFullEndElement()
End Select

End While

End Using

End Using

brokerXML.Text = output.ToString()

xmlDisplay.ShowDialog()

Catch
Throw
Finally
If (xml IsNot Nothing) Then
xml = Nothing
End If

If (brokerXML IsNot Nothing) Then
brokerXML.Dispose()
End If

If (output IsNot Nothing) Then
output = Nothing
End If

If (ws IsNot Nothing) Then
ws = Nothing
End If

If (xmlDisplay IsNot Nothing) Then
xmlDisplay.Dispose()
xmlDisplay = Nothing
End If
End Try

End If

End Sub

End Class

Read More →

Accessing 32-bit DLLs from 64-bit code

net_logo

October 3, 2013 | Posted in .Net

Migrating your 32-bit Windows application to a 64-bit machine can be problematic if you have 32-bit DLLs that you cannot re-write. Mike Becker shows you how you can access 32-bit DLLs from 64-bit code using built-in IPC mechanisms.

Originally published on DNJ Online, June 2007.

Microsoft’s 64-bit technology first appeared with Windows Server 2003 for Itanium 2 (also known as IA64 Architecture) and for eXtended technology CPUs (also known as x64 Architecture). It offers many advantages but also raises new issues for the software developer. For example, you may still need to access existing 32-bit DLLs from a 64-bit process.

A key advantage of 64-bit technology is its ability to address up to 8Tb of memory, against a maximum of 2Gb for 32-bit processes. As a result, 64-bit technology allows most data processing to take place in memory, without any need for temporary disk storage. This can considerably increase performance and open up new data processing scenarios. There are therefore good arguments for migrating current 32-bit software products to a 64-bit platform.

Many C or C++ applications are easy to migrated to a 64-bit platform, particularly if they are written in a monolithic fashion. Sometimes they just need to be rebuilt with an x64/IA64 compiler to run as native 64-bit applications. However distributed or module-based software can cause more problems.

 

The conflict: 64-bit versus 32-bit

A major migration issue concerns 32-bit software components which cannot be migrated, perhaps because the source code is lost or one of the dependencies cannot be migrated.

Your 32-bit software is still supported on a 64-bit platform as 32-bit processes can be executed inside the dedicated Windows on Windows’ (WOW64) subsystem which is part of all 64-bit Windows operating systems. However a 64-bit process cannot load a 32-bit module into its process space, and a 32-bit processes cannot load a 64-bit module into its process space. The only way that communication can happen between 32-bit and 64-bit modules is through interprocess communication (IPC). In other words, 32-bit and 64-bit processes can exchange data using IPC techniques such as out-of-process COM, sockets, Windows messages or memory mapped files.

A 32-bit software product contains the main module WeatherReport which calls into the DLL WeatherStationControl. As long as both the main module and the DLL are 32-bit processes the product can run on both 32-bit and 64-bit platforms (inside WOW64). If both the main module and the DLL are migrated to the 64-bit platform, then they can both run in a native 64-bit 
process. However if only the main module is migrated to 64-bit, it will not be able to load the 32-bit DLL.

The best way to migrate such a product to a 64-bit platform is to migrate both the main module and the dependency DLL, but if the dependency DLL cannot be migrated then it cannot be loaded into the 64-bit process and the application won’t work.

The solution: a surrogate process

This issue can be solved by loading the dependency DLL into a separate 32-bit process space. The main module, running as a 64-bit process, can then access the dependency DLL across the process boundary using IPC (see MSDN reference).

A 64-bit process can access a 32-bit DLL across a process boundary if the 32-bit DLL is loaded into a separate 32-bit surrogate process space, and the application makes use of the built-in IPC mechanisms that support data exchange between 32-bit and 64-bit processes.

This solution requires additional work as the 32-bit surrogate process that loads the 32-bit DLL and exposes its API must be created. Also, some changes will be necessary on the 64-bit side as the consumer must use one of the IPC techniques instead of directly accessing the 32-bit DLL. It is worth noting that, in extreme cases, this additional work could be comparable to the work involved in developing a 64-bit version of the 32-bit DLL from scratch.

One possible way of reducing these costs is to implement a 64-bit wrapper’ DLL that exposes the same functions, parameters, types and so forth as the original 32-bit DLL. This wrapper DLL can then make IPC-based calls to the original 32-bit DLL, which has been loaded into a surrogate process.

A 64-bit wrapper DLL (WeatherStationControl64.DLL) exports the same interface as the original 32-bit DLL (WeatherStationControl.DLL), so providing the same services to the main process 
(WeatherReport) without you needing to make any changes to the code of either the main process or the 32-bit DLL. This wrapper DLL delegates calls to the 32-bit DLL, which is running in a surrogate process, using IPC.

The main costs of this solution arise from implementing the surrogate process, loading the 32-bit DLL and implementing the 64-bit wrapper DLL. The actual cost depends on the IPC technique used to exchange data between the 64-bit and 32-bit processes.

COM as an IPC mechanism

One of most popular IPC techniques is DCOM (Distributed COM). Originally designed for distributed systems, DCOM is still supported on 64-bit Windows platforms, so both 32-bit and 64-bit COM modules can be built. The only limitation is that 64-bit and 32-bit modules cannot reside in the same process space, so they have to interoperate across process boundaries. This is done using out-of-process’ (OOP) COM components, in the following way:

  1. Create a 32-bit component implementing a COM object which loads and calls
    into the 32-bit DLL, and exposes the 32-bit DLL interface as a COM interface.
  2. Configure this COM components for OOP by either creating a standard COM+ OOP application (using dllhost as the surrogate process), or by implementing the COM component as a dedicated COM server process using, for example, an ATL COM
    server as hosting process or a Win32 service as a dedicated COM server.
  3. Create a 64-bit wrapper DLL which implements the same interface as the
    original 32-bit DLL, imports the COM interface of the COM object created above,
    translates current calls to the exposed interface into calls to the COM object interface, transfers the call parameters, receives return values and delegates
    them to the callers.

The 32-bit DLL (WeatherStationControl.DLL) is used by a COM object (WeatherStationWrapper) which exposes the interface of the 32-bit DLL as a COM interface. The 64-bit wrapper DLL (WeatherStationControl64.DLL) makes calls to this interface which are delegated to the original 32-bit DLL. The main process (WeatherReport) calls the interface exposed by the 64-bit wrapper DLL but is in fact served by the original 32-bit DLL.

This solution should be significantly less expensive than creating a 64-bit version of the 32-bit DLL from scratch. Microsoft’s ATL technology is supported by Visual Studio with wizards and ready-written code fragments which should also help lower migration costs by saving time and reducing the likelihood of errors.

Implications

There are, however, a number of things that you still need to keep in mind:

1. Alignment
The alignment of data in memory is different for 32-bit and 64-bit processes. This means that your more complicated custom data structures may be serialized by a 32-bit process in a way that is different to that expected by a 64-bit process, and vice versa. Microsoft Windows Platform
SDK includes documentation about the differences in memory data alignment between 32-bit and 64-bit processes.

2. Data types
In most instances, 64-bit Windows uses the same data types as the 32-bit version. The differences are mainly in pointers which are 32 bits long in 32-bit Windows and 64 bits long in 64-bit Windows. The pointer-derived data types such as HANDLE and HWND are also different between 32-bit and 64-bit versions. Windows helps you to keep a single code base for both 32-bit and 64-bit software versions by offering polymorphic data types that have a different length depending on the target platform, for example INT_PTR declares an integer with the size of a pointer’. Any variable of this type is an integer which is 32 bits long on a 32-bit platform and 64 bits long on a 64-bit platform.

3. COM initialize
You can only access a COM object from a Windows application the object has been successfully initialized. The COM API function CoInitialize()must be called for each thread that is going to access a COM object before any COM interface calls are made, and the complementary call CoUninitialize() must be performed before the thread exits (see MSDN reference). This rule must be strictly respected if the main process calls to the original 32-bit DLL are multi-threaded.

4. Security
The OOP COM component instantiates COM objects in a separate process, whether a surrogate process, a COM server or Win32 service. This can mean that calls to the 32-bit DLL may happen in a different security context to the main process, especially if the main process makes intensive use of impersonation. If this is the case you may want to configure dedicated credentials for the OOP component, or implement internal impersonation in the COM object.

5. Performance
The IPC-based solution is almost certain to be slower than making direct calls into the DLL. Data marshaling over process boundaries, automatic data conversion between 32 and 64 bits, WOW64 features and delays while instantiating the COM object will all impact performance. However
there are numerous optimizing techniques that you can use such as COM pooling, caching inside the wrapper DLL, chunky’ versus chatty’ calls over process boundaries, implementing performance critical interfaces directly in the 64-bit DLL, and so forth.

6. Redirection
The WOW64 subsystem is in charge of supporting 32-bit modules on 64-bit Windows. To avoid unwanted collisions between 32-bit and 64-bit software, particularly when accessing the file system and registry, WOW64 isolates 32-bit modules using a process called redirection’ (see MSDN reference). For example, for a 64-bit process the call to obtain the system folder pathname returns %WINDOWS%\System32, but for a 32-bit process it returns %WINDOWS%\SysWOW64. The program folder path for a 64-bit process is Program Files’, but for 32-bit process it is Program Files (x86)’. The registry key HKEY_LOCAL_MACHINE\Software contains 64-bit process settings and data, while the key HKEY_LOCAL_MACHINE\Software\WOW6432Node contains 32-bit process settings and data.

This redirection is activated automatically when software modules call to popular pre-defined system paths or registry keys.

7. Kernel modules
The solution proposed here is for 32-bit user level DLLs, and doesn’t work with 32-bit drivers. This is because 32-bit kernel modules cannot be used on a 64-bit platform, with no exceptions or workarounds. If your product includes any kernel level module, such as a device driver, then the only possible migration route is to re-write the kernel module as a 64-bit process.

8. Setup
Using a COM OOP component in place of direct calls to a DLL requires changes to your setup procedure as the COM components must be installed and registered by the system. As discussed under ‘Security’ above, this may involve configuring dedicated credentials for the COM
component.

Read More →

Win32 API user32.dll – SendMessage() Function

net_logo

October 3, 2013 | Posted in .Net

“user32.dll implements the Windows USER component that creates and manipulates the standard elements of the Windows user interface, such as the desktop, windows, and menus. It thus enables programs to implement a graphical user interface that matches the Windows look and feel. Programs call functions from Windows USER to perform operations such as creating and managing windows, receiving window messages (which are mostly user input such as mouse and keyboard events, but also notifications from the operating system), displaying text in a window, and displaying message boxes.

Many of the functions in User32.dll call upon GDI functions exported by Gdi32.dll to do the actual rendering of the various elements of the user interface. Some types of programs will also call GDI functions directly to perform lower-level drawing operations within a window previously created via User32 functions.”

I needed to suspend the mdi from painting whilst displaying child forms in an application. The following code illustrates how this can be achieved:

 

[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
private const int WM_SETREDRAW = 11;

private void DoSomething()
{
// suspend drawing
SendMessage(this.Handle, WM_SETREDRAW, false, 0);

// do something here

// resume drawing
SendMessage(this.Handle, WM_SETREDRAW, true, 0);

// repaint client area
this.Refresh();
}

For more information on SendMessage(), see http://msdn.microsoft.com/en-us/library/windows/desktop/ms644950%28v=vs.85%29.aspx

Read More →

The perils of GC.Collect (or when to use GC.Collect)

net_logo

October 3, 2013 | Posted in .Net

An interesting article (linked to other interesting articles) regarding garbage collection, and when to force the collector to free memory when you’re seeing OOM exceptions.

http://blogs.msdn.com/b/scottholden/archive/2004/12/28/339733.aspx

Read More →