Hello all-
I've written a simple C# powershell cmdlet (Get-Store) that returns an Outlook Object Model Store object. Another cmdlet I've written reads the above Store object from the pipeline and creates an email folder (Get-Folder)
I get a ParameterBindingException when piping the returned store object from Get-Store to Get-Folder.
If I create the store object manually on the PS command line, via new-object, then pipe it to Get-Folder, it works.
It appears the errant store object is a __comObject type, while the store object that works is a Outlook.StoreClass type. Does anyone know how I can make this work?
Here's a transcript of the PS session:
---------------------------------------------------------------
PS c:\ps\mapi\bin\x64\Debug> import-module .\mapi.dll
PS C:\ps\mapi\bin\x64\Debug> $app = new-object -com Outlook.Application
PS C:\ps\mapi\bin\x64\Debug> $stores = $app.Session.stores
PS C:\ps\mapi\bin\x64\Debug> $storeOK = $stores[1]
PS C:\ps\mapi\bin\x64\Debug> $storeOK.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False StoreClass System.__ComObject
PS C:\ps\mapi\bin\x64\Debug> $storeOK | Get-Folder -path inbox\works -CreateIfNotExist
Application : Microsoft.Office.Interop.Outlook.ApplicationClass
Class : 2
Session : Microsoft.Office.Interop.Outlook.NameSpaceClass
Parent : System.__ComObject
DefaultItemType : 0
DefaultMessageClass : IPM.Note
Description :
EntryID : 0000000029542A42175B114D983D2C3446907A490100B870629719727B4BA82A6C06A31C2912004C5FB6DB8F0000
Folders : System.__ComObject
Items : System.__ComObject
Name : works
StoreID : 0000000038A1BB1005E5101AA1BB08002B2A56C20000454D534D44422E444C4C00000000000000001B55FA20AA6611
CD9BC800AA002FC45A0C00000048514D41494C5356523031002F6F3D4964656E746943727970742F6F753D45786368
616E67652041646D696E6973747261746976652047726F7570202846594449424F484632335350444C54292F636E3D
526563697069656E74732F636E3D6C657300
UnReadItemCount : 0
UserPermissions : System.__ComObject
WebViewOn : False
WebViewURL :
WebViewAllowNavigation : True
AddressBookName :
ShowAsOutlookAB : False
FolderPath :\\les@voltage.com\Inbox\works
InAppFolderSyncObject : False
CurrentView : System.__ComObject
CustomViewsOnly : False
Views : System.__ComObject
MAPIOBJECT : System.__ComObject
FullFolderPath :\\les@voltage.com\Inbox\works
IsSharePointFolder : False
ShowItemCount : 1
Store : System.__ComObject
PropertyAccessor : System.__ComObject
UserDefinedProperties : System.__ComObject
PS C:\ps\mapi\bin\x64\Debug> $storeNotOK = Get-Store -StoreNameles@voltage.com
PS C:\ps\mapi\bin\x64\Debug> $storeNotOK.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False __ComObject System.MarshalByRefObject
PS C:\ps\mapi\bin\x64\Debug> $storeNotOK | Get-Folder -path inbox\DoesntWork -CreateIfNotExist
Get-Folder : The input object cannot be bound to any parameters for the command either because the command does not
take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
At line:1 char:15
+ $storeNotOK | Get-Folder -path inbox\DoesntWork -CreateIfNotExist
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (System.__ComObject:PSObject) [Get-Folder], ParameterBindingException
+ FullyQualifiedErrorId : InputObjectNotBound,mapi.Get_OutlookFolder
Here's the code:
-------------------------------------------------------
namespace mapi
{
[Cmdlet(VerbsCommon.Get,"Store")]
publicclass Get_Store : PSCmdlet
{
protectedoverridevoid ProcessRecord()
{
base.ProcessRecord();
this.WriteObject(_getStore());
this.WriteDebug("Get-App::ProcessRecord");
}
publicApplication _getApplication()
{
Application app = newApplication();
return app;
}
[Parameter(Position = 0, ValueFromPipeline =false)]
[ValidateNotNullOrEmpty]
publicstring StoreName
{
get { return _storeName; }
set { _storeName = value.ToLower(); }
}
string _storeName;
publicStore _getStore()
{
Application app = null;
try
{
if (null == _storeName)
thrownew ArgumentException("Missing argument 'StoreName'");
app = _getApplication();
foreach (Store storein app.Session.Stores)
{
if (store.DisplayName.ToLower() == _storeName)
return store;
if (null != store)
Marshal.ReleaseComObject(store);
}
returnnull;
}
finally
{
if (null != app)
Marshal.ReleaseComObject(app);
}
}
}
[Cmdlet(VerbsCommon.Get,"Folder")]
publicclass Get_OutlookFolder : PSCmdlet
{
[Parameter(Position = 0, ValueFromPipeline =true, ValueFromPipelineByPropertyName = false)]
[ValidateNotNullOrEmpty]
public Microsoft.Office.Interop.Outlook.Store Store
{
get
{
return _store;
}
set
{
_store =value;
}
}
Store _store;
[Parameter(Position = 0,ValueFromPipeline =false)]
publicstring Path
{
get { return _folderPath; }
set { _folderPath = value; }
}
string _folderPath;
[Parameter(Position = 1, ValueFromPipeline =false)]
publicSwitchParameter CreateIfNotExist
{
get { return _createIfNotExist; }
set { _createIfNotExist = value; }
}
bool _createIfNotExist=false;
protectedoverridevoid ProcessRecord()
{
this.WriteDebug("Get-Folder::ProcessRecord");
this.WriteObject(_createFolder());
}
privatevoid _createOrOpenFolder(string path,MAPIFolder parent, refMAPIFolder ret)
{
if (null == path ||"" == path)
{
ret = parent;
return;
}
string [] toks = path.Split('\\');
if (null == toks)
thrownew ArgumentException("folder path is invalid: "+ _folderPath);
string folderName = toks[0];
MAPIFolder targetFolder = SearchChildFolders(parent, folderName);
if (null != targetFolder)
{
path = path.Remove(0, folderName.Length);
path = path.TrimStart('\\');
_createOrOpenFolder(path, targetFolder,ref ret);
}
else
{
// start creating
if (_createIfNotExist)
{
foreach (string newFolderNamein toks)
{
//if (null != targetFolder)
// Marshal.ReleaseComObject(targetFolder);
targetFolder = parent.Folders.Add(newFolderName);
//Marshal.ReleaseComObject(parent);
parent = targetFolder;
}
// return the last one on the path
ret = targetFolder;
}
else
thrownew ItemNotFoundException("Folder '"+ folderName +"' not on the path '"+ _folderPath +"' and CreateIfNotExist argument not passed.");
}
}
MAPIFolder SearchChildFolders(MAPIFolder parent,string name)
{
foreach (MAPIFolder fin parent.Folders)
if (f.Name.ToLower() == name)
return f;
else
Marshal.ReleaseComObject(f);
returnnull;
}
// return the requested folder.
publicMAPIFolder _createFolder()
{
if (null == _folderPath)
thrownew ArgumentNullException("_folderPath");
if (null == _store)
thrownew ArgumentNullException("_store");
MAPIFolder ret = null;
_createOrOpenFolder(_folderPath,
_store.GetRootFolder(),
ref ret);
return ret;
}
}
}