1 // Copyright (c) Microsoft. All rights reserved. 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 4 using System; 5 using System.IO; 6 using System.Diagnostics; 7 using System.Globalization; 8 using System.Runtime.CompilerServices; 9 using System.Threading; 10 11 #if BUILDINGAPPXTASKS 12 namespace Microsoft.Build.AppxPackage.Shared 13 #else 14 namespace Microsoft.Build.Shared 15 #endif 16 { 17 /// <summary> 18 /// This class contains methods that are useful for error checking and validation. 19 /// </summary> 20 internal static class ErrorUtilities 21 { 22 /// <summary> 23 /// Emergency escape hatch. If a customer hits a bug in the shipped product causing an internal exception, 24 /// and fortuitously it happens that ignoring the VerifyThrow allows execution to continue in a reasonable way, 25 /// then we can give them this undocumented environment variable as an immediate workaround. 26 /// </summary> 27 private static readonly bool s_throwExceptions = String.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSBUILDDONOTTHROWINTERNAL")); 28 private static readonly bool s_enableMSBuildDebugTracing = !String.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSBUILDENABLEDEBUGTRACING")); 29 30 #region DebugTracing DebugTraceMessage(string category, string formatstring, params object[] parameters)31 public static void DebugTraceMessage(string category, string formatstring, params object[] parameters) 32 { 33 if (s_enableMSBuildDebugTracing) 34 { 35 if (parameters != null) 36 { 37 Trace.WriteLine(String.Format(CultureInfo.CurrentCulture, formatstring, parameters), category); 38 } 39 else 40 { 41 Trace.WriteLine(formatstring, category); 42 } 43 } 44 } 45 #endregion 46 47 #if !BUILDINGAPPXTASKS 48 #region VerifyThrow -- for internal errors 49 50 /// <summary> 51 /// Throws InternalErrorException. 52 /// This is only for situations that would mean that there is a bug in MSBuild itself. 53 /// </summary> ThrowInternalError(string message, params object[] args)54 internal static void ThrowInternalError(string message, params object[] args) 55 { 56 if (s_throwExceptions) 57 { 58 throw new InternalErrorException(ResourceUtilities.FormatString(message, args)); 59 } 60 } 61 62 /// <summary> 63 /// Throws InternalErrorException. 64 /// This is only for situations that would mean that there is a bug in MSBuild itself. 65 /// </summary> ThrowInternalError(string message, Exception innerException, params object[] args)66 internal static void ThrowInternalError(string message, Exception innerException, params object[] args) 67 { 68 if (s_throwExceptions) 69 { 70 throw new InternalErrorException(ResourceUtilities.FormatString(message, args), innerException); 71 } 72 } 73 74 /// <summary> 75 /// Throws InternalErrorException. 76 /// Indicates the code path followed should not have been possible. 77 /// This is only for situations that would mean that there is a bug in MSBuild itself. 78 /// </summary> ThrowInternalErrorUnreachable()79 internal static void ThrowInternalErrorUnreachable() 80 { 81 if (s_throwExceptions) 82 { 83 throw new InternalErrorException("Unreachable?"); 84 } 85 } 86 87 /// <summary> 88 /// Throws InternalErrorException. 89 /// Indicates the code path followed should not have been possible. 90 /// This is only for situations that would mean that there is a bug in MSBuild itself. 91 /// </summary> ThrowIfTypeDoesNotImplementToString(object param)92 internal static void ThrowIfTypeDoesNotImplementToString(object param) 93 { 94 #if DEBUG 95 // Check it has a real implementation of ToString() 96 if (String.Equals(param.GetType().ToString(), param.ToString(), StringComparison.Ordinal)) 97 { 98 ErrorUtilities.ThrowInternalError("This type does not implement ToString() properly {0}", param.GetType().FullName); 99 } 100 #endif 101 } 102 103 /// <summary> 104 /// Helper to throw an InternalErrorException when the specified parameter is null. 105 /// This should be used ONLY if this would indicate a bug in MSBuild rather than 106 /// anything caused by user action. 107 /// </summary> 108 /// <param name="parameter">The value of the argument.</param> 109 /// <param name="parameterName">Parameter that should not be null</param> VerifyThrowInternalNull(object parameter, string parameterName)110 internal static void VerifyThrowInternalNull(object parameter, string parameterName) 111 { 112 if (parameter == null) 113 { 114 ThrowInternalError("{0} unexpectedly null", parameterName); 115 } 116 } 117 118 /// <summary> 119 /// Helper to throw an InternalErrorException when a lock on the specified object is not already held. 120 /// This should be used ONLY if this would indicate a bug in MSBuild rather than 121 /// anything caused by user action. 122 /// </summary> 123 /// <param name="locker">The object that should already have been used as a lock.</param> VerifyThrowInternalLockHeld(object locker)124 internal static void VerifyThrowInternalLockHeld(object locker) 125 { 126 #if !CLR2COMPATIBILITY 127 if (!Monitor.IsEntered(locker)) 128 { 129 ThrowInternalError("Lock should already have been taken"); 130 } 131 #endif 132 } 133 134 /// <summary> 135 /// Helper to throw an InternalErrorException when the specified parameter is null or zero length. 136 /// This should be used ONLY if this would indicate a bug in MSBuild rather than 137 /// anything caused by user action. 138 /// </summary> 139 /// <param name="parameterValue">The value of the argument.</param> 140 /// <param name="parameterName">Parameter that should not be null or zero length</param> VerifyThrowInternalLength(string parameterValue, string parameterName)141 internal static void VerifyThrowInternalLength(string parameterValue, string parameterName) 142 { 143 VerifyThrowInternalNull(parameterValue, parameterName); 144 145 if (parameterValue.Length == 0) 146 { 147 ThrowInternalError("{0} unexpectedly empty", parameterName); 148 } 149 } 150 151 /// <summary> 152 /// Helper to throw an InternalErrorException when the specified parameter is not a rooted path. 153 /// This should be used ONLY if this would indicate a bug in MSBuild rather than 154 /// anything caused by user action. 155 /// </summary> 156 /// <param name="value">Parameter that should be a rooted path</param> VerifyThrowInternalRooted(string value)157 internal static void VerifyThrowInternalRooted(string value) 158 { 159 if (!Path.IsPathRooted(value)) 160 { 161 ThrowInternalError("{0} unexpectedly not a rooted path", value); 162 } 163 } 164 165 /// <summary> 166 /// This method should be used in places where one would normally put 167 /// an "assert". It should be used to validate that our assumptions are 168 /// true, where false would indicate that there must be a bug in our 169 /// code somewhere. This should not be used to throw errors based on bad 170 /// user input or anything that the user did wrong. 171 /// </summary> 172 /// <param name="condition"></param> 173 /// <param name="unformattedMessage"></param> VerifyThrow( bool condition, string unformattedMessage )174 internal static void VerifyThrow 175 ( 176 bool condition, 177 string unformattedMessage 178 ) 179 { 180 if (!condition) 181 { 182 // PERF NOTE: explicitly passing null for the arguments array 183 // prevents memory allocation 184 ThrowInternalError(unformattedMessage, null, null); 185 } 186 } 187 188 /// <summary> 189 /// Overload for one string format argument. 190 /// </summary> 191 /// <param name="condition"></param> 192 /// <param name="unformattedMessage"></param> 193 /// <param name="arg0"></param> VerifyThrow( bool condition, string unformattedMessage, object arg0 )194 internal static void VerifyThrow 195 ( 196 bool condition, 197 string unformattedMessage, 198 object arg0 199 ) 200 { 201 // PERF NOTE: check the condition here instead of pushing it into 202 // the ThrowInternalError() method, because that method always 203 // allocates memory for its variable array of arguments 204 if (!condition) 205 { 206 ThrowInternalError(unformattedMessage, arg0); 207 } 208 } 209 210 /// <summary> 211 /// Overload for two string format arguments. 212 /// </summary> 213 /// <param name="condition"></param> 214 /// <param name="unformattedMessage"></param> 215 /// <param name="arg0"></param> 216 /// <param name="arg1"></param> VerifyThrow( bool condition, string unformattedMessage, object arg0, object arg1 )217 internal static void VerifyThrow 218 ( 219 bool condition, 220 string unformattedMessage, 221 object arg0, 222 object arg1 223 ) 224 { 225 // PERF NOTE: check the condition here instead of pushing it into 226 // the ThrowInternalError() method, because that method always 227 // allocates memory for its variable array of arguments 228 if (!condition) 229 { 230 ThrowInternalError(unformattedMessage, arg0, arg1); 231 } 232 } 233 234 /// <summary> 235 /// Overload for three string format arguments. 236 /// </summary> 237 /// <param name="condition"></param> 238 /// <param name="unformattedMessage"></param> 239 /// <param name="arg0"></param> 240 /// <param name="arg1"></param> 241 /// <param name="arg2"></param> VerifyThrow( bool condition, string unformattedMessage, object arg0, object arg1, object arg2 )242 internal static void VerifyThrow 243 ( 244 bool condition, 245 string unformattedMessage, 246 object arg0, 247 object arg1, 248 object arg2 249 ) 250 { 251 // PERF NOTE: check the condition here instead of pushing it into 252 // the ThrowInternalError() method, because that method always 253 // allocates memory for its variable array of arguments 254 if (!condition) 255 { 256 ThrowInternalError(unformattedMessage, arg0, arg1, arg2); 257 } 258 } 259 260 /// <summary> 261 /// Overload for four string format arguments. 262 /// </summary> 263 /// <param name="condition"></param> 264 /// <param name="unformattedMessage"></param> 265 /// <param name="arg0"></param> 266 /// <param name="arg1"></param> 267 /// <param name="arg2"></param> 268 /// <param name="arg3"></param> VerifyThrow( bool condition, string unformattedMessage, object arg0, object arg1, object arg2, object arg3 )269 internal static void VerifyThrow 270 ( 271 bool condition, 272 string unformattedMessage, 273 object arg0, 274 object arg1, 275 object arg2, 276 object arg3 277 ) 278 { 279 // PERF NOTE: check the condition here instead of pushing it into 280 // the ThrowInternalError() method, because that method always 281 // allocates memory for its variable array of arguments 282 if (!condition) 283 { 284 ThrowInternalError(unformattedMessage, arg0, arg1, arg2, arg3); 285 } 286 } 287 288 #endregion 289 290 #region VerifyThrowInvalidOperation 291 292 /// <summary> 293 /// Throws an InvalidOperationException with the specified resource string 294 /// </summary> 295 /// <param name="resourceName">Resource to use in the exception</param> 296 /// <param name="args">Formatting args.</param> ThrowInvalidOperation(string resourceName, params object[] args)297 internal static void ThrowInvalidOperation(string resourceName, params object[] args) 298 { 299 #if DEBUG 300 ResourceUtilities.VerifyResourceStringExists(resourceName); 301 #endif 302 if (s_throwExceptions) 303 { 304 throw new InvalidOperationException(ResourceUtilities.FormatResourceString(resourceName, args)); 305 } 306 } 307 308 /// <summary> 309 /// Throws an InvalidOperationException if the given condition is false. 310 /// </summary> 311 /// <param name="condition"></param> 312 /// <param name="resourceName"></param> VerifyThrowInvalidOperation( bool condition, string resourceName )313 internal static void VerifyThrowInvalidOperation 314 ( 315 bool condition, 316 string resourceName 317 ) 318 { 319 if (!condition) 320 { 321 // PERF NOTE: explicitly passing null for the arguments array 322 // prevents memory allocation 323 ThrowInvalidOperation(resourceName, null); 324 } 325 } 326 327 /// <summary> 328 /// Overload for one string format argument. 329 /// </summary> 330 /// <param name="condition"></param> 331 /// <param name="resourceName"></param> 332 /// <param name="arg0"></param> VerifyThrowInvalidOperation( bool condition, string resourceName, object arg0 )333 internal static void VerifyThrowInvalidOperation 334 ( 335 bool condition, 336 string resourceName, 337 object arg0 338 ) 339 { 340 // PERF NOTE: check the condition here instead of pushing it into 341 // the ThrowInvalidOperation() method, because that method always 342 // allocates memory for its variable array of arguments 343 if (!condition) 344 { 345 ThrowInvalidOperation(resourceName, arg0); 346 } 347 } 348 349 /// <summary> 350 /// Overload for two string format arguments. 351 /// </summary> 352 /// <param name="condition"></param> 353 /// <param name="resourceName"></param> 354 /// <param name="arg0"></param> 355 /// <param name="arg1"></param> VerifyThrowInvalidOperation( bool condition, string resourceName, object arg0, object arg1 )356 internal static void VerifyThrowInvalidOperation 357 ( 358 bool condition, 359 string resourceName, 360 object arg0, 361 object arg1 362 ) 363 { 364 // PERF NOTE: check the condition here instead of pushing it into 365 // the ThrowInvalidOperation() method, because that method always 366 // allocates memory for its variable array of arguments 367 if (!condition) 368 { 369 ThrowInvalidOperation(resourceName, arg0, arg1); 370 } 371 } 372 373 /// <summary> 374 /// Overload for three string format arguments. 375 /// </summary> 376 /// <param name="condition"></param> 377 /// <param name="resourceName"></param> 378 /// <param name="arg0"></param> 379 /// <param name="arg1"></param> 380 /// <param name="arg2"></param> VerifyThrowInvalidOperation( bool condition, string resourceName, object arg0, object arg1, object arg2 )381 internal static void VerifyThrowInvalidOperation 382 ( 383 bool condition, 384 string resourceName, 385 object arg0, 386 object arg1, 387 object arg2 388 ) 389 { 390 // PERF NOTE: check the condition here instead of pushing it into 391 // the ThrowInvalidOperation() method, because that method always 392 // allocates memory for its variable array of arguments 393 if (!condition) 394 { 395 ThrowInvalidOperation(resourceName, arg0, arg1, arg2); 396 } 397 } 398 399 /// <summary> 400 /// Overload for four string format arguments. 401 /// </summary> 402 /// <param name="condition"></param> 403 /// <param name="resourceName"></param> 404 /// <param name="arg0"></param> 405 /// <param name="arg1"></param> 406 /// <param name="arg2"></param> 407 /// <param name="arg3"></param> VerifyThrowInvalidOperation( bool condition, string resourceName, object arg0, object arg1, object arg2, object arg3 )408 internal static void VerifyThrowInvalidOperation 409 ( 410 bool condition, 411 string resourceName, 412 object arg0, 413 object arg1, 414 object arg2, 415 object arg3 416 ) 417 { 418 // PERF NOTE: check the condition here instead of pushing it into 419 // the ThrowInvalidOperation() method, because that method always 420 // allocates memory for its variable array of arguments 421 if (!condition) 422 { 423 ThrowInvalidOperation(resourceName, arg0, arg1, arg2, arg3); 424 } 425 } 426 427 #endregion 428 429 #region VerifyThrowArgument 430 431 /// <summary> 432 /// Throws an ArgumentException that can include an inner exception. 433 /// 434 /// PERF WARNING: calling a method that takes a variable number of arguments 435 /// is expensive, because memory is allocated for the array of arguments -- do 436 /// not call this method repeatedly in performance-critical scenarios 437 /// </summary> ThrowArgument( string resourceName, params object[] args )438 internal static void ThrowArgument 439 ( 440 string resourceName, 441 params object[] args 442 ) 443 { 444 ThrowArgument(null, resourceName, args); 445 } 446 447 /// <summary> 448 /// Throws an ArgumentException that can include an inner exception. 449 /// 450 /// PERF WARNING: calling a method that takes a variable number of arguments 451 /// is expensive, because memory is allocated for the array of arguments -- do 452 /// not call this method repeatedly in performance-critical scenarios 453 /// </summary> 454 /// <remarks> 455 /// This method is thread-safe. 456 /// </remarks> 457 /// <param name="innerException">Can be null.</param> 458 /// <param name="resourceName"></param> 459 /// <param name="args"></param> ThrowArgument( Exception innerException, string resourceName, params object[] args )460 private static void ThrowArgument 461 ( 462 Exception innerException, 463 string resourceName, 464 params object[] args 465 ) 466 { 467 #if DEBUG 468 ResourceUtilities.VerifyResourceStringExists(resourceName); 469 #endif 470 if (s_throwExceptions) 471 { 472 throw new ArgumentException(ResourceUtilities.FormatResourceString(resourceName, args), innerException); 473 } 474 } 475 476 /// <summary> 477 /// Throws an ArgumentException if the given condition is false. 478 /// </summary> 479 /// <remarks>This method is thread-safe.</remarks> 480 /// <param name="condition"></param> 481 /// <param name="resourceName"></param> VerifyThrowArgument( bool condition, string resourceName )482 internal static void VerifyThrowArgument 483 ( 484 bool condition, 485 string resourceName 486 ) 487 { 488 VerifyThrowArgument(condition, null, resourceName); 489 } 490 491 /// <summary> 492 /// Overload for one string format argument. 493 /// </summary> 494 /// <remarks>This method is thread-safe.</remarks> 495 /// <param name="condition"></param> 496 /// <param name="resourceName"></param> 497 /// <param name="arg0"></param> VerifyThrowArgument( bool condition, string resourceName, object arg0 )498 internal static void VerifyThrowArgument 499 ( 500 bool condition, 501 string resourceName, 502 object arg0 503 ) 504 { 505 VerifyThrowArgument(condition, null, resourceName, arg0); 506 } 507 508 /// <summary> 509 /// Overload for two string format arguments. 510 /// </summary> 511 /// <remarks>This method is thread-safe.</remarks> 512 /// <param name="condition"></param> 513 /// <param name="resourceName"></param> 514 /// <param name="arg0"></param> 515 /// <param name="arg1"></param> VerifyThrowArgument( bool condition, string resourceName, object arg0, object arg1 )516 internal static void VerifyThrowArgument 517 ( 518 bool condition, 519 string resourceName, 520 object arg0, 521 object arg1 522 ) 523 { 524 VerifyThrowArgument(condition, null, resourceName, arg0, arg1); 525 } 526 527 /// <summary> 528 /// Overload for three string format arguments. 529 /// </summary> 530 /// <remarks>This method is thread-safe.</remarks> VerifyThrowArgument( bool condition, string resourceName, object arg0, object arg1, object arg2 )531 internal static void VerifyThrowArgument 532 ( 533 bool condition, 534 string resourceName, 535 object arg0, 536 object arg1, 537 object arg2 538 ) 539 { 540 VerifyThrowArgument(condition, null, resourceName, arg0, arg1, arg2); 541 } 542 543 /// <summary> 544 /// Overload for four string format arguments. 545 /// </summary> 546 /// <remarks>This method is thread-safe.</remarks> VerifyThrowArgument( bool condition, string resourceName, object arg0, object arg1, object arg2, object arg3 )547 internal static void VerifyThrowArgument 548 ( 549 bool condition, 550 string resourceName, 551 object arg0, 552 object arg1, 553 object arg2, 554 object arg3 555 ) 556 { 557 VerifyThrowArgument(condition, null, resourceName, arg0, arg1, arg2, arg3); 558 } 559 560 /// <summary> 561 /// Throws an ArgumentException that includes an inner exception, if 562 /// the given condition is false. 563 /// </summary> 564 /// <remarks>This method is thread-safe.</remarks> 565 /// <param name="condition"></param> 566 /// <param name="innerException">Can be null.</param> 567 /// <param name="resourceName"></param> VerifyThrowArgument( bool condition, Exception innerException, string resourceName )568 internal static void VerifyThrowArgument 569 ( 570 bool condition, 571 Exception innerException, 572 string resourceName 573 ) 574 { 575 if (!condition) 576 { 577 // PERF NOTE: explicitly passing null for the arguments array 578 // prevents memory allocation 579 ThrowArgument(innerException, resourceName, null); 580 } 581 } 582 583 /// <summary> 584 /// Overload for one string format argument. 585 /// </summary> 586 /// <remarks>This method is thread-safe.</remarks> 587 /// <param name="condition"></param> 588 /// <param name="innerException"></param> 589 /// <param name="resourceName"></param> 590 /// <param name="arg0"></param> VerifyThrowArgument( bool condition, Exception innerException, string resourceName, object arg0 )591 internal static void VerifyThrowArgument 592 ( 593 bool condition, 594 Exception innerException, 595 string resourceName, 596 object arg0 597 ) 598 { 599 // PERF NOTE: check the condition here instead of pushing it into 600 // the ThrowArgument() method, because that method always allocates 601 // memory for its variable array of arguments 602 if (!condition) 603 { 604 ThrowArgument(innerException, resourceName, arg0); 605 } 606 } 607 608 /// <summary> 609 /// Overload for two string format arguments. 610 /// </summary> 611 /// <remarks>This method is thread-safe.</remarks> 612 /// <param name="condition"></param> 613 /// <param name="innerException"></param> 614 /// <param name="resourceName"></param> 615 /// <param name="arg0"></param> 616 /// <param name="arg1"></param> VerifyThrowArgument( bool condition, Exception innerException, string resourceName, object arg0, object arg1 )617 internal static void VerifyThrowArgument 618 ( 619 bool condition, 620 Exception innerException, 621 string resourceName, 622 object arg0, 623 object arg1 624 ) 625 { 626 // PERF NOTE: check the condition here instead of pushing it into 627 // the ThrowArgument() method, because that method always allocates 628 // memory for its variable array of arguments 629 if (!condition) 630 { 631 ThrowArgument(innerException, resourceName, arg0, arg1); 632 } 633 } 634 635 /// <summary> 636 /// Overload for three string format arguments. 637 /// </summary> 638 /// <remarks>This method is thread-safe.</remarks> VerifyThrowArgument( bool condition, Exception innerException, string resourceName, object arg0, object arg1, object arg2 )639 internal static void VerifyThrowArgument 640 ( 641 bool condition, 642 Exception innerException, 643 string resourceName, 644 object arg0, 645 object arg1, 646 object arg2 647 ) 648 { 649 // PERF NOTE: check the condition here instead of pushing it into 650 // the ThrowArgument() method, because that method always allocates 651 // memory for its variable array of arguments 652 if (!condition) 653 { 654 ThrowArgument(innerException, resourceName, arg0, arg1, arg2); 655 } 656 } 657 658 /// <summary> 659 /// Overload for four string format arguments. 660 /// </summary> 661 /// <remarks>This method is thread-safe.</remarks> VerifyThrowArgument( bool condition, Exception innerException, string resourceName, object arg0, object arg1, object arg2, object arg3 )662 internal static void VerifyThrowArgument 663 ( 664 bool condition, 665 Exception innerException, 666 string resourceName, 667 object arg0, 668 object arg1, 669 object arg2, 670 object arg3 671 ) 672 { 673 // PERF NOTE: check the condition here instead of pushing it into 674 // the ThrowArgument() method, because that method always allocates 675 // memory for its variable array of arguments 676 if (!condition) 677 { 678 ThrowArgument(innerException, resourceName, arg0, arg1, arg2, arg3); 679 } 680 } 681 682 #endregion 683 684 #region VerifyThrowArgumentXXX 685 686 /// <summary> 687 /// Throws an argument out of range exception. 688 /// </summary> ThrowArgumentOutOfRange(string parameterName)689 internal static void ThrowArgumentOutOfRange(string parameterName) 690 { 691 if (s_throwExceptions) 692 { 693 throw new ArgumentOutOfRangeException(parameterName); 694 } 695 } 696 697 /// <summary> 698 /// Throws an ArgumentOutOfRangeException using the given parameter name 699 /// if the condition is false. 700 /// </summary> VerifyThrowArgumentOutOfRange(bool condition, string parameterName)701 internal static void VerifyThrowArgumentOutOfRange(bool condition, string parameterName) 702 { 703 if (!condition) 704 { 705 ThrowArgumentOutOfRange(parameterName); 706 } 707 } 708 709 /// <summary> 710 /// Throws an ArgumentNullException if the given string parameter is null 711 /// and ArgumentException if it has zero length. 712 /// </summary> 713 /// <param name="parameter"></param> 714 /// <param name="parameterName"></param> VerifyThrowArgumentLength(string parameter, string parameterName)715 internal static void VerifyThrowArgumentLength(string parameter, string parameterName) 716 { 717 VerifyThrowArgumentNull(parameter, parameterName); 718 719 if (parameter.Length == 0 && s_throwExceptions) 720 { 721 throw new ArgumentException(ResourceUtilities.FormatResourceString("Shared.ParameterCannotHaveZeroLength", parameterName)); 722 } 723 } 724 725 /// <summary> 726 /// Throws an ArgumentNullException if the given string parameter is null 727 /// and ArgumentException if it has zero length. 728 /// </summary> 729 /// <param name="parameter"></param> 730 /// <param name="parameterName"></param> VerifyThrowArgumentInvalidPath(string parameter, string parameterName)731 internal static void VerifyThrowArgumentInvalidPath(string parameter, string parameterName) 732 { 733 VerifyThrowArgumentNull(parameter, parameterName); 734 735 if (FileUtilities.PathIsInvalid(parameter) && s_throwExceptions) 736 { 737 throw new ArgumentException(ResourceUtilities.FormatResourceString("Shared.ParameterCannotHaveInvalidPathChars", parameterName, parameter)); 738 } 739 } 740 741 /// <summary> 742 /// Throws an ArgumentException if the string has zero length, unless it is 743 /// null, in which case no exception is thrown. 744 /// </summary> VerifyThrowArgumentLengthIfNotNull(string parameter, string parameterName)745 internal static void VerifyThrowArgumentLengthIfNotNull(string parameter, string parameterName) 746 { 747 if (parameter != null && parameter.Length == 0 && s_throwExceptions) 748 { 749 throw new ArgumentException(ResourceUtilities.FormatResourceString("Shared.ParameterCannotHaveZeroLength", parameterName)); 750 } 751 } 752 753 /// <summary> 754 /// Throws an ArgumentNullException if the given parameter is null. 755 /// </summary> 756 /// <remarks>This method is thread-safe.</remarks> 757 /// <param name="parameter"></param> 758 /// <param name="parameterName"></param> VerifyThrowArgumentNull(object parameter, string parameterName)759 internal static void VerifyThrowArgumentNull(object parameter, string parameterName) 760 { 761 VerifyThrowArgumentNull(parameter, parameterName, "Shared.ParameterCannotBeNull"); 762 } 763 764 /// <summary> 765 /// Throws an ArgumentNullException if the given parameter is null. 766 /// </summary> 767 /// <remarks>This method is thread-safe.</remarks> VerifyThrowArgumentNull(object parameter, string parameterName, string resourceName)768 internal static void VerifyThrowArgumentNull(object parameter, string parameterName, string resourceName) 769 { 770 if (parameter == null && s_throwExceptions) 771 { 772 // Most ArgumentNullException overloads append its own rather clunky multi-line message. 773 // So use the one overload that doesn't. 774 throw new ArgumentNullException( 775 ResourceUtilities.FormatResourceString(resourceName, parameterName), 776 (Exception)null); 777 } 778 } 779 780 /// <summary> 781 /// Verifies the given arrays are not null and have the same length 782 /// </summary> 783 /// <param name="parameter1"></param> 784 /// <param name="parameter2"></param> 785 /// <param name="parameter1Name"></param> 786 /// <param name="parameter2Name"></param> VerifyThrowArgumentArraysSameLength(Array parameter1, Array parameter2, string parameter1Name, string parameter2Name)787 internal static void VerifyThrowArgumentArraysSameLength(Array parameter1, Array parameter2, string parameter1Name, string parameter2Name) 788 { 789 VerifyThrowArgumentNull(parameter1, parameter1Name); 790 VerifyThrowArgumentNull(parameter2, parameter2Name); 791 792 if (parameter1.Length != parameter2.Length && s_throwExceptions) 793 { 794 throw new ArgumentException(ResourceUtilities.FormatResourceString("Shared.ParametersMustHaveTheSameLength", parameter1Name, parameter2Name)); 795 } 796 } 797 798 #endregion 799 #endif 800 } 801 } 802