Src/EntityObjects.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
using System;
using System.Linq;
using System.IO;
using System.Xml;
using System.Text;
using System.Globalization;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Management.Automation;
using Microsoft.EnterpriseManagement;
using Microsoft.EnterpriseManagement.Common;
using Microsoft.EnterpriseManagement.Configuration;
using Microsoft.EnterpriseManagement.Configuration.IO;
using Microsoft.EnterpriseManagement.ConnectorFramework;
using System.Text.RegularExpressions;

namespace SMLets
{

public class ObjectCmdletHelper : SMCmdletBase
{
    // For the Object cmdlets, they all pretty much can use ObjectQueryOptions, so
        // we'll just make it part of the base class private ObjectQueryOptions _queryOption = ObjectQueryOptions.Default; [Parameter] public ObjectQueryOptions QueryOption { get { return _queryOption; } set { _queryOption = value; } } public void AssignNewValues(EnterpriseManagementObject o, Hashtable ht) { foreach(string s in ht.Keys) { bool found = false; WriteDebug("Attempting to find property " + s); foreach(ManagementPackProperty p in o.GetProperties()) { int CompareResult = String.Compare(p.Name,s,ic); WriteDebug("PROPERTY " + p.Name + " == " + s + " Result: " + CompareResult); if ( CompareResult == 0 ) { found = true; WriteDebug("Assigning " + ht[s] + " to " + p.Name ); try { AssignNewValue(p, o[p], ht[s]); } catch (Exception e ) { string errmsg = "Assigning " + ht[s] + " to " + p.Name; WriteError(new ErrorRecord(e, errmsg, ErrorCategory.InvalidOperation, ht[s])); } break; } } if ( ! found ) { WriteDebug("Could not find property " + s + " on object"); } } } // in PowerShell, string comparisons are done with case ignored public StringComparison ic = StringComparison.OrdinalIgnoreCase; // Assign a value to a managementpack property // This code is clever enough to handle nearly all of the types that // a management pack property can be // if you attempt to assign something which is an enum type // we'll go looking for the appropriate enumeration and use that
        // TODO: handle the binary property type (it should take a stream)
        public void AssignNewValue(ManagementPackProperty p, EnterpriseManagementSimpleObject so, object newValue)
        {
            string PropertyType = p.Type.ToString();
            WriteVerbose("Want to set " + p.Name + "(" + PropertyType + ") to " + newValue);
            // so, if new value is null, set and return immediately
            if (newValue == null)
            {
                try
                {
                    so.Value = null;
                }
                catch (Exception e)
                {
                    WriteError(new ErrorRecord(e, "Could not assign " + p.Name + " to null", ErrorCategory.InvalidOperation, newValue));
                }
                return;
            }
            switch (PropertyType)
            {
                case "richtext" :
                case "string" :
                    try
                    {
                        so.Value = newValue;
                    }
                    catch (InvalidSimpleObjectValueException)
                    {
                        WriteWarning("Converting new value ('" + newValue.GetType().ToString() + ":" + newValue.ToString() + "') to string");
                        so.Value = newValue.ToString();
                    }
                    break;
                case "double":
                case "int":
                case "bool":
                    so.Value = newValue;
                    break;
                case "guid":
                    // This should be done in a try/catch
                    // otherwise it will fail poorly
                    try
                    {
                        so.Value = new Guid(newValue.ToString());
                    }
                    catch ( Exception e )
                    {
                        WriteError(new ErrorRecord(e, "Could not assign guid", ErrorCategory.InvalidOperation, newValue));
                    }
                    break;
                case "enum":
                    WriteDebug("Looking for Enumeration: " + newValue);
                    ManagementPackEnumeration mpe;
                    // We might have gotten an enum, try the assignment
                    if ( newValue is ManagementPackEnumeration )
                    {
                        WriteVerbose("Actually an enumeration");
                        try
                        {
                            mpe = (ManagementPackEnumeration)newValue;
                            so.Value = mpe;
                        }
                        catch ( Exception e )
                        {
                            WriteError(new ErrorRecord(e, "Could not assign enum", ErrorCategory.InvalidOperation, newValue));
                        }
                    }
                    else
                    {
                        WriteVerbose("Looking Enum via string " + newValue.ToString() + " in " + p.EnumType.GetElement());
                        try
                        {
                            mpe = SMHelpers.GetEnum(newValue.ToString(), p.EnumType.GetElement());
                            WriteVerbose("found enum: " + mpe.ToString());
                            so.Value = mpe;
                            WriteVerbose("set the value");
                        }
                        catch ( Exception e )
                        {
                            WriteError(new ErrorRecord(e, "Could not assign enum ", ErrorCategory.ObjectNotFound, newValue));
                        }
                    }
                    break;
                case "datetime":
                    // TODO: handle failure gracefully
                    try
                    {
                        so.Value = DateTime.Parse(newValue.ToString(), CultureInfo.CurrentCulture).ToString();
                    }
                    catch ( Exception e )
                    {
                        WriteError(new ErrorRecord(e, "Could not assign date ", ErrorCategory.ObjectNotFound, newValue));
                    }
                    break;
                case "binary":
                    // TODO: HANDLE filename
                    FileStream myStream = null;
                    // Deal with the case that we got a PSObject
                    if ( newValue is PSObject )
                    {
                        myStream = ((PSObject)newValue).BaseObject as FileStream;
                    }
                    else
                    {
                        // see if we get lucky
                        myStream = newValue as FileStream;
                    }
                    if (myStream != null)
                    {
                        so.Value = myStream;
                    }
                    else 
                    {
                        WriteError(new ErrorRecord(new ArgumentException(newValue.ToString()),
                           String.Format("Property must be a file stream, received a {0}", newValue.GetType().FullName), ErrorCategory.InvalidArgument, newValue));
                    }
                    break;
                default:
                    WriteVerbose("Could not find type setter for " + PropertyType);
                    WriteError(new ErrorRecord(new ItemNotFoundException("PropertySetterNotFound"), "No such property setter", ErrorCategory.ObjectNotFound, PropertyType));
                    break;
            }
            
        }

        // All this does is convert the PowerShell filter language to the criteria syntax
        public string ConvertFilterToGenericCriteria(string filter)
        {
            Dictionary<string,string> OpToOp = new Dictionary<string,string>();
            Regex re;
            // "-gt","-ge","-lt","-le","-eq","-ne","-like","-notlike","-match","-notmatch"
            // Add -isnull and -isnotnull, even though they aren't PowerShell operators OpToOp.Add("-and", "and"); OpToOp.Add("-or", "or"); OpToOp.Add("-eq","="); OpToOp.Add("-ne","!="); OpToOp.Add("-lt","<"); OpToOp.Add("-gt",">"); OpToOp.Add("-le","<="); OpToOp.Add("-ge",">="); OpToOp.Add("-like","like"); OpToOp.Add("-notlike","! like"); OpToOp.Add("-isnull", "is null"); OpToOp.Add("-isnotnull", "is not null"); re = new Regex("\\*"); filter = re.Replace(filter, "%"); re = new Regex("\\?"); filter = re.Replace(filter,"_"); re = new Regex("\""); filter = re.Replace(filter, "'"); foreach(string k in OpToOp.Keys) { re = new Regex(k, RegexOptions.CultureInvariant|RegexOptions.IgnoreCase); filter = re.Replace(filter, OpToOp[k]); } return filter; } public string FixUpPropertyNames(string filter, ManagementPackClass mpClass) { Dictionary<string,string> propertyFixes = new Dictionary<string,string>(); Regex re; foreach (ManagementPackProperty p in mpClass.GetProperties(BaseClassTraversalDepth.Recursive)) { re = new Regex(p.Name, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); filter = re.Replace(filter, p.Name); } WriteDebug("returning: " + filter);
            return filter;
        }
 
        public string ConvertFilterToCriteriaString( ManagementPackClass mpClass, string filter, bool isProjection )
        {
            WriteVerbose("
ConvertFilterToCriteriaString: " + filter);
            StringBuilder sb = new StringBuilder();
            List<PropertyOperatorValue> POVs = new List<PropertyOperatorValue>();
            foreach (string subFilter in Regex.Split(filter, "
-or", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) { WriteVerbose("SubFilter => " + subFilter);
                try
                {
                    POVs.Add(new PropertyOperatorValue(subFilter));
                }
                catch
                {
                    WriteError(new ErrorRecord(new ObjectNotFoundException("
criteria"), "Bad Filter", ErrorCategory.NotSpecified, filter)); return null; } } // Construct the Criteria XML // This should really be done with an XML DOM methods sb.Append("<Criteria xmlns='http://Microsoft.EnterpriseManagement.Core.Criteria/'>"); sb.Append("<Reference Id='"); sb.Append(mpClass.GetManagementPack().Name); sb.Append("' Version='"); sb.Append(mpClass.GetManagementPack().Version.ToString()); sb.Append("'"); if ( mpClass.GetManagementPack().KeyToken != null) { sb.Append(" PublicKeyToken='"); sb.Append(mpClass.GetManagementPack().KeyToken); sb.Append("'"); } sb.Append(" Alias='myMP' />"); // JWT START OF EXPRESSION // CHECK FOR AND/OR HERE if (POVs.Count > 1) { sb.Append("<Expression>"); sb.Append("<Or>"); } foreach (PropertyOperatorValue POV in POVs) { sb.Append("<Expression>"); sb.Append("<SimpleExpression>"); // check to be sure the property exists on the class // do this with a creatable EMO as *all* the properties are presented // If the class is abstract, you can't create it. This means you have // to use the properties on the class as you get it. List<ManagementPackProperty> proplist = new List<ManagementPackProperty>(); if (mpClass.Abstract) { foreach (ManagementPackProperty p in mpClass.PropertyCollection) { proplist.Add(p); } } else { // The proper way to get at the properties of a class foreach (ManagementPackProperty p in mpClass.GetProperties(BaseClassTraversalDepth.Recursive, PropertyExtensionMode.All)) { proplist.Add(p); } } bool foundproperty = false; foreach (ManagementPackProperty p in proplist) { if (String.Compare(POV.Property, p.Name, StringComparison.InvariantCultureIgnoreCase) == 0) { sb.Append("<ValueExpressionLeft>"); if (isProjection) { // projection not quite supported sb.Append("<Property>$Target/Property[Type='myMP!" + mpClass.Name + "']/" + p.Name + "$</Property>"); } else { sb.Append("<Property>$Target/Property[Type='myMP!" + mpClass.Name + "']/" + p.Name + "$</Property>"); } sb.Append("</ValueExpressionLeft>"); foundproperty = true; break; } } // perhaps the provided property is a generic property if (!foundproperty) { foreach (GenericProperty p in GenericProperty.GetGenericProperties()) { if (String.Compare(POV.Property, p.PropertyName, StringComparison.InvariantCultureIgnoreCase) == 0) { sb.Append("<ValueExpressionLeft>"); // sb.Append("<GenericProperty>$Target/Property[Type='myMP!" + mpClass.Name + "']/" + p.PropertyName + "$</GenericProperty>"); sb.Append("<GenericProperty>" + p.PropertyName + "</GenericProperty>"); sb.Append("</ValueExpressionLeft>"); foundproperty = true; } } } if (!foundproperty) { WriteError(new ErrorRecord(new ObjectNotFoundException("property"), "Property Not Found", ErrorCategory.NotSpecified, filter)); return null; } // Now add the operator sb.Append("<Operator>" + POV.Operator + "</Operator>"); // Finally, the value - no checking here, just add it sb.Append("<ValueExpressionRight><Value>"); // TODO: HANDLE ENUMS sb.Append(POV.Value); sb.Append("</Value></ValueExpressionRight>"); sb.Append("</SimpleExpression>"); sb.Append("</Expression>"); } if (POVs.Count > 1) { sb.Append("</Or>"); sb.Append("</Expression>"); } // JWT END OF EXPRESSION sb.Append("</Criteria>"); WriteVerbose(sb.ToString()); return sb.ToString(); } // This doesn't completely work yet // TODO: handle generic property queries // I think it will look like: // PROPERTY OPERATOR VALUE // so, you could do: // DISPLAYNAME -EQ 'Boo ya!' // and you'll get the filter back // Also need to support Enumeration values, so user can provide a string rather than a guid for an enum // value public EnterpriseManagementObjectCriteria ConvertFilterToObjectCriteria ( ManagementPackClass mpClass, string filter) { EnterpriseManagementObjectCriteria myCriteria = null; string filterString = null; // First attempt to use the simple constructor for the ObjectCriteria, just the filter and the class // First replace all the PowerShell operators // this will return a criteria if we have success try { WriteVerbose("Original Filter: " + filter);
            filterString = ConvertFilterToGenericCriteria(filter);
            filterString = FixUpPropertyNames(filterString, mpClass);
            WriteVerbose("
Fixed Filter: " + filterString);
            myCriteria = new EnterpriseManagementObjectCriteria(filterString, mpClass);
            WriteVerbose("
Using " + filterString + " as criteria"); return myCriteria; } catch // This is non-catastrophic - it's our first attempt { WriteDebug("failed: " + filter);
        }
 
        try
        {
            filterString = ConvertFilterToCriteriaString(mpClass, filter, false);
            myCriteria = new EnterpriseManagementObjectCriteria(filterString, mpClass, _mg);
        }
        catch (InvalidCriteriaException e)
        {
            ThrowTerminatingError(new ErrorRecord(e, "
Bad Filter", ErrorCategory.InvalidOperation, filterString)); } catch (Exception e) { ThrowTerminatingError(new ErrorRecord(e, "Bad Filter", ErrorCategory.InvalidOperation, filter)); } return myCriteria; } public ObjectProjectionCriteria ConvertFilterToProjectionCriteria ( ManagementPackTypeProjection projection, string filter ) { XmlDocument x = new XmlDocument(); try { // if you can create an ObjectProjectionCriteria because you got some XML, groovy x.LoadXml(filter); // if we get to here, then we know we at least have some well formed XML // now try to create an ObjectProjectionCriteria WriteVerbose(filter); ObjectProjectionCriteria opc = new ObjectProjectionCriteria(filter, projection, _mg); return opc; } // don't do anything here, just keep going as an XML exception // means that we probably got a real filter rather than some XML Criteria catch (XmlException) { ; } // OK, we got valid XML but a bad criteria, notify and bail catch (InvalidCriteriaException e) { ThrowTerminatingError( new ErrorRecord(e, "InvalidCriteria", ErrorCategory.InvalidData, filter)); } string filterString = ConvertFilterToCriteriaString ( projection.TargetType, filter, true ); ObjectProjectionCriteria myCriteria = new ObjectProjectionCriteria(filterString, projection, _mg); return myCriteria; } } public class FilterCmdletBase : ObjectCmdletHelper { protected string _filter = null; [Parameter] public string Filter { get { return _filter; } set { _filter = value; } } private Int32 _maxCount = Int32.MaxValue; [Parameter] public Int32 MaxCount { get { return _maxCount; } set { _maxCount = value; } } // By default, we'll collect the projections base on // when they were created private string _sortBy = "TimeAdded"; [Parameter] public string SortBy { get { return _sortBy; } set { _sortBy = value; } } internal const string xmlns = "xmlns=\"http://Microsoft.EnterpriseManagement.Core.Sorting\""; internal const string ascending = "Ascending"; internal const string descending = "Descending"; internal string Order = ascending; internal void addSortProperty(ObjectQueryOptions options, string sortProperty, ManagementPackClass c) { SortingOrder sOrder = SortingOrder.Ascending; if (sortProperty == null || c == null || options == null) { return; } if (sortProperty[0] == '-') { sOrder = SortingOrder.Descending; sortProperty = SortBy.Substring(1); } WriteVerbose("look for instance properties first"); foreach (ManagementPackProperty mpp in c.GetProperties(BaseClassTraversalDepth.Recursive)) { if (string.Compare(mpp.Name, sortProperty, true) == 0) { options.AddSortProperty(mpp, sOrder); return; } } WriteVerbose("now look for generic properties"); foreach (GenericProperty gp in GenericProperty.GetGenericProperties()) { if (string.Compare(gp.PropertyName, sortProperty, true) == 0) { Type t = typeof(EnterpriseManagementObjectGenericPropertyName); EnterpriseManagementObjectGenericPropertyName pn = (EnterpriseManagementObjectGenericPropertyName)Enum.Parse(t, gp.PropertyName); EnterpriseManagementObjectGenericProperty gProperty = new EnterpriseManagementObjectGenericProperty(pn); options.AddSortProperty(gProperty, sOrder); return; } } } internal string makeSortCriteriaString(string sortProperty, ManagementPackClass c) { WriteDebug("makeSortCriteriaString with MP Class"); Order = ascending; // Now that we have a projection, create the sort order if (sortProperty[0] == '-') { Order = descending; sortProperty = SortBy.Substring(1); } WriteVerbose("checking for targettype property"); foreach (ManagementPackProperty mpp in c.GetProperties(BaseClassTraversalDepth.Recursive)) { WriteVerbose("Checking TargetType properties: " + mpp.Name + " - " + sortProperty);
                if (string.Compare(mpp.Name, sortProperty, true) == 0)
                {
                    WriteVerbose("
Sort Property: " + mpp.Name);
                    return String.Format(
                        "
<Sorting {0}><SortProperty SortOrder=\"{1}\">$Target/Property[Type='{2}']/{3}$</SortProperty></Sorting>", xmlns, Order, c.Id, mpp.Name ); } } // OK, we'll check targettype properties first foreach (GenericProperty gp in GenericProperty.GetGenericProperties()) { if (string.Compare(gp.PropertyName, sortProperty, true) == 0) { WriteVerbose("Sort property: " + gp.PropertyName);
                    return String.Format(
                        "
<Sorting {0}><GenericSortProperty SortOrder=\"{1}\">{2}</GenericSortProperty></Sorting>", xmlns, Order, gp.PropertyName ); } } return null; } internal string makeSortCriteriaString(string sortProperty, ManagementPackTypeProjection p) { WriteDebug("start makeSortCriteriaString"); Order = ascending; // Now that we have a projection, create the sort order if (SortBy[0] == '-') { Order = descending; sortProperty = SortBy.Substring(1); } // OK, we'll check generic properties first WriteVerbose("makeSortCriteriaString"); foreach (GenericProperty gp in GenericProperty.GetGenericProperties()) { if (string.Compare(gp.PropertyName, sortProperty, true) == 0) { WriteVerbose("Sort property: " + gp.PropertyName);
                    return String.Format(
                        "
<Sorting {0}><GenericSortProperty SortOrder=\"{1}\">{2}</GenericSortProperty></Sorting>", xmlns, Order, gp.PropertyName ); } } WriteVerbose("checking further"); foreach (ManagementPackProperty mpp in p.TargetType.GetProperties(BaseClassTraversalDepth.Recursive)) { WriteVerbose("Checking TargetType properties: " + mpp.Name + " - " + sortProperty);
                if (string.Compare(mpp.Name, sortProperty, true) == 0)
                {
                    WriteVerbose("
Sort Property: " + mpp.Name);
                    return String.Format(
                        "
<Sorting {0}><SortProperty SortOrder=\"{1}\">$Target/Property[Type='{2}']/{3}$</SortProperty></Sorting>", xmlns, Order, p.TargetType.Id, mpp.Name ); } } return null; } } public sealed class ServiceManagerObjectHelper { // a helper class to read a stream and adapt an EMO // We handle the retrival of binary types // if it's a binary property type, we'll return an array of // bytes private static Byte[] GetBytes(Stream s) { // Why SM binary fields don't have a valid length property is a mystery if ( s == null ) { return null; } byte[] buffer = new byte[4096]; Collection<Byte[]> balist = new Collection<Byte[]>(); int count; int totalLength = 0; while ( (count = s.Read(buffer,0,4096)) != 0 ) { totalLength += count; byte[] tbyte = new byte[count]; Array.Copy(buffer, tbyte, count); balist.Add(tbyte); } byte[] ReturnBytes = new byte[totalLength]; int offset = 0; foreach(byte[]b in balist) { b.CopyTo(ReturnBytes,offset); offset += b.Length; } return ReturnBytes; } public static PSObject AdaptProjection(Cmdlet myCmdlet, EnterpriseManagementObjectProjection p, string projectionName) { myCmdlet.WriteVerbose("Adapting " + p);
        /*
         * We can't just wrap a type projection because it is Enumerable. This means that we would only see the
         * components of the projection in the output so we have to construct this artificial wrapper. It would be easier if
         * projections weren't Enumerable, which means that PowerShell wouldn't treat a projection as a collection, or if
         * PowerShell understood that certain collections shouldn't be unspooled, but that's not how PowerShell works.
         * Neither of those two options are available, so we adapt the object and present a PSObject with all the component
         * parts.
         */
        PSObject o = new PSObject();
        o.Members.Add(new PSNoteProperty("
__base", p)); o.Members.Add(new PSScriptMethod("GetAsXml", ScriptBlock.Create("[xml]($this.__base.CreateNavigator().OuterXml)")));
        o.Members.Add(new PSNoteProperty("
Object", AdaptManagementObject(myCmdlet, p.Object))); // Now promote all the properties on Object foreach (EnterpriseManagementSimpleObject so in p.Object.Values) { try { o.Members.Add(new PSNoteProperty(so.Type.Name, so.Value)); } catch { myCmdlet.WriteWarning("could not promote: " + so.Type.Name);
            }
        }
 
        o.TypeNames[0] = String.Format(CultureInfo.CurrentCulture, "
EnterpriseManagementObjectProjection#{0}", projectionName);
        o.TypeNames.Insert(1, "
EnterpriseManagementObjectProjection"); o.Members.Add(new PSNoteProperty("__ProjectionType", projectionName)); foreach (KeyValuePair<ManagementPackRelationshipEndpoint, IComposableProjection> helper in p) { // EnterpriseManagementObject myEMO = (EnterpriseManagementObject)helper.Value.Object; myCmdlet.WriteVerbose("Adapting related objects: " + helper.Key.Name);
            String myName = helper.Key.Name;
            PSObject adaptedEMO = AdaptManagementObject(myCmdlet, helper.Value.Object);
            // If the MaxCardinality is greater than one, it's definitely a collection
            // so start out that way
            if (helper.Key.MaxCardinality > 1)
            {
                // OK, this is a collection, so add the critter
                // This is so much easier in PowerShell
                if (o.Properties[myName] == null)
                {
                    o.Members.Add(new PSNoteProperty(myName, new ArrayList()));
                }
                ((ArrayList)o.Properties[myName].Value).Add(adaptedEMO);
            }
            else
            {
                try
                {
                    o.Members.Add(new PSNoteProperty(helper.Key.Name, adaptedEMO));
                }
                catch (ExtendedTypeSystemException e)
                {
                    myCmdlet.WriteVerbose("
Readapting relationship object -> collection :" + e.Message); // We should really only get this exception if we // try to add a create a new property which already exists Object currentPropertyValue = o.Properties[myName].Value; ArrayList newValue = new ArrayList(); newValue.Add(currentPropertyValue); newValue.Add(adaptedEMO); o.Properties[myName].Value = newValue; // TODO // If this already exists, it should be converted to a collection } } } return o; } // Adapt the EnterpriseManagementObject // We need to do this because the interest bits of the EMO (from our perspective) // are in the values collection, we promote them to NoteProperties so displaying // the contents work better. This should really be done with a Type adapter, but // this is ok. public static PSObject AdaptManagementObject(Cmdlet myCmdlet, EnterpriseManagementObject managementObject) { PSObject PromotedObject = new PSObject(managementObject); PromotedObject.TypeNames.Insert(1, managementObject.GetType().FullName); PromotedObject.TypeNames[0] = String.Format(CultureInfo.CurrentCulture, "EnterpriseManagementObject#{0}",managementObject.GetLeastDerivedNonAbstractClass().Name);
        // loop through the properties and promote them into the PSObject we're going to return
        foreach ( ManagementPackProperty p in managementObject.GetProperties())
        {
            try
            {
                if ( p.SystemType.ToString() == "
System.IO.Stream" ) { if ( managementObject[p].Value != null ) { PSObject StreamObject = new PSObject(managementObject[p].Value); Byte[] Data = GetBytes(managementObject[p].Value as Stream); StreamObject.Members.Add(new PSNoteProperty("Data", Data)); PromotedObject.Members.Add(new PSNoteProperty(p.Name, StreamObject)); } else { PromotedObject.Members.Add(new PSNoteProperty(p.Name, new Byte[0])); } } else { PromotedObject.Members.Add(new PSNoteProperty(p.Name, managementObject[p].Value)); } } catch ( ExtendedTypeSystemException ets) { myCmdlet.WriteWarning(String.Format("The property '{0}' already exists, skipping.\nException: {1}", p.Name,ets.Message));
            }
            catch ( Exception e )
            {
                myCmdlet.WriteError(new ErrorRecord(e, "
Property", ErrorCategory.NotSpecified, p.Name)); } } return PromotedObject; } // This overload is so we can call the adapter from the script layer // where we may not have a cmdlet reference. In the case of errors, we'll // just let it get thrown public static PSObject AdaptManagementObject(EnterpriseManagementObject managementObject) { PSObject PromotedObject = new PSObject(managementObject); PromotedObject.TypeNames.Insert(1, managementObject.GetType().FullName); PromotedObject.TypeNames[0] = String.Format(CultureInfo.CurrentCulture, "EnterpriseManagementObject#{0}",managementObject.GetLeastDerivedNonAbstractClass().Name);
        // loop through the properties and promote them into the PSObject we're going to return
        foreach ( ManagementPackProperty p in managementObject.GetProperties())
        {
            try
            {
                if ( p.SystemType.ToString() == "
System.IO.Stream" ) { if ( managementObject[p].Value != null ) { PSObject StreamObject = new PSObject(managementObject[p].Value); Byte[] Data = GetBytes(managementObject[p].Value as Stream); StreamObject.Members.Add(new PSNoteProperty("Data", Data)); PromotedObject.Members.Add(new PSNoteProperty(p.Name, StreamObject)); } else { PromotedObject.Members.Add(new PSNoteProperty(p.Name, new Byte[0])); } } else { PromotedObject.Members.Add(new PSNoteProperty(p.Name, managementObject[p].Value)); } } catch ( ExtendedTypeSystemException ets) { throw(new InvalidOperationException(String.Format("The property '{0}' already exists, skipping.\nException: {1}", p.Name,ets.Message)));
            }
            catch ( Exception e )
            {
                throw(e);
            }
        }
        return PromotedObject;
 
    }
    private ServiceManagerObjectHelper() { ; }
}
 
#region SCSMObject cmdlets
 
[Cmdlet(VerbsCommon.New, "
SCSMObject", SupportsShouldProcess = true, DefaultParameterSetName = "name")] public class NewSMObjectCommand : ObjectCmdletHelper { private ManagementPackClass _class = null; [Parameter(Position = 0, Mandatory = true, ParameterSetName = "class")] public ManagementPackClass Class { get { return _class; } set { _class = value; } } private Hashtable _property; [Parameter(Position = 1, Mandatory = true, ValueFromPipeline = true)] public Hashtable PropertyHashtable { get { return _property; } set { _property = value; } } private ManagementPackObjectTemplate _template = null; [Parameter] public ManagementPackObjectTemplate Template { get { return _template; } set { _template = value; } } private SwitchParameter _passthru; [Parameter] public SwitchParameter PassThru { get { return _passthru; } set { _passthru = value; } } // On NoCommit, don't commit, just return // the created object. This is needed for those // operations that require that an instance not // already exist private SwitchParameter _noCommit; [Parameter] public SwitchParameter NoCommit { get { return _noCommit; } set { _noCommit = value; } } private IncrementalDiscoveryData pendingChanges; private int batchSize = 200; private int toCommit = 0; private SwitchParameter _bulk; [Parameter] public SwitchParameter Bulk { get { return _bulk; } set { _bulk = value; } } protected override void BeginProcessing() { base.BeginProcessing(); if (Bulk) { pendingChanges = new IncrementalDiscoveryData(); } if (Class == null) { ThrowTerminatingError(new ErrorRecord(new ArgumentNullException("Class"), "Class Not Found", ErrorCategory.ObjectNotFound, "Class")); } } // We're going to call commit for each object passed to us // TODO: Create an array of objects and commit them in // one operation protected override void ProcessRecord() { // Create an object CreatableEnterpriseManagementObject o = new CreatableEnterpriseManagementObject(_mg, Class); // Apply the template if needed if (Template != null) { o.ApplyTemplate(Template); } // Just to make things easier to deal with, we'll create a hash table of // the properties in the object. // // TODO: ADD GENERIC PROPERTIES // Create a hashtable of the properties, ignore case so if we find one // we can grab the property and assign the new value! Hashtable ht = new Hashtable(StringComparer.OrdinalIgnoreCase); foreach (ManagementPackProperty prop in o.GetProperties()) { try { ht.Add(prop.Name, prop); } catch ( Exception e ) { WriteError(new ErrorRecord(e, "property '" + prop.Name + "' has already been added to collection", ErrorCategory.InvalidOperation, prop)); } } // now go through the hashtable that has the values we we want to use and // assigned them into the new values foreach (string s in PropertyHashtable.Keys) { if (!ht.ContainsKey(s)) { WriteError(new ErrorRecord(new ObjectNotFoundException(s), "property not found on object", ErrorCategory.NotSpecified, o)); } else { ManagementPackProperty p = ht[s] as ManagementPackProperty; AssignNewValue(p, o[p], PropertyHashtable[s]); } } // Now that we're done, we can commit it // TODO: if we get an exception indicating we're disconnected // Reconnect and try again. if (ShouldProcess(Class.Name)) { try { if (Bulk) { toCommit++; pendingChanges.Add(o); if (toCommit >= batchSize) { toCommit = 0; pendingChanges.Commit(_mg); pendingChanges = new IncrementalDiscoveryData(); } } else { if (NoCommit) { WriteObject(o); } else { o.Commit(); // on PassThru get the ID and call GetObject // we don't want to hand back the CreatableEnterpriseObject, but rather the thing // that was saved. if (_passthru) { WriteObject( ServiceManagerObjectHelper.AdaptManagementObject( this, _mg.EntityObjects.GetObject<EnterpriseManagementObject>(o.Id, ObjectQueryOptions.Default) ) ); } } } } catch (Exception e) { WriteError(new ErrorRecord(e, "Could not save new object", ErrorCategory.InvalidOperation, o)); } } } protected override void EndProcessing() { base.EndProcessing(); if (Bulk) { try { pendingChanges.Commit(_mg); } catch (Exception e) { WriteWarning("Commit failed, trying Overwrite: " + e.Message);
                try
                {
                    pendingChanges.Overwrite(_mg);
                }
                catch (Exception x)
                {
                    WriteError(new ErrorRecord(x, "
Could not save new object with commit or overwrite", ErrorCategory.InvalidOperation, pendingChanges)); } } } } } [Cmdlet(VerbsCommon.Get, "SCSMObject", DefaultParameterSetName = "Class")] public class GetSMObjectCommand : FilterCmdletBase { // Note: Four parameter sets so you can retrieve by class, guid or criteria private ManagementPackClass _class = null; [Parameter(ParameterSetName = "Class", Position = 0, Mandatory = true, ValueFromPipeline = true)] [Parameter(ParameterSetName = "Statistic", Mandatory = true, ValueFromPipeline = true)] public ManagementPackClass Class { get { return _class; } set { _class = value; } } private Guid _id = Guid.Empty; [Parameter(ParameterSetName = "Guid", Position = 0, Mandatory = true)] public Guid Id { get { return _id; } set { _id = value; } } private EnterpriseManagementObjectCriteria _criteria; [Parameter(ParameterSetName = "Criteria", Mandatory = true)] public EnterpriseManagementObjectCriteria Criteria { get { return _criteria; } set { _criteria = value; } } // If set, don't wrap the EMO private SwitchParameter _noAdapt; [Parameter] public SwitchParameter NoAdapt { get { return _noAdapt; } set { _noAdapt = value; } } // Only retrieve statistics private SwitchParameter _statistic; [Parameter(ParameterSetName = "Statistic")] public SwitchParameter Statistic { get { return _statistic; } set { _statistic = value; } } protected override void BeginProcessing() { base.BeginProcessing(); if (Statistic) { QueryOption = new ObjectQueryOptions(); QueryOption.DefaultPropertyRetrievalBehavior = ObjectPropertyRetrievalBehavior.None; QueryOption.ObjectRetrievalMode = ObjectRetrievalOptions.NonBuffered; return; } else { QueryOption = new ObjectQueryOptions(); QueryOption.DefaultPropertyRetrievalBehavior = ObjectPropertyRetrievalBehavior.All; if (MaxCount != Int32.MaxValue) { QueryOption.MaxResultCount = MaxCount; QueryOption.ObjectRetrievalMode = ObjectRetrievalOptions.NonBuffered; } } string sortProperty = SortBy; } protected override void ProcessRecord() { if (Id != Guid.Empty) { WriteObject(ServiceManagerObjectHelper.AdaptManagementObject(this, _mg.EntityObjects.GetObject<EnterpriseManagementObject>(Id, ObjectQueryOptions.Default))); return; } // If someone provides us a filter, we'll use that instead of a criteria if (Filter != null) { Criteria = ConvertFilterToObjectCriteria(Class, Filter); } if (Class == null && Criteria != null) { Class = Criteria.ManagementPackClass; } try { addSortProperty(QueryOption, SortBy, Class); } catch { ; } int count = 0; if (Criteria == null) // no criteria and no filter, get all the instances of the class { // If getting statistics, don't do anything if (Statistic) { WriteObject(new ItemStatistics(Class, Class.Name, _mg.EntityObjects.GetObjectReader<EnterpriseManagementObject>(Class, QueryOption).Count)); return; } else { foreach (EnterpriseManagementObject o in _mg.EntityObjects.GetObjectReader<EnterpriseManagementObject>(Class, QueryOption)) { count++; if (NoAdapt) { WriteObject(o); } else { WriteObject(ServiceManagerObjectHelper.AdaptManagementObject(this, o)); } if (count >= MaxCount) { break; } } } } else // OK, we got a criteria - we'll use that { if (Statistic) { WriteObject(new ItemStatistics(Class, Class.Name, _mg.EntityObjects.GetObjectReader<EnterpriseManagementObject>(Criteria, QueryOption).Count)); return; } foreach (EnterpriseManagementObject o in _mg.EntityObjects.GetObjectReader<EnterpriseManagementObject>(Criteria, QueryOption)) { count++; if (NoAdapt) { WriteObject(o); } else { WriteObject(ServiceManagerObjectHelper.AdaptManagementObject(this, o)); } if (count >= MaxCount) { break; } } } } } public enum Change { Property, Relationship, Instance }; public enum ChangeType { Modify, Insert, Delete }; public class PropertyChange { public Change WhatChanged; public ChangeType TypeOfChange; public string Name; public object OldValue; public object NewValue; public PropertyChange() { ; } public PropertyChange(Change type,ChangeType operation, string name, object oldval, object newval) { WhatChanged = type; TypeOfChange = operation; Name = name; OldValue = oldval; NewValue = newval; } } public class ObjectChange { public List<PropertyChange> Changes; public DateTime LastModified; public string UserName; public string Connector; public ObjectChange() { Changes = new List<PropertyChange>(); } } public class SCSMHistory { public EnterpriseManagementObject Instance; public List<ObjectChange> History; private List<EnterpriseManagementObjectHistoryTransaction> __HistoryData; public List<EnterpriseManagementObjectHistoryTransaction> get_RawHistoryData() { return this.__HistoryData; } private SCSMHistory() { History = new List<ObjectChange>(); __HistoryData = new List<EnterpriseManagementObjectHistoryTransaction>(); } public SCSMHistory(EnterpriseManagementObject emo) { History = new List<ObjectChange>(); __HistoryData = new List<EnterpriseManagementObjectHistoryTransaction>(); Instance = emo; foreach (EnterpriseManagementObjectHistoryTransaction ht in emo.ManagementGroup.EntityObjects.GetObjectHistoryTransactions(emo)) { __HistoryData.Add(ht); ObjectChange pc = new ObjectChange(); pc.LastModified = ht.DateOccurred.ToLocalTime(); pc.UserName = ht.UserName; pc.Connector = ht.ConnectorDisplayName; bool addToHistory = false; foreach (KeyValuePair<Guid, EnterpriseManagementObjectHistory> h in ht.ObjectHistory) { foreach (EnterpriseManagementObjectClassHistory ch in h.Value.ClassHistory) { foreach (KeyValuePair<ManagementPackProperty, Pair<EnterpriseManagementSimpleObject, EnterpriseManagementSimpleObject>> hpc in ch.PropertyChanges) { addToHistory = true; pc.Changes.Add(new PropertyChange(Change.Property, ChangeType.Modify, hpc.Key.DisplayName, hpc.Value.First, hpc.Value.Second)); } } foreach (EnterpriseManagementObjectRelationshipHistory rh in h.Value.RelationshipHistory) { addToHistory = true; ManagementPackRelationship mpr = emo.ManagementGroup.EntityTypes.GetRelationshipClass(rh.ManagementPackRelationshipTypeId); pc.Changes.Add(new PropertyChange(Change.Relationship, ChangeType.Modify, mpr.DisplayName, rh.SourceObjectId, rh.TargetObjectId)); } } if (addToHistory) { History.Add(pc); } } } } [Cmdlet(VerbsCommon.Get, "SCSMObjectHistory")] public class GetSCSMObjectHistoryCommand : ObjectCmdletHelper { private EnterpriseManagementObject[] _object; [Parameter(Mandatory = true, Position = 0, ValueFromPipeline = true)] public EnterpriseManagementObject[] Object { get { return _object; } set { _object = value; } } protected override void ProcessRecord() { foreach (EnterpriseManagementObject emo in Object) { WriteObject(new SCSMHistory(emo)); } } } [Cmdlet(VerbsCommon.Set,"SCSMObject", SupportsShouldProcess=true)] public class SetSMObjectCommand : ObjectCmdletHelper { // Set properties on an EMO // this takes a hashtable where the // KEY => PropertyName // VALUE => new value for the property // The adapted EMO private PSObject _smobject; [Parameter(Position=0,Mandatory=true,ValueFromPipeline=true)] public PSObject SMObject { set { _smobject = value; } get { return _smobject; } } // the property/value pairs private Hashtable _propertyValueHashTable; [Parameter(ParameterSetName="hashtable",Position=1,Mandatory=true)] [Alias("PH")] public Hashtable PropertyHashtable { get { return _propertyValueHashTable; } set { _propertyValueHashTable = value; } } // The following two parameters are a short-cut, // if you only want to set a single property // You don't need the hashtable private string _property; [Parameter(ParameterSetName="pair",Position=1,Mandatory=true)] public string Property { set { _property = value; } get { return _property; } } private List<Guid> objectList; private SwitchParameter _passThru; [Parameter] public SwitchParameter PassThru { get { return _passThru; } set { _passThru = value; } } private string _value; [Parameter(ParameterSetName="pair",Position=2,Mandatory=true)] [AllowEmptyString] [AllowNull] public string Value { set { _value = value; } get { return _value; } } // By default, we use IncrementalDiscoveryData to reduce the round // trips to the CMDB private SwitchParameter _noBulkOperation; [Parameter] public SwitchParameter NoBulkOperation { get { return _noBulkOperation; } set { _noBulkOperation = value; } } private IncrementalDiscoveryData pendingChanges; private Hashtable ht; protected override void BeginProcessing() { base.BeginProcessing(); objectList = new List<Guid>(); if ( ParameterSetName == "pair" ) { ht = new Hashtable(); ht.Add(Property,Value); } else { ht = new Hashtable(PropertyHashtable); } // if we're doing bulk operations, we'll need this if ( ! NoBulkOperation ) { pendingChanges = new IncrementalDiscoveryData(); } } protected override void ProcessRecord() { // EnterpriseManagementObject o = (EnterpriseManagementObject)SMObject.Members["__base"].Value; // Coerce the EnterpriseManagementObject o = (EnterpriseManagementObject)SMObject.BaseObject; AssignNewValues ( o, ht ); // If we're not doing bulk operations, we'll need to call this for each object if ( NoBulkOperation ) { if ( ShouldProcess("Commit Change for " + o.Id))
            {
                o.Overwrite();
                if ( PassThru )
                {
                    WriteObject(ServiceManagerObjectHelper.AdaptManagementObject(this, _mg.EntityObjects.GetObject<EnterpriseManagementObject>(o.Id, ObjectQueryOptions.Default)));
                }
 
            }
        }
        else
        {
            // One could argue that ShouldProcess is called here,
            // but to reduce verbosity, I do it below
            WriteVerbose("
Adding " + o.Id + " to change list"); objectList.Add(o.Id); pendingChanges.Add(o); } } protected override void EndProcessing() { // If we're doing bulk operations if ( ! NoBulkOperation ) { if(ShouldProcess("SMObjects")) { pendingChanges.Overwrite(_mg); if(PassThru) { foreach(EnterpriseManagementObject emo in _mg.EntityObjects.GetObjectReader<EnterpriseManagementObject>(objectList, ObjectQueryOptions.Default)) { WriteObject(ServiceManagerObjectHelper.AdaptManagementObject(this, emo)); } } } } } } [Cmdlet(VerbsCommon.Remove, "SCSMObject", SupportsShouldProcess = true)] public class RemoveSMObjectCommand : ObjectCmdletHelper { // The adapted EMO private PSObject _smobject; [Parameter(Position = 0, Mandatory = true, ValueFromPipeline = true)] public PSObject SMObject { set { _smobject = value; } get { return _smobject; } } private SwitchParameter _force; [Parameter] public SwitchParameter Force { set { _force = value; } get { return _force; } } private SwitchParameter _progress; [Parameter] public SwitchParameter Progress { get { return _progress; } set { _progress = value; } } private ManagementPackEnumeration pendingDelete = null; // Remove is done via IncrementalDiscoveryData private IncrementalDiscoveryData idd; protected override void BeginProcessing() { base.BeginProcessing(); pendingDelete = _mg.ManagementPacks.GetManagementPack(SystemManagementPack.System).GetEnumeration("System.ConfigItem.ObjectStatusEnum.PendingDelete"); idd = new IncrementalDiscoveryData(); } protected override void ProcessRecord() { EnterpriseManagementObject orig = (EnterpriseManagementObject)SMObject.BaseObject; if (ShouldProcess(orig.Name)) { try { if (Progress) { WriteProgress(new ProgressRecord(0, "Remove Instance", orig.Name)); } if (Force) { idd.Remove(orig); } else { try { orig[null, "ObjectStatus"].Value = pendingDelete; idd.Add(orig); } catch (NullReferenceException e) { ErrorRecord er = new ErrorRecord(e, "ObjectStatus Property", ErrorCategory.ObjectNotFound, orig); ErrorDetails ed = new ErrorDetails("This object cannot be marked for deletion because it is not derived from System.ConfigItem"); ed.RecommendedAction = "Use the -Force parameter to remove this object"; er.ErrorDetails = ed; WriteError(er); } } } catch (Exception e) { WriteError(new ErrorRecord(e, "Object", ErrorCategory.NotSpecified, orig.Name)); } } } // after you've added all the instances to the incrementaldiscoverydata // commit the changes protected override void EndProcessing() { if (ShouldProcess("Commit")) { try { if (Progress) { WriteProgress(new ProgressRecord(0, "Remove Instance", "Committing Removal")); } idd.Commit(_mg); } catch (Exception e) { WriteError(new ErrorRecord(e, "Object", ErrorCategory.NotSpecified, "Commit")); } } } } #endregion #region SCSMRelationshipObject cmdlets [Cmdlet(VerbsCommon.Remove,"SCSMRelationshipObject", SupportsShouldProcess=true)] public class RemoveSMRelationshipObjectCommand : ObjectCmdletHelper { // The adapted EMO private PSObject _smobject; [Parameter(Position=0,Mandatory=true,ValueFromPipeline=true)] public PSObject SMObject { set { _smobject = value; } get { return _smobject; } } // Remove is done via IncrementalDiscoveryData private IncrementalDiscoveryData idd; protected override void BeginProcessing() { base.BeginProcessing(); // pendingDelete = _mg.ManagementPacks.GetManagementPack(SystemManagementPack.System).GetEnumeration("System.ConfigItem.ObjectStatusEnum.PendingDelete"); idd = new IncrementalDiscoveryData(); } protected override void ProcessRecord() { EnterpriseManagementRelationshipObject<EnterpriseManagementObject> orig = (EnterpriseManagementRelationshipObject<EnterpriseManagementObject>)SMObject.BaseObject; if ( ShouldProcess(orig.Id.ToString())) { try { idd.Remove(orig); } catch ( Exception e ) { WriteError(new ErrorRecord(e, "Object", ErrorCategory.NotSpecified, orig.Id)); } } } // after you've added all the instances to the incrementaldiscoverydata // commit the changes protected override void EndProcessing() { if ( ShouldProcess("Commit")) { try { idd.Commit(_mg); } catch ( Exception e ) { WriteError(new ErrorRecord(e, "Object", ErrorCategory.NotSpecified, "Commit")); } } } } [Cmdlet(VerbsCommon.New, "SCSMRelationshipObject", SupportsShouldProcess = true)] public class NewSCSMRelationshipObject : ObjectCmdletHelper { private ManagementPackRelationship _relationship; [Parameter(Position = 0, Mandatory = true, ValueFromPipelineByPropertyName = true)] public ManagementPackRelationship Relationship { get { return _relationship; } set { _relationship = value; } } private Hashtable _properties; [Parameter(Position = 3, ValueFromPipelineByPropertyName = true)] public Hashtable Properties { get { return _properties; } set { _properties = value; } } private SwitchParameter _passThru; [Parameter] public SwitchParameter PassThru { get { return _passThru; } set { _passThru = value; } } private EnterpriseManagementObject _source; [Parameter(Position = 1, Mandatory = true, ValueFromPipelineByPropertyName = true)] public EnterpriseManagementObject Source { get { return _source; } set { _source = value; } } private EnterpriseManagementObject _target; [Parameter(Position = 2, Mandatory = true, ValueFromPipelineByPropertyName = true)] public EnterpriseManagementObject Target { get { return _target; } set { _target = value; } } private SwitchParameter _bulk; [Parameter(ParameterSetName = "bulk")] public SwitchParameter Bulk { get { return _bulk; } set { _bulk = value; } } private IncrementalDiscoveryData idd = null; private SwitchParameter _noCommit; [Parameter(ParameterSetName = "NoCommit")] public SwitchParameter NoCommit { get { return _noCommit; } set { _noCommit = value; } } private SwitchParameter _progress; [Parameter(ParameterSetName = "bulk")] public SwitchParameter Progress { get { return _progress; } set { _progress = value; } } protected override void BeginProcessing() { base.BeginProcessing(); if (Bulk) { idd = new IncrementalDiscoveryData(); } } private int count = 0; protected override void ProcessRecord() { CreatableEnterpriseManagementRelationshipObject ro = new Microsoft.EnterpriseManagement.Common.CreatableEnterpriseManagementRelationshipObject(_mg, Relationship); try { ro.SetSource(Source); } catch (Exception e) { ThrowTerminatingError(new ErrorRecord(e, "SourceError", ErrorCategory.InvalidOperation, ro)); } try { ro.SetTarget(Target); } catch (Exception e) { ThrowTerminatingError(new ErrorRecord(e, "TargetError", ErrorCategory.InvalidOperation, ro)); } IList<ManagementPackProperty> props = ro.GetProperties(); if (Properties != null) { foreach (string s in Properties.Keys) { try { WriteVerbose("looking for property " + s);
                    foreach (ManagementPackProperty p in props)
                    {
                        if (String.Compare(p.Name, s, true) == 0)
                        {
                            WriteVerbose("
Setting " + s + " to " + Properties[s]);
                            AssignNewValue(p, ro[p], Properties[s]);
                            // ro[p].Value = Properties[s];
                            break;
                        }
                    }
                }
                catch
                {
                    WriteError(new ErrorRecord(new ItemNotFoundException(s), "
Value " + s + " is null", ErrorCategory.ObjectNotFound, Properties)); } } } if (ShouldProcess("Commit changes")) { try { if (Bulk) { WriteVerbose("Adding " + ro.RelationshipId.ToString() + " to IDD"); if (Progress) { count++; WriteProgress(new ProgressRecord(1, "Adding to incremental discovery data", ro.TargetObject.DisplayName)); } idd.Add(ro); } else if (NoCommit) { WriteObject(ro); } else { ro.Commit(); } } catch (Exception e) { WriteError(new ErrorRecord(e, "Relationshipship Error", ErrorCategory.InvalidOperation, ro)); } } if (PassThru && !NoCommit) { WriteObject(ro); } // WriteObject(ro); } protected override void EndProcessing() { base.EndProcessing(); if (Bulk) { if (ShouldProcess("Commit Relationship Object")) { if (Progress) { WriteProgress(new ProgressRecord(1, "Committing Relationships", count + " instances")); } idd.Commit(_mg); } } } } #endregion #region SCSMObjectProjection cmdlets [Cmdlet(VerbsCommon.New, "SCSMObjectProjection", SupportsShouldProcess = true)] public class NewSCSMObjectProjectionCommand : ObjectCmdletHelper { private string _type = null; [Parameter(Mandatory = true, Position = 0)] public String Type { get { return _type; } set { _type = value; } } /* ** A projection is represented as a complicated hashtable which has the following layout ** @{ ** __CLASS = <classname of seed object> ** __OBJECT = @{ ** <property value pairs of seed object> ** } ** # ALIASNAME is the RELATIONSHIP alias as known by the projection ** ALIASNAME = @{ ** __CLASS = <classname of the object in the relationship> ** # this could be an array, but unlike the case of the seed object, ** # this object may already exist, so we have to support a combination ** # of EMOs or HashTables (for example, in an incident we may want to associate ** # a number of comment logs with the incident, but there's no reason that we shouldn't ** # create the comments in real time ** __OBJECT = EMO1,EMO2,@{ ** __CLASS = <classname of target> ** __OBJECT = @{ ** <property value pairs of target object ** } ** },EMO3,etc ** } ** } */ private Hashtable _projection = null; [Parameter(Mandatory = true, Position = 1, ValueFromPipeline = true)] public Hashtable Projection { get { return _projection; } set { _projection = value; } } private ManagementPackObjectTemplate _template; [Parameter] public ManagementPackObjectTemplate Template { get { return _template; } set { _template = value; } } private SwitchParameter _passThru; [Parameter] public SwitchParameter PassThru { get { return _passThru; } set { _passThru = value; } } private SwitchParameter _bulk; [Parameter] public SwitchParameter Bulk { get { return _bulk; } set { _bulk = value; } } private SwitchParameter _noCommit; [Parameter] public SwitchParameter NoCommit { get { return _noCommit; } set { _noCommit = value; } } private ManagementPackTypeProjection emop = null; private List<string> aliasCollection = null; private Hashtable aliasHT; private int count = 0; private int batchSize = 200; private IncrementalDiscoveryData pendingChanges; protected override void BeginProcessing() { base.BeginProcessing(); if (Bulk && !NoCommit) { pendingChanges = new IncrementalDiscoveryData(); } if (NoCommit) { Bulk = false; } // Find the projection we need Regex r = new Regex(Type, RegexOptions.IgnoreCase); foreach (ManagementPackTypeProjection p in _mg.EntityTypes.GetTypeProjections()) { if (r.Match(p.Name).Success) { emop = p; } } if (emop == null) { ThrowTerminatingError(new ErrorRecord(new ItemNotFoundException("Projection"), "No such projection", ErrorCategory.ObjectNotFound, Type)); } aliasHT = new Hashtable(); aliasCollection = new List<string>(); foreach (ManagementPackTypeProjectionComponent pc in emop.ComponentCollection) { aliasCollection.Add(pc.Alias); // Is there a way to handle SeedRole='Target' here? aliasHT.Add(pc.Alias, pc.TargetEndpoint); // WriteVerbose("Adding Alias: " + pc.Alias);
        }
        // WriteObject(aliasHT);
    }
 
    // emop guaranteed to be a valid projection type
    private EnterpriseManagementObjectProjection p = null;
    protected override void ProcessRecord()
    {
        if (Projection.ContainsKey("
__SEED")) { // WriteVerbose("SEED"); if (Projection["__SEED"] is PSObject) { WriteVerbose("Seed is PSObject"); PSObject o = (PSObject)Projection["__SEED"]; WriteVerbose("Type of seed: " + o.GetType());
                if (o.ImmediateBaseObject is EnterpriseManagementObject)
                {
                    WriteVerbose("
Attempting to cast"); EnterpriseManagementObject seed = (EnterpriseManagementObject)o.ImmediateBaseObject; WriteVerbose("Attempting to create projection"); WriteVerbose("Seed is a " + seed.GetType());
                    p = new EnterpriseManagementObjectProjection(seed);
                    WriteVerbose("
Created Projection"); } else { ThrowTerminatingError(new ErrorRecord(new NullReferenceException("Projection"), "Bad Projection", ErrorCategory.InvalidArgument, o)); } } else if (Projection["__SEED"] is EnterpriseManagementObject) { WriteVerbose("Seed is EMO"); EnterpriseManagementObject seed = (EnterpriseManagementObject)Projection["__SEED"]; p = new EnterpriseManagementObjectProjection(seed); } else { ThrowTerminatingError(new ErrorRecord(new NullReferenceException("Projection"), "Bad Projection", ErrorCategory.InvalidArgument, Projection["__SEED"])); } } else { // Construct the projection seed if (!Projection.ContainsKey("__CLASS")) { ThrowTerminatingError(new ErrorRecord(new ArgumentException("__CLASS"), "Hashtable Failure", ErrorCategory.InvalidArgument, Projection)); } // WriteVerbose("Seed Class is " + (string)Projection["__CLASS"]); ManagementPackClass c = getClassFromName((string)Projection["__CLASS"]); if (c == null) { ThrowTerminatingError(new ErrorRecord(new ItemNotFoundException("CLASS"), "No such class", ErrorCategory.ObjectNotFound, Projection["__CLASS"])); } if (!Projection.ContainsKey("__OBJECT")) { // WriteObject(Projection); // ThrowTerminatingError( new ErrorRecord(new ArgumentException("__OBJECT"), "Hashtable Failure", ErrorCategory.InvalidArgument, Projection)); WriteError(new ErrorRecord(new ArgumentException("__OBJECT"), "Hashtable Failure", ErrorCategory.InvalidArgument, Projection)); } // CreatableEnterpriseManagementObject cemo = new CreatableEnterpriseManagementObject(c.ManagementGroup,c); Hashtable seedHash = (Hashtable)Projection["__OBJECT"]; // WriteVerbose("__OBJECT is " + seedHash);
            p = new EnterpriseManagementObjectProjection(_mg, c);
            AssignNewValues(p.Object, seedHash);
        }
        WriteVerbose("
Null Projection? " + (p == null).ToString());
        // OK - the seed is now complete - so work on the rest of the projection.
        // go through the projection again - since hash tables are
        // TODO:: HANDLE CASE INSENSITIVE COMPARISON
        foreach (string k in Projection.Keys)
        {
            // skip the __CLASS (we did it above)
            if (
                String.Compare(k, "
__CLASS", true) == 0 || String.Compare(k, "__OBJECT", true) == 0 || String.Compare(k, "__SEED", true) == 0) { continue; } WriteVerbose("Hunting for key: " + k);
            if (aliasCollection.Contains(k))
            {
                // WriteVerbose("
>>>> setting up alias " + k);
                // TODO: Check the endpoint take the source or target endpoint where needed.
                ManagementPackRelationshipEndpoint endpoint = (ManagementPackRelationshipEndpoint)aliasHT[k];
                // ok - we've got something that is pointed to by an alias
                if (Projection[k] is Array)
                {
                    // WriteVerbose("
**** inspecting array ****"); foreach (Object o in (Array)Projection[k]) { if (o is PSObject) { PSObject hashValue = (PSObject)o; // WriteVerbose("  PSObject is of type: " + ((PSObject)o).ImmediateBaseObject.GetType());
                            if (hashValue.ImmediateBaseObject is EnterpriseManagementObject)
                            {
                                try
                                {
                                    // WriteVerbose("
   Adding EMO to projection"); EnterpriseManagementObject target = (EnterpriseManagementObject)hashValue.ImmediateBaseObject; p.Add(target, endpoint); } catch (Exception e) { WriteError(new ErrorRecord(e, "Could not add EMO to projection", ErrorCategory.InvalidOperation, Projection[k])); } } else if (hashValue.ImmediateBaseObject is EnterpriseManagementObjectProjection) { try { // WriteVerbose("   Adding EMOP to projection"); EnterpriseManagementObjectProjection target = (EnterpriseManagementObjectProjection)hashValue.ImmediateBaseObject; p.Add(target, endpoint); } catch (Exception e) { WriteError(new ErrorRecord(e, "Could not add EMOP to projection", ErrorCategory.InvalidOperation, Projection[k])); } } } else if (o is Hashtable) { // WriteVerbose("  Subelement is hash, creating CEMO"); Hashtable v = (Hashtable)o; // WriteObject(v); CreatableEnterpriseManagementObject cEMO = MakecEMOFromHash(v); // WriteVerbose("    Adding cEMO to projection for " + k);
                            p.Add(cEMO, endpoint);
                        }
                        else
                        {
                            // WriteVerbose("
   Object is of type: " + o.GetType() + " IGNORING THIS OBJECT"); } } // WriteVerbose("**** Done inspecting array ****"); } else if (Projection[k] is EnterpriseManagementObject) { // WriteVerbose("Object is an EMO: " + Projection[k]);
 
                    try
                    {
                        // WriteVerbose("
Adding to projection"); p.Add((EnterpriseManagementObject)Projection[k], (ManagementPackRelationshipEndpoint)aliasHT[k]); } catch (Exception e) { WriteError(new ErrorRecord(e, "foo", ErrorCategory.InvalidOperation, Projection[k])); } } else if (Projection[k] is PSObject) { PSObject pso = (PSObject)Projection[k]; // WriteVerbose("PSObject ImmediateBase: " + pso.ImmediateBaseObject.GetType());
                    if (pso.ImmediateBaseObject is EnterpriseManagementObject)
                    {
                        EnterpriseManagementObject target = (EnterpriseManagementObject)pso.ImmediateBaseObject;
                        try
                        {
                            // WriteVerbose("
Adding " + target + " to projection as " + target);
                            p.Add(target, endpoint);
                        }
                        catch (Exception e)
                        {
                            WriteError(new ErrorRecord(e, "
foo", ErrorCategory.InvalidOperation, Projection[k])); } } } else if (Projection[k] is EnterpriseManagementObjectProjection) { // WriteVerbose("Object is an EMOP: " + Projection[k]);
                    try
                    {
                        EnterpriseManagementObjectProjection target = (EnterpriseManagementObjectProjection)Projection[k];
                        p.Add(target, endpoint);
                    }
                    catch (Exception e)
                    {
                        WriteError(new ErrorRecord(e, "
foo", ErrorCategory.InvalidOperation, Projection[k])); } } else if (Projection[k] is Hashtable) { // WriteVerbose("got a hashtable - will need to build EMO"); try { Hashtable relHash = (Hashtable)Projection[k]; CreatableEnterpriseManagementObject cEMO = MakecEMOFromHash(relHash); p.Add(cEMO, endpoint); } catch (Exception e) { WriteError(new ErrorRecord(e, "foo", ErrorCategory.InvalidOperation, Projection[k])); } // new CreatableEnterpriseManagementObject(_mg,mpc); } else if (Projection[k] == null) { WriteWarning("!!!! " + k + " value is null, ignoring"); } else { WriteVerbose("Got something strange : " + Projection[k].GetType());
                }
                // WriteObject(emop[k]);
                // WriteObject(cEMO);
                // emop[k];
                // now attach the object to the projection
                // p.Add(cEMO, k);
                // foreach(ManagementPackRelationship o in _mg.EntityTypes.GetRelationshipClasses())
                // {
                // ok, we've got a match, so let's add the build and add the object
                // if ( String.Compare(o.Alias, k, true)) { p.Add(cEMO, o.Target); }
                // }
            }
            else
            {
                WriteError(new ErrorRecord(new ObjectNotFoundException(k), "
Alias not found on projection", ErrorCategory.NotSpecified, k)); } } if (Template != null) { p.ApplyTemplate(Template); } // WriteObject(p); // WriteObject(emop); // WriteVerbose("So far so good!"); // WriteObject(p); // NoCommit is used in those cases where you need a projection // as an element of another projection if (ShouldProcess("projection batch")) { if (NoCommit) { WriteObject(p); } else if (Bulk) { WriteVerbose("!!!! Adding projection to IDD"); pendingChanges.Add(p); count++; if (count >= batchSize) { WriteVerbose("!!!! committing " + count + " projections"); pendingChanges.Commit(_mg); pendingChanges = new IncrementalDiscoveryData(); count = 0; } } else { try { p.Commit(); } catch (Exception e) { WriteError(new ErrorRecord(e, "projection commit failure", ErrorCategory.InvalidOperation, p)); } } } if (PassThru) { WriteObject(p); } } protected override void EndProcessing() { base.EndProcessing(); if (ShouldProcess("!!!! Commit last batch of " + count + " projections")) { if (Bulk && count > 0) { WriteVerbose("!!!! Committing last batch of " + count + " incidents"); pendingChanges.Commit(_mg); } } } private CreatableEnterpriseManagementObject MakecEMOFromHash(Hashtable ht) { ManagementPackClass mpc = getClassFromName((string)ht["__CLASS"]); WriteDebug("type of __OBJECT: " + ht["__OBJECT"].GetType().FullName); Hashtable relValues = (Hashtable)ht["__OBJECT"]; CreatableEnterpriseManagementObject cEMO = new CreatableEnterpriseManagementObject(_mg, mpc); WriteDebug("Created new cEMO based on " + mpc.Name);
        AssignNewValues(cEMO, relValues);
        return cEMO;
    }
    private ManagementPackClass getClassFromName(string name)
    {
        foreach (ManagementPackClass c in _mg.EntityTypes.GetClasses())
        {
            if (String.Compare(name, c.Name, true) == 0) { return c; }
        }
        return null;
    }
}
     
[Cmdlet(VerbsCommon.Get, "
SCSMObjectProjection", DefaultParameterSetName = "Wrapped")] public class GetSMObjectProjectionCommand : FilterCmdletBase { private PSObject _projectionObject; [Parameter(Position = 0, Mandatory = true, ValueFromPipeline = true, ParameterSetName = "Wrapped")] [Parameter(ParameterSetName = "Statistics", ValueFromPipeline = true, Mandatory = true)] public PSObject ProjectionObject { get { return _projectionObject; } set { _projectionObject = value; } } private ManagementPackTypeProjection _projection; [Parameter(Position = 0, Mandatory = true, ParameterSetName = "Raw", ValueFromPipeline = true)] public ManagementPackTypeProjection Projection { get { return _projection; } set { _projection = value; } } private string _projectionName = null; [Parameter(Position = 0, Mandatory = true, ParameterSetName = "Name")] public string ProjectionName { get { return _projectionName; } set { _projectionName = value; } } private ObjectProjectionCriteria _criteria = null; [Parameter(ParameterSetName = "Criteria", Mandatory = true)] public ObjectProjectionCriteria Criteria { get { return _criteria; } set { _criteria = value; } } private SwitchParameter _noSort; [Parameter] public SwitchParameter NoSort { get { return _noSort; } set { _noSort = value; } } private SwitchParameter _statistic; [Parameter(ParameterSetName = "Statistics", Mandatory = true)] public SwitchParameter Statistic { get { return _statistic; } set { _statistic = value; } } // This is used for instream projection // creation. needed for those projections whose // alias targets are themselves a projection // (such as ResolutionAndBillableLog // alias BillableLogs while requires a billabletime // and workeduponbyuser private SwitchParameter _noCommit; [Parameter] public SwitchParameter NoCommit { get { return _noCommit; } set { _noCommit = value; } } protected override void BeginProcessing() { base.BeginProcessing(); if (Statistic) { WriteDebug("Getting Statistics"); QueryOption = new ObjectQueryOptions(); QueryOption.DefaultPropertyRetrievalBehavior = ObjectPropertyRetrievalBehavior.None; QueryOption.ObjectRetrievalMode = ObjectRetrievalOptions.Buffered; return; } string sortProperty = SortBy; QueryOption = new ObjectQueryOptions(); QueryOption.DefaultPropertyRetrievalBehavior = ObjectPropertyRetrievalBehavior.All; QueryOption.ObjectRetrievalMode = ObjectRetrievalOptions.NonBuffered; if (MaxCount != Int32.MaxValue) { QueryOption.MaxResultCount = MaxCount; QueryOption.ObjectRetrievalMode = ObjectRetrievalOptions.NonBuffered; } if (ProjectionName != null) { foreach (ManagementPackTypeProjection p in _mg.EntityTypes.GetTypeProjections()) { if (String.Compare(p.Name, ProjectionName, StringComparison.CurrentCultureIgnoreCase) == 0) { Projection = p; break; } } if (Projection == null) { ThrowTerminatingError(new ErrorRecord(new ArgumentNullException("No Projection found"), "Need Projection", ErrorCategory.InvalidOperation, "projection")); } } // Only build the sortCriteria if the Projection is not null // Current architecture means that we can't sort if we pipe a TypeProjection // TODO: AddSortProperty to QueryOptions for each projection seen on the pipeline if (Projection != null && !NoSort) { WriteVerbose("Sort property is: " + sortProperty);
            // sort the results
            // string sortCriteria = String.Format("
<Sorting {0}><GenericSortProperty SortOrder=\"{1}\">{2}</GenericSortProperty></Sorting>", xmlns, Order, pName); string sortCriteria = null; try { sortCriteria = makeSortCriteriaString(sortProperty, Projection.TargetType); WriteDebug("sorting criteria : " + sortCriteria);
                QueryOption.AddSortProperty(sortCriteria, Projection, _mg);
            }
            catch (Exception e) // It's not a failure
            {
                WriteError(new ErrorRecord(e, "
Sort Failure", ErrorCategory.InvalidArgument, sortCriteria)); } } else { WriteDebug("Not Sorting"); } } private int count = 0; protected override void ProcessRecord() { ObjectProjectionCriteria myCriteria = null; // If we got a wrapped object, unwrap it if (ProjectionObject != null) { WriteDebug("unwrapping PSObject to get projection"); Projection = (ManagementPackTypeProjection)ProjectionObject.Properties["__base"].Value; } if (Statistic) { // Should this just be a call to get the seed? WriteVerbose("Getting Statistics"); WriteDebug("Before Criteria: " + DateTime.Now.ToString());
            ObjectProjectionCriteria StatisticCriteria = new ObjectProjectionCriteria(Projection);
            WriteDebug("
Before Reader: " + DateTime.Now.ToString());
            IObjectProjectionReader<EnterpriseManagementObject> reader = _mg.EntityObjects.GetObjectProjectionReader<EnterpriseManagementObject>(StatisticCriteria, QueryOption);
            WriteDebug("
After Reader: " + DateTime.Now.ToString());
            WriteObject(new ItemStatistics(Projection, Projection.Name, reader.Count));
            WriteDebug("
After Reader.Count: " + DateTime.Now.ToString());
            return;
        }
 
        // Create the criteria
        // first, by checking whether there's a filter (and no criteria)
        // This has to be created for each object in the pipeline because we may have gotten a
        // heterogenous collection of projections
        if (Criteria != null)
        {
            myCriteria = Criteria;
        }
        if (Filter != null && Criteria == null)
        {
            WriteDebug("
converting filter to criteria"); myCriteria = ConvertFilterToProjectionCriteria(Projection, Filter); } // ok - neither criteria, nor filter was provided, build a criteria from the projection if (myCriteria == null) { WriteDebug("null criteria"); myCriteria = new ObjectProjectionCriteria(Projection); } QueryOption.ObjectRetrievalMode = ObjectRetrievalOptions.Buffered; // QueryOption.DefaultPropertyRetrievalBehavior = ObjectPropertyRetrievalBehavior.None; WriteDebug("Retrieval Mode: " + QueryOption.ObjectRetrievalMode.ToString());
        WriteDebug("
Before projectionReader: " + DateTime.Now.ToString());
 
        IObjectProjectionReader<EnterpriseManagementObject> projectionReader =
            _mg.EntityObjects.GetObjectProjectionReader<EnterpriseManagementObject>(myCriteria, QueryOption);
        WriteDebug("
After projectionReader: " + DateTime.Now.ToString() + " Count is :" + projectionReader.Count); // Set the page size to a small number to decrease initial time to results projectionReader.PageSize = 1; WriteDebug("MaxCount = " + projectionReader.MaxCount);
        WriteDebug("
Enter foreach: " + DateTime.Now.ToString());
        // while(projectionReader.
        // EnterpriseManagementObjectProjection p = projectionReader.First<EnterpriseManagementObjectProjection>();
        // for(int i=0;i < 1; i++)
        foreach (EnterpriseManagementObjectProjection p in projectionReader)
        {
            count++;
            WriteDebug("
Current count: " + count + " at " + DateTime.Now.ToString());
            if (count > MaxCount) { break; }
            WriteVerbose("
Adapting " + p);
            /*
             * We can't just wrap a type projection because it is Enumerable. This means that we would only see the
             * components of the projection in the output so we have to construct this artificial wrapper. It would be easier if
             * projections weren't Enumerable, which means that PowerShell wouldn't treat a projection as a collection, or if
             * PowerShell understood that certain collections shouldn't be unspooled, but that's not how PowerShell works.
             * Neither of those two options are available, so we adapt the object and present a PSObject with all the component
             * parts.
             */
            PSObject o = new PSObject();
            o.Members.Add(new PSNoteProperty("
__base", p)); o.Members.Add(new PSScriptMethod("GetAsXml", ScriptBlock.Create("[xml]($this.__base.CreateNavigator().OuterXml)")));
            o.Members.Add(new PSNoteProperty("
Object", ServiceManagerObjectHelper.AdaptManagementObject(this, p.Object))); // Now promote all the properties on Object foreach (EnterpriseManagementSimpleObject so in p.Object.Values) { try { o.Members.Add(new PSNoteProperty(so.Type.Name, so.Value)); } catch { WriteWarning("could not promote: " + so.Type.Name);
                }
            }
 
            o.TypeNames[0] = String.Format(CultureInfo.CurrentCulture, "
EnterpriseManagementObjectProjection#{0}", myCriteria.Projection.Name);
            o.TypeNames.Insert(1, "
EnterpriseManagementObjectProjection"); o.Members.Add(new PSNoteProperty("__ProjectionType", myCriteria.Projection.Name)); foreach (KeyValuePair<ManagementPackRelationshipEndpoint, IComposableProjection> helper in p) { // EnterpriseManagementObject myEMO = (EnterpriseManagementObject)helper.Value.Object; WriteVerbose("Adapting related objects: " + helper.Key.Name);
                String myName = helper.Key.Name;
                PSObject adaptedEMO = ServiceManagerObjectHelper.AdaptManagementObject(this, helper.Value.Object);
                // If the MaxCardinality is greater than one, it's definitely a collection
                // so start out that way
                if (helper.Key.MaxCardinality > 1)
                {
                    // OK, this is a collection, so add the critter
                    // This is so much easier in PowerShell
                    if (o.Properties[myName] == null)
                    {
                        o.Members.Add(new PSNoteProperty(myName, new ArrayList()));
                    }
                    ((ArrayList)o.Properties[myName].Value).Add(adaptedEMO);
                }
                else
                {
                    try
                    {
                        o.Members.Add(new PSNoteProperty(helper.Key.Name, adaptedEMO));
                    }
                    catch (ExtendedTypeSystemException e)
                    {
                        WriteVerbose("
Readapting relationship object -> collection :" + e.Message); // We should really only get this exception if we // try to add a create a new property which already exists Object currentPropertyValue = o.Properties[myName].Value; ArrayList newValue = new ArrayList(); newValue.Add(currentPropertyValue); newValue.Add(adaptedEMO); o.Properties[myName].Value = newValue; // TODO // If this already exists, it should be converted to a collection } } } WriteObject(o); } } } [Cmdlet(VerbsCommon.Set, "SCSMObjectProjection", SupportsShouldProcess = true)] public class SetSCSMObjectProjectionCommand : ObjectCmdletHelper { private PSObject _projection = null; [Parameter(Mandatory = true, Position = 0, ValueFromPipeline = true)] public PSObject Projection { get { return _projection; } set { _projection = value; } } private Hashtable _propertyValues = null; [Parameter(Mandatory = true, Position = 1)] [Alias("ph")] public Hashtable PropertyValues { get { return _propertyValues; } set { _propertyValues = value; } } private SwitchParameter _passThru; [Parameter] public SwitchParameter PassThru { get { return _passThru; } set { _passThru = value; } } protected override void ProcessRecord() { EnterpriseManagementObjectProjection p = Projection.Members["__base"].Value as EnterpriseManagementObjectProjection; // EnterpriseManagementObject o = (EnterpriseManagementObject)SMObject.Members["__base"].Value; if (p != null) { EnterpriseManagementObject o = p.Object; // create a hashtable of management pack properties Hashtable ht = new Hashtable(StringComparer.OrdinalIgnoreCase); Hashtable valuesToUse = new Hashtable(StringComparer.OrdinalIgnoreCase); foreach (ManagementPackProperty prop in o.GetProperties()) { ht.Add(prop.Name, prop); } // TODO: Add support for relationships foreach (string s in PropertyValues.Keys) { if (!ht.ContainsKey(s)) { WriteError(new ErrorRecord(new ObjectNotFoundException(s), "property not found on object", ErrorCategory.NotSpecified, o)); } else { valuesToUse.Add(s, PropertyValues[s]); } } AssignNewValues(o, valuesToUse); if (ShouldProcess("Save changes to projection")) { p.Commit(); } if (PassThru) { WriteObject(p); } } else { WriteError(new ErrorRecord(new ArgumentException("SetProjection"), "object was not a projection", ErrorCategory.InvalidOperation, Projection)); } } } #endregion [Cmdlet(VerbsCommon.Get,"SCSMRelatedObject", DefaultParameterSetName="Wrapped")] public class GetSMRelatedObjectCommand : ObjectCmdletHelper { private EnterpriseManagementObject _smobject; [Parameter(Position=0,Mandatory=true,ValueFromPipeline=true,ParameterSetName="Wrapped")] public EnterpriseManagementObject SMObject { get { return _smobject; } set { _smobject = value; } } private ManagementPackRelationship _relationship; [Parameter] public ManagementPackRelationship Relationship { get { return _relationship; } set { _relationship = value; } } private TraversalDepth _depth = TraversalDepth.OneLevel; [Parameter] public TraversalDepth Depth { get { return _depth; } set { _depth = value; } } protected override void ProcessRecord() { if ( Relationship != null) { foreach(EnterpriseManagementObject o in _mg.EntityObjects.GetRelatedObjects<EnterpriseManagementObject>(SMObject.Id, Relationship, Depth, QueryOption)) { WriteObject(ServiceManagerObjectHelper.AdaptManagementObject(this, o)); } } else { foreach(EnterpriseManagementObject o in _mg.EntityObjects.GetRelatedObjects<EnterpriseManagementObject>(SMObject.Id, Depth, QueryOption)) { WriteObject(ServiceManagerObjectHelper.AdaptManagementObject(this, o)); } } } } [Cmdlet(VerbsCommon.Get, "SCSMRelationshipObject", DefaultParameterSetName="ID")] public class GetSCSMRelationshipObjectCommand : ObjectCmdletHelper { private Guid _id = Guid.Empty; [Parameter(Position = 0, ParameterSetName="ID", Mandatory = true)] public Guid Id { get { return _id; } set { _id = value; } } private ManagementPackRelationship[] _relationship = null; [Parameter(ParameterSetName="RELATIONSHIP",Mandatory=true,ValueFromPipeline=true,Position=0)] public ManagementPackRelationship[] Relationship { get { return _relationship; } set { _relationship = value; } } private ManagementPackRelationship _trelationship; [Parameter(ParameterSetName = "TARGETANDRELATIONSHIP", Mandatory = true)] public ManagementPackRelationship TargetRelationship { get { return _trelationship; } set { _trelationship = value; } } private ManagementPackClass _target = null; [Parameter(ParameterSetName="TARGET",Mandatory=true)] public ManagementPackClass Target { get { return _target; } set { _target = value; } } private ManagementPackClass _source = null; [Parameter(ParameterSetName="SOURCE",Mandatory=true)] public ManagementPackClass Source { get { return _source; } set { _source = value; } } private EnterpriseManagementObject _byTarget; [Parameter(ParameterSetName="TARGETOBJECT",Mandatory=true)] public EnterpriseManagementObject ByTarget { get { return _byTarget; } set { _byTarget = value; } } [Parameter(ParameterSetName = "TARGETANDRELATIONSHIP", Mandatory = true)] public EnterpriseManagementObject TargetObject { get { return _byTarget; } set { _byTarget = value; } } private EnterpriseManagementObject _bySource; [Parameter(ParameterSetName="SOURCEOBJECT",Mandatory=true)] public EnterpriseManagementObject BySource { get { return _bySource; } set { _bySource = value; } } private string _filter = null; [Parameter(ParameterSetName = "SOURCEOBJECT")] [Parameter(ParameterSetName = "TARGET")] [Parameter(ParameterSetName = "SOURCE")] [Parameter(ParameterSetName = "RELATIONSHIP")] [Parameter(ParameterSetName = "FILTER", Mandatory=true)] public string Filter { get { return _filter; } set { _filter = value; } } private enum QueryBy { TargetClass, SourceClass, Target, Source, Relationship, TargetAndRelationship }; #region GetRelationshipsHelper private IList<EnterpriseManagementRelationshipObject<EnterpriseManagementObject>> GetRelationshipObjects(ManagementPackRelationship r) { return GetRelationshipObjects(null, null, r, QueryBy.Relationship, null); } private IList<EnterpriseManagementRelationshipObject<EnterpriseManagementObject>> GetRelationshipObjects(ManagementPackRelationship r, string filter) { return GetRelationshipObjects(null, null, r, QueryBy.Relationship, filter); } private IList<EnterpriseManagementRelationshipObject<EnterpriseManagementObject>> GetRelationshipObjects(string filter) { return GetRelationshipObjects(null, null, null, QueryBy.Relationship, filter); } private IList<EnterpriseManagementRelationshipObject<EnterpriseManagementObject>> GetRelationshipObjects(ManagementPackClass c, QueryBy q) { return GetRelationshipObjects(c, null, null, q, null); } private IList<EnterpriseManagementRelationshipObject<EnterpriseManagementObject>> GetRelationshipObjects(ManagementPackClass c, QueryBy q, string filter) { return GetRelationshipObjects(c, null, null, q, filter); } private IList<EnterpriseManagementRelationshipObject<EnterpriseManagementObject>> GetRelationshipObjects(EnterpriseManagementObject emo, QueryBy q) { return GetRelationshipObjects(null, emo, null, q, null); } private IList<EnterpriseManagementRelationshipObject<EnterpriseManagementObject>> GetRelationshipObjects(EnterpriseManagementObject emo, QueryBy q, string filter) { return GetRelationshipObjects(null, emo, null, q, filter); } private IList<EnterpriseManagementRelationshipObject<EnterpriseManagementObject>> GetRelationshipObjects(EnterpriseManagementObject emo, ManagementPackRelationship r) { return GetRelationshipObjects(null, emo, r, QueryBy.TargetAndRelationship, null); } private IList<EnterpriseManagementRelationshipObject<EnterpriseManagementObject>> GetRelationshipObjects(ManagementPackClass classType, EnterpriseManagementObject emo, ManagementPackRelationship r, QueryBy q, string filter) { EnterpriseManagementRelationshipObjectGenericCriteria criteria = null; IList<EnterpriseManagementRelationshipObject<EnterpriseManagementObject>> Results = null; WriteVerbose("Retrieving Relationship Objects. QueryBy is:" + q.ToString() ); if (filter != null) { WriteVerbose(" Using Filter: " + filter);
            Regex re;
            foreach (string s in EnterpriseManagementRelationshipObjectGenericCriteria.GetValidPropertyNames())
            {
                re = new Regex(s, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
                filter = re.Replace(filter, s);
            }
            WriteVerbose("
 After property name substitution: " + filter);
            try
            {
                string convertedFilter = ConvertFilterToGenericCriteria(filter);
                WriteVerbose("
 Converted filter is: " + convertedFilter);
                criteria = new EnterpriseManagementRelationshipObjectGenericCriteria(convertedFilter);
            }
            catch (Exception e)
            {
                ThrowTerminatingError(new ErrorRecord(e, "
CreateRelationshipCriteria", ErrorCategory.InvalidOperation, filter)); } } try { switch (q) { case QueryBy.TargetClass: { if (criteria != null) { Results = _mg.EntityObjects.GetRelationshipObjectsByTargetClass<EnterpriseManagementObject>(criteria, classType, ObjectQueryOptions.Default); } else { Results = _mg.EntityObjects.GetRelationshipObjectsByTargetClass<EnterpriseManagementObject>(classType, ObjectQueryOptions.Default); } break; } case QueryBy.SourceClass: { if (criteria != null) { Results = _mg.EntityObjects.GetRelationshipObjectsBySourceClass<EnterpriseManagementObject>(criteria, classType, ObjectQueryOptions.Default); } else { Results = _mg.EntityObjects.GetRelationshipObjectsBySourceClass<EnterpriseManagementObject>(classType, ObjectQueryOptions.Default); } break; } case QueryBy.Target: { Results = _mg.EntityObjects.GetRelationshipObjectsWhereTarget<EnterpriseManagementObject>(emo.Id, ObjectQueryOptions.Default); break; } case QueryBy.TargetAndRelationship: { Results = _mg.EntityObjects.GetRelationshipObjectsWhereTarget<EnterpriseManagementObject>(emo.Id, r, DerivedClassTraversalDepth.Recursive, TraversalDepth.OneLevel, ObjectQueryOptions.Default); break; } case QueryBy.Source: { if (criteria != null) { Results = _mg.EntityObjects.GetRelationshipObjectsWhereSource<EnterpriseManagementObject>(emo.Id, criteria, TraversalDepth.Recursive, ObjectQueryOptions.Default); } else { Results = _mg.EntityObjects.GetRelationshipObjectsWhereSource<EnterpriseManagementObject>(emo.Id, TraversalDepth.Recursive, ObjectQueryOptions.Default); } break; } case QueryBy.Relationship: { if (criteria != null) { WriteVerbose("Relationship with criteria"); Results = _mg.EntityObjects.GetRelationshipObjects<EnterpriseManagementObject>(criteria, ObjectQueryOptions.Default); } else { Results = _mg.EntityObjects.GetRelationshipObjects<EnterpriseManagementObject>(r, DerivedClassTraversalDepth.Recursive, ObjectQueryOptions.Default); WriteVerbose("Relationship via r: " + r.Id.ToString() + ". Count = " + Results.Count.ToString());
                        }
                        break;
                    }
                default:
                    {
                        ThrowTerminatingError(new ErrorRecord(new InvalidOperationException("
No relationship query type specified"), "BadRelationshipQueryRequest", ErrorCategory.InvalidOperation, this)); break; } } } catch (Exception e) { ThrowTerminatingError(new ErrorRecord(e, "RelationshipQuery", ErrorCategory.InvalidOperation, this)); } foreach (EnterpriseManagementRelationshipObject<EnterpriseManagementObject> o in Results) { WriteVerbose("ID: " + o.Id.ToString()); }
        return Results;
    }
#endregion GetRelationshipHelper
 
    protected override void ProcessRecord()
    {
        if ( this.ParameterSetName == "
TARGET" ) { WriteObject(GetRelationshipObjects(Target, QueryBy.Target, Filter), true); } else if ( this.ParameterSetName == "RELATIONSHIP" ) { foreach (ManagementPackRelationship r in Relationship) { WriteObject(GetRelationshipObjects(r, Filter), true); } } else if ( this.ParameterSetName == "SOURCE" ) { WriteObject(GetRelationshipObjects(Source, QueryBy.Source, Filter), true); } else if ( this.ParameterSetName == "TARGETOBJECT" ) { WriteObject(GetRelationshipObjects(ByTarget, QueryBy.Target), true); } else if (this.ParameterSetName == "TARGETANDRELATIONSHIP") { WriteObject(GetRelationshipObjects(TargetObject, TargetRelationship)); } else if (this.ParameterSetName == "SOURCEOBJECT") { WriteObject(GetRelationshipObjects(BySource, QueryBy.Source, Filter), true); } else if (this.ParameterSetName == "FILTER") { WriteObject(GetRelationshipObjects(Filter), true); } else { WriteObject(_mg.EntityObjects.GetRelationshipObject<EnterpriseManagementObject>(Id, ObjectQueryOptions.Default)); WriteVerbose("By Id: " + Id.ToString());
        }
    }
}
 
[Cmdlet(VerbsCommon.Get, "
SCSMConfigItem", SupportsShouldProcess = true)] public class SCSMConfigItemGet : SMCmdletBase { private String _DisplayName = null; private String _TargetProjection = "8ab27adb-13b1-2b7b-56e6-91598417cbee"; [Parameter(Position = 0, Mandatory = true, ValueFromPipelineByPropertyName = true, HelpMessage = "The display name of the config item.")] [ValidateNotNullOrEmpty] public string DisplayName { get { return _DisplayName; } set { _DisplayName = value; } } [Parameter(Position = 1, Mandatory = false, ValueFromPipelineByPropertyName = true, HelpMessage = "The display name of the config item.")] [ValidateNotNullOrEmpty] public string TargetProjection { get { return _TargetProjection; } set { _TargetProjection = value; } } protected override void ProcessRecord() { ManagementPackTypeProjection targetProjection = _mg.EntityTypes.GetTypeProjection(new Guid(TargetProjection)); ManagementPack trgProjMp = targetProjection.GetManagementPack(); ManagementPack systemMp = _mg.ManagementPacks.GetManagementPack(SystemManagementPack.System); WriteVerbose("Starting to build search criteria..."); List<string> criterias = new List<string>(); // Define the query criteria string. // This is XML that validates against the Microsoft.EnterpriseManagement.Core.Criteria schema. StringBuilder configCriteria = new StringBuilder(String.Format(@"
                <Criteria xmlns=""http://Microsoft.EnterpriseManagement.Core.Criteria/"">
                  <Reference Id=""System.Library"" PublicKeyToken=""{0}"" Version=""{1}"" Alias=""targetMp"" />
                      <Expression>", systemMp.KeyToken, systemMp.Version.ToString())); if (this._DisplayName != null) { WriteVerbose(string.Format("Adding \"DisplayName like {0}\" to search criteria", this.DisplayName)); criterias.Add(@"<SimpleExpression>
                                    <ValueExpressionLeft>
                                    <Property>$Context/Property[Type='targetMp!System.ConfigItem']/DisplayName$</Property>
                                    </ValueExpressionLeft>
                                    <Operator>Like</Operator>
                                    <ValueExpressionRight>
                                    <Value>" + this.DisplayName + @"</Value>
                                    </ValueExpressionRight>
                                </SimpleExpression>"); } if (criterias.Count > 1) { for (int i = 0; i < criterias.Count; i++) { criterias[i] = "<Expression>" + criterias[i] + "</Expression>"; } } if (criterias.Count > 1) { configCriteria.AppendLine("<And>"); } foreach (var item in criterias) { configCriteria.AppendLine(item); } if (criterias.Count > 1) { configCriteria.AppendLine("</And>"); } configCriteria.AppendLine(@"</Expression>
                </Criteria>"); WriteDebug("Search criteria: " + configCriteria.ToString());
 
        // Define the criteria object by using one of the criteria strings.
        ObjectProjectionCriteria criteria = new ObjectProjectionCriteria(configCriteria.ToString(),
            targetProjection, _mg);
 
        // For each retrieved type projection, display the properties.
        List<EnterpriseManagementObjectProjection> result = new List<EnterpriseManagementObjectProjection>();
        foreach (EnterpriseManagementObjectProjection projection in
            _mg.EntityObjects.GetObjectProjectionReader<EnterpriseManagementObject>(criteria, ObjectQueryOptions.Default))
        {
            WriteVerbose(String.Format("
Adding config item \"{0}\" to the pipeline", projection.Object.DisplayName)); WriteObject(projection, false); } } } }