The more I develop for Windows Phone 7…

2
share
 

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

RegistryPolicyProcessing

4
share
 

I recently encountered a server that was having problems applying group policy. I encountered the following errors:

Log: Application
Source: Group Policy Registry
Event ID: 8194
Message:The client-side extension could not remove user policy settings for 'GPONAME {n-n-n-n-n}' because it failed with error code '0x8007000d The data is invalid.' See trace file for more details.
Log: System
Source: GroupPolicy
Event ID: 1085
Message: Windows failed to apply the Group Policy Registry settings. Group Policy Registry settings might have its own log file. Please click on the "More information" link.

 

The More info link is useless -don’t waste your time. Also, it would appear there is no trace file. Searching for these errors on Google will get you suggestions about deleting GPOs on the Domain controller, but the thing is, I need this GPO.

To diagnose this issue, you will first need to enable Group Policy tracing. On the machine having the problems, open up the local group policy editor (run gpedit.msc) and browse to:

Computer Policy \ Administrative Templates \ System \ Group Policy \ Logging and tracing

This contains a list of all the Group Policy Modules / extensions. Select the one that matches the error message in the system event log. (In my case, it was Registry Policy Processing)
enable the policy, change Tracing to “On” and click Ok.

Now open an elevated (Run as Administrator) command prompt, and type gpupdate. This should get the errors to throw again, but this time it will write out a trace file.

You should be able to find that trace file in C:\ProgramData\GroupPolicy\Preference\Trace\User.log. Open it up and look for a line containing “The data is Invalid”. You should see something like the following:

GPH data file : C:\ProgramData\Microsoft\Group Policy\History\{...-...-...-...-...}\S-1-5-21-...-...-...-...\Preferences\Registry\Registry.xml
Completed parse of GPH XML. [ hr = 0x8007000d "The data is invalid." ]
Completed remove GPH. [ hr = 0x8007000d "The data is invalid." ]
Leaving ProcessGroupPolicyExRegistry() returned 0x8007000d

The filename after GPH data file is the corrupt file. Most likely is is an empty XML File. I just renamed the folder C:\ProgramData\Microsoft\Group Policy\History\{guid}\{sid} to be {sid}.bak.

(Note: you may need to change your folder options to be able to access the file)

Now run gpupdate again, and it should recreate the history file with the correct contents. Problem solved!

Finally, remember to disable the tracing.

UserControl1

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

0
share
 

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("62E5FF98-E843-47EF-82FC-85C501C9977E"), 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

0
share
 

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!

Fixing Server 2008 boot issues

0
share
 

A vista or Windows 7 boot disk has a real handy feature called Startup Repair. This feature is conspicuously missing from the Server 2008 disc… or is it?

http://www.binarywar.com/2010/01/windows-server-2008-bootmgr-is-missing-error/

It is there, you just have to run it from the command prompt. And that fixed it!

x:\sources\recovery\StartRep.exe

Error loading operating system after vmware converter

8
share
 

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!

sharepoint_too_big

Not sure what to make of this

0
share
 

I’m installing the Sharepoint Foundation 2010 prerequisites, and happened to notice this little gem:

Already downloaded more than the size of the file

This does not bode well..

GlenBeck

Glen Beck = Alex Beer?

0
share
 

Political persuasion aside, I fail to see how this follows…

Welcome back!

0
share
 

Shulerent.com is relaunched as Jason Shuler’s Tech Blog using WordPress (instead of Nucleus).

I have decided to venture outside the realm of obscurity, and join the community. Nucleus really wasn’t up to the challenge, and Shuler Enterprises is no real company… so a change of venue and name was in order. I will still need to go back through and perform some cleanup, since all previous posts were imported.

Stay tuned for more frequent updates and I attempt to integrate my online presence

-Jason

Using Process related API calls in VB.NET

0
share
 

I’m working on an app that will monitor the number of GDI Objects of another process (in this case, the spooler)

To do this in VB.NET requires an API call to GetGuiResources. While testing, I was using Process.GetProcesses to get a list of all the available processes, passed the handle of each process to the API function, and writing the result to a textbox.

Problem was, all process that I did not own throw security errors, even when I set the app to run with elevated privs. The internet once again failed me, and I stumbled across the solution while browsing the system.diagnostics.process documentation on MSDN.

The solution is to call Process.EnterDebugMode() before getting your process list and calling the API, then calling Process.LeaveDebugMode() when you are done.

MSDN EnterDebugMode Documentation

Here is an example. remember to run with elevate privs, and create a multiline textbox called txtOut.

Public Class Form1
  Declare Function GetGuiResources Lib "user32" (ByVal hProcess As Long, ByVal uiFlags As Long) As Long
  ' uiFlags: 0 - Count of GDI objects
  ' uiFlags: 1 - Count of USER objects

  Private Sub btnGo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGo.Click
    Dim procList As Process()

    Dim TYPE_GDI As UInteger = 0

    Process.EnterDebugMode()
    procList = Process.GetProcesses

    For Each proc As Process In procList
      Dim objCnt As Long
      Try
        objCnt = GetGuiResources(proc.Handle, TYPE_GDI)
      Catch ex As Exception
        objCnt = -1
      End Try

      txOut.AppendText(proc.ProcessName & vbTab & "GDI: " & objCnt.ToString & vbNewLine)
    Next proc

    Process.LeaveDebugMode()

  End Sub
End Class
Go to Top