Launching Internet Explorer without address bar in .NET

I needed to launch an Internet Explorer window to a particular URL in a near “chromeless” fashion – no toolbar, no address bar, no scrollbars, from a C# .NET application. At first I used thread.start(url), but you cannot specify how Internet Explorer should open – there are no command line options to customize the window.

The internet failed me – I was supposed to reference some web COM dll, that I didn’t even have.

The solution is painfully simple. Make sure you have a reference to System.Windows.Forms, create a WebBrowser object in code (no need to add it to a form), give it an about:blank url, then use Document.Window.OpenNew() to launch a new IE window with parameters.

 

Examples speak louder than words: this snippet will open google in a new browser window

using (WebBrowser wb = new WebBrowser())
{
    wb.Url = new System.Uri("about:blank");
    wb.Document.Window.OpenNew("http://google.com", "location=no,menubar=no,scrollbars=no,status=yes,toolbar=no,resizable=yes");
}

If you will be opening a lot of windows, maybe you should keep the WebBrowser object in a class variable.

Maybe this one was out there somewhere, but I couldn’t find it…

CRM 4.0 loader.aspx specify default page parameters

Lets say you want to provide a direct link into CRM (4.0) that opens it up to a particular Area / Section / Entity. Microsoft provides documentation on opening specific Views and Forms, but as far as the internet is concerned, loader.aspx accepts no parameters.

Well, this isn’t entirely true :). Digging through some of the CRM internals, I was able to determine that loader.aspx accepts two parameters: “page” and “area”. The meanings of these fields are a bit reversed. “page” refers to the sitemap Area Id (“Workplace”, “SFA”, “MA”, “CS”, “Settings”, “ResourceCenter” are out of the box). “area” refers to the subAreaId – probably the easiest wat to find this is using Internet Explorer dev tools.

I should note that this is unsupported: you cannot expect it to work past any patches.

For example, if you wanted to provide a link that opened CRM to the Workplace section -> Accounts, you would using the following url:

http://<server>/<organization>/loader.aspx?page=Workplace&area=nav_accts

It also works with custom entities – generally the area for custom entities is simply the logical name.

So there you have it – hope this helps somebody!

Getting fingerprint reader working on Dell laptop

Dell really likes ot make it tricky to get the fingerprint reader working when you install Windows from scratch.

Update 9/7/2012:
Good news! Dell has quietly released a single installer that takes care of installing all the sub-components correctly, in the correct order (thanks Mark for pointing this out). As of this update, the latest version (for the e6520) is here:

http://www.dell.com/support/drivers/us/en/04/DriverDetails/DriverFileFormats/Product/latitude-e6520?DriverId=TDC1K&FileId=2999613592&urlProductCode=False

The catch: you have to follow a specific procedure to uninstall any old versions. Also, I don’t know if this allows you to use the lighter-weight biometric framework version. I probably won’t try it until they start supporting Windows 8.

 

UPDATE 8/25/2011: Dell has released new firmware, software and several different drivers for the fingerprint readers, whihc I have not had time to evaluate yet. My experience with the first release of the “Data Protection | Access” is that is is poorly documented, incredibly slow, buggy, and flat-out not worth the effort. Fingerprint login took so much longer than password login that I stopped using it, and did not install the drivers when I later reinstalled windows.
When I get a chance to evaluate the new drivers (which will involve some image backups) I will update this post. See the comments for some more info.

Previously, you had to download several different ControlPoint packages and install them, hoping one was the right one. Well now as of the dell E6520 they have renamed everything to Dell Data Protection | Access (Dell data protection access). You will need to download these three packages and install in this order:

Data Protection | Access — Driver Package

Data Protection | Access — Middleware Package

Data Protection | Access — Application Package

You might also need the ControlVault driver, but I’m not sure – I did for safety’s sake. Update: Do NOT install the ControlVault driver. This will cause “no fingerprint reader found” rn 02000051 error message.

I hope this helps somebody.

UPDATE: If you did install the ControlVault driver, try using system restore to roll back (This is what I did after installing the driver a second time, after reinstalling windows to recover from the first time…). Uninstalling will not remove it. If System Restore doesn’t work, you will probably need to reinstall windows (or call Dell)
Reader Kristof posted some steps in a comment below that other folks confirmed successful – I’m quoting it here for reference:

I also installed the controlvault, but did not have to reinstall windows (restore points were disabled). I solved it as follows:
– uninstall controlvault
– remove fingerprint reader from installed hardware (when it asks, also remove driver)
– uninstall all other DELL Data Protection things you might have installed
– reboot
– reinstall ONLY the Data Protection tools as described in the post
– reboot

and then it just worked… (finally!)

D-link router_info.xml (and other interesting things)

It occurred to me that if D-Link has a desktop gadget that can poll bandwidth statistics from my router (DIR-628) then I should be able to do the same!

Turns out the router has a web service of sorts at http://<router ip>/router_info.xml?section=<section name>

where section is one of:
system_info
filter_config
wan_stats
lan_stats
wlan_stats
scheduler
dhcp_server
virtual_server
application_rule
port_forwarding
rip_config
time
misc_config
ddns
dmz
system_log
qos
wps

(Note: I found these by digging through the firmware)

Perfect! If you poll this service, you get stats (and much more) all packaged up in XML. There is something potentially troubling, though. The ddns and wlan_stats sections provide cleartext passwords, even if you are logged in with normal user credentials. In other words, all a person would need in order to get the wireless password is about 10 seconds plugged in to an ethernet port.

This isn’t the only little bit of undocumented goodness though. Here are a bunch of undocumented urls that provide info of various sorts:

/setconfig.cgi
/plt_command.cgi
/wifi_assoc.xml
/wlan_radio_status.xml
/save_log_data.cgi
/redirect.cgi
/wait.cgi
/active_sessions.xml
/computer_list.xml
/wlan_stats_get.cgi
/wlan_stats_reset.cgi
/get_pcmac.cgi
/get_pcip.cgi
/reboot.cgi
/dhcp_clients.xml
/mac_filter.xml
/log.cgi
/get_time.cgi
/wan_lan_status.xml
/wan_connection_status.xml
/internet_service_provider_list.xml
/login_salt.cgi
/post_login.xml
/get_auth_id.cgi
/wan_dhcp.cgi
/wan_pppoe.cgi
/wan_mpppoe.cgi
/wan_pptp.cgi
/wan_l2tp.cgi
/get_uptime.cgi
/ssi_ping_test.xml
/ssi_dns_resolve.xml
/log_cmd.xml
/interface_stats.xml
/interface_stats_cls.xml
/dhcp_lease_revoke.cgi
/widget_wan_stats.xml
/widget_wan_get_settings.xml
/interface_option_list.cgi
/routing_table_ssi.xml
/cgi_ssi_igmp_group_memberships.xml
/get_reboot_timeout.cgi
/regdump.cgi
/get_current_wlan_channel.xml
/get_wifisc_pin.cgi
/wifisc_add_sta.xml
/wifisc_ap_get_wpa_settings.xml
/wifisc_ap_save_wpa_settings.xml
/wifisc_add_sta_progress.xml
/wifisc_cancel_add_sta.xml
/check_admin.cgi
/get_admin_pwd.cgi
/check_admin_password_changed.cgi
/wifi_log.xml
/logout.cgi
/logged_in.cgi
/lltd_bw_start.xml
/lltd_bw_stop.xml
/lltd_bw_result.xml
/chklst.txt
/version.txt
/get_ddns_status.xml
/get_usb3g_status.xml
/usb3g_connect.cgi
/reset_unconfiged.cgi
/get_auto_wepkey.xml
/get_router_timer.xml
/dfw_query.xml
/dlink_query.xml
/dlink_query_fw.xml
/getconfig.cgi
/router_info.xml

Some of them would appear to provide data for the router interface’s ajax – I would assume all the information is also avilable via the interface. It’s just nice to have access to XML.

Have fun!

Hotfix for remote debugging error “A security package specific error occurred”

It amazes me sometimes how hard it can be to find a solution to a very common problem…

The scenario:

You are using Visual Studio 2008 or Visual Studio 2010 on Windows Vista, Windows 7, Server 2008 or Server 2008 R2, and are attempting to perform remote debugging to Windows XP or Server 2003. You are using domain credentials. Most likely you will receive an error in Visual studio that “A security package specific error occurred”. You may not be able to find anything in any event logs. The Windows XP remote debugging client says you connected ok, but it doesn’t work.

The long standing workaround is to create local users on both machines with identical names and passwords; then jump through a bunch of hoops to get things to run using the alternate credentials. This is FAR from ideal.

Turns out, it is a kerberos bug, and there is a hotfix. Install this on the Windows XP machine, and you will be remote debugging in no time!

http://support.microsoft.com/kb/969442
KB969442 – Error message when you try to connect to the Product Studio middle-tier server that is running on a Windows Server 2008-based computer from a computer that is running Windows XP: “Could not connect to the Product Studio datastore listed above”

It is unfortunate that Microsoft neglected to mention in the KB article that this also applies to Visual Studio.

The more I develop for Windows Phone 7…

… I’m not sure how to finish that sentence.

I signed up to be a Windows Phone 7 developer for free via Dreamspark, which lets you submit 5 apps for free. Considering Microsoft decided to be even greedier than Apple (which is hard to do…) and charges $100/year PLUS a $25 submission fee PER APP (including free apps), I figured this was quite a deal.

While it probably is, I’ve already run into a couple really annoying snags. The latest of which has me downright mad.

First off, I consider it a fundamental right that when you buy something, you should be able to modify it. If that something happens to be a computer, you should be able to write your own programs for it. When Microsoft first announced that Windows Phone 7 would be locked down in a manner akin to Apple… (you have to pay to put YOUR code on YOUR device) well lets just say I was disappointed. Tremendously. Nevertheless, I have been wanting to try my hand at mobile developement, and I despise Objective-C. WP7 uses .NET. I know .NET.

So after I signed up for the Dreamspark account, I learned that you cannot actually deploy an app to the phone until after your identity has been verified. If you have a Paid account, this happens as soon as you sign up. For students, it doesn’t happen until you submit your first app.

So I wrote a silly junk app and sumbitted it. (I later realized that if it passed inspection, I would have wasted one of my 5 free submissions…)
Identity verified, Phone unlocked. FINALLY, I could write my own phone apps.

So I have a couple ideas I’m banging away at – some of them are really just for my own benefit, some are headed to the marketplace.
Just today I realized that the prominent free Tip Calculator sucked, and that I could write a better one. I get it developed to the point of testing, and attempt to deploy it to the phone.
And I quote,

“Unable to install application. The maximum number of developer applications on this phone has been reached. Please uninstall a developer application and try again.”

WHAT??!!?

Why in the name of God’s green earth would they limit the number of MY OWN apps I can deploy to MY OWN phone? What possible rationale could they have?
Does this mean that I would have to buy my own app in order to use it without restriction?

Apparently if I had a paid account, I could have 10 developer apps instead of 3, but it doesn’t matter – in fact it’s even worse.

Requiring me to have a developer account to deploy my apps on my phone is stupid.
Requiring me to verify my identity to deploy my apps on my phone is stupid.
Limiting the number of my apps I can deploy on my phone is downright asinine.

Since I am having such a good time ranting, here are more greivances:

  • MVVM (Model View View-Model) Designed to create a logical separation of Design and Code. Great in theory. In practice, it makes the code much harder to read and write by a casual coder; it comes with significant overhead (most guides are recommending against using it if performance is a concern), and the name is ridiculous.
  • You have XNA or Silverlight. XNA requires redesigning the wheel if you want UI elements. Silverlight is a framework in a framework (i.e., slow)
  • Making your app resemble the functionality of the built-in apps requires reinventing the wheel. Page transitions, for example, should be built-in. Instead you have to create XAML animations to do it yourself.
    (And did I mention that the more XAML your app has, the longer it takes to load?)
  • Something as simple as the built in “I’m working” animation has a bug that causes major performance issues.
  • You cannot access the compass. Seriously? iPhones and Android phones have had compasses for how long?
  • You cannot access video from the camera. This seriously limits the usefulness of barcode scanner software…
  • You cannot do anything involving the web synchronously (inherited from silverlight). I know, I know, blocking the UI thread is a bad idea, but the sheer quantity of code required to simply pull down a web page is staggering compared to the synchronous equivalent. To do an HTTP post? Why on earth do I need a callback for a stream containing “u=jason”…

Word on the street is that Microsoft is planning to open things up a little. I really hope so. I just dusted off my Mac Mini and installed Xcode — if I’m going to have my hands tied, it might as well be on the more popular platform…

Adding task panes in a Office Add-in when using IDTExtensibility2

If you are creating an Office Add-in using VSTO, it is easy to create task panes. But what if you do not want to involve the VSTO Runtime?

Using VSTO makes creating Add-ins very simple, but that simplicity comes at a cost. ClickOnce is a major pain to deploy to users, VSTO Add-ins have a tendency to mysteriously disable themselves, and they load slow.

I have recently switched to using the Visual Studio Add-in wizard, which created Add-ins using the IDTExtensibility2 interface. It requires you to do a bit more legwork, but the generated solution comes with a pre-configured MSI installer project, just asking to be deployed via Group Policy.

My latest project needs to prompt a user to perform an action when Word documents of a certain type are opened. Sure, I could use a pop-up form, but that is so very un-office-like. Taskpanes are a much more integrated solution, but for some reason the documentation and examples on the internet are pretty bad. And confusing. And WAY over complicated.
While working on this, I almost gave up (deleted and then started over once), but persistence and experimentation paid off – I got it to work, and it was much easier than I expected.

The following assumes you have some experience creating Add-ins using IDTExtensibility2.

Create your add-in project (be sure to change the debug properties to run your desired application – it defaults to Visual Studio) , add a reference to System.Windows.Forms, and add the following using statements:

using System.Windows.Forms;
using Microsoft.Office.Core;

First you need to create a user control for your task pane. Microsoft’s example says you have to create a Form and a user control in a separate project, well this is simply not true.

Add a user control to your project. I left the default name of “UserControl1”. Just for fun, we’ll add a button and a label to the user control as well.

Find the modifiers property on the button and change it to public.

We are doing this so we can access the button’s events from the Add-in, and because I am lazy. (The correct way would be to add a public event to your UserControl1 class, and call it from your private button1 event handler)

Next, modify your Connect class to also implement the ICustomTaskPaneConsumer interface.

    public class Connect : Object, Extensibility.IDTExtensibility2, ICustomTaskPaneConsumer
    {
    //
    //

Lets also add a couple more class variables, just to keep life simple (and prevent things from going out of scope unexpectedly)

        private object applicationObject;
        private object addInInstance;
        // New vars for Custom task pane
        private ICTPFactory myCtpFactory;
        private CustomTaskPane myPane;
        private UserControl1 myControl;

Finally, you implement the CTPFactoryAvailable method – this provides you with the ICTPFactory instance that you will use to actually create the task pane. I have also included the example code to create and display our task pane.

        public void CTPFactoryAvailable(ICTPFactory CTPFactoryInst)
        {
            // Store the CTP Factory for future use. You need this to display
            // Custom Task Panes
            myCtpFactory = CTPFactoryInst;

            // Create the task pane using UserControl1 as the contents
            // The third parameter, when supplied, is Window object.
            myPane = myCtpFactory.CreateCTP("MyAddin1.UserControl1", "My Task Pane", Type.Missing);

            //Set the dock position and show the task pane
            myPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionRight;
            myPane.Visible = true;

            // CustomTaskPane.ContentControl is a reference to the control object
            myControl = (UserControl1)myPane.ContentControl;

            // assuming UserControl1.button1 is public, add a handler to the click event.
            myControl.button1.Click += new EventHandler(button1_Click);
        }

And lastly, add an event handler for the click event

        void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Hello World!");
        }

Now run your project, and the task pane should be there to greet you. Clicking the button will then display the hello world messagebox.

In my project, I kept my application logic in a separate class from the Connect class. All you need is a reference to the instance of ICTPFactory supplied by CTPFactoryAvailable to create and hide task panes.

For reference, here is the entire Connect.cs file.

namespace MyAddin1
{
    using System;
    using Extensibility;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    using Microsoft.Office.Core;
    /// <summary>
    ///   The object for implementing an Add-in.
    /// </summary>
    /// <seealso class='IDTExtensibility2' />
    [GuidAttribute("62EFAKE8-FAKE-47EF-82FC-85C5FAKE977E"), ProgId("MyAddin1.Connect")]
    public class Connect : Object, Extensibility.IDTExtensibility2, ICustomTaskPaneConsumer
    {

        public Connect()
        {
        }

        public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom)
        {
            applicationObject = application;
            addInInstance = addInInst;
        }

        public void OnDisconnection(Extensibility.ext_DisconnectMode disconnectMode, ref System.Array custom)
        {
        }

        public void OnAddInsUpdate(ref System.Array custom)
        {
        }

        public void OnStartupComplete(ref System.Array custom)
        {
        }

        public void OnBeginShutdown(ref System.Array custom)
        {
        }

        public void CTPFactoryAvailable(ICTPFactory CTPFactoryInst)
        {
            // Store the CTP Factory for future use. You need this to display
            // Custom Task Panes
            myCtpFactory = CTPFactoryInst;

            // Create the task pane using UserControl1 as the contents
            // The third parameter, when supplied, is Window object.
            myPane = myCtpFactory.CreateCTP("MyAddin1.UserControl1", "My Task Pane", Type.Missing);

            //Set the dock position and show the task pane
            myPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionRight;
            myPane.Visible = true;

            // CustomTaskPane.ContentControl is a reference to the control object
            myControl = (UserControl1)myPane.ContentControl;

            // assuming UserControl1.button1 is public, add a handler to the click event.
            myControl.button1.Click += new EventHandler(button1_Click);
        }

        void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Hello World!");
        }


        private object applicationObject;
        private object addInInstance;
        // New vars for Custom task pane
        private ICTPFactory myCtpFactory;
        private CustomTaskPane myPane;
        private UserControl1 myControl;

    }
}

Getting around activation when virtualizing windows

I have been duplicating servers at work in preparation for testing upgrades. The virtualized environment lives in a completely isolated network, and it will only exist long enough to test some major upgrades.

Most of the servers p2v’d without asking for activation, but on the last server I was not so lucky.

When server 2008 demands activation, you either have to activate or it logs you out. Thankfully, I stumbled across this article:

http://www.petri.co.il/bypass-windows-server-2008-activation.htm

Essentially, you tell it to try activating (which fails, because there is no internet), then you select other options, and click on the “What is Activation” help link at the bottom. When the help window pops up, you search for “cmd”, and select the help article for Opening a command prompt. This will let you open a command prompt, where you can then type “explorer” and you will get your start menu and desktop, etc.

At this point, you could configure the network, and complete activation if you were so inclined. I was not.

Server 2008 (and Vista and Windows 7 and Server 2008 R2) normally provides a 60-day “grace period” for activation. This grace period can be extended by “rearming” windows activation up to three times. Most literature on the internet states that this allows you a 240-day trial period. What they don’t mention is that you can also rearm a machine that has “lost” its activation well beyond 240 days after installation.

Follow the directions here:

http://support.microsoft.com/kb/948472

That is,
Open an elevated command prompt, and run “slmgr.vbs -rearm”. After a bit you should get a pop up telling you that it succeeded.
Note: because this must be run from an elevated command prompt, you still need to start explorer first.

Hope this helps save you some time!

Error loading operating system after vmware converter

Today I performed a p2v conversion of a Windows XP workstation into VMWare ESXi using the free VMware Converter. This tool is really wonderful, but sometimes it likes to leave windows in an inconsistent state – especially if you resize the partition.
This case is complicated by the fact that the source computer has the Dell recovery partition, which I decided to bring along as well. After conversion, I shut down the source PC, and power on the VM, only to get Error loading operating system.

The internets failed me. Plenty of people have had the problem, but most of the solutions involved Linux or Vista+ (or reformatting. Obviously not an option). Additionally, I have encountered this problem when performing a p2v on a Server 2008 box…

I tried using the windows XP cd recovery console with fixboot and fixmbr. It didn’t work. I fooled around with the UBCD. Again, didn’t work (and wasted a lot of time) Finally, I fell back on previous experience, and found my solution: use the server 2008 CD to fix windows XP! (This would probably work with the Vista or windows 7 images as well)

So here are the steps to fix the “Error loading operating system” issue (with Windows XP ONLY) caused by vmware converter:

  1. Boot with a Server 2008 disk (Vista, Win 7 might work as well)
  2. At the language screen click next
  3. At the “Install windows” screen, click “Repair your computer” to the lower left
  4. The next screen “System Recovery Options” will have an empty list, but that is ok! Click Next
  5. Click “Command Prompt”
  6. At the command prompt, type the following:
    bootsect /nt52 ALL /force /mbr
    note: in my case, using “ALL” instead of “c:” or “SYS” was what finally solved it
  7. exit out and reboot – with any luck, windows XP will now boot!

If you still have a problem, my only other suggestion would be to use diskpart to ensure that the correct partition is active. If that diesn’t solve it, maybe the other Google results will

Good luck, and please leave a comment if this helped!