Thursday, November 30, 2006
Sometimes you run into a problem that’s really just too much to figure out. It involves multiple groups, multiple vendors, and multiple headaches. One of my recent challenges has been getting Live Messenger to work from Vista.
I built a new Vista Ultimate machine with the x64 release bits. Everything was fine until I realized that none of my MSN messenger buddies ever appeared like they were online. I dug a little and realized that I could login from the Windows XP system sitting next to me but Vista wouldn’t work I'd get an error during the sign in process. I opened a support case with SonicWall who told me that it was a Microsoft Windows problem – and oh by the way, they don’t support Vista yet. They were seeing a TCP ReSeT from the client. It was a client problem.
I travel out to Redmond, WA on business and guess what … my MSN contacts work fine from the vista box. Now I’m really confused. It works when the system is remote but not when it’s on my network.
I’m already frustrated as I try to understand why for firewall functionality the client OS mattered – however, I opened a case with Microsoft. After fighting to get the issue landed in the Vista Networking queue instead of the MSN queue… we started working on the resolution.
The net of it – after dozens of hours wasted – was that I updated my SonicWall to the latest firmware (22.214.171.124-54e). I then went in and UNCHECKED the option under Firewall-Advanced labeled ‘Enable support for Windows Messenger’. That’s right, I turned it off. Unchecked it. Said, I don’t want it.
Live Messenger fired up immediate on the Vista Machine.
Arg. It should have been easier than this.
Special thanks to my friends in Microsoft PSS who stayed with me to help find the resolution.
[Keywords: Sonicwall, Windows Live Messenger, Error 81000306, Sudden disconnect Added 06-12-20]
Thursday, November 30, 2006
Thursday, November 30, 2006
If you're dropping a onTaskChanged activity and you're finding an event in the ULS like the following ...
11/30/2006 08:56:04.12 OWSTIMER.EXE (0x05D4) 0x0B48 Windows SharePoint Services Workflow Infrastructure 72er Medium System.InvalidOperationException: The event receiver context for Workflow is invalid. at Microsoft.SharePoint.SPEventReceiverDefinition.ValidContext() at Microsoft.SharePoint.SPEventReceiverDefinition.ValidReceiverFields() at Microsoft.SharePoint.SPEventReceiverDefinition.GetSqlCommandToAddEventReceivers(IList`1 erds) at Microsoft.SharePoint.Workflow.SPWinOESubscriptionService.CommitNewSubscriptions(Transaction txn, IList`1 erds)
The problem may no with the event receiver, rather that in the CreateTask activity you didn't associate properties for TaskID, TaskProperties, or CorrelationToken. Thus there's no context for the event to call back to.
Wednesday, November 29, 2006
Sometimes things aren’t as easy as they seem. Adding a CreateTask activity to a SharePoint Workflow is one of those things. Drag-and-Drop and you’re ready to go. Not quite. There are several things that you need to know about adding a CreateTask Activity.
First, you need to know about Correlation tokens. Basically, the task needs a different correlation token than the workflow itself. You can find the documentation for this in the SDK under Server Technologies\Windows SharePoint Services 3.0\SDK Documentation\General Reference\Workflows in Windows SharePoint Services\Workflow Development for Windows SharePoint Services\Workflow Development in Visual Studio 2005\Workflow Activities Overview\Correlation Tokens in Workflows. You can also read Eilene Hao’s post on the SharePoint Team Blog titled “Developing Workflows in VS: Part 3 - Five Steps for Developing Your Workflow”.
Next, you have to do some manual manipulation of the code for the workflow to define the appropriate properties and get them setup for the activity’s use. In the SDK documentation at Office solutions Development\SharePoint Server 2007\SDK Documentation\General Reference\Managing Enterprise Document Content\Workflows in Office SharePoint Server 2007\Walkthrough: Creating Office SharePoint Server 2007 Workflows in Visual Studio\Step 1: Create the Workflow there is a section “Adding and Configuring Workflow Activities\To add the CreateTask activity” which contains a suggestion for the properties to be set – and more importantly some code you’ll need to get the task to work correctly.
The net of it is that you must declare public fields tasked as a Guid – and get a new Guid in the value when the MethodInvoking is called. You must also declare and new a Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties. These must be assigned to the TaskId and TaskProperties of the activity respectively.
If for some reason you fail to do this you may see an error in the log like the following:
[Note: You don’t have to read through the following, it’s mainly included here so that it can be indexed so if someone is searching for the cause of the error they might find it. Rlb]
11/29/2006 22:30:43.57 w3wp.exe (0x00C4) 0x0C6C Windows SharePoint Services Workflow Infrastructure 88xr Unexpected WinWF Internal Error, terminating workflow Id# 4a62891e-f779-499c-86d1-a2362f461978
11/29/2006 22:30:43.58 w3wp.exe (0x00C4) 0x0C6C Windows SharePoint Services Workflow Infrastructure 98d4 Unexpected System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object. at Microsoft.SharePoint.Workflow.SPWinOETaskService.CreateTaskWithContentTypeInternal(Guid taskId, SPWorkflowTaskProperties properties, Boolean useDefaultContentType, SPContentTypeId ctid, HybridDictionary specialPermissions) at Microsoft.SharePoint.Workflow.SPWinOETaskService.CreateTask(Guid taskId, SPWorkflowTaskProperties properties, HybridDictionary specialPermissions) --- End of inner exception stack trace --- at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) ...
11/29/2006 22:30:43.58* w3wp.exe (0x00C4) 0x0C6C Windows SharePoint Services Workflow Infrastructure 98d4 Unexpected ... at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture) at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object providedArgs, ParameterModifier modifiers, CultureInfo culture, String namedParams) at System.Workflow.Activities.CallExternalMethodActivity.Execute(ActivityExecutionContext executionContext) ...
11/29/2006 22:30:43.58* w3wp.exe (0x00C4) 0x0C6C Windows SharePoint Services Workflow Infrastructure 98d4 Unexpected ... at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(T activity, ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(Activity activity, ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.ActivityExecutorOperation.Run(IWorkflowCoreRuntime workflowCoreRuntime) at System.Workflow.Runtime.Scheduler.Run()
11/29/2006 22:18:01.14 w3wp.exe (0x0D18) 0x0AB0 Windows SharePoint Services Workflow Infrastructure 72ev Medium Value cannot be null.
11/29/2006 22:18:01.31 w3wp.exe (0x0D18) 0x0AB0 Windows SharePoint Services Workflow Infrastructure 88xr Unexpected WinWF Internal Error, terminating workflow Id# b0474e92-3e38-443e-9ac1-c27afb1d20cf
11/29/2006 22:18:01.31 w3wp.exe (0x0D18) 0x0AB0 Windows SharePoint Services Workflow Infrastructure 98d4 Unexpected System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentNullException: Value cannot be null. at Microsoft.SharePoint.Workflow.SPWorkflow.GetReservedItemId(SPList list, Guid taskId, Boolean createNew) at Microsoft.SharePoint.Workflow.SPWorkflowInstanceBase.GetReservedItemId(SPList list, Guid taskId) at Microsoft.SharePoint.Workflow.SPWinOETaskService.CreateTaskWithContentTypeInternal(Guid taskId, SPWorkflowTaskProperties properties, Boolean useDefaultContentType, SPContentTypeId ctid, HybridDictionary specialPermissions) at Microsoft.SharePoint.Workflow.SPWinOETaskService.CreateTask(Guid taskId, SPWorkflowTaskProperties properties, HybridDictionary specialPermissions) --- End of inner exception stack trac...
11/29/2006 22:18:01.31* w3wp.exe (0x0D18) 0x0AB0 Windows SharePoint Services Workflow Infrastructure 98d4 Unexpected ...e --- at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture) at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object providedArgs, Parame...
11/29/2006 22:18:01.31* w3wp.exe (0x0D18) 0x0AB0 Windows SharePoint Services Workflow Infrastructure 98d4 Unexpected ...terModifier modifiers, CultureInfo culture, String namedParams) at System.Workflow.Activities.CallExternalMethodActivity.Execute(ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(T activity, ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(Activity activity, ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.ActivityExecutorOperation.Run(IWorkflowCoreRuntime workflowCoreRuntime) at System.Workflow.Runtime.Scheduler.Run()
(These are located in the Universal Logging Service log at C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\LOGS)
Wednesday, November 29, 2006
Tuesday, November 28, 2006
Monday, November 27, 2006
Somewhere along the journey of beta cycles Dan Winter made me realize how important the logs in the C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\LOGS directory was. In that case we were dealing with a setup issue and we were looking for the PSCDiagnostics*.log files. However, I didn't associate that directory with logging for the entire product. So when I started struggling with workflows (see my two previous posts: Adding the second workflow to a SharePoint Workflow Assembly and Renaming the Default Workflow with the ECM Starter Kit B2TR) I didn't connect that the unified logging service would have the answers I needed. However, Todd Baginski was kind enough to remind me that these logs actually contained everything SharePoint in them. When I cracked the latest log file open I saw my error. Of course, that doesn't resolve the problem -- but it at least allows me to work on it. So, if it's SharePoint and it's broken the LOGS directory is a good place to look first.
By the way, if you want to change the interval that the log files are changed or the number of log files that are kept, you can get to that under Central Administration->Operations->Diagnostics Logging.
Sunday, November 26, 2006
With the 2007 Office System: Enterprise Content Management Starter Kit (ECMsk), you get a project type that will create a SharePoint aware workflow (in either sequential or state machine format.) However, if you want more than one SharePoint workflow in the same assembly you’ve got a problem. The ECMsk (at least in Beta2TR which is the latest publically available version as of this writing) doesn’t add the project item type into Visual Studio so you can’t create a second workflow easily. Great. Here’s how to do it by hand.
1. Create a workflow of your choice. Choose the option indicated (code) not the one indicated (with code separation). [Note: I used sequential workflow for my example – and technically this should be possible with code separation I just didn’t test the steps, yet.]
2. Open the code view of your new workflow (*.cs)
3. Add a using statements to the top of the file, after the existing using statements
a. using Microsoft.SharePoint
b. using Microsoft.SharePoint.Workflow
c. using Microsoft.SharePoint.WorkflowActions
4. Change the class to derive from SharePointSequentialWorkflowActivity instead of SequentialWorkflowActivity.
5. Save your work and close the file.
6. Open the design view of the workflow(*.cs [Design])
7. Drop the onWorkflowActivated activity on the workflow surface.
8. Double click on the onWorkflowActivated activity to create the invoked code behind.
9. Save the file and then close the design view (*.cs [Design])
10. Open the designer.cs file for the workflow (*.designer.cs) (It’s stacked underneath the *.cs file of the workflow by default.)
11. Add a using statement to the top of the file after the existing using statements
a. using Microsoft.SharePoint.Workflow;
12. Add two variable declarations above the onWorkflowActivated1 definition
a. public Guid workflowId = default(System.Guid);
b. public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();
13. Expand the “Designer generated code” segment.
14. After the line in InitializeComponent() which reads “this.CanModifyActivities = true;” add the following:
a. System.Workflow.ComponentModel.ActivityBind activitybind2 = new System.Workflow.ComponentModel.ActivityBind();
b. System.Workflow.ComponentModel.ActivityBind activitybind1 = new System.Workflow.ComponentModel.ActivityBind();
c. activitybind2.Name = “myWorkflowName”;
d. activitybind2.Path = “workflowId”;
e. activitybind1.Name = “myWorkflowName”;
f. activitybind1.Path = “workflowProperties”
15. After the line in InitializeComponent() which reads “this.onWorkflowActivated1.Invoked += new System.EventHandler(this.onWorkflowActivated1_Invoked) add the following:
a. this.onWorkflowActivated1.SetBinding(Microsoft.SharePoint.WorkflowActions.OnWorkflowActivated.WorkflowIdProperty, ((System.Workflow.ComponentModel.ActivityBind)(activitybind2)));
b. this.onWorkflowActivated1.SetBinding(Microsoft.SharePoint.WorkflowActions.OnWorkflowActivated.WorkflowPropertiesProperty, ((System.Workflow.ComponentModel.ActivityBind)(activitybind1)));
16. Save the *.designer.cs file.
17. Open the design view of the workflow (*.cs [Design])
18. Click on the CorrelationToken property and type ‘workflowToken’.
19. Expand CorrelationToken and in the OwnerActivityName that appears beneath it select the name of your workflow.
20. Save the file.
21. You’re ready to build. Press Ctrl-Shift-B to build – and your new workflow should just work.
Not as simple as it should be – and I have no way of knowing if this is a supported (or supportable) way of getting a standard workflow to work as a SharePoint workflow – but it’s worked thus far in my testing.
Sunday, November 26, 2006
I’m about neck deep with Visual Studio 2005 and SharePoint workflow right now. (Actually, I’m breathing through a straw as you may see.)
The 2007 Office System Starter Kit: Enterprise Content Management Starter Kit (ECMsk) has in it some Visual Studio project templates to get you started with using SharePoint and Workflow together. However, it’s in beta so it’s not perfect…
The first issue isn’t that bad, it adds a reference to Microsoft.Office.Workflow.Tasks – which isn’t installed with WSSv3 – even with Office 2007 Pro and InfoPath 2007 installed. It means removing the reference and the using line ‘using Microsoft.Office.Workflow.Utility’ in the workflow1.cs file. Not that big a deal all things considered.
The other problem is a bit more tangled. That is you can’t easily rename the workflow to be something else. If you try renaming the workflow you’ll get a friendly prompt from Visual Studio stating “You are renaming a file. Would you also like to perform a rename in this project of all references to the code element ‘Workflow1’?” It’s pretty nice of it to ask so sure. Click the Yes button. This is where you have your first signs it’s going to be ugly. Visual Studio’s next dialog states: “Your project or one of its dependencies does not currently build. References may not be updated. Continue: Perform the refactoring, Preview: Show a preview of the references that will be updated, Cancel: Cancel the refactoring” followed by a helpful “Show this dialog every time” checkbox and the option to continue, preview, or cancel. You can click continue, but it’s right. Not all the references were updated.
If you open the newworkflowname.designer.cs (*.designer.cs) file for the workflow you’ll find a section of code marked “do not touch” – said only in a slightly nicer way. In that section you’ll find an InitializeComponent() method. It contains four references to the old workflow1 (and a comment) – all in text references. A quick search and replace and the rename will be complete. However, there’s one little catch. You must have the Design view of the newworkflowname.cs file (*.cs [Design]) closed in order for your changes to be recorded. Make sure you do that before the search and replace. Do a save then a Ctrl-Shift-B to build and see if it builds for you.
Easy as pie, right?
Sunday, November 26, 2006
Let me start in a rather odd way. I don’t have all the answers about developing products. Frankly, I probably have only the slightest sliver of understanding of what is needed to develop products. Having been stuck at the phase where I have completed products that I haven’t been able to release to the market – I’m focused on thinking about the problem and trying to find solutions.
My son is at the stage where he likes dot-to-dot puzzles. He connects each dot not knowing what the end result will be. He carefully connects one dot and then the next and then the next and doesn’t take the time to step back until he’s completed.
It strikes me that this isn’t much different than the process of creating a product. I realize that there are lots of dots – most of which need to be connected – to make the complete picture – the product. I’m sure (because I’ve not managed to make my product sales what I would call successful) that I’m missing a few, but I wanted to share what I’ve figured out thus far.
Developing the Product
Perhaps the easiest part of the process for me is developing the solution. I’ve spent the last 15 years of my professional career creating solutions for clients. Writing the program and understanding how to make it reusable isn’t something I really struggle with any more. If you look in my source control system you’ll find dozens of testing harnesses and tools designed to perform reusable operations – and that doesn’t even include the things that I’ve packaged to be products.
Also in the easy category for me is writing. I’ve spent the last several years writing articles and books. Writing isn’t something I dread (very often). It’s just another thing to do. Once I have working and tested code, it’s off to write some documentation that will help people understand how to use it. The trick here, if there is one, is writing the documentation to spark the user’s creativity on how the tool can solve problems other than the one it was intended to solve.
Ouch. This one hurts. Every experience I have had making anything but the most trivial installation package has ended in disaster. However, a good solution to the need to get the software installed is an essential part of the overall solution. I bias strongly towards programs that require little or no installation – but that’s honestly because my experience with installers has been so bad.
Somewhere in this process you have to integrate a licensing engine. As much as I hate to say it software piracy runs rampant in the world. People don’t quite understand the intellectual property which is wrapped up in the software and the need to compensate the author for that intellectual property. I like to ignore this but I’m painfully reminded by my friends and colleagues that I cannot.
I learned that in the publishing world there’s not a lot that matters other than shelf space. Good authors, good books, and good ideas have died a slow death because they were never provided the shelf space in the book stores that they required. A product is the same way. The product needs a home. It needs a place for people to come to find it. It needs a place that describes it and explains how it works, what the values are, and the cost. Without this place no one will know the product exists – or they won’t be able to find it if they do know it exists – and you won’t get any sales.
By the way, this is the point where I’m stuck. I, in part, build commercial grade eCommerce solutions for large organizations. My threshold for the system to deliver my products is really, really high. That means that some of the traditional options for Micro-ISVs just don’t just make me feel comfortable presenting my solutions there. I haven’t yet invested the time to get my platform up and running personally… so I am stuck.
Once you have a store front and people have a way to know that they want to buy the solution, it’s important that you have a way to take their money. Honestly, this part has become much simpler over the last few years. With credit card processors owned by large banks now supporting web service calls to authorize transactions, and the services offered by PayPal, there are real options for conducting commerce over the web. Credit Cards are not quite universal; however, they are pervasive enough that they are an effective payment mechanism. The real challenges here are managing fraud and dealing with “returns.”
Supporting a product once it’s in the market is critical to long term success, but how does a small software vendor cope with the time that supporting customers requires? Support is one part about preparing – so you can track defects, customer satisfaction, etc., but more than anything else it is about creating and preserving timely communications with the users trying to use the product. Not an easy task for most organizations. Perhaps this is why so many software companies struggle with support today.
Build it and they will come doesn’t work. You need to let people know that your product exists. For most folks this means buying advertising. It is money out of your pocket to get people to look at, think about, and perhaps even evaluate your product. The folks that I know who are successful at selling products all talk about how their advertising relates to product sales. They don’t see a one-to-one relationship – but they definitely see an impact on sales. So your product (and perhaps your company) needs some sort of a marketing strategy.
The final part of developing a product is developing a lifecycle for the product. What will the next version of the product do? When will you make the investment in the next version of the product? Planning for the next revision is as much a part of the total solution as any other part of the process.
I don’t know what all of these dots make when connected. I’m pretty sure it’s not a bunny rabbit, but beyond that I haven’t a clue what to expect. When you’re looking at putting together a product ask yourself if you can connect all of these dots – or not.