@@ -6943,12 +6943,6 @@ internal static DynamicMetaObject InvokeDotNetMethod(
6943
6943
expr = Expression . Block ( expr , ExpressionCache . AutomationNullConstant ) ;
6944
6944
}
6945
6945
6946
- // Expression block runs two expressions in order:
6947
- // - Log method invocation to AMSI Notifications (can throw PSSecurityException)
6948
- // - Invoke method
6949
- string targetName = methodInfo . ReflectedType ? . FullName ?? string . Empty ;
6950
- expr = MaybeAddMemberInvocationLogging ( expr , targetName , name , args ) ;
6951
-
6952
6946
// If we're calling SteppablePipeline.{Begin|Process|End}, we don't want
6953
6947
// to wrap exceptions - this is very much a special case to help error
6954
6948
// propagation and ensure errors are attributed to the correct code (the
@@ -7111,6 +7105,7 @@ internal static Expression InvokeMethod(MethodBase mi, DynamicMetaObject target,
7111
7105
invocationType != MethodInvocationType . NonVirtual ;
7112
7106
var parameters = mi . GetParameters ( ) ;
7113
7107
var argExprs = new Expression [ parameters . Length ] ;
7108
+ var argsToLog = new List < Expression > ( Math . Max ( parameters . Length , args . Length ) ) ;
7114
7109
7115
7110
for ( int i = 0 ; i < parameters . Length ; ++ i )
7116
7111
{
@@ -7135,16 +7130,21 @@ internal static Expression InvokeMethod(MethodBase mi, DynamicMetaObject target,
7135
7130
7136
7131
if ( expandParameters )
7137
7132
{
7138
- argExprs [ i ] = Expression . NewArrayInit (
7139
- paramElementType ,
7140
- args . Skip ( i ) . Select (
7141
- a => a . CastOrConvertMethodArgument (
7133
+ IEnumerable < Expression > elements = args
7134
+ . Skip ( i )
7135
+ . Select ( a =>
7136
+ a . CastOrConvertMethodArgument (
7142
7137
paramElementType ,
7143
7138
paramName ,
7144
7139
mi . Name ,
7145
7140
allowCastingToByRefLikeType : false ,
7146
7141
temps ,
7147
- initTemps ) ) ) ;
7142
+ initTemps ) )
7143
+ . ToList ( ) ;
7144
+
7145
+ argExprs [ i ] = Expression . NewArrayInit ( paramElementType , elements ) ;
7146
+ // User specified the element arguments, so we log them instead of the compiler-created array.
7147
+ argsToLog . AddRange ( elements ) ;
7148
7148
}
7149
7149
else
7150
7150
{
@@ -7155,13 +7155,18 @@ internal static Expression InvokeMethod(MethodBase mi, DynamicMetaObject target,
7155
7155
allowCastingToByRefLikeType : false ,
7156
7156
temps ,
7157
7157
initTemps ) ;
7158
+
7158
7159
argExprs [ i ] = arg ;
7160
+ argsToLog . Add ( arg ) ;
7159
7161
}
7160
7162
}
7161
7163
else if ( i >= args . Length )
7162
7164
{
7163
- Diagnostics . Assert ( parameters [ i ] . IsOptional ,
7165
+ // We don't log the default value for an optional parameter, as it's not specified by the user.
7166
+ Diagnostics . Assert (
7167
+ parameters [ i ] . IsOptional ,
7164
7168
"if there are too few arguments, FindBestMethod should only succeed if parameters are optional" ) ;
7169
+
7165
7170
var argValue = parameters [ i ] . DefaultValue ;
7166
7171
if ( argValue == null )
7167
7172
{
@@ -7199,17 +7204,25 @@ internal static Expression InvokeMethod(MethodBase mi, DynamicMetaObject target,
7199
7204
var psRefValue = Expression . Property ( args [ i ] . Expression . Cast ( typeof ( PSReference ) ) , CachedReflectionInfo . PSReference_Value ) ;
7200
7205
initTemps . Add ( Expression . Assign ( temp , psRefValue . Convert ( temp . Type ) ) ) ;
7201
7206
copyOutTemps . Add ( Expression . Assign ( psRefValue , temp . Cast ( typeof ( object ) ) ) ) ;
7207
+
7202
7208
argExprs [ i ] = temp ;
7209
+ argsToLog . Add ( temp ) ;
7203
7210
}
7204
7211
else
7205
7212
{
7206
- argExprs [ i ] = args [ i ] . CastOrConvertMethodArgument (
7213
+ var convertedArg = args [ i ] . CastOrConvertMethodArgument (
7207
7214
parameterType ,
7208
7215
paramName ,
7209
7216
mi . Name ,
7210
7217
allowCastingToByRefLikeType ,
7211
7218
temps ,
7212
7219
initTemps ) ;
7220
+
7221
+ argExprs [ i ] = convertedArg ;
7222
+ // If the converted arg is a byref-like type, then we log the original arg.
7223
+ argsToLog . Add ( convertedArg . Type . IsByRefLike
7224
+ ? args [ i ] . Expression
7225
+ : convertedArg ) ;
7213
7226
}
7214
7227
}
7215
7228
}
@@ -7255,6 +7268,12 @@ internal static Expression InvokeMethod(MethodBase mi, DynamicMetaObject target,
7255
7268
}
7256
7269
}
7257
7270
7271
+ // We need to add one expression to log the .NET invocation before actually invoking:
7272
+ // - Log method invocation to AMSI Notifications (can throw PSSecurityException)
7273
+ // - Invoke method
7274
+ string targetName = mi . ReflectedType ? . FullName ?? string . Empty ;
7275
+ string methodName = mi . Name is ".ctor" ? "new" : mi . Name ;
7276
+
7258
7277
if ( temps . Count > 0 )
7259
7278
{
7260
7279
if ( call . Type != typeof ( void ) && copyOutTemps . Count > 0 )
@@ -7265,8 +7284,13 @@ internal static Expression InvokeMethod(MethodBase mi, DynamicMetaObject target,
7265
7284
copyOutTemps . Add ( retValue ) ;
7266
7285
}
7267
7286
7287
+ AddMemberInvocationLogging ( initTemps , targetName , methodName , argsToLog ) ;
7268
7288
call = Expression . Block ( call . Type , temps , initTemps . Append ( call ) . Concat ( copyOutTemps ) ) ;
7269
7289
}
7290
+ else
7291
+ {
7292
+ call = AddMemberInvocationLogging ( call , targetName , methodName , argsToLog ) ;
7293
+ }
7270
7294
7271
7295
return call ;
7272
7296
}
@@ -7559,28 +7583,50 @@ internal static void InvalidateCache()
7559
7583
}
7560
7584
7561
7585
#nullable enable
7562
- private static Expression MaybeAddMemberInvocationLogging (
7586
+ private static Expression AddMemberInvocationLogging (
7563
7587
Expression expr ,
7564
7588
string targetName ,
7565
7589
string name ,
7566
- DynamicMetaObject [ ] args )
7590
+ List < Expression > args )
7567
7591
{
7568
- #if UNIX && ! DEBUG
7569
- // For efficiency this is a no-op on non-Windows platforms in release builds .
7592
+ #if UNIX
7593
+ // For efficiency this is a no-op on non-Windows platforms.
7570
7594
return expr ;
7571
7595
#else
7572
- Expression [ ] invocationArgs = new Expression [ args . Length ] ;
7573
- for ( int i = 0 ; i < args . Length ; i ++ )
7596
+ Expression [ ] invocationArgs = new Expression [ args . Count ] ;
7597
+ for ( int i = 0 ; i < args . Count ; i ++ )
7574
7598
{
7575
- invocationArgs [ i ] = args [ i ] . Expression . Cast ( typeof ( object ) ) ;
7599
+ invocationArgs [ i ] = args [ i ] . Cast ( typeof ( object ) ) ;
7576
7600
}
7601
+
7577
7602
return Expression . Block (
7578
7603
Expression . Call (
7579
7604
CachedReflectionInfo . MemberInvocationLoggingOps_LogMemberInvocation ,
7580
7605
Expression . Constant ( targetName ) ,
7581
7606
Expression . Constant ( name ) ,
7582
7607
Expression . NewArrayInit ( typeof ( object ) , invocationArgs ) ) ,
7583
7608
expr ) ;
7609
+ #endif
7610
+ }
7611
+
7612
+ private static void AddMemberInvocationLogging (
7613
+ List < Expression > exprs ,
7614
+ string targetName ,
7615
+ string name ,
7616
+ List < Expression > args )
7617
+ {
7618
+ #if ! UNIX
7619
+ Expression [ ] invocationArgs = new Expression [ args . Count ] ;
7620
+ for ( int i = 0 ; i < args . Count ; i ++ )
7621
+ {
7622
+ invocationArgs [ i ] = args [ i ] . Cast ( typeof ( object ) ) ;
7623
+ }
7624
+
7625
+ exprs . Add ( Expression . Call (
7626
+ CachedReflectionInfo . MemberInvocationLoggingOps_LogMemberInvocation ,
7627
+ Expression . Constant ( targetName ) ,
7628
+ Expression . Constant ( name ) ,
7629
+ Expression . NewArrayInit ( typeof ( object ) , invocationArgs ) ) ) ;
7584
7630
#endif
7585
7631
}
7586
7632
#nullable disable
0 commit comments