forked from PowerShell/PowerShell
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathParameter.cs
More file actions
311 lines (264 loc) · 12 KB
/
Copy pathParameter.cs
File metadata and controls
311 lines (264 loc) · 12 KB
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
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
using System.Management.Automation.Language;
using Microsoft.Management.Infrastructure;
namespace System.Management.Automation.Runspaces
{
using System;
using System.Collections.ObjectModel;
using Debug = System.Management.Automation.Diagnostics;
/// <summary>
/// Define a parameter for <see cref="Command"/>
/// </summary>
public sealed class CommandParameter
{
#region Public constructors
/// <summary>
/// Create a named parameter with a null value
/// </summary>
/// <param name="name">parameter name</param>
/// <exception cref="ArgumentNullException">
/// name is null.
/// </exception>
/// <exception cref="ArgumentException">
/// Name length is zero after trimming whitespace.
/// </exception>
public CommandParameter(string name)
: this(name, null)
{
if (name == null)
{
throw PSTraceSource.NewArgumentNullException("name");
}
}
/// <summary>
/// Create a named parameter
/// </summary>
/// <param name="name">parameter name</param>
/// <param name="value">parameter value</param>
/// <exception cref="ArgumentException">
/// Name is non null and name length is zero after trimming whitespace.
/// </exception>
public CommandParameter(string name, object value)
{
if (name != null)
{
if (string.IsNullOrWhiteSpace(name))
{
throw PSTraceSource.NewArgumentException("name");
}
Name = name;
}
else
{
Name = null;
}
Value = value;
}
#endregion Public constructors
#region Public properties
/// <summary>
/// gets the parameter name
/// </summary>
public string Name { get; }
/// <summary>
/// gets the value of the parameter
/// </summary>
public object Value { get; }
#endregion Public properties
#region Private Fields
#endregion Private Fields
#region Conversion from and to CommandParameterInternal
internal static CommandParameter FromCommandParameterInternal(CommandParameterInternal internalParameter)
{
if (internalParameter == null)
{
throw PSTraceSource.NewArgumentNullException("internalParameter");
}
// we want the name to preserve 1) dashes, 2) colons, 3) followed-by-space information
string name = null;
if (internalParameter.ParameterNameSpecified)
{
name = internalParameter.ParameterText;
if (internalParameter.SpaceAfterParameter)
{
name = name + " ";
}
Diagnostics.Assert(name != null, "'name' variable should be initialized at this point");
Diagnostics.Assert(name[0].IsDash(), "first character in parameter name must be a dash");
Diagnostics.Assert(name.Trim().Length != 1, "Parameter name has to have some non-whitespace characters in it");
}
if (internalParameter.ParameterAndArgumentSpecified)
{
return new CommandParameter(name, internalParameter.ArgumentValue);
}
if (name != null) // either a switch parameter or first part of parameter+argument
{
return new CommandParameter(name);
}
// either a positional argument or second part of parameter+argument
return new CommandParameter(null, internalParameter.ArgumentValue);
}
internal static CommandParameterInternal ToCommandParameterInternal(CommandParameter publicParameter, bool forNativeCommand)
{
if (publicParameter == null)
{
throw PSTraceSource.NewArgumentNullException("publicParameter");
}
string name = publicParameter.Name;
object value = publicParameter.Value;
Debug.Assert((name == null) || (name.Trim().Length != 0), "Parameter name has to null or have some non-whitespace characters in it");
if (name == null)
{
return CommandParameterInternal.CreateArgument(value);
}
string parameterText;
if (!name[0].IsDash())
{
parameterText = forNativeCommand ? name : "-" + name;
return CommandParameterInternal.CreateParameterWithArgument(
/*parameterAst*/null, name, parameterText,
/*argumentAst*/null, value,
true);
}
// if first character of name is '-', then we try to fake the original token
// reconstructing dashes, colons and followed-by-space information
// find the last non-whitespace character
bool spaceAfterParameter = false;
int endPosition = name.Length;
while ((endPosition > 0) && char.IsWhiteSpace(name[endPosition - 1]))
{
spaceAfterParameter = true;
endPosition--;
}
Debug.Assert(endPosition > 0, "parameter name should have some non-whitespace characters in it");
// now make sure that parameterText doesn't have whitespace at the end,
parameterText = name.Substring(0, endPosition);
// parameterName should contain only the actual name of the parameter (no whitespace, colons, dashes)
bool hasColon = (name[endPosition - 1] == ':');
var parameterName = parameterText.Substring(1, parameterText.Length - (hasColon ? 2 : 1));
// At this point we have rebuilt the token. There are 3 strings that might be different:
// name = nameToken.Script = "-foo: " <- needed to fake FollowedBySpace=true (i.e. for "testecho.exe -a:b -c: d")
// tokenString = nameToken.TokenText = "-foo:" <- needed to preserve full token text (i.e. for write-output)
// nameToken.Data = "foo" <- needed to preserve name of parameter so parameter binding works
// Now we just need to use the token to build appropriate CommandParameterInternal object
// is this a name+value pair, or is it just a name (of a parameter)?
if (!hasColon && value == null)
{
// just a name
return CommandParameterInternal.CreateParameter(parameterName, parameterText);
}
// name+value pair
return CommandParameterInternal.CreateParameterWithArgument(
/*parameterAst*/null, parameterName, parameterText,
/*argumentAst*/null, value,
spaceAfterParameter);
}
#endregion
#region Serialization / deserialization for remoting
/// <summary>
/// Creates a CommandParameter object from a PSObject property bag.
/// PSObject has to be in the format returned by ToPSObjectForRemoting method.
/// </summary>
/// <param name="parameterAsPSObject">PSObject to rehydrate</param>
/// <returns>
/// CommandParameter rehydrated from a PSObject property bag
/// </returns>
/// <exception cref="ArgumentNullException">
/// Thrown if the PSObject is null.
/// </exception>
/// <exception cref="System.Management.Automation.Remoting.PSRemotingDataStructureException">
/// Thrown when the PSObject is not in the expected format
/// </exception>
internal static CommandParameter FromPSObjectForRemoting(PSObject parameterAsPSObject)
{
if (parameterAsPSObject == null)
{
throw PSTraceSource.NewArgumentNullException("parameterAsPSObject");
}
string name = RemotingDecoder.GetPropertyValue<string>(parameterAsPSObject, RemoteDataNameStrings.ParameterName);
object value = RemotingDecoder.GetPropertyValue<object>(parameterAsPSObject, RemoteDataNameStrings.ParameterValue);
return new CommandParameter(name, value);
}
/// <summary>
/// Returns this object as a PSObject property bag
/// that can be used in a remoting protocol data object.
/// </summary>
/// <returns>This object as a PSObject property bag</returns>
internal PSObject ToPSObjectForRemoting()
{
PSObject parameterAsPSObject = RemotingEncoder.CreateEmptyPSObject();
parameterAsPSObject.Properties.Add(new PSNoteProperty(RemoteDataNameStrings.ParameterName, this.Name));
parameterAsPSObject.Properties.Add(new PSNoteProperty(RemoteDataNameStrings.ParameterValue, this.Value));
return parameterAsPSObject;
}
#endregion
#region Win Blue Extensions
#if !CORECLR // PSMI Not Supported On CSS
internal CimInstance ToCimInstance()
{
CimInstance c = InternalMISerializer.CreateCimInstance("PS_Parameter");
CimProperty nameProperty = InternalMISerializer.CreateCimProperty("Name", this.Name,
Microsoft.Management.Infrastructure.CimType.String);
c.CimInstanceProperties.Add(nameProperty);
Microsoft.Management.Infrastructure.CimType cimType = CimConverter.GetCimType(this.Value.GetType());
CimProperty valueProperty;
if (cimType == Microsoft.Management.Infrastructure.CimType.Unknown)
{
valueProperty = InternalMISerializer.CreateCimProperty("Value", (object)PSMISerializer.Serialize(this.Value),
Microsoft.Management.Infrastructure.CimType.Instance);
}
else
{
valueProperty = InternalMISerializer.CreateCimProperty("Value", this.Value, cimType);
}
c.CimInstanceProperties.Add(valueProperty);
return c;
}
#endif
#endregion Win Blue Extensions
}
/// <summary>
/// Defines a collection of parameters.
/// </summary>
public sealed class CommandParameterCollection : Collection<CommandParameter>
{
//TODO: this class needs a mechanism to lock further changes
/// <summary>
/// Create a new empty instance of this collection type
/// </summary>
public CommandParameterCollection()
{
}
/// <summary>
/// Add a parameter with given name and default null value
/// </summary>
/// <param name="name">name of the parameter</param>
/// <exception cref="ArgumentNullException">
/// name is null.
/// </exception>
/// <exception cref="ArgumentException">
/// Name length is zero after trimming whitespace.
/// </exception>
public void Add(string name)
{
Add(new CommandParameter(name));
}
/// <summary>
/// Add a parameter with given name and value
/// </summary>
/// <param name="name">name of the parameter</param>
/// <param name="value">value of the parameter</param>
/// <exception cref="ArgumentNullException">
/// Both name and value are null. One of these must be non-null.
/// </exception>
/// <exception cref="ArgumentException">
/// Name is non null and name length is zero after trimming whitespace.
/// </exception>
public void Add(string name, object value)
{
Add(new CommandParameter(name, value));
}
}
}