Unable To Instantiate TRIM Database: 80040154

I recently came across this error while attempting to connect to TRIM 6 R2 via the TRIMSDKRetrieving the COM class factory for component with CLSID {8A354548-6BCB-11D3-B273-00A0C9FC3DC0} failed due to the following error: 80040154.

This was a little alarming because it was using the same data adapter as a few other TRIM projects, which were working fine; the only difference between the project was that this particular project was a WPF application, and all of the other applications were ASP.NET applications. This particular application had also previously worked fine, the only change was that I had been upgraded to a 64-bit environment.

After a bit of playing around and research, I discovered the TRIM SDK will not connect under a 64-bit process.

Workaround

  1. In Visual Studio, right-click your project and go to Properties (last item).
  2. Select the Build tab.
  3. Change the Configuration option to All Configurations.
  4. Change the Platform Target to x86.

This will ensure that your application will only run under an x86 architecture, and will be able to connect to TRIM even on a 64-bit host.

Looking at the QuickSpecs for TRIM 7 it is being based on a 64-bit architecture and therefore this issue should be eliminated come TRIM 7 (in addition to some SDK enhancements and UI integration tools).

Oracle 06413: Connection Not Open (x64)

Having changed to a 64-bit development machine at work recently I ran into an Oracle error while trying to generate files using CodeSmith. This error was ORA-06413: Connection Not Open. Assuming it was a connection string error, as I had not run this particular generation in some time and it was likely that the server or username/password had changed, I proceeded to test the connection from SQL Developer. Success!

After ruling out that the connection was indeed valid I did a quick Google search for the error message. After a few clicks I discovered a very well known (has been around for a few years) Oracle issue; When executing an Oracle command from an application with parentheses or equals — ‘(‘ or ’)’ or ‘=’ — in the path than the specified error message is thrown.

In this particular case, CodeSmith had been installed under C:/Program Files (x86)/CodeSmith which was causing Oracle to fail. The quickest workaround was to simply move CodeSmith from the Program Files (x86) path e.g. into C:/CodeSmith. However; there is a patch (5383042) for Oracle 10g, which is also applied to Oracle 11G.

See Code, See CodeRun

Merbla wrote a short post today about a site he came across, CodeRun. The site is an online code repository, with the added advantage of an online IDE include on the site which allows you to see the code and run/debug it as it is. After signing up for a free account you can create your own projects (AJAX, ASP.NET, PHP and WPF — AJAX and ASP.NET also have support for Facebook applications) which you can develop, store and run all from their website.

The concept is brilliant — everything from start to go can be done online via your standard web browser (currently only supports Internet Explorer and FireFox) and publishing of your source code is as simple as a right-click and a left-click. Once the source has been published other people can freely go and search for source code in the repository and open it directly in the browser, make modifications and run them all from within the browser.

However; The actual implementation of it so far (while still very impressive) is significantly lacking from a development perspective. Although it is possible to do the majority of thing you can do in Visual Studio, it is a little cumbersome and slow at times and does have a few limitations. For example, there is no toolbar — and therefore no drag and dropping of controls (which Microsoft presentations always seem to contain a lot of ;-).

Although the site seems to be focused on web applications some features are also available in the online IDE. You do not have the ability to create folders with underscores in them, and there does not seem to be any way of creating the special ASP.NET folders such as App_Data or App_Themes… not such a big deal. Designer files are not automatically created and if you try to create one an exception is thrown saying the file already exists.

The biggest problem, however, is the speed. Perhaps it is just my machine or my internet connection, but the online IDE is very slow to use and navigate. Menus and prompts tend to hang the browser for a couple of seconds before they load and the IntelliSense (ctrl+space) does not allow function correctly. Code highlighting, although not important or required, is lacking from the Visual Studio equivalent and take a significant amount of time to process and display.

Copying and pasting from Visual Studio into the online IDE also seems to be out of the question, as it seems to paste the text multiple times; Copy and paste from within the online IDE works fine.

All that being said the online IDE quite features rich and imitates Visual Studio very well. You are able to apply breakpoints and step through code, attach to processes (only online applications — not system processes), watch variables, etc. There is also an option to open a project from a zip file — which works great, providing you zip the project from the root of the project folder (it must not be in a sub folder).

In the end (as Merbla suggested in his post) something like this teamed up with StackOverflow, for the purpose of displaying simple solutions to problems with working example would be brilliant! However, as far as online development goes I think there is a long way to go.

See running example: Hello World!

InfoPath Roles And Views

One useful feature of InfoPath is its built in support for user Roles. While it is not an overly powerful (and it should not be used for security purposes as all data can be viewed and edited in XML format via notepad or a similar) it can be handy for automatically switching views based on AD users or groups.

To add a role simply go to Tools -> User Roles (alt + t + e) and click Add (alt + a). You can then specify which users, groups or user names from the form should belong to the new role.

One thing to note is that when you are designing an InfoPath form and click “Preview Form” it shows the form based on the default role. If you wish to preview the form under a different role you need to go to File -> Preview Form -> With User Role… (alt + f + r + r). The form will then be launched in preview mode under the select role.

There is also the option to set a role as either the default role or the initiator role (only one role can occupy either or both of these options). The default setting specifies that this role is the default role for all users, should they not meet the requirements of another role. The initiator setting is the role assigned to a user when they open the InfoPath form for the first time.

Another point of interest is that roles are assessed on a top-down approach, however, you can not change the ordering of roles from within the InfoPath IDE. In order to change the ordering of roles, should you be required to, you must open the manifest.xsf and manually reorder the <xsf:role /> elements.

Creating A Simple SharePoint Workflow In SharePoint Designer

This one is a quick and easy one but is the basis for creating some very useful workflows in for use in SharePoint lists. Firstly you will need a SharePoint website and a copy of SharePoint Designer (a 60-day trial version is available from Microsoft) and a list in SharePoint which you can apply the workflow to – for this example, I am using a fairly simple Travel Requisition list which is a document library which contains InfoPath documents.

To create the workflow open SharePoint Designer and connect to your SharePoint website. Once connected, go to File -> New and select the SharePoint Content tab and select Workflow (blank workflow). You should now be presented with a form similar to the following. Here you can specify a name for your workflow (each workflow in a site must have a unique name) which list the workflow is attached (associated) to and when the workflow should be triggered. In this case, we want to trigger the workflow whenever a list item is added or updated.

Continue reading “Creating A Simple SharePoint Workflow In SharePoint Designer”

Getting SharePoint Users In InfoPath 2003

Recently I have been doing some work with SharePoint and InfoPath 2003 and one of my tasks was to get a list of SharePoint users into a drop-down list box in an InfoPath form – sound simple right? Wrong! What should be an easy task is made more complicated due to that fact that the SharePoint web services which return user information do not provide complete definitions of their return types, so InfoPath does not know what it can do with the result.

User / Group information can be retrieved from SharePoint via the UserGroup web service located at http://yourserver/_vti_bin/UserGroup.asmx – the web method I am going to be using is GetUserCollectionFromSite, but of course you can use whichever method you require.

In order to be able to get the information and use it in InfoPath 2003 we are going to need to create a new InfoPath Form Template in Visual Studio 2005. Before we can do this we need to install the Office InfoPath 2003 Toolkit For Visual Studio 2005, which can be found in your MSDN subscription – or alternatively you can download the InfoPath 2003 Toolkit For Visual Studio .NET (2003) although I have not tested this. Once you have installed the toolkit and created a new project you will be presented with a wizard which will guide you through the processes of setting up the project and you can either base the project an existing InfoPath form or create a new one, either is OK.

The first thing to do now is to set up our reference to the SharePoint web service; In InfoPath go to Tools -> Data Connections and click Add. Select Receive data, on the next page select Web Service, and on the following page enter in the URI to your UserGroup web service (E.G. http://yourserver/_vti_bin/UserGroup.asmx). On the next page you should be able to select your desired web methods, in this case we want GetUserCollectionFromSite. You can now enter a name for the data connection, I am just going leave it as the default name “GetUserCollectionFromSite“. Underneath the textbox where you can enter in the name there is a checkbox option “Automatically retrieve data when form is opened“, ensure this is ticked (if you do not tick this you can retrieve the manually retrieve the data later by calling the Query() method on the data connection).

Now that we have a connection the SharePoint we need to create a data connection which we can easily use in SharePoint, which will allow us to bind default values or in this example populate a drop-down list box. To do this we are going to create an XML file containing the same format as the return type of the SharePoint web service. In notepad, or your preferred text editor, enter the following:

<?xml version="1.0" encoding="utf-8" ?>
<SiteUsersAndGroups>
  <Users xmlns="http://schemas.microsoft.com/sharepoint/soap/directory/">
    <User ID="" Sid="" Name="" LoginName="" Email="" Notes="" IsSiteAdmin="" IsDomainGroup=""/>
    <User ID="" Sid="" Name="" LoginName="" Email="" Notes="" IsSiteAdmin="" IsDomainGroup=""/>
  </Users>
</SiteUsersAndGroups>

Save the file as SiteUsersAndGroups.xml. Back in InfoPath create a new receiving data connection, but this time instead selecting Web service select XML document. On the next page click Resource Files… and click Add… -> select theSiteUsersAndGroups.xml file we just saved earlier and click OK twice. On the next page, once again we are going to leave the data connection name as the default “SiteUsersAndGroups“.

To populate the drop-down list box all we have to do now is double-click on the drop-down list box we want to populate and under List box entreis select the option “Look up values in a data connection to a database, Web service, file or SharePoint library or list“. In the Data Connection drop-down select SiteUsersAndGroups. Next to the Entries textbox click the Select XPath button and select the User node. You can now select the attributes we want to display in the Value and Display name fields (the Display name attribute will be the text presented to the user – typically this should be @Name to display the users name). After saving the form we now need to switch back to Visual Studio in order to transfer the data from the web service data connection to the xml data connection.

In Visual Studio open FormCode.cs – by default there should be two methods and two properties: _Startup(…)_Shutdown()thisXDocument and thisApplication. Although we will not need to use the startup or shutdown methods we will need to use the thisXDocument property.

The first thing we need to do is capture the load event of the InfoPath form. In order to handle InfoPath events methods need to have the InfoPathEventHandler attribute specified. For example our OnLoad event handler is going to look like the following:

[InfoPathEventHandler(EventType = InfoPathEventType.OnLoad)]
public void OnLoad(DocReturnEvent e)
{
  // ... code goes here ...
}

To test if the method is being executed a dialog prompt can be triggered by calling thisXDocument.UI.Alert(”Hello World”);. When the InfoPath form loads a standard dialog box should be displayed saying “Hello World“.

Now that we have an entry point for our code we need to read the data returned from the SharePoint web service, stored in the GetUserCollectionFromSite data connection, and copy it into our SiteUsersAndGroups data connection which we are binding to the drop-down list. As all of the data is returned in XML format, as is the case with all InfoPath data sources, we are going to need to use XPath to retrieve the data. The first step is to get an XPathNavigator we can use to perform out XPath query, in order to do this we first need to take the DataObject from thisXDocument and place it into an XmlDocument and from the XmlDocument create a navigator.

XmlDocument userCollectionFromSite = new XmlDocument();
userCollectionFromSite.LoadXml(_thisXDocument.DataObjects["GetUserCollectionFromSite"].DOM.xml);
XPathNavigator siteUsers = userCollectionFromSite.CreateNavigator();

If you look back at the xml file we created earlier you will notice that the Users node is under the http://schemas.microsoft.com/sharepoint/soap/directory/ namespace. Along with this namespace InfoPath data connections are placed under thehttp://schemas.microsoft.com/office/infopath/2003/dataFormSolution namespace. In order to access these namespaces in our XPath query we need to create an XmlNamespaceManager.

XmlNamespaceManager manager = new XmlNamespaceManager(siteUsers.NameTable);
manager.AddNamespace("dfs", "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution");
manager.AddNamespace("tns", "http://schemas.microsoft.com/sharepoint/soap/directory/");

Our actual XPath query, to get the nodes we are interested in, is going to look similar to the follow:

XPathNavigator allUsers = siteUsers.SelectSingleNode("/dfs:myFields/dfs:dataFields/tns:GetUserCollectionFromSiteResponse/tns:GetUserCollectionFromSiteResult/tns:GetUserCollectionFromSite/tns:Users", manager);

Now that we have the all of the users (and groups) returned from the SharePoint web service we simply need to load the xml in to the SiteUsersAndGroups data connection as follows:

thisXDocument.DataObjects["SiteUsersAndGroups"].DOM.loadXML("<SiteUsersAndGroups>" + allUsers.OuterXml + "</SiteUsersAndGroups>");

That’s it! When the form is opened the drop-down list should not be populated with the users and groups from SharePoint. The final class should look similar to the following:

#region Using Statement
using System;
using System.Xml;
using System.Xml.XPath;
using Microsoft.Office.Interop.InfoPath.SemiTrust;
#endregion

[assembly: System.ComponentModel.DescriptionAttribute("InfoPathStartupClass, Version=1.0, Class=TravelRequisitionForm.TravelRequisitionForm")]
namespace TravelRequisitionForm
{
    [InfoPathNamespace("xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:xsf="http://schemas.microsoft.com/office/infopath/2003/solutionDefinition" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tr="http://schemas.microsoft.com/office/infopath/2003/sample/TravelRequest" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD" xmlns:xdUtil="http://schemas.microsoft.com/office/infopath/2003/xslt/Util" xmlns:xdXDocument="http://schemas.microsoft.com/office/infopath/2003/xslt/xDocument" xmlns:xdMath="http://schemas.microsoft.com/office/infopath/2003/xslt/Math" xmlns:xdDate="http://schemas.microsoft.com/office/infopath/2003/xslt/Date" xmlns:dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution" xmlns:tns="http://www.tarongenergy.com.au/activedirectory" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns1="http://schemas.microsoft.com/sharepoint/soap/" xmlns:s1="http://microsoft.com/wsdl/types/" xmlns:ns2="http://www.tarongenergy.com.au/SharePoint" xmlns:ns3="http://schemas.microsoft.com/sharepoint/soap/directory/" xmlns:ns4="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"")]
    public class TravelRequisitionForm
    {
        #region Member Variables
        private XDocument thisXDocument;
        private Application thisXApplication;
        #endregion

        #region StartUp / ShutDown

        /// <summary>
        /// Handles the startup procedure.
        /// </summary>
        /// <param name="app">The application.</param>
        /// <param name="doc">The Document.</param>
        public void _Startup(Application app, XDocument doc)
        {
            thisXDocument = doc;
            thisXApplication = app;
        }

        /// <summary>
        /// Handles the shut down procedure.
        /// </summary>
        public void _Shutdown()
        {
            // Do nothing
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Handles the Load event.
        /// </summary>
        /// <param name="e">Event Arguments.</param>
        [InfoPathEventHandler(EventType = InfoPathEventType.OnLoad)]
        public void OnLoad(DocReturnEvent e)
        {
            // Get all of the Users and Groups from the SharePoint web service connection.
            XmlDocument userCollectionFromSite = new XmlDocument();
            userCollectionFromSite.LoadXml(thisXDocument.DataObjects["GetUserCollectionFromSite"].DOM.xml);
            XPathNavigator siteUsers = userCollectionFromSite.CreateNavigator();

            // Add support for the required namespaces
            XmlNamespaceManager manager = new XmlNamespaceManager(siteUsers.NameTable);
            manager.AddNamespace("dfs", "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution");
            manager.AddNamespace("tns", "http://schemas.microsoft.com/sharepoint/soap/directory/");

            // Query the user nodes
            XPathNavigator allUsers = siteUsers.SelectSingleNode("/dfs:myFields/dfs:dataFields/tns:GetUserCollectionFromSiteResponse/tns:GetUserCollectionFromSiteResult/tns:GetUserCollectionFromSite/tns:Users", manager);

            // Load the users into the SiteUsersAndGroups connection
            thisXDocument.DataObjects["SiteUsersAndGroups"].DOM.loadXML("<SiteUsersAndGroups>" + allUsers.OuterXml + "</SiteUsersAndGroups>");
        }

        #endregion
    }
}

Note: Instead of writing managed code behind the InfoPath form you could write a proxy web service which contains a complete return type in the WSDL, which InfoPath can then use directly; However, note that the SharePoint web services require windows authentication so you will either need to set up a service account to access the web services, or more preferably set up Kerberos to allow authentication to be delegated to your proxy web service.

Incrementing The Project Version Number Using NAnt

The following code depends on getVersion.

<target name="incrementBuildNumber" description="Increments The Build Number" depends="getVersion">
    <script language="C#">
        <references>
            <include name="System.dll"/>
            <include name="System.Xml.dll"/>
        </references>
        <imports>
            <import namespace="System"/>
            <import namespace="System.IO"/>
            <import namespace="System.Text"/>
            <import namespace="System.Text.RegularExpressions"/>
        </imports>
        <code><![CDATA[
        public static void ScriptMain(Project project)
        {
            string file;

            using (StreamReader reader = File.OpenText(project.Properties["project.version.file"]))
            {
                file = reader.ReadToEnd();
            }

            string version = project.Properties["project.version"];
            string[] versions = version.Split('.');
            int buildNumber = int.Parse(versions[3]);
            string newVersion = string.Format("{0}.{1}.{2}.{3}", versions[0], versions[1], versions[2], ++buildNumber);

            project.Properties["project.version"] = newVersion;
            file = file.Replace(version, newVersion);

            using (StreamWriter writer = new StreamWriter(project.Properties["project.version.file"]))
            {
                writer.Write(file);
            }
        }
        ]]></code>
    </script>
    <call target="commitAssemblyInfo"/>
</target>

The script works simply by getting the current version number and then replacing it with the build number incremented (it assumes you use all four version number sections). It will also replace any other references to the version number in the file, keeping them consistent.

The script could be enhanced using regex trickery to target a specific instance of the version number (e.g. those between AssemblyVersion(”…”) etc), allow for use of only the first few number sections, or be self-dependent if desired.

Committing the changes to subversion:

<target name="commitAssemblyInfo" description="Commits the assembly information file to subversion">
    <exec program="${subversion.exe}" workingdir="./">
        <arg value="commit"/>
        <arg value="${project.version.file}"/>
        <arg value='-m "Incremented Version Number To ${project.version}"'/>
    </exec>
</target>

The ${subversion.exe} property should reference your tortoise subversion.exe file. Note: the user account calling the script will be the user account used to submit the file to the subversion repository – this means if you have a build server automating this process the service account must have access to commit changes.

Getting The Project Version Number Using NAnt

Specifying the file containing the global assembly information:

<property name="project.version.file" value="./AssemblyInfo.cs"/>

Retrieving the version information:

<target name="getVersion" description="Gets the project version number from the assembly information file">
    <script language="C#">
        <references>
            <include name="System.dll"/>
            <include name="System.Xml.dll"/>
        </references>
        <imports>
            <import namespace="System"/>
            <import namespace="System.IO"/>
            <import namespace="System.Text"/>
            <import namespace="System.Text.RegularExpressions"/>
        </imports>
        <code><![CDATA[
            public static void ScriptMain(Project project)
            {
                Regex expression = new Regex("\[assembly: AssemblyVersion\("(.*)"\)\]");

                using (StreamReader reader = File.OpenText(project.Properties["project.version.file"]))
                {
                    string file = reader.ReadToEnd();
                    Match match = expression.Match(file);
                    project.Properties["project.version"] = match.Groups[1].Captures[0].Value;
                }
            }
        ]]></code>
    </script>
</target>

Usage: ${project.version}

Prior to using the project.version property the getVersion target must be called or the target using the property must be directly or indirectly dependent on the getVersion target.

Note: The previous code applies to C# assembly version information only. A simple alteration of the Regex value will allow the code to work with vb assembly version information.

Adding Custom Toolbar Buttons To VS2008

So you’re a smart cookie and you’ve written yourself some scripts to build your DAL or perhaps to deploy or package for a different environment; However, when you want to run said scripts you have to open up a command window, navigate to the working folder and run the scripts. Not only is this a pain and waste of valuable time, it also inevitably results in a taskbar full of command prompt windows! Well, there is a quick and easy way to add custom buttons to your Visual Studio 2008 toolbar which will fire off your scripts and display the results in the output window.

The first step is to ensure you have a consistent approach to how your projects are set up in order to run your scripts. After all, you don’t want to have to create a unique toolbar button for every single application you’re developing. One simple approach to this is to create a batch file of the same name (e.g. GenerateDAL.bat) for each application which can then call of to project specific actions. Once you have a consistent pattern to your projects your custom toolbar buttons will become much more useful and save you lots of time.

Steps for creating a custom toolbar button:

  1. In Visual Studio 2008 go to Tools -> External Tools…
  2. Click Add -> (Complete the form)
    Title: (Name of the script e.g. Generate)
    Command: (Location of script e.g. $(SolutionDir)CodeSmithCode.Generate.cmd if your script is in the folder ‘CodeSmith’ of all your project)
    Arguments: (Leave this one empty if you wish)
    Initial directory: (Location of script or the folder level from which you would usually call your script e.g. $(SolutionDir)CodeSmith)
    (Check Use output window to display results in the output window)
  3. Click Ok.
  4. Right-Click on the toolbar -> Click Customize…
  5. Select the Toolbars tab -> Click New -> (Enter a suitable name e.g. Scripts)
  6. Select the Commands tab.
  7. Under Categories scroll down and select Tools -> Under Commands scroll down to External Command 3 (this assumes you only have to default 2 commands in Visual Studio — if you have more than the external command number will match the order of your external commands list)
  8. Drag-and-Drop “External Command 3″ and/or any other external commands you created previously.
  9. Click Close (At this point the button should automatically be renamed to the title of the external command they are linked to).
  10. Drag the new toolbar group to where you want it on the toolbar and enjoy 🙂