mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1003.md
1234 lines
49 KiB
C#
1234 lines
49 KiB
C#
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Management.Automation;
|
|
using System.Management.Automation.Internal;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using Dbg = System.Management.Automation.Diagnostics;
|
|
|
|
//
|
|
// Now define the set of commands for manipulating modules.
|
|
//
|
|
|
|
namespace Microsoft.PowerShell.Commands
|
|
{
|
|
#region New-ModuleManifest
|
|
/// <summary>
|
|
/// Cmdlet to create a new module manifest file.
|
|
/// </summary>
|
|
[Cmdlet(VerbsCommon.New, "ModuleManifest", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.Low,
|
|
HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2096487")]
|
|
[OutputType(typeof(string))]
|
|
public sealed class NewModuleManifestCommand : PSCmdlet
|
|
{
|
|
/// <summary>
|
|
/// Gets or sets the output path for the generated file.
|
|
/// </summary>
|
|
[Parameter(Mandatory = true, Position = 0)]
|
|
public string Path
|
|
{
|
|
get { return _path; }
|
|
|
|
set { _path = value; }
|
|
}
|
|
|
|
private string _path;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the list of files to load by default.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyCollection]
|
|
public object[] NestedModules
|
|
{
|
|
get { return _nestedModules; }
|
|
|
|
set { _nestedModules = value; }
|
|
}
|
|
|
|
private object[] _nestedModules;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the GUID in the manifest file.
|
|
/// </summary>
|
|
[Parameter]
|
|
public Guid Guid
|
|
{
|
|
get { return _guid; }
|
|
|
|
set { _guid = value; }
|
|
}
|
|
|
|
private Guid _guid = Guid.NewGuid();
|
|
|
|
/// <summary>
|
|
/// Gets or sets the author string in the manifest.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyString]
|
|
public string Author
|
|
{
|
|
get { return _author; }
|
|
|
|
set { _author = value; }
|
|
}
|
|
|
|
private string _author;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the company name in the manifest.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyString]
|
|
public string CompanyName
|
|
{
|
|
get { return _companyName; }
|
|
|
|
set { _companyName = value; }
|
|
}
|
|
|
|
private string _companyName = string.Empty;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the copyright string in the module manifest.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyString]
|
|
public string Copyright
|
|
{
|
|
get { return _copyright; }
|
|
|
|
set { _copyright = value; }
|
|
}
|
|
|
|
private string _copyright;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the root module.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyString]
|
|
[Alias("ModuleToProcess")]
|
|
public string RootModule
|
|
{
|
|
get { return _rootModule; }
|
|
|
|
set { _rootModule = value; }
|
|
}
|
|
|
|
private string _rootModule = null;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the module version.
|
|
/// </summary>
|
|
[Parameter]
|
|
[ValidateNotNull]
|
|
public Version ModuleVersion
|
|
{
|
|
get { return _moduleVersion; }
|
|
|
|
set { _moduleVersion = value; }
|
|
}
|
|
|
|
private Version _moduleVersion = new Version(0, 0, 1);
|
|
|
|
/// <summary>
|
|
/// Gets or sets the module description.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyString]
|
|
public string Description
|
|
{
|
|
get { return _description; }
|
|
|
|
set { _description = value; }
|
|
}
|
|
|
|
private string _description;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the ProcessorArchitecture required by this module.
|
|
/// </summary>
|
|
[Parameter]
|
|
public ProcessorArchitecture ProcessorArchitecture
|
|
{
|
|
get { return _processorArchitecture.HasValue ? _processorArchitecture.Value : ProcessorArchitecture.None; }
|
|
|
|
set { _processorArchitecture = value; }
|
|
}
|
|
|
|
private ProcessorArchitecture? _processorArchitecture = null;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the PowerShell version required by this module.
|
|
/// </summary>
|
|
[Parameter]
|
|
public Version PowerShellVersion
|
|
{
|
|
get { return _powerShellVersion; }
|
|
|
|
set { _powerShellVersion = value; }
|
|
}
|
|
|
|
private Version _powerShellVersion = null;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the CLR version required by the module.
|
|
/// </summary>
|
|
[Parameter]
|
|
public Version ClrVersion
|
|
{
|
|
get { return _ClrVersion; }
|
|
|
|
set { _ClrVersion = value; }
|
|
}
|
|
|
|
private Version _ClrVersion = null;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the version of .NET Framework required by the module.
|
|
/// </summary>
|
|
[Parameter]
|
|
public Version DotNetFrameworkVersion
|
|
{
|
|
get { return _DotNetFrameworkVersion; }
|
|
|
|
set { _DotNetFrameworkVersion = value; }
|
|
}
|
|
|
|
private Version _DotNetFrameworkVersion = null;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the name of PowerShell host required by the module.
|
|
/// </summary>
|
|
[Parameter]
|
|
public string PowerShellHostName
|
|
{
|
|
get { return _PowerShellHostName; }
|
|
|
|
set { _PowerShellHostName = value; }
|
|
}
|
|
|
|
private string _PowerShellHostName = null;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the version of PowerShell host required by the module.
|
|
/// </summary>
|
|
[Parameter]
|
|
public Version PowerShellHostVersion
|
|
{
|
|
get { return _PowerShellHostVersion; }
|
|
|
|
set { _PowerShellHostVersion = value; }
|
|
}
|
|
|
|
private Version _PowerShellHostVersion = null;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the list of Dependencies for the module.
|
|
/// </summary>
|
|
[Parameter]
|
|
[ArgumentTypeConverter(typeof(ModuleSpecification[]))]
|
|
public object[] RequiredModules
|
|
{
|
|
get { return _requiredModules; }
|
|
|
|
set { _requiredModules = value; }
|
|
}
|
|
|
|
private object[] _requiredModules;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the list of types files for the module.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyCollection]
|
|
public string[] TypesToProcess
|
|
{
|
|
get { return _types; }
|
|
|
|
set { _types = value; }
|
|
}
|
|
|
|
private string[] _types;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the list of formats files for the module.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyCollection]
|
|
public string[] FormatsToProcess
|
|
{
|
|
get { return _formats; }
|
|
|
|
set { _formats = value; }
|
|
}
|
|
|
|
private string[] _formats;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the list of ps1 scripts to run in the session state of the import-module invocation.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyCollection]
|
|
public string[] ScriptsToProcess
|
|
{
|
|
get { return _scripts; }
|
|
|
|
set { _scripts = value; }
|
|
}
|
|
|
|
private string[] _scripts;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the list of assemblies to load for this module.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyCollection]
|
|
public string[] RequiredAssemblies
|
|
{
|
|
get { return _requiredAssemblies; }
|
|
|
|
set { _requiredAssemblies = value; }
|
|
}
|
|
|
|
private string[] _requiredAssemblies;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the additional files used by this module.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyCollection]
|
|
public string[] FileList
|
|
{
|
|
get { return _miscFiles; }
|
|
|
|
set { _miscFiles = value; }
|
|
}
|
|
|
|
private string[] _miscFiles;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the list of other modules included with this module.
|
|
/// Like the RequiredModules key, this list can be a simple list of module names or a complex list of module hashtables.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyCollection]
|
|
[ArgumentTypeConverter(typeof(ModuleSpecification[]))]
|
|
public object[] ModuleList
|
|
{
|
|
get { return _moduleList; }
|
|
|
|
set { _moduleList = value; }
|
|
}
|
|
|
|
private object[] _moduleList;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the functions to export from this manifest.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyCollection]
|
|
public string[] FunctionsToExport
|
|
{
|
|
get { return _exportedFunctions; }
|
|
|
|
set { _exportedFunctions = value; }
|
|
}
|
|
|
|
private string[] _exportedFunctions;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the aliases to export from this manifest.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyCollection]
|
|
public string[] AliasesToExport
|
|
{
|
|
get { return _exportedAliases; }
|
|
|
|
set { _exportedAliases = value; }
|
|
}
|
|
|
|
private string[] _exportedAliases;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the variables to export from this manifest.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyCollection]
|
|
public string[] VariablesToExport
|
|
{
|
|
get { return _exportedVariables; }
|
|
|
|
set { _exportedVariables = value; }
|
|
}
|
|
|
|
private string[] _exportedVariables = new string[] { "*" };
|
|
|
|
/// <summary>
|
|
/// Gets or sets the cmdlets to export from this manifest.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyCollection]
|
|
public string[] CmdletsToExport
|
|
{
|
|
get { return _exportedCmdlets; }
|
|
|
|
set { _exportedCmdlets = value; }
|
|
}
|
|
|
|
private string[] _exportedCmdlets;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the dsc resources to export from this manifest.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyCollection]
|
|
public string[] DscResourcesToExport
|
|
{
|
|
get { return _dscResourcesToExport; }
|
|
|
|
set { _dscResourcesToExport = value; }
|
|
}
|
|
|
|
private string[] _dscResourcesToExport;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the compatible PSEditions of this module.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowEmptyCollection]
|
|
[ValidateSet("Desktop", "Core")]
|
|
public string[] CompatiblePSEditions
|
|
{
|
|
get { return _compatiblePSEditions; }
|
|
|
|
set { _compatiblePSEditions = value; }
|
|
}
|
|
|
|
private string[] _compatiblePSEditions;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the module-specific private data here.
|
|
/// </summary>
|
|
[Parameter(Mandatory = false)]
|
|
[AllowNull]
|
|
public object PrivateData
|
|
{
|
|
get { return _privateData; }
|
|
|
|
set { _privateData = value; }
|
|
}
|
|
|
|
private object _privateData;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the Tags.
|
|
/// </summary>
|
|
[Parameter(Mandatory = false)]
|
|
[ValidateNotNullOrEmpty]
|
|
public string[] Tags { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the ProjectUri.
|
|
/// </summary>
|
|
[Parameter(Mandatory = false)]
|
|
[ValidateNotNullOrEmpty]
|
|
public Uri ProjectUri { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the LicenseUri.
|
|
/// </summary>
|
|
[Parameter(Mandatory = false)]
|
|
[ValidateNotNullOrEmpty]
|
|
public Uri LicenseUri { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the IconUri.
|
|
/// </summary>
|
|
[Parameter(Mandatory = false)]
|
|
[ValidateNotNullOrEmpty]
|
|
public Uri IconUri { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the ReleaseNotes.
|
|
/// </summary>
|
|
[Parameter(Mandatory = false)]
|
|
[ValidateNotNullOrEmpty]
|
|
public string ReleaseNotes { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets whether or not the module is a prerelease.
|
|
/// </summary>
|
|
[Parameter]
|
|
[ValidateNotNullOrEmpty]
|
|
public string Prerelease { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets whether or not the module requires explicit user acceptance for install/update/save.
|
|
/// </summary>
|
|
[Parameter]
|
|
public SwitchParameter RequireLicenseAcceptance { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the external module dependencies.
|
|
/// </summary>
|
|
[Parameter]
|
|
[ValidateNotNullOrEmpty]
|
|
public string[] ExternalModuleDependencies { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the HelpInfo URI.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowNull]
|
|
public string HelpInfoUri
|
|
{
|
|
get { return _helpInfoUri; }
|
|
|
|
set { _helpInfoUri = value; }
|
|
}
|
|
|
|
private string _helpInfoUri;
|
|
|
|
/// <summary>
|
|
/// Gets or sets whether the module manifest string should go to the output stream.
|
|
/// </summary>
|
|
[Parameter]
|
|
public SwitchParameter PassThru
|
|
{
|
|
get { return (SwitchParameter)_passThru; }
|
|
|
|
set { _passThru = value; }
|
|
}
|
|
|
|
private bool _passThru;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the Default Command Prefix.
|
|
/// </summary>
|
|
[Parameter]
|
|
[AllowNull]
|
|
public string DefaultCommandPrefix
|
|
{
|
|
get { return _defaultCommandPrefix; }
|
|
|
|
set { _defaultCommandPrefix = value; }
|
|
}
|
|
|
|
private string _defaultCommandPrefix;
|
|
|
|
private string _indent = string.Empty;
|
|
|
|
/// <summary>
|
|
/// Return a single-quoted string. Any embedded single quotes will be doubled.
|
|
/// </summary>
|
|
/// <param name="name">The string to quote.</param>
|
|
/// <returns>The quoted string.</returns>
|
|
private static string QuoteName(string name)
|
|
{
|
|
if (name == null)
|
|
return "''";
|
|
return ("'" + name.Replace("'", "''") + "'");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return a single-quoted string using the AbsoluteUri member to ensure it is escaped correctly.
|
|
/// </summary>
|
|
/// <param name="name">The Uri to quote.</param>
|
|
/// <returns>The quoted AbsoluteUri.</returns>
|
|
private static string QuoteName(Uri name)
|
|
{
|
|
if (name == null)
|
|
return "''";
|
|
return QuoteName(name.AbsoluteUri);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return a single-quoted string from a Version object.
|
|
/// </summary>
|
|
/// <param name="name">The Version object to quote.</param>
|
|
/// <returns>The quoted Version string.</returns>
|
|
private static string QuoteName(Version name)
|
|
{
|
|
if (name == null)
|
|
return "''";
|
|
return QuoteName(name.ToString());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Takes a collection of strings and returns the collection
|
|
/// quoted.
|
|
/// </summary>
|
|
/// <param name="names">The list to quote.</param>
|
|
/// <param name="streamWriter">Streamwriter to get end of line character from.</param>
|
|
/// <returns>The quoted list.</returns>
|
|
private static string QuoteNames(IEnumerable names, StreamWriter streamWriter)
|
|
{
|
|
if (names == null)
|
|
return "@()";
|
|
|
|
StringBuilder result = new StringBuilder();
|
|
|
|
int offset = 15;
|
|
bool first = true;
|
|
foreach (string name in names)
|
|
{
|
|
if (!string.IsNullOrEmpty(name))
|
|
{
|
|
if (first)
|
|
{
|
|
first = false;
|
|
}
|
|
else
|
|
{
|
|
result.Append(", ");
|
|
}
|
|
|
|
string quotedString = QuoteName(name);
|
|
offset += quotedString.Length;
|
|
if (offset > 80)
|
|
{
|
|
result.Append(streamWriter.NewLine);
|
|
result.Append(" ");
|
|
offset = 15 + quotedString.Length;
|
|
}
|
|
|
|
result.Append(quotedString);
|
|
}
|
|
}
|
|
|
|
if (result.Length == 0)
|
|
return "@()";
|
|
|
|
return result.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// This function is created to PreProcess -NestedModules in Win8.
|
|
/// In Win7, -NestedModules is of type string[]. In Win8, we changed
|
|
/// this to object[] to support module specification using hashtable.
|
|
/// To be backward compatible, this function calls ToString() on any
|
|
/// object that is not of type hashtable or string.
|
|
/// </summary>
|
|
/// <param name="moduleSpecs"></param>
|
|
/// <returns></returns>
|
|
private static IEnumerable PreProcessModuleSpec(IEnumerable moduleSpecs)
|
|
{
|
|
if (moduleSpecs != null)
|
|
{
|
|
foreach (object spec in moduleSpecs)
|
|
{
|
|
if (spec is not Hashtable)
|
|
{
|
|
yield return spec.ToString();
|
|
}
|
|
else
|
|
{
|
|
yield return spec;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Takes a collection of "module specifications" (string or hashtable)
|
|
/// and returns the collection as a string that can be inserted into a module manifest.
|
|
/// </summary>
|
|
/// <param name="moduleSpecs">The list to quote.</param>
|
|
/// <param name="streamWriter">Streamwriter to get end of line character from.</param>
|
|
/// <returns>The quoted list.</returns>
|
|
private static string QuoteModules(IEnumerable moduleSpecs, StreamWriter streamWriter)
|
|
{
|
|
StringBuilder result = new StringBuilder();
|
|
result.Append("@(");
|
|
|
|
if (moduleSpecs != null)
|
|
{
|
|
bool firstModule = true;
|
|
foreach (object spec in moduleSpecs)
|
|
{
|
|
if (spec == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ModuleSpecification moduleSpecification = (ModuleSpecification)LanguagePrimitives.ConvertTo(
|
|
spec,
|
|
typeof(ModuleSpecification),
|
|
CultureInfo.InvariantCulture);
|
|
|
|
if (!firstModule)
|
|
{
|
|
result.Append(", ");
|
|
result.Append(streamWriter.NewLine);
|
|
result.Append(" ");
|
|
}
|
|
|
|
firstModule = false;
|
|
|
|
if ((moduleSpecification.Guid == null) && (moduleSpecification.Version == null) && (moduleSpecification.MaximumVersion == null) && (moduleSpecification.RequiredVersion == null))
|
|
{
|
|
result.Append(QuoteName(moduleSpecification.Name));
|
|
}
|
|
else
|
|
{
|
|
result.Append("@{");
|
|
|
|
result.Append("ModuleName = ");
|
|
result.Append(QuoteName(moduleSpecification.Name));
|
|
result.Append("; ");
|
|
|
|
if (moduleSpecification.Guid != null)
|
|
{
|
|
result.Append("GUID = ");
|
|
result.Append(QuoteName(moduleSpecification.Guid.ToString()));
|
|
result.Append("; ");
|
|
}
|
|
|
|
if (moduleSpecification.Version != null)
|
|
{
|
|
result.Append("ModuleVersion = ");
|
|
result.Append(QuoteName(moduleSpecification.Version.ToString()));
|
|
result.Append("; ");
|
|
}
|
|
|
|
if (moduleSpecification.MaximumVersion != null)
|
|
{
|
|
result.Append("MaximumVersion = ");
|
|
result.Append(QuoteName(moduleSpecification.MaximumVersion));
|
|
result.Append("; ");
|
|
}
|
|
|
|
if (moduleSpecification.RequiredVersion != null)
|
|
{
|
|
result.Append("RequiredVersion = ");
|
|
result.Append(QuoteName(moduleSpecification.RequiredVersion.ToString()));
|
|
result.Append("; ");
|
|
}
|
|
|
|
result.Append('}');
|
|
}
|
|
}
|
|
}
|
|
|
|
result.Append(')');
|
|
return result.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Takes a collection of file names and returns the collection
|
|
/// quoted.
|
|
/// </summary>
|
|
/// <param name="names">The list to quote.</param>
|
|
/// <param name="streamWriter">Streamwriter to get end of line character from.</param>
|
|
/// <returns>The quoted list.</returns>
|
|
private string QuoteFiles(IEnumerable names, StreamWriter streamWriter)
|
|
{
|
|
List<string> resolvedPaths = new List<string>();
|
|
|
|
if (names != null)
|
|
{
|
|
foreach (string name in names)
|
|
{
|
|
if (!string.IsNullOrEmpty(name))
|
|
{
|
|
foreach (string path in TryResolveFilePath(name))
|
|
{
|
|
resolvedPaths.Add(path);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return QuoteNames(resolvedPaths, streamWriter);
|
|
}
|
|
|
|
///// <summary>
|
|
///// Takes a collection of file names and returns the collection
|
|
///// quoted. It does not expand wildcard to actual files (as QuoteFiles does).
|
|
///// It throws an error when the entered filename is different than the allowedExtension.
|
|
///// If any file name falls outside the directory tree basPath a warning is issued.
|
|
///// </summary>
|
|
///// <param name="basePath">This is the path which will be used to determine whether a warning is to be displayed.</param>
|
|
///// <param name="names">The list to quote</param>
|
|
///// <param name="allowedExtension">This is the allowed file extension, any other extension will give an error.</param>
|
|
///// <param name="streamWriter">Streamwriter to get end of line character from</param>
|
|
///// <param name="item">The item of the manifest file for which names are being resolved.</param>
|
|
///// <returns>The quoted list.</returns>
|
|
// private string QuoteFilesWithWildcard(string basePath, IEnumerable names, string allowedExtension, StreamWriter streamWriter, string item)
|
|
// {
|
|
// if (names != null)
|
|
// {
|
|
// foreach (string name in names)
|
|
// {
|
|
// if (string.IsNullOrEmpty(name))
|
|
// continue;
|
|
|
|
// string fileName = name;
|
|
|
|
// string extension = System.IO.Path.GetExtension(fileName);
|
|
// if (string.Equals(extension, allowedExtension, StringComparison.OrdinalIgnoreCase))
|
|
// {
|
|
// string drive = string.Empty;
|
|
// if (!SessionState.Path.IsPSAbsolute(fileName, out drive) && !System.IO.Path.IsPathRooted(fileName))
|
|
// {
|
|
// fileName = SessionState.Path.Combine(SessionState.Path.CurrentLocation.ProviderPath, fileName);
|
|
// }
|
|
|
|
// string basePathDir = System.IO.Path.GetDirectoryName(SessionState.Path.GetUnresolvedProviderPathFromPSPath(basePath));
|
|
// if (basePathDir[basePathDir.Length - 1] != StringLiterals.DefaultPathSeparator)
|
|
// {
|
|
// basePathDir += StringLiterals.DefaultPathSeparator;
|
|
// }
|
|
// string fileDir = null;
|
|
|
|
// // Call to SessionState.Path.GetUnresolvedProviderPathFromPSPath throws an exception
|
|
// // when the drive in the path does not exist.
|
|
// // Based on the exception it is obvious that the path is outside the basePath, because
|
|
// // basePath must always exist.
|
|
// try
|
|
// {
|
|
// fileDir = System.IO.Path.GetDirectoryName(SessionState.Path.GetUnresolvedProviderPathFromPSPath(fileName));
|
|
// if (fileDir[fileDir.Length - 1] != StringLiterals.DefaultPathSeparator)
|
|
// {
|
|
// fileDir += StringLiterals.DefaultPathSeparator;
|
|
// }
|
|
// }
|
|
// catch
|
|
// {
|
|
// }
|
|
|
|
// if (fileDir == null
|
|
// || !fileDir.StartsWith(basePathDir, StringComparison.OrdinalIgnoreCase))
|
|
// {
|
|
// WriteWarning(StringUtil.Format(Modules.IncludedItemPathFallsOutsideSaveTree, name,
|
|
// fileDir ?? name, item));
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// string message = StringUtil.Format(Modules.InvalidWorkflowExtension);
|
|
// InvalidOperationException invalidOp = new InvalidOperationException(message);
|
|
// ErrorRecord er = new ErrorRecord(invalidOp, "Modules_InvalidWorkflowExtension",
|
|
// ErrorCategory.InvalidOperation, null);
|
|
// ThrowTerminatingError(er);
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// return QuoteNames(names, streamWriter);
|
|
// }
|
|
|
|
/// <summary>
|
|
/// Glob a set of files then resolve them to relative paths.
|
|
/// </summary>
|
|
/// <param name="filePath"></param>
|
|
/// <returns></returns>
|
|
private List<string> TryResolveFilePath(string filePath)
|
|
{
|
|
List<string> result = new List<string>();
|
|
ProviderInfo provider = null;
|
|
SessionState sessionState = Context.SessionState;
|
|
try
|
|
{
|
|
Collection<string> filePaths =
|
|
sessionState.Path.GetResolvedProviderPathFromPSPath(filePath, out provider);
|
|
|
|
// If the name doesn't resolve to something we can use, just return the unresolved name...
|
|
if (!provider.NameEquals(this.Context.ProviderNames.FileSystem) || filePaths == null || filePaths.Count < 1)
|
|
{
|
|
result.Add(filePath);
|
|
return result;
|
|
}
|
|
|
|
// Otherwise get the relative resolved path and trim the .\ or ./ because
|
|
// modules are always loaded relative to the manifest base directory.
|
|
foreach (string path in filePaths)
|
|
{
|
|
string adjustedPath = SessionState.Path.NormalizeRelativePath(path,
|
|
SessionState.Path.CurrentLocation.ProviderPath);
|
|
if (adjustedPath.StartsWith(".\\", StringComparison.OrdinalIgnoreCase) ||
|
|
adjustedPath.StartsWith("./", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
adjustedPath = adjustedPath.Substring(2);
|
|
}
|
|
|
|
result.Add(adjustedPath);
|
|
}
|
|
}
|
|
catch (ItemNotFoundException)
|
|
{
|
|
result.Add(filePath);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// This routine builds a fragment of the module manifest file
|
|
/// for a particular key. It returns a formatted string that includes
|
|
/// a comment describing the key as well as the key and its value.
|
|
/// </summary>
|
|
/// <param name="key">The manifest key to use.</param>
|
|
/// <param name="resourceString">ResourceString that holds the message.</param>
|
|
/// <param name="value">The formatted manifest fragment.</param>
|
|
/// <param name="streamWriter">Streamwriter to get end of line character from.</param>
|
|
/// <returns></returns>
|
|
private string ManifestFragment(string key, string resourceString, string value, StreamWriter streamWriter)
|
|
{
|
|
return string.Format(CultureInfo.InvariantCulture, "{0}# {1}{2}{0}{3:19} = {4}{2}{2}",
|
|
_indent, resourceString, streamWriter.NewLine, key, value);
|
|
}
|
|
|
|
private string ManifestFragmentForNonSpecifiedManifestMember(string key, string resourceString, string value, StreamWriter streamWriter)
|
|
{
|
|
return string.Format(CultureInfo.InvariantCulture, "{0}# {1}{2}{0}# {3:19} = {4}{2}{2}",
|
|
_indent, resourceString, streamWriter.NewLine, key, value);
|
|
}
|
|
|
|
private static string ManifestComment(string insert, StreamWriter streamWriter)
|
|
{
|
|
// Prefix a non-empty string with a space for formatting reasons...
|
|
if (!string.IsNullOrEmpty(insert))
|
|
{
|
|
insert = " " + insert;
|
|
}
|
|
|
|
return string.Format(CultureInfo.InvariantCulture, "#{0}{1}", insert, streamWriter.NewLine);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate the module manifest...
|
|
/// </summary>
|
|
protected override void EndProcessing()
|
|
{
|
|
// Win8: 264471 - Error message for New-ModuleManifest -ProcessorArchitecture is obsolete.
|
|
// If an undefined value is passed for the ProcessorArchitecture parameter, the error message from parameter binder includes all the values from the enum.
|
|
// The value 'IA64' for ProcessorArchitecture is not supported. But since we do not own the enum System.Reflection.ProcessorArchitecture, we cannot control the values in it.
|
|
// So, we add a separate check in our code to give an error if user specifies IA64
|
|
if (ProcessorArchitecture == ProcessorArchitecture.IA64)
|
|
{
|
|
string message = StringUtil.Format(Modules.InvalidProcessorArchitectureInManifest, ProcessorArchitecture);
|
|
InvalidOperationException ioe = new InvalidOperationException(message);
|
|
ErrorRecord er = new ErrorRecord(ioe, "Modules_InvalidProcessorArchitectureInManifest",
|
|
ErrorCategory.InvalidArgument, ProcessorArchitecture);
|
|
ThrowTerminatingError(er);
|
|
}
|
|
|
|
ProviderInfo provider = null;
|
|
PSDriveInfo drive;
|
|
string filePath = SessionState.Path.GetUnresolvedProviderPathFromPSPath(_path, out provider, out drive);
|
|
|
|
if (!provider.NameEquals(Context.ProviderNames.FileSystem) || !filePath.EndsWith(StringLiterals.PowerShellDataFileExtension, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
string message = StringUtil.Format(Modules.InvalidModuleManifestPath, _path);
|
|
InvalidOperationException ioe = new InvalidOperationException(message);
|
|
ErrorRecord er = new ErrorRecord(ioe, "Modules_InvalidModuleManifestPath",
|
|
ErrorCategory.InvalidArgument, _path);
|
|
ThrowTerminatingError(er);
|
|
}
|
|
|
|
// By default, we want to generate a module manifest the encourages the best practice of explicitly specifying
|
|
// the commands exported (even if it's an empty array.) Unfortunately, changing the default breaks automation
|
|
// (however unlikely, this cmdlet isn't really meant for automation). Instead of trying to detect interactive
|
|
// use (which is quite hard), we infer interactive use if none of RootModule/NestedModules/RequiredModules is
|
|
// specified - because the manifest needs to be edited to actually be of use in those cases.
|
|
//
|
|
// If one of these parameters has been specified, default back to the old behavior by specifying
|
|
// wildcards for exported commands that weren't specified on the command line.
|
|
if (_rootModule != null || _nestedModules != null || _requiredModules != null)
|
|
{
|
|
if (_exportedFunctions == null)
|
|
_exportedFunctions = new string[] { "*" };
|
|
if (_exportedAliases == null)
|
|
_exportedAliases = new string[] { "*" };
|
|
if (_exportedCmdlets == null)
|
|
_exportedCmdlets = new string[] { "*" };
|
|
}
|
|
|
|
ValidateUriParameterValue(ProjectUri, "ProjectUri");
|
|
ValidateUriParameterValue(LicenseUri, "LicenseUri");
|
|
ValidateUriParameterValue(IconUri, "IconUri");
|
|
if (_helpInfoUri != null)
|
|
{
|
|
ValidateUriParameterValue(new Uri(_helpInfoUri), "HelpInfoUri");
|
|
}
|
|
|
|
if (CompatiblePSEditions != null && (CompatiblePSEditions.Distinct(StringComparer.OrdinalIgnoreCase).Count() != CompatiblePSEditions.Length))
|
|
{
|
|
string message = StringUtil.Format(Modules.DuplicateEntriesInCompatiblePSEditions, string.Join(",", CompatiblePSEditions));
|
|
var ioe = new InvalidOperationException(message);
|
|
var er = new ErrorRecord(ioe, "Modules_DuplicateEntriesInCompatiblePSEditions", ErrorCategory.InvalidArgument, CompatiblePSEditions);
|
|
ThrowTerminatingError(er);
|
|
}
|
|
|
|
string action = StringUtil.Format(Modules.CreatingModuleManifestFile, filePath);
|
|
|
|
if (ShouldProcess(filePath, action))
|
|
{
|
|
if (string.IsNullOrEmpty(_author))
|
|
{
|
|
_author = Environment.UserName;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(_companyName))
|
|
{
|
|
_companyName = Modules.DefaultCompanyName;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(_copyright))
|
|
{
|
|
_copyright = StringUtil.Format(Modules.DefaultCopyrightMessage, _author);
|
|
}
|
|
|
|
FileStream fileStream;
|
|
StreamWriter streamWriter;
|
|
FileInfo readOnlyFileInfo;
|
|
|
|
// Now open the output file...
|
|
PathUtils.MasterStreamOpen(
|
|
cmdlet: this,
|
|
filePath: filePath,
|
|
resolvedEncoding: new UTF8Encoding(encoderShouldEmitUTF8Identifier: false),
|
|
defaultEncoding: false,
|
|
Append: false,
|
|
Force: false,
|
|
NoClobber: false,
|
|
fileStream: out fileStream,
|
|
streamWriter: out streamWriter,
|
|
readOnlyFileInfo: out readOnlyFileInfo,
|
|
isLiteralPath: false
|
|
);
|
|
|
|
try
|
|
{
|
|
StringBuilder result = new StringBuilder();
|
|
|
|
// Insert the formatted manifest header...
|
|
result.Append(ManifestComment(string.Empty, streamWriter));
|
|
result.Append(ManifestComment(StringUtil.Format(Modules.ManifestHeaderLine1, System.IO.Path.GetFileNameWithoutExtension(filePath)),
|
|
streamWriter));
|
|
result.Append(ManifestComment(string.Empty, streamWriter));
|
|
result.Append(ManifestComment(StringUtil.Format(Modules.ManifestHeaderLine2, _author),
|
|
streamWriter));
|
|
result.Append(ManifestComment(string.Empty, streamWriter));
|
|
result.Append(ManifestComment(StringUtil.Format(Modules.ManifestHeaderLine3, DateTime.Now.ToString("d", CultureInfo.CurrentCulture)),
|
|
streamWriter));
|
|
result.Append(ManifestComment(string.Empty, streamWriter));
|
|
result.Append(streamWriter.NewLine);
|
|
result.Append("@{");
|
|
result.Append(streamWriter.NewLine);
|
|
result.Append(streamWriter.NewLine);
|
|
|
|
if (_rootModule == null)
|
|
_rootModule = string.Empty;
|
|
|
|
BuildModuleManifest(result, nameof(RootModule), Modules.RootModule, !string.IsNullOrEmpty(_rootModule), () => QuoteName(_rootModule), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(ModuleVersion), Modules.ModuleVersion, _moduleVersion != null && !string.IsNullOrEmpty(_moduleVersion.ToString()), () => QuoteName(_moduleVersion), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(CompatiblePSEditions), Modules.CompatiblePSEditions, _compatiblePSEditions != null && _compatiblePSEditions.Length > 0, () => QuoteNames(_compatiblePSEditions, streamWriter), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(Modules.GUID), Modules.GUID, !string.IsNullOrEmpty(_guid.ToString()), () => QuoteName(_guid.ToString()), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(Author), Modules.Author, !string.IsNullOrEmpty(_author), () => QuoteName(Author), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(CompanyName), Modules.CompanyName, !string.IsNullOrEmpty(_companyName), () => QuoteName(_companyName), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(Copyright), Modules.Copyright, !string.IsNullOrEmpty(_copyright), () => QuoteName(_copyright), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(Description), Modules.Description, !string.IsNullOrEmpty(_description), () => QuoteName(_description), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(PowerShellVersion), Modules.PowerShellVersion, _powerShellVersion != null && !string.IsNullOrEmpty(_powerShellVersion.ToString()), () => QuoteName(_powerShellVersion), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(PowerShellHostName), Modules.PowerShellHostName, !string.IsNullOrEmpty(_PowerShellHostName), () => QuoteName(_PowerShellHostName), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(PowerShellHostVersion), Modules.PowerShellHostVersion, _PowerShellHostVersion != null && !string.IsNullOrEmpty(_PowerShellHostVersion.ToString()), () => QuoteName(_PowerShellHostVersion), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(DotNetFrameworkVersion), StringUtil.Format(Modules.DotNetFrameworkVersion, Modules.PrerequisiteForDesktopEditionOnly), _DotNetFrameworkVersion != null && !string.IsNullOrEmpty(_DotNetFrameworkVersion.ToString()), () => QuoteName(_DotNetFrameworkVersion), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(ClrVersion), StringUtil.Format(Modules.CLRVersion, Modules.PrerequisiteForDesktopEditionOnly), _ClrVersion != null && !string.IsNullOrEmpty(_ClrVersion.ToString()), () => QuoteName(_ClrVersion), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(ProcessorArchitecture), Modules.ProcessorArchitecture, _processorArchitecture.HasValue, () => QuoteName(_processorArchitecture.ToString()), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(RequiredModules), Modules.RequiredModules, _requiredModules != null && _requiredModules.Length > 0, () => QuoteModules(_requiredModules, streamWriter), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(RequiredAssemblies), Modules.RequiredAssemblies, _requiredAssemblies != null, () => QuoteFiles(_requiredAssemblies, streamWriter), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(ScriptsToProcess), Modules.ScriptsToProcess, _scripts != null, () => QuoteFiles(_scripts, streamWriter), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(TypesToProcess), Modules.TypesToProcess, _types != null, () => QuoteFiles(_types, streamWriter), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(FormatsToProcess), Modules.FormatsToProcess, _formats != null, () => QuoteFiles(_formats, streamWriter), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(NestedModules), Modules.NestedModules, _nestedModules != null, () => QuoteModules(PreProcessModuleSpec(_nestedModules), streamWriter), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(FunctionsToExport), Modules.FunctionsToExport, true, () => QuoteNames(_exportedFunctions, streamWriter), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(CmdletsToExport), Modules.CmdletsToExport, true, () => QuoteNames(_exportedCmdlets, streamWriter), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(VariablesToExport), Modules.VariablesToExport, _exportedVariables != null && _exportedVariables.Length > 0, () => QuoteNames(_exportedVariables, streamWriter), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(AliasesToExport), Modules.AliasesToExport, true, () => QuoteNames(_exportedAliases, streamWriter), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(DscResourcesToExport), Modules.DscResourcesToExport, _dscResourcesToExport != null && _dscResourcesToExport.Length > 0, () => QuoteNames(_dscResourcesToExport, streamWriter), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(ModuleList), Modules.ModuleList, _moduleList != null, () => QuoteModules(_moduleList, streamWriter), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(FileList), Modules.FileList, _miscFiles != null, () => QuoteFiles(_miscFiles, streamWriter), streamWriter);
|
|
|
|
BuildPrivateDataInModuleManifest(result, streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(Modules.HelpInfoURI), Modules.HelpInfoURI, !string.IsNullOrEmpty(_helpInfoUri), () => QuoteName((_helpInfoUri != null) ? new Uri(_helpInfoUri) : null), streamWriter);
|
|
|
|
BuildModuleManifest(result, nameof(DefaultCommandPrefix), Modules.DefaultCommandPrefix, !string.IsNullOrEmpty(_defaultCommandPrefix), () => QuoteName(_defaultCommandPrefix), streamWriter);
|
|
|
|
result.Append('}');
|
|
result.Append(streamWriter.NewLine);
|
|
result.Append(streamWriter.NewLine);
|
|
string strResult = result.ToString();
|
|
|
|
if (_passThru)
|
|
{
|
|
WriteObject(strResult);
|
|
}
|
|
|
|
streamWriter.Write(strResult);
|
|
}
|
|
finally
|
|
{
|
|
streamWriter.Dispose();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void BuildModuleManifest(StringBuilder result, string key, string keyDescription, bool hasValue, Func<string> action, StreamWriter streamWriter)
|
|
{
|
|
if (hasValue)
|
|
{
|
|
result.Append(ManifestFragment(key, keyDescription, action(), streamWriter));
|
|
}
|
|
else
|
|
{
|
|
result.Append(ManifestFragmentForNonSpecifiedManifestMember(key, keyDescription, action(), streamWriter));
|
|
}
|
|
}
|
|
|
|
// PrivateData format in manifest file when PrivateData value is a HashTable or not specified.
|
|
// <#
|
|
// # Private data to pass to the module specified in RootModule/ModuleToProcess
|
|
// PrivateData = @{
|
|
//
|
|
// PSData = @{
|
|
// # Tags of this module
|
|
// Tags = @()
|
|
// # LicenseUri of this module
|
|
// LicenseUri = ''
|
|
// # ProjectUri of this module
|
|
// ProjectUri = ''
|
|
// # IconUri of this module
|
|
// IconUri = ''
|
|
// # ReleaseNotes of this module
|
|
// ReleaseNotes = ''
|
|
// }# end of PSData hashtable
|
|
//
|
|
// # User's private data keys
|
|
//
|
|
// }# end of PrivateData hashtable
|
|
// #>
|
|
private void BuildPrivateDataInModuleManifest(StringBuilder result, StreamWriter streamWriter)
|
|
{
|
|
var privateDataHashTable = PrivateData as Hashtable;
|
|
bool specifiedPSDataProperties = !(Tags == null && ReleaseNotes == null && ProjectUri == null && IconUri == null && LicenseUri == null);
|
|
|
|
if (_privateData != null && privateDataHashTable == null)
|
|
{
|
|
if (specifiedPSDataProperties)
|
|
{
|
|
var ioe = new InvalidOperationException(Modules.PrivateDataValueTypeShouldBeHashTableError);
|
|
var er = new ErrorRecord(ioe, "PrivateDataValueTypeShouldBeHashTable", ErrorCategory.InvalidArgument, _privateData);
|
|
ThrowTerminatingError(er);
|
|
}
|
|
else
|
|
{
|
|
WriteWarning(Modules.PrivateDataValueTypeShouldBeHashTableWarning);
|
|
|
|
BuildModuleManifest(result, nameof(PrivateData), Modules.PrivateData, _privateData != null,
|
|
() => QuoteName((string)LanguagePrimitives.ConvertTo(_privateData, typeof(string), CultureInfo.InvariantCulture)),
|
|
streamWriter);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result.Append(ManifestComment(Modules.PrivateData, streamWriter));
|
|
result.Append("PrivateData = @{");
|
|
result.Append(streamWriter.NewLine);
|
|
|
|
result.Append(streamWriter.NewLine);
|
|
result.Append(" PSData = @{");
|
|
result.Append(streamWriter.NewLine);
|
|
result.Append(streamWriter.NewLine);
|
|
|
|
_indent = " ";
|
|
|
|
BuildModuleManifest(result, nameof(Tags), Modules.Tags, Tags != null && Tags.Length > 0, () => QuoteNames(Tags, streamWriter), streamWriter);
|
|
BuildModuleManifest(result, nameof(LicenseUri), Modules.LicenseUri, LicenseUri != null, () => QuoteName(LicenseUri), streamWriter);
|
|
BuildModuleManifest(result, nameof(ProjectUri), Modules.ProjectUri, ProjectUri != null, () => QuoteName(ProjectUri), streamWriter);
|
|
BuildModuleManifest(result, nameof(IconUri), Modules.IconUri, IconUri != null, () => QuoteName(IconUri), streamWriter);
|
|
BuildModuleManifest(result, nameof(ReleaseNotes), Modules.ReleaseNotes, !string.IsNullOrEmpty(ReleaseNotes), () => QuoteName(ReleaseNotes), streamWriter);
|
|
BuildModuleManifest(result, nameof(Prerelease), Modules.Prerelease, !string.IsNullOrEmpty(Prerelease), () => QuoteName(Prerelease), streamWriter);
|
|
BuildModuleManifest(result, nameof(RequireLicenseAcceptance), Modules.RequireLicenseAcceptance, RequireLicenseAcceptance.IsPresent, () => RequireLicenseAcceptance.IsPresent ? "$true" : "$false", streamWriter);
|
|
BuildModuleManifest(result, nameof(ExternalModuleDependencies), Modules.ExternalModuleDependencies, ExternalModuleDependencies != null && ExternalModuleDependencies.Length > 0, () => QuoteNames(ExternalModuleDependencies, streamWriter), streamWriter);
|
|
|
|
result.Append(" } ");
|
|
result.Append(ManifestComment(StringUtil.Format(Modules.EndOfManifestHashTable, "PSData"), streamWriter));
|
|
result.Append(streamWriter.NewLine);
|
|
|
|
_indent = " ";
|
|
if (privateDataHashTable != null)
|
|
{
|
|
result.Append(streamWriter.NewLine);
|
|
|
|
foreach (DictionaryEntry entry in privateDataHashTable)
|
|
{
|
|
result.Append(ManifestFragment(entry.Key.ToString(), entry.Key.ToString(), QuoteName((string)LanguagePrimitives.ConvertTo(entry.Value, typeof(string), CultureInfo.InvariantCulture)), streamWriter));
|
|
}
|
|
}
|
|
|
|
result.Append("} ");
|
|
result.Append(ManifestComment(StringUtil.Format(Modules.EndOfManifestHashTable, "PrivateData"), streamWriter));
|
|
|
|
_indent = string.Empty;
|
|
|
|
result.Append(streamWriter.NewLine);
|
|
}
|
|
}
|
|
|
|
private void ValidateUriParameterValue(Uri uri, string parameterName)
|
|
{
|
|
Dbg.Assert(!string.IsNullOrWhiteSpace(parameterName), "parameterName should not be null or whitespace");
|
|
|
|
if (uri != null && !Uri.IsWellFormedUriString(uri.AbsoluteUri, UriKind.Absolute))
|
|
{
|
|
var message = StringUtil.Format(Modules.InvalidParameterValue, uri);
|
|
var ioe = new InvalidOperationException(message);
|
|
var er = new ErrorRecord(ioe, "Modules_InvalidUri",
|
|
ErrorCategory.InvalidArgument, parameterName);
|
|
ThrowTerminatingError(er);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|