This all started when I was trying to serialize a CodeDom graph (actually a CodeNamespace object) using a DataContractSerializer. I hit the dreaded “Enum value ‘20482’ is invalid for type…”
(Note: this error was the showstopper after many other errors)
The problem: System.CodeDom.MemberAttributes should have the [Flags] attribute, but it does not. the value of 20482 is the bitwise OR of MemberAttributes.Final (2) and MemberAttributes.Private (20480). One solution was to go through all object in the CodeDom tree with attributes and force it to a single value – this is not really acceptable. Unfortunately, since we are dealing with a .NET Framework type, there is really no way to fix the type itself.
The solution: Fix the serializer… Read on for details.
My laptop battery’s lifetime has dropped significantly of late, and I wanted some means of determining the actual current being used by the system – sort of like a Power Meter for the laptop battery. I‘ve actually been looking for such a tool off and on for months. I’ve seen things you have to pay for, things that are quite old, and things you can do yourself in C++…
Well I don’t want to pay for something that tells me the power usage in mw (milliwatts). Nor do I want something with “Vista” style. Nor do I want to deal with c++.
1. Performance Monitor
Not sure why I didn’t think to look here – maybe because it’s a big mess – but it turns out the power utilization in mW is in a couple places in windows Performance Monitor:
Under Power Meter –> Power:
Do not use the _Total option – at least on my machine it is incorrect. Use all instances, then look to see which instance corresponds to your actual battery. (note: this only works while your laptop is running on battery power. “Power Meter” returns 0 when you are on AC power)
You can also use Battery Status –> Discharge Rate. There is also a Charge Rate that will have a value when the battery is charging. The only catch is that access to Battery Status requires Administrator privs.
2. .NET Performance Counter – Forms control
Forget WMI queries and System.Management – Be lazy! Visual Studio has a Server Explorer tab that allows you to easily add performance counters to your Windows Forms project.
Open Server Explorer –> You computer –> Performance Counters
Find Power Meter, expand Power, and drag whichever power meters you need onto your form. (In my case I just needed Power Meter (0).
This will add performanceCounter1 to your project. To get the current power usage in mW, just access performanceCounter1.NextValue().
3. .NET Performance Counter – Code
Even easier, once you know the Category (“Power Meter”), Counter (“Power”) and Instance (“Power Meter (0)”), you can create the performance counter in code like so:
(Add a textbox and a button to your form), use this as the button event handler
private void button1_Click(object sender, EventArgs e)
{
var powerCounter = new System.Diagnostics.PerformanceCounter("Power Meter", "Power", "Power Meter (0)", true);
textBox1.Text = powerCounter.NextValue().ToString();
}
Chances are I will release a (free, open source) tool based on this, but it’s painfully simple to just get that current value. (Now to start seeing the effect of the backlight, and hard drive, and cpu load…)
When using CodeDom to generate executables (using CodeCompileUnit.CompileAssemblyFromDom for example), you can easily embed your custom application manifest using the CompilerParameters.CompilerOptions string, like so:
The relevant option being /win32manifest. Make sure you create the manifest before attempting to compile, obviously.
And use the CompileParameters in CompileAssemblyFromDom();
FYI – There are other ways to do this, but they would involve finding and running some command line utilities. This is by far the easiest, and most elegant way I could find.
A Single File Generator or “Custom Tool” is a COM “extension” for Visual Studio that takes a project file as input, and spits out some code. (One example is the .settings files) Visual Studio automatically includes the code in your project, and updates it every time you save.
I developed a tool that reads an Office 2010 Ribbon XML file and produces an interface will all the callbacks in your file (because implementing callback signatures is a bear).
Unfortunately, Microsoft’s documentation on the subject is incomplete and obsolete. If you search the web, you will find contradictory information…
I didn’t want my assembly in the GAC, nor did want to have to register the COM object globally. I didn’t want to create a setup project, or use any fancy generated code… I just wanted it to work.
So here are some tips that should get you going.
First of all, there is no need to use the Visual Studio extensibility project template for this. Just create a standard Class Library in the .NET language of your choice.
Add a reference to Microsoft.VisualStudio.Shell.10.0 and Microsoft.VisualStudio.Shell.Interop to your project. (If you do not have these, you probably need to download the Visual Studio 2010 SP1 SDK)
In the Project Properties, in the Application tab, click “Assembly Information…” and check the “Make Assembly COM Visible” box.
Do NOT select “Register for COM interop” on the Build tab
On the signing tab, check sign the assembly, and select or create a key
Add the following using statements to your class file:
using System.Runtime.InteropServices;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio;
Add the ComVisible attribute
Add a Guid to the class (use the Tools Menu-> Create GUID and select Item 5 for c#, item 6 for vb.net, hit copy)
[ComVisible(true)]
[Guid("FAKEGUID-FFF6-4FF3-FFF7-FFFFRFRFRF45")]
public class Generator : IVsSingleFileGenerator
{
DO NOT USE THIS GUID. YOU MUST GENERATE YOUR OWN
Implement the IVsSingleFileGenerator interface’s two methods – Generate and DefaultExtension (see the documentation for more details)
Build it!
Now for the part where the documentation falls apart – registering and using this bad boy.
The easiest way to register this is using the Visual Studio local registry at HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0
Note: on 32-bit systems, this may be at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0 – I am using the 64-bit
There should be plenty of sub-keys under this key. If there are not, perhaps you need to look in a different version, or bit-ness
First, you need to add the COM information like so
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\CLSID\{FAKEGUID-FFF6-4FF3-FFF7-FFFFRFRFRF45}]
"InprocServer32"="C:\\Windows\\SysWOW64\\mscoree.dll"
"ThreadingModel"="Both"
"Class"="DemoSFGen.Generator"
"Assembly"="DemoSFGen, Version=1.0.0.0, Culture=neutral, PublicKeyToken=faketokenfffff88"
"CodeBase"="file:///C:\\Users\\username\\Documents\\Visual Studio 2010\\Projects\\sfgen\\sfgen\\bin\\Debug\\sfgen.dll"
Replace the GUID after CLSID with the GUID you generated earlier; replace the Class with your Namespace.ClassName; replace Assembly with the information from your dll (I used ILSpy – I’m sure there’s an easier way); replace CodeBase with the full path to your dll.
Next, add the registry info to tell Visual Studio about the Generator:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Generators\{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}\DemoSFGen]
"CLSID"="{FAKEGUID-FFF6-4FF3-FFF7-FFFFRFRFRF45}"
"GeneratesDesignTimeSource"=dword:00000001
@="Nice Name For your Generator"
The GUID after \Generators\ corresponds to the languages in Visual Studio. See the docs for registering single file generators for a couple (or have a look in the registry).
The Key name under the language guid (DemoSFGen in this case) is (I believe) how you will refer to the Custom Tool
The value of CLSID needs to match your generated GUID
Run Visual Studio, open a (different) project, and select an appropriate input file (text, xml, etc) In the properties for the file, add the name of the Custom Tool (“DemoSFGen”).
Right click on the file, and select “Run Custom Tool”
If everything worked, you will now be able to expand the file, and see your generated source underneath it. If there was a problem, Visual Studio may or may not display an error…
I know that Custom Tools aren’t the most often created things in the world, but hopefully these steps can at least get you up and running when you do try.
Here’s another Office 2010 undocumented “feature”.
First a little background regarding required fields in sharepoint:
In Office 2007, in order to attach the Sharepoint properties to a document you had to first Save it into the document library. Word would allow you to save, but the document would remain checked-out to you until you filled in the necessary required properties, and checked it in.
If you were developing a system that automated adding documents to SharePoint, you could not even present the Document Information Panel to the user until the document was already in SharePoint. If the user decided to cancel… you had hanging files.
With Office 2010, Word (and I imagine other apps) will not actually complete the Save operation to a SharePoint Document Library when there are required fields. You get a warning and the document is _not_ placed in SharePoint, but the Fields from the Document Library are attached to your Word document.
In Word, if you want to display the “Save As” dialog box pre-populated to a SharePoint library you do something like this:
This will act the same as the normal “Save As” dialog.
If you want to handle the save process yourself, instead of dlg.Show(), use dlg.Display. This *should* take no action regardless if the user presses Ok or Cancel. If the destination happens to be SharePoint – intsead of doing nothing like it is supposed to – Word happily retreives the Sharepoint properties and attaches them to your document.
In addition to being handy, Word will attach the document properties to Read-Only and Protected files – which is something you cannot do using CustomXMLParts.
And it’s a heck of a lot easier than trying to build and attach them yourself.
While it is undocumented (and therefore subject to change), it is kind of impossible to work around — Word WILL attach the sharepoint properties, so you might as well take advantage of it.
UPDATE 3/20/2012: Unfortunately, I have discovered that this method is unreliable. On one of our user’s machines, the Save As dialog refuses to display the sharepoint folder at all. I don’t know why, but I wouldn’t recommend relying on this.
When creating VSTO Add-Ins that customize the Office Ribbon, the visual Ribbon editor makes some tasks trivial. All Ribbbon controls can be accessed by id using intellisense. The RibbonEditBox.Text field can be directly queried and modified.
Everything changes when you create the RibbonXML directly.
You cannot directly query any of the runtime values on a ribbon control. You must use the OnChange callback to get the value in the box.
public void OnChange(Office.IRibbonControl control, string text)
{
}
But what if you wanted to change the value of the editBox (aka change the text)? Say perform some validation, or formatting?
I tried casting the IRibbonControl object supplied by the callback to a RibbonEditBox object… This didn’t work.
I tried casting the control object as a Dynamic and accessing the “Text” property… No dice.
I looked for some means of getting the ribbon control so I could modify the Text value – nothing.
The solution:
(Which was surprisingly difficult to find)
There are three things you will need to do:
1. Within your ribbon’s class, make sure you are saving the IRibbonUI reference provided by Ribbon_Load to a private variable. I just call it “ribbon”
2. Implement the getText callback and a private string variable to hold the internal value for the editBox
3. Implement the onChange callback to perform validation, update the private variable, and use the IRibbonUI object to invalidate the editBox control. This triggers the ribbon to call the getText callback again, effectively updating the field.
An example:
This snippet when merged into the Ribbon class, will ensure that the text entered in an edit box ends with “of doom”
private string textValue;
private Microsoft.Office.Core.IRibbonUI ribbon;
public void Ribbon_Load(Office.IRibbonUI ribbonUI)
{
this.ribbon = ribbonUI;
textValue= "";
}
public void OnChange(Office.IRibbonControl control, string text)
{
if (!text.EndsWith("of doom"))
{
textValue = text + " of doom";
ribbon.InvalidateControl(control.Id);
//Only invalidating when the value needs to change. You could invalidate after the if block as well
}
else
{
textValue = text;
}
}
public string GetText(Office.IRibbonControl control)
{
return textValue;
}
(Long story short: the property you need is ViewMailMergeFieldCodes. Set it to 0 to enable preview; -1 to disable preview)
The mail merge process in Microsoft Word is a bit of a bear to automate sometimes. I suppose I should be thankful that it can be automated at all, but there are bits of it that are very poorly documented, requring a bit of trial and error to work with. It doesn’t help that most Office interop documentation leans toward Visual Basic…
Anyway, today’s issue was attempting to programmatically Preview the results of a Mail Merge in a C# VSTO project, like the button in the ribbon:
Big surprise: Document.MailMerge doesn’t contain any properties or methods with the word “preview”
Turns out there is a property called ViewMailMergeFieldCodes that does what we need, but in reverse. Microsoft’s documentation states:
This property returns True if merge field names are displayed in a mail merge main document, and False if information from the current data record is displayed
Trouble is, the field is an int, not a bool! A little debugging to the rescue:
When this field is set to -1, Preview is disabled, and the field codes are displayed.
When set to 0, Preview is enabled, and the record data is displayed.
To switch the displayed record, change Document.MailMerge.DataSource.ActiveRecord.
Now if only there was an event that fired when the record changed…
I need to create some objects that will allow me to access columnar data by header name. The access looks something like this:
class ParentObj {
string[] columnNames;
ChildObj[] Children;
}
class ChildObj {
Dictionary<string, string> Items;
}
All the child dictionaries will have the same set of keys, matching the column list from the parent.
Now this particular object is going to be used on computers that are resource constrained, and could contain large quantities of data. My big concern was should I actually use separate dictionaries, or should I just store the values in an array, and lookup the column number from a single dictionary.
After trying both methods with very large random data, I found the memory usage to only increase 10megs using separate Dictionaries. Certainly not worth the added complexity of managing my own Dictionary implementation.
My next question was if the CLR was wasting a bunch of memory on a bunch of duplicate keys. CLR Profiler to the rescue!
I modifed my test program to be able to either use the same keys in all child objects, or use random keys as well. After making all the strings the same size, it was clear that .NET does not keep a separate copy of each of the duplicate strings around:
Object memory when all keys are the same:
Object Memory when the keys are random:
So in conclusion, using many dictionary instances with the same set of keys does not result in a significant amount of duplicate data in memory (or memory waste).
Microsoft Dynamics CRM 4.0 is really a beautiful thing – with a few very annoying exceptions, it is a very flexible, easy to use, easy to customize business application development platform. It includes a comprehensive Web Service that allows you to perform pretty much any UI task programmatically.
There is one problem though – the CrmService proxy class can take upwards of 7 seconds just to initialize the class. Before a singe bit is passed from client to server, you have to wait for the .NET runtime to build the ginormous XmlSerializers for the equally ginormous Web service.
Normally Sgen.exe can be used to improve the startup time of Web Services, but for some reason the CRM Service doesn’t always get along with pregenerated XmlSerializers.
The solution: remove all those unused entities! My organization’s current CRM instance has 192 entities, which translates into (at least) 1,616 separate classes in the generated proxy code.
I have built a tool that consumes a CRM 4.0 web service wsdl, and produces a nice packaged .dll (complete with embedded XmlSerializers) with practically all the unnecessary fluff removed. The produced dll fully supports Fetch and the DynamicEntity – just no static types.
On a .net IIS server, creating a new CrmService now takes 0.12 seconds – instead of 6+.