I spent the last couple of days working on wrapping a native win32 api in managed code.  I’ve been tasked with working with the Task Scheduler portion of windows, which has a pretty good native API, but no managed API.

I thought, ‘hey no problem, a little COM interop and I’m done’.  It was, of course, more challenging than it should have been.

One of the things I have to do is modify the parameters to an existing scheduled task.  There’s an MSDN sample (in c/c++) that was dead easy to follow.  Of course, translating it to C# was more painful than I expected.  Here’s the sample, go check it out: Setting Task Parameters (Windows).

I was able to get the ITask interface in managed code, and could query the current parameters, and even set the new ones no problem.  I created an ITask interface in C#, and marked it up with the ComImport attribute. 

The problem came when I was trying to persist the changes to disk.  The native code used IUnknown::QueryInterface to get a pointer to an IPersistFile object.  Here’s that code:

  IPersistFile *pIPersistFile;
  hr = pITask->QueryInterface(IID_IPersistFile,
                              (void **)&pIPersistFile);

I tried a bunch of methods to do the same thing in managed code, and couldn’t get it to work.  I was getting object references, but they were of the wrong type.  The thing I was missing is that the QueryInterface method above is really just returning a pointer to the same object, cast as an IPersistFile, because ITask implements IPersistFile.  Put that way, it sounds easy, right?

Here’s the C# code to get the IPersistFile interface:

IPersistFile persistFile = nativeTask as IPersistFile;

Simple, right?  I have to say, I felt like an idiot for not realizing that ITask implemented IPersistFile sooner.  Polymorphism is a wonderful thing.