mirror of
https://github.com/aphrody-labs/PowerShell.git
synced 2026-10-17 12:45:47 +00:00
Integrate changes between [SD:717473] and [SD:725290]
This commit is contained in:
1 parent
2280bea11e
commit
0dd425da19
28 files changed
+790
-284
No files matched your search
@@ -32,7 +32,6 @@ namespace Microsoft.PackageManagement.Providers.Internal.Bootstrap {
|
|||||||
using Directory = System.IO.Directory;
|
using Directory = System.IO.Directory;
|
||||||
using ErrorCategory = PackageManagement.Internal.ErrorCategory;
|
using ErrorCategory = PackageManagement.Internal.ErrorCategory;
|
||||||
using File = System.IO.File;
|
using File = System.IO.File;
|
||||||
using System.IO.Compression;
|
|
||||||
|
|
||||||
public class BootstrapProvider {
|
public class BootstrapProvider {
|
||||||
private static readonly Dictionary<string, string[]> _features = new Dictionary<string, string[]> {
|
private static readonly Dictionary<string, string[]> _features = new Dictionary<string, string[]> {
|
||||||
@@ -324,127 +323,12 @@ namespace Microsoft.PackageManagement.Providers.Internal.Bootstrap {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Iso19770_2.MediaType.NuGetPackage:
|
|
||||||
return InstallNugetPackage(provider, link, fastPath, request);
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
request.Warning("Provider '{0}' with link '{1}' has unknown media type '{2}'.", provider.Name, link.HRef, link.MediaType);
|
request.Warning("Provider '{0}' with link '{1}' has unknown media type '{2}'.", provider.Name, link.HRef, link.MediaType);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool InstallNugetPackage(Package provider, Link link, string fastPath, BootstrapRequest request)
|
|
||||||
{
|
|
||||||
// download the nuget package
|
|
||||||
string downloadedNupkg = request.DownloadAndValidateFile(provider._swidtag);
|
|
||||||
|
|
||||||
if (downloadedNupkg != null)
|
|
||||||
{
|
|
||||||
// extracted folder
|
|
||||||
string extractedFolder = String.Concat(FilesystemExtensions.GenerateTemporaryFileOrDirectoryNameInTempDirectory());
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//unzip the file
|
|
||||||
ZipFile.ExtractToDirectory(downloadedNupkg, extractedFolder);
|
|
||||||
|
|
||||||
if (Directory.Exists(extractedFolder))
|
|
||||||
{
|
|
||||||
string versionFolder = Path.Combine(request.DestinationPath(request), provider.Name, provider.Version);
|
|
||||||
// tool folder is where we find things like nuget.exe
|
|
||||||
string toolFolder = Path.Combine(extractedFolder, "tools");
|
|
||||||
string libFolder = Path.Combine(extractedFolder, "lib");
|
|
||||||
|
|
||||||
// create the directory version folder if not exist
|
|
||||||
if (!Directory.Exists(versionFolder))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(versionFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy the tools directory
|
|
||||||
if (Directory.Exists(toolFolder))
|
|
||||||
{
|
|
||||||
string destinationToolFolder = Path.Combine(versionFolder, "tools");
|
|
||||||
|
|
||||||
if (!Directory.Exists(destinationToolFolder))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(destinationToolFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (string child in Directory.EnumerateFiles(toolFolder))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// try copy and overwrite
|
|
||||||
File.Copy(child, Path.Combine(destinationToolFolder, Path.GetFileName(child)), true);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
request.Debug(e.StackTrace);
|
|
||||||
if (!(e is UnauthorizedAccessException || e is IOException))
|
|
||||||
{
|
|
||||||
// something wrong, delete the version folder
|
|
||||||
versionFolder.TryHardToDelete();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise this means the file is just being used. so just moves on to copy other files
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy files from lib
|
|
||||||
if (Directory.Exists(libFolder))
|
|
||||||
{
|
|
||||||
// check that the lib folder has at most 1 dll
|
|
||||||
if (Directory.EnumerateFiles(libFolder).Count(file => String.Equals(Path.GetExtension(file), ".dll", StringComparison.OrdinalIgnoreCase)) > 1)
|
|
||||||
{
|
|
||||||
request.Warning(String.Format(CultureInfo.CurrentCulture, Resources.Messages.MoreThanOneDllExists, provider.Name));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (string child in Directory.EnumerateFiles(libFolder))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File.Copy(child, Path.Combine(versionFolder, Path.GetFileName(child)), true);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
request.Debug(e.StackTrace);
|
|
||||||
if (!(e is UnauthorizedAccessException || e is IOException))
|
|
||||||
{
|
|
||||||
// something wrong, delete the version folder
|
|
||||||
versionFolder.TryHardToDelete();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise this means the file is just being used. so just moves on to copy other files
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// target file name is the assembly provider
|
|
||||||
string targetFile = Path.Combine(versionFolder, Path.GetFileName(link.Attributes[Iso19770_2.Discovery.TargetFilename]));
|
|
||||||
|
|
||||||
if (File.Exists(targetFile))
|
|
||||||
{
|
|
||||||
request.Verbose(Resources.Messages.InstalledPackage, provider.Name, targetFile);
|
|
||||||
request.YieldFromSwidtag(provider, fastPath);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
downloadedNupkg.TryHardToDelete();
|
|
||||||
extractedFolder.TryHardToDelete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool InstallPackageFile(Package provider, string fastPath, BootstrapRequest request) {
|
private bool InstallPackageFile(Package provider, string fastPath, BootstrapRequest request) {
|
||||||
// we can download and verify this package and get the core to install it.
|
// we can download and verify this package and get the core to install it.
|
||||||
var file = request.DownloadAndValidateFile(provider._swidtag);
|
var file = request.DownloadAndValidateFile(provider._swidtag);
|
||||||
@@ -522,7 +406,6 @@ namespace Microsoft.PackageManagement.Providers.Internal.Bootstrap {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string targetFilename = fastPath;
|
string targetFilename = fastPath;
|
||||||
string file = fastPath;
|
string file = fastPath;
|
||||||
|
|
||||||
@@ -551,8 +434,15 @@ namespace Microsoft.PackageManagement.Providers.Internal.Bootstrap {
|
|||||||
//... providername\version\.dll
|
//... providername\version\.dll
|
||||||
var versionFolder = Path.Combine(request.DestinationPath(request), provider.Name, provider.Version);
|
var versionFolder = Path.Combine(request.DestinationPath(request), provider.Name, provider.Version);
|
||||||
|
|
||||||
if (!Directory.Exists(versionFolder)) {
|
// if version folder exists, remove it
|
||||||
//we create it
|
if (Directory.Exists(versionFolder))
|
||||||
|
{
|
||||||
|
RemoveDirectory(versionFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the directory if we successfully deleted it
|
||||||
|
if (!Directory.Exists(versionFolder))
|
||||||
|
{
|
||||||
Directory.CreateDirectory(versionFolder);
|
Directory.CreateDirectory(versionFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,12 +451,6 @@ namespace Microsoft.PackageManagement.Providers.Internal.Bootstrap {
|
|||||||
if (file != null) {
|
if (file != null) {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// looks good! let's keep it
|
|
||||||
if (File.Exists(targetFile)) {
|
|
||||||
request.Debug("Removing old file '{0}'", targetFile);
|
|
||||||
targetFile.TryHardToDelete();
|
|
||||||
}
|
|
||||||
|
|
||||||
// is that file still there?
|
// is that file still there?
|
||||||
if (File.Exists(targetFile)) {
|
if (File.Exists(targetFile)) {
|
||||||
request.Error(ErrorCategory.InvalidOperation, fastPath, Constants.Messages.UnableToRemoveFile, targetFile);
|
request.Error(ErrorCategory.InvalidOperation, fastPath, Constants.Messages.UnableToRemoveFile, targetFile);
|
||||||
@@ -575,8 +459,17 @@ namespace Microsoft.PackageManagement.Providers.Internal.Bootstrap {
|
|||||||
|
|
||||||
request.Debug("Copying file '{0}' to '{1}'", file, targetFile);
|
request.Debug("Copying file '{0}' to '{1}'", file, targetFile);
|
||||||
try {
|
try {
|
||||||
|
if (File.Exists(file))
|
||||||
|
{
|
||||||
|
// if this is a file
|
||||||
File.Copy(file, targetFile);
|
File.Copy(file, targetFile);
|
||||||
}
|
}
|
||||||
|
else if (Directory.Exists(file))
|
||||||
|
{
|
||||||
|
// if this is a directory, copy items over
|
||||||
|
CopyDirectory(file, versionFolder);
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
request.Debug(ex.StackTrace);
|
request.Debug(ex.StackTrace);
|
||||||
return false;
|
return false;
|
||||||
@@ -604,6 +497,56 @@ namespace Microsoft.PackageManagement.Providers.Internal.Bootstrap {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RemoveDirectory(string directoryFolder)
|
||||||
|
{
|
||||||
|
// remove all files
|
||||||
|
foreach (var fileToBeRemoved in Directory.EnumerateFiles(directoryFolder))
|
||||||
|
{
|
||||||
|
fileToBeRemoved.TryHardToDelete();
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove all subdirectories
|
||||||
|
foreach (var folderToBeRemoved in Directory.EnumerateDirectories(directoryFolder))
|
||||||
|
{
|
||||||
|
RemoveDirectory(folderToBeRemoved);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// now try to remove the directory
|
||||||
|
Directory.Delete(directoryFolder);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CopyDirectory(string sourceFolder, string destinationFolder)
|
||||||
|
{
|
||||||
|
// check that source and destination folders exist
|
||||||
|
if (!sourceFolder.DirectoryExists() || !destinationFolder.DirectoryExists())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy the files over
|
||||||
|
foreach (var file in Directory.EnumerateFiles(sourceFolder))
|
||||||
|
{
|
||||||
|
File.Copy(file, Path.Combine(destinationFolder, Path.GetFileName(file)), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy the directories over
|
||||||
|
foreach (var directory in Directory.EnumerateDirectories(sourceFolder))
|
||||||
|
{
|
||||||
|
var destinationDirName = Path.Combine(destinationFolder, Path.GetFileName(directory));
|
||||||
|
|
||||||
|
if (!Directory.Exists(destinationDirName))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(destinationDirName);
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyDirectory(directory, destinationDirName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void InstallPackageFromFile(string fastPath, BootstrapRequest request)
|
private void InstallPackageFromFile(string fastPath, BootstrapRequest request)
|
||||||
{
|
{
|
||||||
var filePath = new Uri(fastPath).LocalPath;
|
var filePath = new Uri(fastPath).LocalPath;
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ namespace Microsoft.PackageManagement.Providers.Internal.Bootstrap {
|
|||||||
using PackageManagement.Internal.Utility.Collections;
|
using PackageManagement.Internal.Utility.Collections;
|
||||||
using PackageManagement.Internal.Utility.Extensions;
|
using PackageManagement.Internal.Utility.Extensions;
|
||||||
using ErrorCategory = PackageManagement.Internal.ErrorCategory;
|
using ErrorCategory = PackageManagement.Internal.ErrorCategory;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using File = System.IO.File;
|
||||||
|
using Directory = System.IO.Directory;
|
||||||
|
|
||||||
public abstract class BootstrapRequest : Request {
|
public abstract class BootstrapRequest : Request {
|
||||||
internal Uri[] _urls
|
internal Uri[] _urls
|
||||||
@@ -201,6 +204,51 @@ namespace Microsoft.PackageManagement.Providers.Internal.Bootstrap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extract zipped package and return the unzipped folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="zippedPackagePath"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string ExtractZipPackage(string zippedPackagePath)
|
||||||
|
{
|
||||||
|
if (zippedPackagePath != null && zippedPackagePath.FileExists())
|
||||||
|
{
|
||||||
|
// extracted folder
|
||||||
|
string extractedFolder = FilesystemExtensions.GenerateTemporaryFileOrDirectoryNameInTempDirectory();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//unzip the file
|
||||||
|
ZipFile.ExtractToDirectory(zippedPackagePath, extractedFolder);
|
||||||
|
|
||||||
|
// extraction fails
|
||||||
|
if (!Directory.Exists(extractedFolder))
|
||||||
|
{
|
||||||
|
Verbose(string.Format(CultureInfo.CurrentCulture, Resources.Messages.FailToExtract, zippedPackagePath, extractedFolder));
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the zipped folder
|
||||||
|
var zippedDirectory = Directory.EnumerateDirectories(extractedFolder).FirstOrDefault();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(zippedDirectory) && Directory.Exists(zippedDirectory))
|
||||||
|
{
|
||||||
|
return zippedDirectory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Verbose(string.Format(CultureInfo.CurrentCulture, Resources.Messages.FailToInstallZipFolder, zippedPackagePath, ex.Message));
|
||||||
|
Debug(ex.StackTrace);
|
||||||
|
|
||||||
|
// remove the extracted folder
|
||||||
|
extractedFolder.TryHardToDelete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper function to retry downloading a file.
|
/// Helper function to retry downloading a file.
|
||||||
/// downloadFileFunction is the main function that is used to download the file when given a uri
|
/// downloadFileFunction is the main function that is used to download the file when given a uri
|
||||||
@@ -258,6 +306,21 @@ namespace Microsoft.PackageManagement.Providers.Internal.Bootstrap {
|
|||||||
|
|
||||||
// got a valid file!
|
// got a valid file!
|
||||||
if (file != null && file.FileExists()) {
|
if (file != null && file.FileExists()) {
|
||||||
|
// if file is zip, unpack it and return the unpacked folder
|
||||||
|
if (link.MediaType == Iso19770_2.MediaType.ZipPackage)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// let's extract the zipped file
|
||||||
|
return ExtractZipPackage(file);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// delete the zipped file
|
||||||
|
file.TryHardToDelete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
@@ -121,6 +121,16 @@
|
|||||||
<value>Fail to extract and copy to '{0}'.</value>
|
<value>Fail to extract and copy to '{0}'.</value>
|
||||||
<comment>0 - The directory we are copying to</comment>
|
<comment>0 - The directory we are copying to</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="FailToDeleteExistingFolder" xml:space="preserve">
|
||||||
|
<value>Cannot delete existing provider folder '{0}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="FailToExtract" xml:space="preserve">
|
||||||
|
<value>Cannot extract from '{0}' to '{1}'</value>
|
||||||
|
</data>
|
||||||
|
<data name="FailToInstallZipFolder" xml:space="preserve">
|
||||||
|
<value>Fail to extract zip package '{0}': '{1}'</value>
|
||||||
|
<comment>0 - package path, 1 - exception message</comment>
|
||||||
|
</data>
|
||||||
<data name="FindingPackage" xml:space="preserve">
|
<data name="FindingPackage" xml:space="preserve">
|
||||||
<value>Finding the package '{0}'.</value>
|
<value>Finding the package '{0}'.</value>
|
||||||
<comment>0 - package name</comment>
|
<comment>0 - package name</comment>
|
||||||
|
|||||||
@@ -240,7 +240,17 @@
|
|||||||
var partialManifestNameMatches = GetPackageFiles(partialManifestName).Where(
|
var partialManifestNameMatches = GetPackageFiles(partialManifestName).Where(
|
||||||
path => FileNameMatchesPattern(packageId, version, path));
|
path => FileNameMatchesPattern(packageId, version, path));
|
||||||
|
|
||||||
return filesMatchingFullName.Concat(partialNameMatches).Concat(partialManifestNameMatches);
|
filesMatchingFullName = filesMatchingFullName.Concat(partialNameMatches).Concat(partialManifestNameMatches);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cannot find matching files, we should try to search for just packageid.nupkg
|
||||||
|
if (filesMatchingFullName.Count() == 0)
|
||||||
|
{
|
||||||
|
// exclude version
|
||||||
|
var packageWithoutVersionName = FileUtility.MakePackageFileName(true, packageId, null, NuGetConstant.PackageExtension);
|
||||||
|
var packageWithoutVersionManifest = Path.ChangeExtension(packageWithoutVersionName, NuGetConstant.ManifestExtension);
|
||||||
|
|
||||||
|
return GetPackageFiles(packageWithoutVersionName).Concat(GetPackageFiles(packageWithoutVersionManifest));
|
||||||
}
|
}
|
||||||
|
|
||||||
return filesMatchingFullName;
|
return filesMatchingFullName;
|
||||||
|
|||||||
+1
-3
@@ -44,10 +44,8 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
request.Verbose("Package: '{0}'", exePackage);
|
request.Verbose("Package: '{0}'", exePackage);
|
||||||
|
|
||||||
// validate the file
|
// validate the file
|
||||||
if (!WebDownloader.PerformSecurityScan(exePackage))
|
if (!WebDownloader.VerifyHash(exePackage,package, request))
|
||||||
{
|
{
|
||||||
//TODO Security Scan work
|
|
||||||
request.WriteError(ErrorCategory.InvalidOperation, Constants.ProviderName, "The package download from '{0}' failed in the security scan.", package.Source);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+51
-1
@@ -180,6 +180,11 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
{
|
{
|
||||||
item.Common = common;
|
item.Common = common;
|
||||||
item.FilePath = packageSpecPath;
|
item.FilePath = packageSpecPath;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(item.Version))
|
||||||
|
{
|
||||||
|
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Messages.VersionNotFound, item.Name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
item.PackageSource = packageSource;
|
item.PackageSource = packageSource;
|
||||||
@@ -201,6 +206,11 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
convertedPackage.Common = new CommonDefinition();
|
convertedPackage.Common = new CommonDefinition();
|
||||||
|
|
||||||
|
if (String.IsNullOrWhiteSpace(convertedPackage.Version))
|
||||||
|
{
|
||||||
|
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Messages.VersionNotFound, convertedPackage.Name, packageSpecPath));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
convertedPackage.FilePath = packageSpecPath;
|
convertedPackage.FilePath = packageSpecPath;
|
||||||
@@ -249,6 +259,13 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
public List<string> installationOption { get; set; }
|
public List<string> installationOption { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class PackageHash
|
||||||
|
{
|
||||||
|
public string algorithm { get; set; }
|
||||||
|
public string hashCode { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public class CommonDefinition
|
public class CommonDefinition
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
@@ -291,10 +308,14 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
private bool _isPackageProvider;
|
private bool _isPackageProvider;
|
||||||
private string _installArguments;
|
private string _installArguments;
|
||||||
private string _unInstallAdditionalArguments;
|
private string _unInstallAdditionalArguments;
|
||||||
|
private string _source;
|
||||||
|
|
||||||
public CommonDefinition Common { get; set; }
|
public CommonDefinition Common { get; set; }
|
||||||
public string Version { get; set; }
|
public string Version { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public PackageHash Hash { get; set; }
|
||||||
|
|
||||||
public SemanticVersion SemVer
|
public SemanticVersion SemVer
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -306,7 +327,36 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public string Source { get; set; }
|
public string Source
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _source;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
Uri uri;
|
||||||
|
|
||||||
|
// check whether source is http instead of https
|
||||||
|
if (!Uri.TryCreate(value, UriKind.Absolute, out uri))
|
||||||
|
{
|
||||||
|
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Messages.UnsuportedUriFormat, Constants.ProviderName, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!uri.IsFile)
|
||||||
|
{
|
||||||
|
if (uri.Scheme != Uri.UriSchemeHttps)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Messages.UriSchemeNotSupported, uri.Scheme, Uri.UriSchemeHttps));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_source = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
|
|||||||
+92
-22
@@ -22,10 +22,12 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using System.Management.Automation;
|
using System.Management.Automation;
|
||||||
using Microsoft.PackageManagement.Provider.Utility;
|
using Microsoft.PackageManagement.Provider.Utility;
|
||||||
using PackageManagement.Packaging;
|
using PackageManagement.Packaging;
|
||||||
using ErrorCategory = PackageManagement.Internal.ErrorCategory;
|
using ErrorCategory = PackageManagement.Internal.ErrorCategory;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
public class PackageSourceListProvider {
|
public class PackageSourceListProvider {
|
||||||
|
|
||||||
@@ -37,6 +39,7 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
private const string RequiredPackageManagementVersion = "1.0.0.1";
|
private const string RequiredPackageManagementVersion = "1.0.0.1";
|
||||||
private static bool _doesPackageManagementVersionMatch = false;
|
private static bool _doesPackageManagementVersionMatch = false;
|
||||||
private static Version _currentPackageManagementVersion;
|
private static Version _currentPackageManagementVersion;
|
||||||
|
private static string _pslDirLocation = Path.Combine(Environment.GetEnvironmentVariable("appdata"), Constants.ProviderName);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The features that this package supports.
|
/// The features that this package supports.
|
||||||
@@ -125,6 +128,7 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
|
|
||||||
case "install":
|
case "install":
|
||||||
request.YieldDynamicOption("Scope", "String", false, new[] {"CurrentUser", "AllUsers"});
|
request.YieldDynamicOption("Scope", "String", false, new[] {"CurrentUser", "AllUsers"});
|
||||||
|
request.YieldDynamicOption("SkipHashValidation", Constants.OptionType.Switch, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,23 +193,16 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
request.Debug(Resources.Messages.DebugInfoCallMethod, PackageProviderName, "GetOptionValue");
|
// Set-PackageSource will update the existing package source. In that case IsUpdate = true.
|
||||||
// if this is supposed to be an update, there will be a dynamic parameter set for IsUpdatePackageSource
|
|
||||||
var isUpdate = request.GetOptionValue(Constants.Parameters.IsUpdate).IsTrue();
|
var isUpdate = request.GetOptionValue(Constants.Parameters.IsUpdate).IsTrue();
|
||||||
|
|
||||||
request.Debug(Resources.Messages.VariableCheck, "IsUpdate", isUpdate);
|
request.Debug(Resources.Messages.VariableCheck, "IsUpdate", isUpdate);
|
||||||
|
|
||||||
// if your source supports credentials you get get them too:
|
|
||||||
// string username =request.Username;
|
|
||||||
// SecureString password = request.Password;
|
|
||||||
// feel free to send back an error here if your provider requires credentials for package sources.
|
|
||||||
|
|
||||||
// check first that we're not clobbering an existing source, unless this is an update
|
// check first that we're not clobbering an existing source, unless this is an update
|
||||||
|
|
||||||
request.Debug(Resources.Messages.DebugInfoCallMethod, PackageProviderName, string.Format(CultureInfo.InvariantCulture, "FindRegisteredSource -name'{0}'", name));
|
request.Debug(Resources.Messages.DebugInfoCallMethod, PackageProviderName, string.Format(CultureInfo.InvariantCulture, "FindRegisteredSource -name'{0}'", name));
|
||||||
|
|
||||||
var src = request.FindRegisteredSource(name);
|
var src = request.FindRegisteredSource(name);
|
||||||
|
|
||||||
if (src != null && !isUpdate) {
|
if (src != null && !isUpdate) {
|
||||||
// tell the user that there's one here already
|
// tell the user that there's one here already
|
||||||
request.WriteError(ErrorCategory.InvalidArgument, name, Constants.Messages.PackageSourceExists, name);
|
request.WriteError(ErrorCategory.InvalidArgument, name, Constants.Messages.PackageSourceExists, name);
|
||||||
@@ -213,29 +210,72 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
// conversely, if it didn't find one, and it is an update, that's bad too:
|
// conversely, if it didn't find one, and it is an update, that's bad too:
|
||||||
if (src == null && isUpdate) {
|
if (src == null && isUpdate)
|
||||||
|
{
|
||||||
// you can't find that package source? Tell that to the user
|
// you can't find that package source? Tell that to the user
|
||||||
request.WriteError(ErrorCategory.ObjectNotFound, name, Constants.Messages.UnableToResolveSource, Constants.ProviderName, name);
|
request.WriteError(ErrorCategory.ObjectNotFound, name, Constants.Messages.UnableToResolveSource, name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ok, we know that we're ok to save this source
|
// ok, we know that we're ok to save this source
|
||||||
// next we check if the location is valid (if we support that kind of thing)
|
// next we check if the location is valid (if we support that kind of thing)
|
||||||
|
|
||||||
var validated = false;
|
var validated = false;
|
||||||
|
|
||||||
if (!request.SkipValidate.Value) {
|
|
||||||
// the user has not opted to skip validating the package source location, so check if the source is valid
|
|
||||||
validated = request.ValidateSourceLocation(location);
|
validated = request.ValidateSourceLocation(location);
|
||||||
|
|
||||||
if (!validated) {
|
if (!validated) {
|
||||||
request.WriteError(ErrorCategory.InvalidData, name, Constants.Messages.SourceLocationNotValid, location);
|
request.WriteError(ErrorCategory.InvalidData, name, Constants.Messages.SourceLocationNotValid, location);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
request.Verbose(Resources.Messages.SuccessfullyValidated, name);
|
request.Verbose(Resources.Messages.SuccessfullyValidated, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool force = request.GetOptionValue("Force") != null;
|
||||||
|
//if source is UNC location/ copy it to local path;
|
||||||
|
Uri uri;
|
||||||
|
if (Uri.TryCreate(location, UriKind.Absolute, out uri))
|
||||||
|
{
|
||||||
|
if (uri.IsFile && uri.IsUnc)
|
||||||
|
{
|
||||||
|
string fileName = Path.GetFileNameWithoutExtension(location);
|
||||||
|
string directory = Path.GetDirectoryName(location);
|
||||||
|
string catalogFilePath = Path.Combine(directory, fileName+".cat");
|
||||||
|
if (!File.Exists(catalogFilePath))
|
||||||
|
{
|
||||||
|
request.WriteError(ErrorCategory.InvalidData, location, Resources.Messages.CatalogFileMissing, location);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!TestCatalogFile(location, catalogFilePath, request))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (force || request.ShouldContinue(Resources.Messages.QueryDownloadPackageSourceList.format(location), Resources.Messages.PackageSourceListNotTrusted))
|
||||||
|
{
|
||||||
|
string destination = Path.Combine(_pslDirLocation, Path.GetFileName(uri.LocalPath));
|
||||||
|
if (File.Exists(destination))
|
||||||
|
{
|
||||||
|
if (force || request.ShouldContinue(Resources.Messages.OverwriteFile, Resources.Messages.FileExists))
|
||||||
|
{
|
||||||
|
File.Copy(location, destination, true);
|
||||||
|
location = destination;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
File.Copy(location, destination);
|
||||||
|
location = destination;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// it's good to check just before you actaully write something to see if the user has cancelled the operation
|
// it's good to check just before you actaully write something to see if the user has cancelled the operation
|
||||||
if (request.IsCanceled) {
|
if (request.IsCanceled) {
|
||||||
return;
|
return;
|
||||||
@@ -320,7 +360,7 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
{
|
{
|
||||||
// if version is specified then name can not be empty or with wildcard. in this case the cmdlet has been errored out already.
|
// if version is specified then name can not be empty or with wildcard. in this case the cmdlet has been errored out already.
|
||||||
// here we just return all packages we can find
|
// here we just return all packages we can find
|
||||||
if (request.FilterOnVersion(packages, requiredVersion, minimumVersion, maximumVersion, minInclusive: true, maxInclusive: true, latest: false).Any(p => !request.YieldFromSwidtag(p, p.Name)))
|
if (request.FilterOnVersion(packages, requiredVersion, minimumVersion, maximumVersion, minInclusive: true, maxInclusive: true, latest: false).OrderBy(p => p.Name).Any(p => !request.YieldFromSwidtag(p, p.Name)))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -329,7 +369,7 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
|
|
||||||
//return the latest version
|
//return the latest version
|
||||||
if (packages.GroupBy(p => p.Name)
|
if (packages.GroupBy(p => p.Name)
|
||||||
.Select(each => each.OrderByDescending(pp => pp.Version).FirstOrDefault()).Any( item =>!request.YieldFromSwidtag(item, item.Name)))
|
.Select(each => each.OrderByDescending(pp => pp.Version).FirstOrDefault()).OrderBy(p=>p.Name).Any( item =>!request.YieldFromSwidtag(item, item.Name)))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -722,15 +762,14 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// validate the file
|
// validate the file
|
||||||
if (!WebDownloader.PerformSecurityScan(destination))
|
if (!WebDownloader.VerifyHash(destination,package, request))
|
||||||
{
|
{
|
||||||
//TODO Security Scan work
|
|
||||||
request.WriteError(ErrorCategory.InvalidOperation, Constants.ProviderName, "The package download from '{0}' failed in the security scan.", package.Source);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!package.IsTrustedSource)
|
if (!package.IsTrustedSource)
|
||||||
{
|
{
|
||||||
if (!request.ShouldContinueWithUntrustedPackageSource(package.Name, package.Source))
|
if (!request.ShouldContinueWithUntrustedPackageSource(package.Name, package.Source))
|
||||||
@@ -869,6 +908,37 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
return Enumerable.Empty<PSModuleInfo>();
|
return Enumerable.Empty<PSModuleInfo>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static bool TestCatalogFile(string jsonFile, string catalogFile, PackageSourceListRequest request)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PSObject result = null;
|
||||||
|
using (PowerShell powershell = PowerShell.Create())
|
||||||
|
{
|
||||||
|
if (powershell != null)
|
||||||
|
{
|
||||||
|
result = powershell
|
||||||
|
.AddCommand("Test-FileCatalog")
|
||||||
|
.AddParameter("CatalogFilePath", catalogFile)
|
||||||
|
.AddParameter("Path", jsonFile)
|
||||||
|
.Invoke().FirstOrDefault();
|
||||||
|
}
|
||||||
|
if (result.ToString().EqualsIgnoreCase("Valid"))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
request.WriteError(ErrorCategory.InvalidData, catalogFile, Resources.Messages.CatalogFileVerificationFailedWithError, catalogFile, ex.Message.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
request.WriteError(ErrorCategory.InvalidData, catalogFile, Resources.Messages.CatalogFileVerificationFailed, jsonFile);
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+85
-82
@@ -43,6 +43,10 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
private string _configurationFileLocation;
|
private string _configurationFileLocation;
|
||||||
private XDocument _config;
|
private XDocument _config;
|
||||||
private string _defaultConfig;
|
private string _defaultConfig;
|
||||||
|
private string PowerShellSourceURL = @"http://go.microsoft.com/fwlink/?LinkID=821777&clcid=0x409";
|
||||||
|
private string PowerShellNanoSourceURL = @"http://go.microsoft.com/fwlink/?LinkID=821783&clcid=0x409";
|
||||||
|
private string PowerShellSourceCatalogURL = @"http://go.microsoft.com/fwlink/?LinkID=823093&clcid=0x409";
|
||||||
|
private string PowerShellNanoSourceCatalogURL = @"http://go.microsoft.com/fwlink/?LinkID=823094&clcid=0x409";
|
||||||
private IEnumerable<string> _packageSources;
|
private IEnumerable<string> _packageSources;
|
||||||
private const string _PackageSourceListRequest = "PackageSourceListRequest";
|
private const string _PackageSourceListRequest = "PackageSourceListRequest";
|
||||||
private HttpClient _httpClient;
|
private HttpClient _httpClient;
|
||||||
@@ -57,6 +61,7 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
internal Lazy<bool> SkipValidate;
|
internal Lazy<bool> SkipValidate;
|
||||||
internal readonly Lazy<bool> AllVersions;
|
internal readonly Lazy<bool> AllVersions;
|
||||||
internal readonly Lazy<string[]> Headers;
|
internal readonly Lazy<string[]> Headers;
|
||||||
|
internal Lazy<bool> SkipHashValidation;
|
||||||
|
|
||||||
internal const WildcardOptions WildcardOptions = System.Management.Automation.WildcardOptions.CultureInvariant | System.Management.Automation.WildcardOptions.IgnoreCase;
|
internal const WildcardOptions WildcardOptions = System.Management.Automation.WildcardOptions.CultureInvariant | System.Management.Automation.WildcardOptions.IgnoreCase;
|
||||||
|
|
||||||
@@ -67,6 +72,12 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
</packageSources>
|
</packageSources>
|
||||||
</configuration>";
|
</configuration>";
|
||||||
|
|
||||||
|
internal const string EmptyConfig = @"<?xml version=""1.0""?>
|
||||||
|
<configuration>
|
||||||
|
<packageSources>
|
||||||
|
</packageSources>
|
||||||
|
</configuration>";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ctor required by the PackageManagement Platform
|
/// Ctor required by the PackageManagement Platform
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -75,20 +86,48 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
AllVersions = new Lazy<bool>(() => GetOptionValue("AllVersions").IsTrue());
|
AllVersions = new Lazy<bool>(() => GetOptionValue("AllVersions").IsTrue());
|
||||||
SkipValidate = new Lazy<bool>(() => GetOptionValue("SkipValidate").IsTrue());
|
SkipValidate = new Lazy<bool>(() => GetOptionValue("SkipValidate").IsTrue());
|
||||||
Headers = new Lazy<string[]>(() => (GetOptionValues("Headers") ?? new string[0]).ToArray());
|
Headers = new Lazy<string[]>(() => (GetOptionValues("Headers") ?? new string[0]).ToArray());
|
||||||
|
SkipHashValidation = new Lazy<bool>(() => GetOptionValue("SkipHashValidation").IsTrue());
|
||||||
}
|
}
|
||||||
internal string DefaultConfigLocation
|
|
||||||
|
internal string DefaultJSONFileLocation
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Path.Combine(Environment.GetEnvironmentVariable("appdata"), Constants.ProviderName, Constants.JSONFileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal string DefaultCatlogFileLocation
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Path.Combine(Environment.GetEnvironmentVariable("appdata"), Constants.ProviderName, Constants.CatFileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal string DefaultJSONSourceLocation
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
#if CORECLR
|
#if CORECLR
|
||||||
return Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles"), "PackageManagement\\ProviderAssemblies\\PSL", "PSL.json");
|
return PowerShellNanoSourceURL;
|
||||||
#else
|
#else
|
||||||
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "PackageManagement\\ProviderAssemblies\\PSL", "PSL.json");
|
return PowerShellSourceURL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal string DefaultJSONCatalogFileLocation
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
#if CORECLR
|
||||||
|
return PowerShellNanoSourceCatalogURL;
|
||||||
|
#else
|
||||||
|
return PowerShellSourceCatalogURL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal string DefaultConfig
|
internal string DefaultConfig
|
||||||
{
|
{
|
||||||
@@ -96,13 +135,13 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
{
|
{
|
||||||
if (_defaultConfig == null)
|
if (_defaultConfig == null)
|
||||||
{
|
{
|
||||||
_defaultConfig = DefaultConfigDefinition.Replace("##", DefaultConfigLocation);
|
_defaultConfig = DefaultConfigDefinition.Replace("##", DefaultJSONFileLocation);
|
||||||
|
|
||||||
}
|
}
|
||||||
return _defaultConfig;
|
return _defaultConfig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal IEnumerable<string> PackageSources
|
internal IEnumerable<string> PackageSources
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -790,66 +829,23 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
|
|
||||||
Debug(Resources.Messages.NotFoundRegisteredSource, src, Constants.ProviderName);
|
Debug(Resources.Messages.NotFoundRegisteredSource, src, Constants.ProviderName);
|
||||||
|
|
||||||
// doesn't look like we have this as a source.
|
|
||||||
if (Uri.IsWellFormedUriString(src, UriKind.Absolute))
|
|
||||||
{
|
|
||||||
// we have been passed in an URI
|
|
||||||
var srcUri = new Uri(src);
|
|
||||||
if (SupportedSchemes.Contains(srcUri.Scheme.ToLower()))
|
|
||||||
{
|
|
||||||
// it's one of our supported uri types.
|
|
||||||
var isValidated = false;
|
|
||||||
|
|
||||||
//if (!SkipValidate.Value)
|
|
||||||
//{
|
|
||||||
// isValidated = PathUtility.ValidateSourceUri(SupportedSchemes, srcUri, this);
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (SkipValidate.Value || isValidated)
|
|
||||||
{
|
|
||||||
Debug(Resources.Messages.SuccessfullyValidated, src);
|
|
||||||
|
|
||||||
yield return new PackageSource
|
|
||||||
{
|
|
||||||
Request = this,
|
|
||||||
Location = srcUri.ToString(),
|
|
||||||
Name = srcUri.ToString(),
|
|
||||||
Trusted = false,
|
|
||||||
IsRegistered = false,
|
|
||||||
IsValidated = isValidated,
|
|
||||||
};
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (userSpecifiesArrayOfSources)
|
|
||||||
{
|
|
||||||
Verbose(Constants.Messages.UnableToResolveSource, Constants.ProviderName, src);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Warning(Constants.Messages.UnableToResolveSource, Constants.ProviderName, src);
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not a valid location?
|
|
||||||
if (userSpecifiesArrayOfSources)
|
|
||||||
{
|
|
||||||
Verbose(Constants.Messages.UnableToResolveSource, Constants.ProviderName, src);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Warning(Constants.Messages.UnableToResolveSource, Constants.ProviderName, src);
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// is it a file path?
|
// is it a file path?
|
||||||
if (System.IO.Directory.Exists(src))
|
if (System.IO.Directory.Exists(src))
|
||||||
{
|
{
|
||||||
Debug(Resources.Messages.SourceIsADirectory, src);
|
Debug(Resources.Messages.SourceIsADirectory, src);
|
||||||
|
PackageSource newSource = new PackageSource
|
||||||
|
{
|
||||||
|
Request = this,
|
||||||
|
Location = src,
|
||||||
|
Name = src,
|
||||||
|
Trusted = true,
|
||||||
|
IsRegistered = false,
|
||||||
|
IsValidated = true,
|
||||||
|
};
|
||||||
|
yield return newSource;
|
||||||
|
}
|
||||||
|
else if (File.Exists(src) && (Path.GetExtension(src).EqualsIgnoreCase(".json")) )
|
||||||
|
{
|
||||||
PackageSource newSource = new PackageSource
|
PackageSource newSource = new PackageSource
|
||||||
{
|
{
|
||||||
Request = this,
|
Request = this,
|
||||||
@@ -947,22 +943,7 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (String.IsNullOrWhiteSpace(_configurationFileLocation))
|
if (string.IsNullOrWhiteSpace(_configurationFileLocation))
|
||||||
{
|
|
||||||
// get the value from the request
|
|
||||||
var path = GetOptionValue("ConfigFile");
|
|
||||||
|
|
||||||
if (!String.IsNullOrWhiteSpace(path))
|
|
||||||
{
|
|
||||||
_configurationFileLocation = path;
|
|
||||||
|
|
||||||
if (!System.IO.File.Exists(_configurationFileLocation))
|
|
||||||
{
|
|
||||||
WriteError(Internal.ErrorCategory.InvalidArgument, _configurationFileLocation, Resources.Messages.FileNotFound);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
var appdataFolder = Environment.GetEnvironmentVariable("appdata");
|
var appdataFolder = Environment.GetEnvironmentVariable("appdata");
|
||||||
_configurationFileLocation = Path.Combine(appdataFolder, Constants.ProviderName, Constants.SettingsFileName);
|
_configurationFileLocation = Path.Combine(appdataFolder, Constants.ProviderName, Constants.SettingsFileName);
|
||||||
@@ -978,16 +959,36 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
if (!System.IO.File.Exists(_configurationFileLocation))
|
if (!System.IO.File.Exists(_configurationFileLocation))
|
||||||
{
|
{
|
||||||
Debug(Resources.Messages.CreateFile, _configurationFileLocation);
|
Debug(Resources.Messages.CreateFile, _configurationFileLocation);
|
||||||
System.IO.File.WriteAllText(_configurationFileLocation, DefaultConfig);
|
bool addDefaultConfig = false;
|
||||||
|
if (System.IO.File.Exists(DefaultJSONFileLocation))
|
||||||
|
{
|
||||||
|
addDefaultConfig = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool force = this.GetOptionValue("Force") != null;
|
||||||
|
if (force || this.ShouldContinue(Resources.Messages.QueryDownloadPackageSourceList.format(DefaultJSONSourceLocation), Resources.Messages.PackageSourceListNotFound.format(DefaultJSONFileLocation)))
|
||||||
|
{
|
||||||
|
WebDownloader.DownloadFile(DefaultJSONSourceLocation, DefaultJSONFileLocation, this, null);
|
||||||
|
WebDownloader.DownloadFile(DefaultJSONCatalogFileLocation, DefaultCatlogFileLocation, this, null);
|
||||||
|
if (System.IO.File.Exists(DefaultJSONFileLocation) && System.IO.File.Exists(DefaultCatlogFileLocation) &&
|
||||||
|
PackageSourceListProvider.TestCatalogFile(DefaultJSONFileLocation, DefaultCatlogFileLocation, this))
|
||||||
|
{
|
||||||
|
addDefaultConfig = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(addDefaultConfig)
|
||||||
|
System.IO.File.WriteAllText(_configurationFileLocation, DefaultConfig);
|
||||||
|
else
|
||||||
|
System.IO.File.WriteAllText(_configurationFileLocation, EmptyConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
return _configurationFileLocation;
|
return _configurationFileLocation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal bool WriteError(Internal.ErrorCategory category, string targetObjectValue, string messageText, params object[] args)
|
internal bool WriteError(Internal.ErrorCategory category, string targetObjectValue, string messageText, params object[] args)
|
||||||
{
|
{
|
||||||
return Error(messageText, category.ToString(), targetObjectValue, base.FormatMessageString(messageText, args));
|
return Error(messageText, category.ToString(), targetObjectValue, base.FormatMessageString(messageText, args));
|
||||||
@@ -1001,10 +1002,12 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
internal bool ValidateSourceLocation(string location)
|
internal bool ValidateSourceLocation(string location)
|
||||||
{
|
{
|
||||||
Debug(Resources.Messages.DebugInfoCallMethod3, _PackageSourceListRequest, "ValidateSourceLocation", location);
|
Debug(Resources.Messages.DebugInfoCallMethod3, _PackageSourceListRequest, "ValidateSourceLocation", location);
|
||||||
|
if (File.Exists(location) && (Path.GetExtension(location).EqualsIgnoreCase(".json")))
|
||||||
//TODO this is needed for register-packagesource
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
internal static IRequest ExtendRequest(Dictionary<string, string[]> options, string[] sources, bool isTrusted, PackageSourceListRequest request) {
|
internal static IRequest ExtendRequest(Dictionary<string, string[]> options, string[] sources, bool isTrusted, PackageSourceListRequest request) {
|
||||||
var srcs = sources ?? new List<string>().ToArray();
|
var srcs = sources ?? new List<string>().ToArray();
|
||||||
|
|||||||
@@ -43,6 +43,12 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
throw new ArgumentNullException("packageSource");
|
throw new ArgumentNullException("packageSource");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(string.IsNullOrWhiteSpace(packageSource.Location) || !System.IO.File.Exists(packageSource.Location))
|
||||||
|
{
|
||||||
|
request.Warning(Resources.Messages.PackageSourceManifestNotFound, packageSource.Location, Constants.ProviderName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Uri uri;
|
Uri uri;
|
||||||
|
|
||||||
if (Uri.TryCreate(packageSource.Location, UriKind.Absolute, out uri))
|
if (Uri.TryCreate(packageSource.Location, UriKind.Absolute, out uri))
|
||||||
@@ -56,6 +62,12 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
request.Warning(ex.Message);
|
||||||
|
while (ex.InnerException != null)
|
||||||
|
{
|
||||||
|
ex = ex.InnerException;
|
||||||
|
request.Warning(ex.Message);
|
||||||
|
}
|
||||||
request.Warning(string.Format(CultureInfo.CurrentCulture, Resources.Messages.InvalidPackageListFormat, uri.AbsolutePath));
|
request.Warning(string.Format(CultureInfo.CurrentCulture, Resources.Messages.InvalidPackageListFormat, uri.AbsolutePath));
|
||||||
ex.Dump(request);
|
ex.Dump(request);
|
||||||
}
|
}
|
||||||
@@ -82,6 +94,12 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
request.Warning(ex.Message);
|
||||||
|
while (ex.InnerException != null)
|
||||||
|
{
|
||||||
|
ex = ex.InnerException;
|
||||||
|
request.Warning(ex.Message);
|
||||||
|
}
|
||||||
request.Warning(string.Format(CultureInfo.CurrentCulture, Resources.Messages.InvalidPackageListFormat, file));
|
request.Warning(string.Format(CultureInfo.CurrentCulture, Resources.Messages.InvalidPackageListFormat, file));
|
||||||
ex.Dump(request);
|
ex.Dump(request);
|
||||||
}
|
}
|
||||||
|
|||||||
+67
-6
@@ -25,8 +25,12 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
using File = System.IO.File;
|
using File = System.IO.File;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.PackageManagement.Provider.Utility;
|
using Microsoft.PackageManagement.Provider.Utility;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Linq;
|
||||||
|
using ErrorCategory = PackageManagement.Internal.ErrorCategory;
|
||||||
|
|
||||||
public class WebDownloader {
|
public class WebDownloader
|
||||||
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Download data from remote via uri query.
|
/// Download data from remote via uri query.
|
||||||
@@ -83,8 +87,11 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
// here we read content that we got from the http response stream into the bytes array
|
// here we read content that we got from the http response stream into the bytes array
|
||||||
current = await input.ReadAsync(bytes, 0, bytes.Length, cts.Token);
|
current = await input.ReadAsync(bytes, 0, bytes.Length, cts.Token);
|
||||||
|
|
||||||
|
int progressPercentage = progressTracker.StartPercent;
|
||||||
// report initial progress
|
// report initial progress
|
||||||
request.Progress(progressTracker.ProgressID, progressTracker.StartPercent, Resources.Messages.BytesRead, current);
|
request.Progress(progressTracker.ProgressID, progressPercentage, Resources.Messages.BytesRead, current);
|
||||||
|
|
||||||
|
int i = progressTracker.StartPercent;
|
||||||
|
|
||||||
while (current > 0)
|
while (current > 0)
|
||||||
{
|
{
|
||||||
@@ -94,7 +101,7 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
await output.WriteAsync(bytes, 0, current, cts.Token);
|
await output.WriteAsync(bytes, 0, current, cts.Token);
|
||||||
|
|
||||||
// report the progress
|
// report the progress
|
||||||
request.Progress(progressTracker.ProgressID, progressTracker.StartPercent, Resources.Messages.BytesRead, totalDownloaded);
|
request.Progress(progressTracker.ProgressID, progressPercentage<progressTracker.EndPercent?progressPercentage++:progressTracker.EndPercent, Resources.Messages.BytesRead, totalDownloaded);
|
||||||
|
|
||||||
// continue reading from the stream
|
// continue reading from the stream
|
||||||
current = await input.ReadAsync(bytes, 0, bytes.Length, cts.Token);
|
current = await input.ReadAsync(bytes, 0, bytes.Length, cts.Token);
|
||||||
@@ -183,7 +190,6 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
progressTracker = new ProgressTracker(request.StartProgress(0, Resources.Messages.DownloadingPackage, queryUrl));
|
progressTracker = new ProgressTracker(request.StartProgress(0, Resources.Messages.DownloadingPackage, queryUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Uri uri;
|
Uri uri;
|
||||||
|
|
||||||
if (!Uri.TryCreate(queryUrl, UriKind.Absolute, out uri))
|
if (!Uri.TryCreate(queryUrl, UriKind.Absolute, out uri))
|
||||||
@@ -233,9 +239,64 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool PerformSecurityScan(string fileFullPath)
|
internal static bool VerifyHash(string fileFullPath,PackageJson package, PackageSourceListRequest request)
|
||||||
{
|
{
|
||||||
//TODO need to do security scan before running install
|
//skip in case the skip switch is specified
|
||||||
|
if (request.SkipHashValidation.Value)
|
||||||
|
{
|
||||||
|
request.Verbose(Resources.Messages.SkipHashValidation);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
PackageHash packageHash = package.Hash;
|
||||||
|
if (packageHash==null || string.IsNullOrWhiteSpace(packageHash.algorithm) || string.IsNullOrWhiteSpace(packageHash.hashCode))
|
||||||
|
{
|
||||||
|
request.WriteError(ErrorCategory.InvalidArgument, Constants.ProviderName, Resources.Messages.HashNotSpecified, package.Name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
HashAlgorithm hashAlgorithm = null;
|
||||||
|
switch (packageHash.algorithm.ToLowerInvariant())
|
||||||
|
{
|
||||||
|
case "sha256":
|
||||||
|
hashAlgorithm = SHA256.Create();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "md5":
|
||||||
|
hashAlgorithm = MD5.Create();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "sha512":
|
||||||
|
hashAlgorithm = SHA512.Create();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
request.WriteError(ErrorCategory.InvalidArgument, Constants.ProviderName, Resources.Messages.InvalidHashAlgorithm, packageHash.algorithm);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (FileStream stream = File.OpenRead(fileFullPath))
|
||||||
|
{
|
||||||
|
// compute the hash
|
||||||
|
byte[] computedHash = hashAlgorithm.ComputeHash(stream);
|
||||||
|
// convert the original hash we got from json
|
||||||
|
byte[] hashFromJSON = Convert.FromBase64String(package.Hash.hashCode);
|
||||||
|
if (!Enumerable.SequenceEqual(computedHash, hashFromJSON))
|
||||||
|
{
|
||||||
|
request.WriteError(ErrorCategory.InvalidOperation, Constants.ProviderName, Resources.Messages.HashVerificationFailed, package.Name, package.Source);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
request.Verbose(Resources.Messages.HashValidationSuccessfull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
request.WriteError(ErrorCategory.InvalidOperation, Constants.ProviderName, Resources.Messages.HashVerificationFailed, package.Name, package.Source);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -54,10 +54,8 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validate the file
|
// validate the file
|
||||||
if (!WebDownloader.PerformSecurityScan(file))
|
if (!WebDownloader.VerifyHash(file, package,request))
|
||||||
{
|
{
|
||||||
//TODO Security Scan work
|
|
||||||
request.WriteError(ErrorCategory.InvalidOperation, Constants.ProviderName, "The package download from '{0}' failed in the security scan.", package.Source);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,12 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly string SettingsFileName = "PSL.config";
|
public static readonly string SettingsFileName = "PSL.config";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sample JSON file containing open powershell entry
|
||||||
|
/// </summary>
|
||||||
|
public static readonly string JSONFileName = "PSL.json";
|
||||||
|
public static readonly string CatFileName = "PSL.cat";
|
||||||
|
|
||||||
internal static class MediaType
|
internal static class MediaType
|
||||||
{
|
{
|
||||||
public const string MsiPackage = "msi";
|
public const string MsiPackage = "msi";
|
||||||
@@ -79,7 +85,7 @@ namespace Microsoft.PackageManagement.PackageSourceListProvider
|
|||||||
public const string ProviderSwidtagUnavailable = "MSG:ProviderSwidtagUnavailable";
|
public const string ProviderSwidtagUnavailable = "MSG:ProviderSwidtagUnavailable";
|
||||||
public const string RemoveEnvironmentVariableRequiresElevation = "MSG:RemoveEnvironmentVariableRequiresElevation";
|
public const string RemoveEnvironmentVariableRequiresElevation = "MSG:RemoveEnvironmentVariableRequiresElevation";
|
||||||
public const string SchemeNotSupported = "MSG:SchemeNotSupported";
|
public const string SchemeNotSupported = "MSG:SchemeNotSupported";
|
||||||
public const string SourceLocationNotValid = "MSG:SourceLocationNotValid";
|
public const string SourceLocationNotValid = "MSG:SourceLocationNotValid_Location";
|
||||||
public const string UnableToCopyFileTo = "MSG:UnableToCopyFileTo";
|
public const string UnableToCopyFileTo = "MSG:UnableToCopyFileTo";
|
||||||
public const string UnableToCreateShortcutTargetDoesNotExist = "MSG:UnableToCreateShortcutTargetDoesNotExist";
|
public const string UnableToCreateShortcutTargetDoesNotExist = "MSG:UnableToCreateShortcutTargetDoesNotExist";
|
||||||
public const string UnableToDownload = "MSG:UnableToDownload";
|
public const string UnableToDownload = "MSG:UnableToDownload";
|
||||||
|
|||||||
+47
-1
@@ -277,7 +277,7 @@
|
|||||||
<value>Unknown category for '{0}'::'{1}': '{2}'</value>
|
<value>Unknown category for '{0}'::'{1}': '{2}'</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UriSchemeNotSupported" xml:space="preserve">
|
<data name="UriSchemeNotSupported" xml:space="preserve">
|
||||||
<value>Uri Scheme '{0}' is not supported.</value>
|
<value>Uri Scheme '{0}' is not supported. Only '{1}' is supported.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UseDefaultConfig" xml:space="preserve">
|
<data name="UseDefaultConfig" xml:space="preserve">
|
||||||
<value>Use the default configuration.</value>
|
<value>Use the default configuration.</value>
|
||||||
@@ -392,4 +392,50 @@
|
|||||||
<data name="InvalidPackageListFormat" xml:space="preserve">
|
<data name="InvalidPackageListFormat" xml:space="preserve">
|
||||||
<value>Package List Source '{0}' has incorrect format.</value>
|
<value>Package List Source '{0}' has incorrect format.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="QueryDownloadPackageSourceList" xml:space="preserve">
|
||||||
|
<value>Do you want to download package source list from '{0}'?</value>
|
||||||
|
<comment>0 - source list path</comment>
|
||||||
|
</data>
|
||||||
|
<data name="FileExists" xml:space="preserve">
|
||||||
|
<value>A file with this name already exists in target directory</value>
|
||||||
|
</data>
|
||||||
|
<data name="OverwriteFile" xml:space="preserve">
|
||||||
|
<value>Do you want to overwrite it?</value>
|
||||||
|
</data>
|
||||||
|
<data name="PackageSourceListNotTrusted" xml:space="preserve">
|
||||||
|
<value>PackageSourceList is not trusted</value>
|
||||||
|
</data>
|
||||||
|
<data name="VersionNotFound" xml:space="preserve">
|
||||||
|
<value>Package '{0}' in json file '{1}' is missing version information.</value>
|
||||||
|
</data>
|
||||||
|
<data name="HashNotSpecified" xml:space="preserve">
|
||||||
|
<value>Invalid hash for package '{0}'. Please correct the values in json file or use -SkipHashValidation switch to skip Hash validation.</value>
|
||||||
|
</data>
|
||||||
|
<data name="HashValidationSuccessfull" xml:space="preserve">
|
||||||
|
<value>Hash validation was successful.</value>
|
||||||
|
</data>
|
||||||
|
<data name="HashVerificationFailed" xml:space="preserve">
|
||||||
|
<value>Hash verification failed for package '{0}' downloaded from '{1}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="InvalidHashAlgorithm" xml:space="preserve">
|
||||||
|
<value>Hash algorithm '{0}' is not supported. We only support sha512, md5 and sha256.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SkipHashValidation" xml:space="preserve">
|
||||||
|
<value>Skipping Hash Validation.</value>
|
||||||
|
</data>
|
||||||
|
<data name="CatalogFileMissing" xml:space="preserve">
|
||||||
|
<value>Catalog file not found for '{0}'. Catalog files are required for non local json files and should have the same name and located in the same directory as json file.</value>
|
||||||
|
</data>
|
||||||
|
<data name="CatalogFileVerificationFailed" xml:space="preserve">
|
||||||
|
<value>Catalog File verification failed for '{0}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="CatalogFileVerificationFailedWithError" xml:space="preserve">
|
||||||
|
<value>Catalog File '{0}' verification failed with '{1}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="PackageSourceListNotFound" xml:space="preserve">
|
||||||
|
<value>Cannot find source list file '{0}'.</value>
|
||||||
|
</data>
|
||||||
|
<data name="PackageSourceManifestNotFound" xml:space="preserve">
|
||||||
|
<value>File '{0}' is registered as a package source location for the provider '{1}'. But it does not exist. Run 'Get-PackageSource' to view the registered package sources, 'Unregister-PackageSource' to unregister the source if you do not wish to use it or 'Set-PackageSource' to fix the source location.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -198,6 +198,43 @@ namespace Microsoft.PowerShell.Workflow
|
|||||||
/// based on the definition provided by this script block.
|
/// based on the definition provided by this script block.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public List<WorkflowInfo> CompileWorkflows(ScriptBlockAst ast, PSModuleInfo definingModule, InitialSessionState initialSessionState, out ParseException parsingErrors, string rootWorkflowName)
|
public List<WorkflowInfo> CompileWorkflows(ScriptBlockAst ast, PSModuleInfo definingModule, InitialSessionState initialSessionState, out ParseException parsingErrors, string rootWorkflowName)
|
||||||
|
{
|
||||||
|
return CompileWorkflowsImpl(ast, definingModule, initialSessionState, null, out parsingErrors, rootWorkflowName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a PowerShell AST into a script block that represents
|
||||||
|
/// the workflow to run.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ast">The PowerShell AST correpsponding to the job's definition.</param>
|
||||||
|
/// <param name="definingModule">The module that is defining this command (if any).</param>
|
||||||
|
/// <param name="initialSessionState">The initial session state of a runspace.</param>
|
||||||
|
/// <param name="sourceLanguageMode">Language mode of source that is creating the workflow.</param>
|
||||||
|
/// <param name="parsingErrors">Optional, once assigned, only root Workflow will be compiled.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A PowerShell script block that invokes an underlying job,
|
||||||
|
/// based on the definition provided by this script block.
|
||||||
|
/// </returns>
|
||||||
|
public List<WorkflowInfo> CompileWorkflows(ScriptBlockAst ast, PSModuleInfo definingModule, InitialSessionState initialSessionState, PSLanguageMode? sourceLanguageMode, out ParseException parsingErrors)
|
||||||
|
{
|
||||||
|
return CompileWorkflowsImpl(ast, definingModule, initialSessionState, sourceLanguageMode, out parsingErrors, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a PowerShell AST into a script block that represents
|
||||||
|
/// the workflow to run.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ast">The PowerShell AST correpsponding to the job's definition.</param>
|
||||||
|
/// <param name="definingModule">The module that is defining this command (if any)</param>
|
||||||
|
/// <param name="initialSessionState">The initial session state of a runspace.</param>
|
||||||
|
/// <param name="sourceLanguageMode">Language mode of source that is creating the workflow.</param>
|
||||||
|
/// <param name="parsingErrors">parsing errors</param>
|
||||||
|
/// <param name="rootWorkflowName">Optional, once assigned, only root Workflow will be compiled</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A PowerShell script block that invokes an underlying job,
|
||||||
|
/// based on the definition provided by this script block.
|
||||||
|
/// </returns>
|
||||||
|
private List<WorkflowInfo> CompileWorkflowsImpl(ScriptBlockAst ast, PSModuleInfo definingModule, InitialSessionState initialSessionState, PSLanguageMode? sourceLanguageMode, out ParseException parsingErrors, string rootWorkflowName)
|
||||||
{
|
{
|
||||||
List<ParseError> errorList = new List<ParseError>();
|
List<ParseError> errorList = new List<ParseError>();
|
||||||
|
|
||||||
@@ -327,7 +364,7 @@ namespace Microsoft.PowerShell.Workflow
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
entry.workflowInfo = CompileSingleWorkflow(entry.scope, func, scriptBlockTokenCache, definingModule, requiredAssemblies, activityMap, processedActivityLibraries, invoker, rootWorkflowName);
|
entry.workflowInfo = CompileSingleWorkflow(entry.scope, func, scriptBlockTokenCache, definingModule, requiredAssemblies, activityMap, processedActivityLibraries, invoker, sourceLanguageMode, rootWorkflowName);
|
||||||
result.Add(entry.workflowInfo);
|
result.Add(entry.workflowInfo);
|
||||||
}
|
}
|
||||||
catch (ParseException e)
|
catch (ParseException e)
|
||||||
@@ -365,6 +402,7 @@ namespace Microsoft.PowerShell.Workflow
|
|||||||
Dictionary<string, Type> activityMap,
|
Dictionary<string, Type> activityMap,
|
||||||
HashSet<string> processedActivityLibraries,
|
HashSet<string> processedActivityLibraries,
|
||||||
System.Management.Automation.PowerShell invoker,
|
System.Management.Automation.PowerShell invoker,
|
||||||
|
PSLanguageMode? sourceLanguageMode = (PSLanguageMode?)null,
|
||||||
string rootWorkflowName = null)
|
string rootWorkflowName = null)
|
||||||
{
|
{
|
||||||
Dictionary<string, ParameterAst> parameterValidation;
|
Dictionary<string, ParameterAst> parameterValidation;
|
||||||
@@ -399,10 +437,11 @@ namespace Microsoft.PowerShell.Workflow
|
|||||||
// Pass either the workflow script file path if available or the full source otherwise.
|
// Pass either the workflow script file path if available or the full source otherwise.
|
||||||
string scriptFile = parentAst.Extent.File;
|
string scriptFile = parentAst.Extent.File;
|
||||||
string scriptSource = string.IsNullOrEmpty(scriptFile) ? parentAst.Extent.StartScriptPosition.GetFullScript() : null;
|
string scriptSource = string.IsNullOrEmpty(scriptFile) ? parentAst.Extent.StartScriptPosition.GetFullScript() : null;
|
||||||
|
ReadOnlyCollection<AttributeAst> attributeAstCollection = (func.Body.ParamBlock != null) ? func.Body.ParamBlock.Attributes : null;
|
||||||
var functionDefinition = ImportWorkflowCommand.CreateFunctionFromXaml(func.Name, xaml,
|
var functionDefinition = ImportWorkflowCommand.CreateFunctionFromXaml(func.Name, xaml,
|
||||||
referencedAssemblies, calledWorkflows.Select(wfi => wfi.NestedXamlDefinition).ToArray(),
|
referencedAssemblies, calledWorkflows.Select(wfi => wfi.NestedXamlDefinition).ToArray(),
|
||||||
null, parameterValidation, modulePath, true, workflowAttributes,
|
null, parameterValidation, modulePath, true, workflowAttributes,
|
||||||
scriptFile, scriptSource, rootWorkflowName);
|
scriptFile, scriptSource, rootWorkflowName, sourceLanguageMode, attributeAstCollection);
|
||||||
|
|
||||||
var helpContent = func.GetHelpContent(scriptBlockTokenCache);
|
var helpContent = func.GetHelpContent(scriptBlockTokenCache);
|
||||||
if (helpContent != null)
|
if (helpContent != null)
|
||||||
|
|||||||
@@ -3545,7 +3545,7 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
{
|
{
|
||||||
if (DownLevelHelper.NativeFilteringSupported())
|
if (DownLevelHelper.NativeFilteringSupported())
|
||||||
{
|
{
|
||||||
Collection<string> ekuCollection = System.Management.Automation.SecuritySupport.GetCertEKU(cert);
|
Collection<string> ekuCollection = System.Management.Automation.Internal.SecuritySupport.GetCertEKU(cert);
|
||||||
|
|
||||||
foreach (string oidString in ekuCollection)
|
foreach (string oidString in ekuCollection)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ Copyright (c) Microsoft Corporation. All rights reserved.
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Management.Automation;
|
using System.Management.Automation;
|
||||||
|
using System.Management.Automation.Internal;
|
||||||
using Dbg=System.Management.Automation.Diagnostics;
|
using Dbg=System.Management.Automation.Diagnostics;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
|||||||
+143
-14
@@ -110,17 +110,15 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
protected override void ProcessRecord()
|
protected override void ProcessRecord()
|
||||||
{
|
{
|
||||||
// In ConstrainedLanguage, XAML workflows are not supported (even from a trusted FullLanguage state),
|
// In ConstrainedLanguage, XAML workflows are not supported (even from a trusted FullLanguage state),
|
||||||
// since we can't prevent tampering.
|
// unless they are signed in-box OS binaries.
|
||||||
|
bool checkSignatures = false;
|
||||||
if ((SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Enforce) ||
|
if ((SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Enforce) ||
|
||||||
(this.SessionState.LanguageMode == PSLanguageMode.ConstrainedLanguage))
|
(this.SessionState.LanguageMode == PSLanguageMode.ConstrainedLanguage))
|
||||||
{
|
{
|
||||||
// However, this static internal property can be changed by tests that can already run a script
|
// However, this static internal property can be changed by tests that can already run a script
|
||||||
// in full-language mode.
|
// in full-language mode.
|
||||||
PropertyInfo xamlProperty = typeof(SystemPolicy).GetProperty("XamlWorkflowSupported", BindingFlags.NonPublic | BindingFlags.Static);
|
PropertyInfo xamlProperty = typeof(SystemPolicy).GetProperty("XamlWorkflowSupported", BindingFlags.NonPublic | BindingFlags.Static);
|
||||||
if (! ((bool) xamlProperty.GetValue(null, null)))
|
checkSignatures = !((bool)xamlProperty.GetValue(null, null));
|
||||||
{
|
|
||||||
throw new NotSupportedException(Resources.XamlWorkflowsNotSupported);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string dependentWorkflowAssemblyPath = string.Empty;
|
string dependentWorkflowAssemblyPath = string.Empty;
|
||||||
@@ -174,8 +172,10 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
WriteError(er);
|
WriteError(er);
|
||||||
Tracer.TraceErrorRecord(er);
|
Tracer.TraceErrorRecord(er);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckFileSignatureAsNeeded(checkSignatures, resolvedPath);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Finally load the file. If there is an access violation, write a
|
// Finally load the file. If there is an access violation, write a
|
||||||
@@ -251,6 +251,8 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckFileSignatureAsNeeded(checkSignatures, resolvedPath);
|
||||||
|
|
||||||
FunctionDetails detailsToUseForUpdate = null;
|
FunctionDetails detailsToUseForUpdate = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -302,7 +304,8 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
requiredAssemblies,
|
requiredAssemblies,
|
||||||
dependentWorkflowContent.ToArray(),
|
dependentWorkflowContent.ToArray(),
|
||||||
dependentWorkflowAssemblyPath,
|
dependentWorkflowAssemblyPath,
|
||||||
resolvedPath);
|
resolvedPath,
|
||||||
|
this.SessionState.LanguageMode);
|
||||||
|
|
||||||
// check if the function cache already has the entry to this file
|
// check if the function cache already has the entry to this file
|
||||||
// If detailsToUseForUpdate is not null it is a forced import module
|
// If detailsToUseForUpdate is not null it is a forced import module
|
||||||
@@ -342,6 +345,14 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
|
|
||||||
} //ProcessRecord
|
} //ProcessRecord
|
||||||
|
|
||||||
|
private static void CheckFileSignatureAsNeeded(bool checkSignatures, string filePath)
|
||||||
|
{
|
||||||
|
if (checkSignatures && !System.Management.Automation.Internal.SecuritySupport.IsProductBinary(filePath))
|
||||||
|
{
|
||||||
|
throw new NotSupportedException(Resources.XamlWorkflowsNotSupported);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static readonly ConcurrentDictionary<string, FunctionDetails> FunctionCache =
|
private static readonly ConcurrentDictionary<string, FunctionDetails> FunctionCache =
|
||||||
new ConcurrentDictionary<string, FunctionDetails>(StringComparer.OrdinalIgnoreCase);
|
new ConcurrentDictionary<string, FunctionDetails>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
@@ -358,7 +369,15 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
/// <param name="dependentWorkflows">Any workflows required by this workflow.</param>
|
/// <param name="dependentWorkflows">Any workflows required by this workflow.</param>
|
||||||
/// <param name="dependentAssemblyPath">Path to the dependent assembly.</param>
|
/// <param name="dependentAssemblyPath">Path to the dependent assembly.</param>
|
||||||
/// <param name="resolvedPath">Resolved Path of the xaml</param>
|
/// <param name="resolvedPath">Resolved Path of the xaml</param>
|
||||||
private static FunctionDetails GenerateFunctionFromXaml(string name, string xaml, Dictionary<string, string> requiredAssemblies, string[] dependentWorkflows, string dependentAssemblyPath, string resolvedPath)
|
/// <param name="sourceLanguageMode">Language mode of source in which workflow should run</param>
|
||||||
|
private static FunctionDetails GenerateFunctionFromXaml(
|
||||||
|
string name,
|
||||||
|
string xaml,
|
||||||
|
Dictionary<string, string> requiredAssemblies,
|
||||||
|
string[] dependentWorkflows,
|
||||||
|
string dependentAssemblyPath,
|
||||||
|
string resolvedPath,
|
||||||
|
PSLanguageMode sourceLanguageMode)
|
||||||
{
|
{
|
||||||
if (name == null)
|
if (name == null)
|
||||||
{
|
{
|
||||||
@@ -368,7 +387,21 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
string modulePath = System.IO.Path.GetDirectoryName(resolvedPath);
|
string modulePath = System.IO.Path.GetDirectoryName(resolvedPath);
|
||||||
string functionDefinition = CreateFunctionFromXaml(name, xaml, requiredAssemblies, dependentWorkflows, dependentAssemblyPath, null, modulePath, false, "[CmdletBinding()]");
|
string functionDefinition = CreateFunctionFromXaml(
|
||||||
|
name,
|
||||||
|
xaml,
|
||||||
|
requiredAssemblies,
|
||||||
|
dependentWorkflows,
|
||||||
|
dependentAssemblyPath,
|
||||||
|
null,
|
||||||
|
modulePath,
|
||||||
|
false,
|
||||||
|
"[CmdletBinding()]",
|
||||||
|
null, /* scriptContent */
|
||||||
|
null, /* fullScript */
|
||||||
|
null, /* rootWorkflowName */
|
||||||
|
sourceLanguageMode,
|
||||||
|
null);
|
||||||
|
|
||||||
FunctionDetails details = new FunctionDetails
|
FunctionDetails details = new FunctionDetails
|
||||||
{Name = name, FunctionDefinition = functionDefinition, Xaml = xaml};
|
{Name = name, FunctionDefinition = functionDefinition, Xaml = xaml};
|
||||||
@@ -438,6 +471,24 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
[SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "workFlowDefinition")]
|
[SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "workFlowDefinition")]
|
||||||
public static ContainerParentJob StartWorkflowApplication(PSCmdlet command, string jobName, string workflowGuid, bool startAsync,
|
public static ContainerParentJob StartWorkflowApplication(PSCmdlet command, string jobName, string workflowGuid, bool startAsync,
|
||||||
bool parameterCollectionProcessed, Hashtable[] parameters, bool debuggerActive)
|
bool parameterCollectionProcessed, Hashtable[] parameters, bool debuggerActive)
|
||||||
|
{
|
||||||
|
return StartWorkflowApplication(command, jobName, workflowGuid, startAsync, parameterCollectionProcessed, parameters, false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes an instance of the workflow object graph identified by the passed
|
||||||
|
/// GUID, binding parameters from the Parameters hastable.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="command">The powershell command.</param>
|
||||||
|
/// <param name="workflowGuid">The GUID used to identify the workflow to run.</param>
|
||||||
|
/// <param name="parameters">The parameters to pass to the workflow instance.</param>
|
||||||
|
/// <param name="jobName">The friendly name for the job</param>
|
||||||
|
/// <param name="parameterCollectionProcessed">True if there was a PSParameters collection</param>
|
||||||
|
/// <param name="startAsync"></param>
|
||||||
|
/// <param name="debuggerActive">True if debugger is in active state.</param>
|
||||||
|
/// <param name="SourceLanguageMode">Language mode of source creating workflow.</param>
|
||||||
|
public static ContainerParentJob StartWorkflowApplication(PSCmdlet command, string jobName, string workflowGuid, bool startAsync,
|
||||||
|
bool parameterCollectionProcessed, Hashtable[] parameters, bool debuggerActive, string SourceLanguageMode)
|
||||||
{
|
{
|
||||||
Guid trackingGuid = Guid.NewGuid();
|
Guid trackingGuid = Guid.NewGuid();
|
||||||
_structuredTracer.BeginStartWorkflowApplication(trackingGuid);
|
_structuredTracer.BeginStartWorkflowApplication(trackingGuid);
|
||||||
@@ -573,6 +624,15 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
myJob = command.JobManager.NewJob(specification) as ContainerParentJob;
|
myJob = command.JobManager.NewJob(specification) as ContainerParentJob;
|
||||||
_structuredTracer.EndCreateNewJob(trackingGuid);
|
_structuredTracer.EndCreateNewJob(trackingGuid);
|
||||||
|
|
||||||
|
// Pass the source language mode to the workflow job so that it can be
|
||||||
|
// applied during activity execution.
|
||||||
|
PSLanguageMode sourceLanguageModeValue;
|
||||||
|
PSLanguageMode? sourceLanguageMode = null;
|
||||||
|
if (!string.IsNullOrEmpty(SourceLanguageMode) && Enum.TryParse<PSLanguageMode>(SourceLanguageMode, out sourceLanguageModeValue))
|
||||||
|
{
|
||||||
|
sourceLanguageMode = sourceLanguageModeValue;
|
||||||
|
}
|
||||||
|
|
||||||
// Raise engine event of new WF job start for debugger, if
|
// Raise engine event of new WF job start for debugger, if
|
||||||
// debugger is active (i.e., has breakpoints set).
|
// debugger is active (i.e., has breakpoints set).
|
||||||
if (debuggerActive)
|
if (debuggerActive)
|
||||||
@@ -581,13 +641,14 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (startAsync)
|
if (startAsync)
|
||||||
{
|
|
||||||
if (!PSSessionConfigurationData.IsServerManager)
|
|
||||||
{
|
{
|
||||||
foreach(PSWorkflowJob childjob in myJob.ChildJobs)
|
foreach(PSWorkflowJob childjob in myJob.ChildJobs)
|
||||||
|
{
|
||||||
|
if (!PSSessionConfigurationData.IsServerManager)
|
||||||
{
|
{
|
||||||
childjob.EnableStreamUnloadOnPersistentState();
|
childjob.EnableStreamUnloadOnPersistentState();
|
||||||
}
|
}
|
||||||
|
childjob.SourceLanguageMode = sourceLanguageMode;
|
||||||
}
|
}
|
||||||
myJob.StartJobAsync();
|
myJob.StartJobAsync();
|
||||||
}
|
}
|
||||||
@@ -598,6 +659,7 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
foreach (PSWorkflowJob childJob in myJob.ChildJobs)
|
foreach (PSWorkflowJob childJob in myJob.ChildJobs)
|
||||||
{
|
{
|
||||||
childJob.SynchronousExecution = true;
|
childJob.SynchronousExecution = true;
|
||||||
|
childJob.SourceLanguageMode = sourceLanguageMode;
|
||||||
}
|
}
|
||||||
myJob.StartJob();
|
myJob.StartJob();
|
||||||
}
|
}
|
||||||
@@ -605,8 +667,8 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
// write an event specifying that job creation is done
|
// write an event specifying that job creation is done
|
||||||
_structuredTracer.EndStartWorkflowApplication(trackingGuid);
|
_structuredTracer.EndStartWorkflowApplication(trackingGuid);
|
||||||
_structuredTracer.TrackingGuidContainerParentJobCorrelation(trackingGuid, myJob.InstanceId);
|
_structuredTracer.TrackingGuidContainerParentJobCorrelation(trackingGuid, myJob.InstanceId);
|
||||||
return myJob;
|
|
||||||
|
|
||||||
|
return myJob;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void RaiseWFJobEvent(PSCmdlet command, ContainerParentJob job, bool startAsync)
|
private static void RaiseWFJobEvent(PSCmdlet command, ContainerParentJob job, bool startAsync)
|
||||||
@@ -1010,6 +1072,46 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
string fullScript,
|
string fullScript,
|
||||||
string rootWorkflowName
|
string rootWorkflowName
|
||||||
)
|
)
|
||||||
|
{
|
||||||
|
return CreateFunctionFromXaml(name, xaml, requiredAssemblies, dependentWorkflows, dependentAssemblyPath, parameterValidation, modulePath,
|
||||||
|
scriptWorkflow, workflowAttributes, scriptContent, fullScript, rootWorkflowName, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a workflow activity based on the provided Xaml and returns PowerShell script that will
|
||||||
|
/// run the workflow.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">Workflow name</param>
|
||||||
|
/// <param name="xaml">Workflow Xaml definition</param>
|
||||||
|
/// <param name="requiredAssemblies">Required assemblies</param>
|
||||||
|
/// <param name="dependentWorkflows">Dependent workflows</param>
|
||||||
|
/// <param name="dependentAssemblyPath">Path for dependent assemblies</param>
|
||||||
|
/// <param name="parameterValidation">Workflow parameters</param>
|
||||||
|
/// <param name="modulePath">Module path</param>
|
||||||
|
/// <param name="scriptWorkflow">True if this is script workflow</param>
|
||||||
|
/// <param name="workflowAttributes">the attribute string to use for the workflow, should be '[CmdletBinding()]'</param>
|
||||||
|
/// <param name="scriptContent">File path containing script content.</param>
|
||||||
|
/// <param name="fullScript">Full source script.</param>
|
||||||
|
/// <param name="rootWorkflowName">Only root Workflow will be compiled</param>
|
||||||
|
/// <param name="sourceLanguageMode">Language mode of source that is creating the workflow</param>
|
||||||
|
/// <param name="attributeAstCollection">Optional collection of parameter attribute Asts</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string CreateFunctionFromXaml(
|
||||||
|
string name,
|
||||||
|
string xaml,
|
||||||
|
Dictionary<string, string> requiredAssemblies,
|
||||||
|
string[] dependentWorkflows,
|
||||||
|
string dependentAssemblyPath,
|
||||||
|
Dictionary<string, ParameterAst> parameterValidation,
|
||||||
|
string modulePath,
|
||||||
|
bool scriptWorkflow,
|
||||||
|
string workflowAttributes,
|
||||||
|
string scriptContent,
|
||||||
|
string fullScript,
|
||||||
|
string rootWorkflowName,
|
||||||
|
PSLanguageMode? sourceLanguageMode,
|
||||||
|
ReadOnlyCollection<AttributeAst> attributeAstCollection
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// check to see if the specified name is allowed
|
// check to see if the specified name is allowed
|
||||||
if (!Regex.IsMatch(name, functionNamePattern))
|
if (!Regex.IsMatch(name, functionNamePattern))
|
||||||
@@ -1304,9 +1406,15 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
completeFunctionDefinitionTemplate.AppendLine(" }}");
|
completeFunctionDefinitionTemplate.AppendLine(" }}");
|
||||||
completeFunctionDefinitionTemplate.AppendLine(FunctionBodyTemplate);
|
completeFunctionDefinitionTemplate.AppendLine(FunctionBodyTemplate);
|
||||||
|
|
||||||
|
// Mark the function definition with sourceLanguageMode (language mode that function can run under, i.e.,
|
||||||
|
// as trusted or not trusted), unless the workflow script is marked with the "SecurityCritical" attribute in
|
||||||
|
// which case the function will always be run under the current system lock down setting.
|
||||||
|
bool isSecurityCritical = ContainsSecurityCriticalAttribute(attributeAstCollection);
|
||||||
|
string sourceLanguageModeStr = (!isSecurityCritical && (sourceLanguageMode != null)) ? sourceLanguageMode.ToString() : string.Empty;
|
||||||
|
|
||||||
// Combine the pieces to create the complete function
|
// Combine the pieces to create the complete function
|
||||||
string functionDefinition = String.Format(CultureInfo.InvariantCulture, completeFunctionDefinitionTemplate.ToString(),
|
string functionDefinition = String.Format(CultureInfo.InvariantCulture, completeFunctionDefinitionTemplate.ToString(),
|
||||||
defaultUpdates, workflowGuid, modulePath);
|
defaultUpdates, workflowGuid, modulePath, sourceLanguageModeStr);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
// Verify that the generated function is valid powershell. This is only an issue when changing the
|
// Verify that the generated function is valid powershell. This is only an issue when changing the
|
||||||
@@ -1334,6 +1442,23 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
return functionDefinition;
|
return functionDefinition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Type securityCriticalAttributeType = typeof(System.Security.SecurityCriticalAttribute);
|
||||||
|
private static bool ContainsSecurityCriticalAttribute(ReadOnlyCollection<AttributeAst> attributeAsts)
|
||||||
|
{
|
||||||
|
if (attributeAsts != null)
|
||||||
|
{
|
||||||
|
foreach (var attributeAst in attributeAsts)
|
||||||
|
{
|
||||||
|
if (attributeAst.TypeName.GetReflectionAttributeType() == securityCriticalAttributeType)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
@@ -1515,6 +1640,9 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
# which uses this as a base path to find localized content files.
|
# which uses this as a base path to find localized content files.
|
||||||
$psBoundParameters['" + Constants.ModulePath + @"'] = '{2}'
|
$psBoundParameters['" + Constants.ModulePath + @"'] = '{2}'
|
||||||
|
|
||||||
|
# Variable that contains the source language mode.
|
||||||
|
[string] $SourceLanguageMode = '{3}'
|
||||||
|
|
||||||
if (Test-Path variable:\PSSenderInfo)
|
if (Test-Path variable:\PSSenderInfo)
|
||||||
{{
|
{{
|
||||||
$psBoundParameters['" + Constants.PSSenderInfo + @"'] = $PSSenderInfo
|
$psBoundParameters['" + Constants.PSSenderInfo + @"'] = $PSSenderInfo
|
||||||
@@ -1693,7 +1821,8 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
$AsJob,
|
$AsJob,
|
||||||
$parameterCollectionProcessed,
|
$parameterCollectionProcessed,
|
||||||
$finalParameterCollection,
|
$finalParameterCollection,
|
||||||
$debuggerActive)
|
$debuggerActive,
|
||||||
|
$SourceLanguageMode)
|
||||||
}}
|
}}
|
||||||
catch
|
catch
|
||||||
{{
|
{{
|
||||||
|
|||||||
+30
-3
@@ -80,23 +80,29 @@ namespace Microsoft.PowerShell.Workflow
|
|||||||
return EndGetRunspace(asyncResult);
|
return EndGetRunspace(asyncResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Runspace AssignRunspaceIfPossible()
|
private Runspace AssignRunspaceIfPossible(PSLanguageMode? sourceLanguageMode = null)
|
||||||
{
|
{
|
||||||
Runspace runspace = null;
|
Runspace runspace = null;
|
||||||
|
PSLanguageMode languageMode = (sourceLanguageMode != null) ? sourceLanguageMode.Value :
|
||||||
|
(_languageMode != null) ? _languageMode.Value : GetSystemLanguageMode();
|
||||||
lock (_runspaceCache.TimerServicingSyncObject)
|
lock (_runspaceCache.TimerServicingSyncObject)
|
||||||
{
|
{
|
||||||
|
// Retrieve or create a local runspace having the same language mode as the source, if provided.
|
||||||
foreach (Item<Runspace> item in _runspaceCache.Cast<Item<Runspace>>().Where(item => !item.Busy))
|
foreach (Item<Runspace> item in _runspaceCache.Cast<Item<Runspace>>().Where(item => !item.Busy))
|
||||||
|
{
|
||||||
|
if (item.Value.SessionStateProxy.LanguageMode == languageMode)
|
||||||
{
|
{
|
||||||
item.Idle = false;
|
item.Idle = false;
|
||||||
item.Busy = true;
|
item.Busy = true;
|
||||||
runspace = item.Value;
|
runspace = item.Value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((runspace == null || runspace.RunspaceStateInfo.State != RunspaceState.Opened) &&
|
if ((runspace == null || runspace.RunspaceStateInfo.State != RunspaceState.Opened) &&
|
||||||
(_maxRunspaces == MaxRunspacesPossible || _runspaceCache.Cache.Count < _maxRunspaces))
|
(_maxRunspaces == MaxRunspacesPossible || _runspaceCache.Cache.Count < _maxRunspaces))
|
||||||
{
|
{
|
||||||
runspace = CreateLocalActivityRunspace(_languageMode);
|
runspace = CreateLocalActivityRunspace(languageMode);
|
||||||
|
|
||||||
runspace.Open();
|
runspace.Open();
|
||||||
_tracer.WriteMessage("New local runspace created");
|
_tracer.WriteMessage("New local runspace created");
|
||||||
@@ -108,6 +114,11 @@ namespace Microsoft.PowerShell.Workflow
|
|||||||
return runspace;
|
return runspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static PSLanguageMode GetSystemLanguageMode()
|
||||||
|
{
|
||||||
|
return (SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Enforce) ?
|
||||||
|
PSLanguageMode.ConstrainedLanguage : PSLanguageMode.FullLanguage;
|
||||||
|
}
|
||||||
|
|
||||||
private void TraceThreadPoolInfo(string message)
|
private void TraceThreadPoolInfo(string message)
|
||||||
{
|
{
|
||||||
@@ -208,7 +219,23 @@ namespace Microsoft.PowerShell.Workflow
|
|||||||
|
|
||||||
LocalRunspaceAsyncResult asyncResult = new LocalRunspaceAsyncResult(state, callback, Guid.Empty);
|
LocalRunspaceAsyncResult asyncResult = new LocalRunspaceAsyncResult(state, callback, Guid.Empty);
|
||||||
|
|
||||||
Runspace runspace = AssignRunspaceIfPossible();
|
// Get the source language mode from the activity arguments if available and pass to runspace fetching.
|
||||||
|
PSLanguageMode? sourceLanguageMode = null;
|
||||||
|
RunCommandsArguments args = state as RunCommandsArguments;
|
||||||
|
if (args != null)
|
||||||
|
{
|
||||||
|
PSWorkflowRuntime wfRuntime = args.WorkflowHost as PSWorkflowRuntime;
|
||||||
|
if (wfRuntime != null)
|
||||||
|
{
|
||||||
|
PSWorkflowJob wfJob = wfRuntime.JobManager.GetJob(args.PSActivityContext.JobInstanceId);
|
||||||
|
if (wfJob != null)
|
||||||
|
{
|
||||||
|
sourceLanguageMode = wfJob.SourceLanguageMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Runspace runspace = AssignRunspaceIfPossible(sourceLanguageMode);
|
||||||
if (runspace != null)
|
if (runspace != null)
|
||||||
{
|
{
|
||||||
asyncResult.Runspace = runspace;
|
asyncResult.Runspace = runspace;
|
||||||
|
|||||||
@@ -1205,6 +1205,8 @@ namespace Microsoft.PowerShell.Workflow
|
|||||||
|
|
||||||
internal bool? IsSuspendable = null;
|
internal bool? IsSuspendable = null;
|
||||||
|
|
||||||
|
internal PSLanguageMode? SourceLanguageMode { get; set; }
|
||||||
|
|
||||||
#endregion Internal Accessors
|
#endregion Internal Accessors
|
||||||
|
|
||||||
#region Internal Methods
|
#region Internal Methods
|
||||||
|
|||||||
@@ -413,7 +413,7 @@ For more information about how to add checkpoints, see the help topics for Windo
|
|||||||
<comment>{0} is a number and should not be localized.</comment>
|
<comment>{0} is a number and should not be localized.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="XamlWorkflowsNotSupported" xml:space="preserve">
|
<data name="XamlWorkflowsNotSupported" xml:space="preserve">
|
||||||
<value>Cannot load workflow. XAML-based workflows are not supported in this language mode. Only script-based workflows are supported.</value>
|
<value>Cannot load the workflow. Only signed in-box XAML-based workflows or script-based workflows are supported in the current language mode.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RetryingConnection" xml:space="preserve">
|
<data name="RetryingConnection" xml:space="preserve">
|
||||||
<value>Retrying activity connection: attempt {0} of {1}.</value>
|
<value>Retrying activity connection: attempt {0} of {1}.</value>
|
||||||
|
|||||||
+7
-8
@@ -1,17 +1,17 @@
|
|||||||
@{
|
@{
|
||||||
GUID="1DA87E53-152B-403E-98DC-74D7B4D63D59"
|
GUID="1DA87E53-152B-403E-98DC-74D7B4D63D59"
|
||||||
Author="Microsoft Corporation"
|
Author="Microsoft Corporation"
|
||||||
CompanyName="Microsoft Corporation"
|
CompanyName="Microsoft Corporation"
|
||||||
Copyright="© Microsoft Corporation. All rights reserved."
|
Copyright="© Microsoft Corporation. All rights reserved."
|
||||||
ModuleVersion="3.1.0.0"
|
ModuleVersion="3.1.0.0"
|
||||||
PowerShellVersion="3.0"
|
PowerShellVersion="3.0"
|
||||||
CmdletsToExport= "Format-List", "Format-Custom", "Format-Table", "Format-Wide",
|
CmdletsToExport= "Format-List", "Format-Custom", "Format-Table", "Format-Wide",
|
||||||
"Out-File", "Out-String", "Get-FormatData", "Export-FormatData", "ConvertFrom-Json", "ConvertTo-Json",
|
"Out-File", "Out-String", "Get-FormatData", "Export-FormatData", "ConvertFrom-Json", "ConvertTo-Json",
|
||||||
"Invoke-RestMethod", "Invoke-WebRequest",
|
"Invoke-RestMethod", "Invoke-WebRequest", "Register-ObjectEvent", "Register-EngineEvent",
|
||||||
"Register-ObjectEvent", "Register-EngineEvent", "Wait-Event", "Get-Event", "Remove-Event",
|
"Wait-Event", "Get-Event", "Remove-Event", "Get-EventSubscriber", "Unregister-Event",
|
||||||
"Get-EventSubscriber", "Unregister-Event", "New-Event", "Add-Member", "Add-Type", "Compare-Object",
|
"New-Event", "Add-Member", "Add-Type", "Compare-Object", "ConvertFrom-StringData",
|
||||||
"ConvertFrom-StringData", "Export-Csv", "Import-Csv", "ConvertTo-Csv", "ConvertFrom-Csv", "Export-Alias",
|
"Export-Csv", "Import-Csv", "ConvertTo-Csv", "ConvertFrom-Csv", "Export-Alias", "Invoke-Expression",
|
||||||
"Invoke-Expression", "Get-Alias", "Get-Culture", "Get-Date", "Get-Host", "Get-Member", "Get-Random",
|
"Get-Alias", "Get-Culture", "Get-Date", "Get-Host", "Get-Member", "Get-Random",
|
||||||
"Get-UICulture", "Get-Unique", "Import-Alias", "Import-LocalizedData",
|
"Get-UICulture", "Get-Unique", "Import-Alias", "Import-LocalizedData",
|
||||||
"Select-String", "Measure-Object", "New-Alias", "New-TimeSpan", "Read-Host", "Set-Alias", "Set-Date",
|
"Select-String", "Measure-Object", "New-Alias", "New-TimeSpan", "Read-Host", "Set-Alias", "Set-Date",
|
||||||
"Start-Sleep", "Tee-Object", "Measure-Command", "Update-TypeData", "Update-FormatData",
|
"Start-Sleep", "Tee-Object", "Measure-Command", "Update-TypeData", "Update-FormatData",
|
||||||
@@ -20,7 +20,6 @@ CmdletsToExport= "Format-List", "Format-Custom", "Format-Table", "Format-Wide",
|
|||||||
"Clear-Variable", "Export-Clixml", "Import-Clixml", "ConvertTo-Xml", "Select-Xml", "Write-Debug",
|
"Clear-Variable", "Export-Clixml", "Import-Clixml", "ConvertTo-Xml", "Select-Xml", "Write-Debug",
|
||||||
"Write-Verbose", "Write-Warning", "Write-Error", "Write-Information", "Write-Output", "Set-PSBreakpoint",
|
"Write-Verbose", "Write-Warning", "Write-Error", "Write-Information", "Write-Output", "Set-PSBreakpoint",
|
||||||
"Get-PSBreakpoint", "Remove-PSBreakpoint", "Enable-PSBreakpoint", "Disable-PSBreakpoint", "Get-PSCallStack",
|
"Get-PSBreakpoint", "Remove-PSBreakpoint", "Enable-PSBreakpoint", "Disable-PSBreakpoint", "Get-PSCallStack",
|
||||||
"Get-TraceSource", "Set-TraceSource", "Trace-Command",
|
|
||||||
"Unblock-File", "Get-Runspace", "Debug-Runspace", "Enable-RunspaceDebug", "Disable-RunspaceDebug",
|
"Unblock-File", "Get-Runspace", "Debug-Runspace", "Enable-RunspaceDebug", "Disable-RunspaceDebug",
|
||||||
"Get-RunspaceDebug", "Wait-Debugger"
|
"Get-RunspaceDebug", "Wait-Debugger"
|
||||||
FunctionsToExport= "Get-FileHash", "New-TemporaryFile", "New-Guid", "Format-Hex", "Import-PowerShellDataFile",
|
FunctionsToExport= "Get-FileHash", "New-TemporaryFile", "New-Guid", "Format-Hex", "Import-PowerShellDataFile",
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
workflow Invoke-AsWorkflow
|
workflow Invoke-AsWorkflow
|
||||||
{
|
{
|
||||||
<#
|
<#
|
||||||
.EXTERNALHELP Microsoft.PowerShell.Workflow.ServiceCore.dll-help.xml
|
.EXTERNALHELP Microsoft.PowerShell.Workflow.ServiceCore.dll-help.xml
|
||||||
#>
|
#>
|
||||||
|
[System.Security.SecurityCritical()]
|
||||||
[CmdletBinding(DefaultParameterSetName='Command', HelpUri='http://go.microsoft.com/fwlink/?LinkId=238267')]
|
[CmdletBinding(DefaultParameterSetName='Command', HelpUri='http://go.microsoft.com/fwlink/?LinkId=238267')]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$true,ParameterSetName="Command")]
|
[Parameter(Mandatory=$true,ParameterSetName="Command")]
|
||||||
|
|||||||
@@ -3777,23 +3777,38 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
if (workflowsToProcess != null && workflowsToProcess.Count > 0)
|
if (workflowsToProcess != null && workflowsToProcess.Count > 0)
|
||||||
{
|
{
|
||||||
// In ConstrainedLanguage, XAML workflows are not supported (even from a trusted FullLanguage state),
|
// In ConstrainedLanguage, XAML workflows are not supported (even from a trusted FullLanguage state),
|
||||||
// since we can't prevent tampering.
|
// unless they are signed in-box OS binaries.
|
||||||
if ((SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Enforce) ||
|
if ((SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Enforce) ||
|
||||||
(Context.LanguageMode == PSLanguageMode.ConstrainedLanguage))
|
(Context.LanguageMode == PSLanguageMode.ConstrainedLanguage))
|
||||||
{
|
{
|
||||||
// However, this static internal property can be changed by tests that can already run a script
|
// However, this static internal property can be changed by tests that can already run a script
|
||||||
// in full-language mode.
|
// in full-language mode.
|
||||||
if (! SystemPolicy.XamlWorkflowSupported)
|
if (! SystemPolicy.XamlWorkflowSupported)
|
||||||
|
{
|
||||||
|
foreach (string workflowPath in ResolveWorkflowFiles(moduleBase, workflowsToProcess))
|
||||||
|
{
|
||||||
|
if (!SecuritySupport.IsProductBinary(workflowPath))
|
||||||
{
|
{
|
||||||
throw new NotSupportedException(Modules.XamlWorkflowsNotSupported);
|
throw new NotSupportedException(Modules.XamlWorkflowsNotSupported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SessionStateInternal oldSessionStateWF = Context.EngineSessionState;
|
SessionStateInternal oldSessionStateWF = Context.EngineSessionState;
|
||||||
|
PSLanguageMode? savedLanguageMode = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Context.EngineSessionState = ss.Internal;
|
Context.EngineSessionState = ss.Internal;
|
||||||
|
|
||||||
|
// Always run workflow import script as trusted since only signed in-box files can be imported
|
||||||
|
// on locked down machines.
|
||||||
|
if (Context.LanguageMode != PSLanguageMode.FullLanguage)
|
||||||
|
{
|
||||||
|
savedLanguageMode = Context.LanguageMode;
|
||||||
|
Context.LanguageMode = PSLanguageMode.FullLanguage;
|
||||||
|
}
|
||||||
|
|
||||||
if (dependentWorkflows != null && dependentWorkflows.Count > 0)
|
if (dependentWorkflows != null && dependentWorkflows.Count > 0)
|
||||||
{
|
{
|
||||||
ScriptBlock importWorkflow = ScriptBlock.Create(Context,
|
ScriptBlock importWorkflow = ScriptBlock.Create(Context,
|
||||||
@@ -3830,6 +3845,11 @@ namespace Microsoft.PowerShell.Commands
|
|||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
Context.EngineSessionState = oldSessionStateWF;
|
Context.EngineSessionState = oldSessionStateWF;
|
||||||
|
|
||||||
|
if (savedLanguageMode != null)
|
||||||
|
{
|
||||||
|
Context.LanguageMode = savedLanguageMode.Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11084,6 +11084,9 @@ namespace System.Management.Automation.Internal
|
|||||||
/// <summary/>
|
/// <summary/>
|
||||||
List<WorkflowInfo> CompileWorkflows(ScriptBlockAst ast, PSModuleInfo definingModule, InitialSessionState initialSessionState, out ParseException parsingErrors);
|
List<WorkflowInfo> CompileWorkflows(ScriptBlockAst ast, PSModuleInfo definingModule, InitialSessionState initialSessionState, out ParseException parsingErrors);
|
||||||
|
|
||||||
|
/// <summary/>
|
||||||
|
List<WorkflowInfo> CompileWorkflows(ScriptBlockAst ast, PSModuleInfo definingModule, InitialSessionState initialSessionState, PSLanguageMode? languageMode, out ParseException parsingErrors);
|
||||||
|
|
||||||
/// <summary/>
|
/// <summary/>
|
||||||
List<WorkflowInfo> CompileWorkflows(ScriptBlockAst ast, PSModuleInfo definingModule, string rootWorkflowName);
|
List<WorkflowInfo> CompileWorkflows(ScriptBlockAst ast, PSModuleInfo definingModule, string rootWorkflowName);
|
||||||
|
|
||||||
|
|||||||
@@ -1828,7 +1828,7 @@ namespace System.Management.Automation
|
|||||||
|
|
||||||
if (_scriptBlock.HasBeginBlock)
|
if (_scriptBlock.HasBeginBlock)
|
||||||
{
|
{
|
||||||
RunClause(_runOptimized ? _scriptBlock.BeginBlock : _scriptBlock.UnoptimizedBeginBlock, AutomationNull.Value, _input.GetEnumerator());
|
RunClause(_runOptimized ? _scriptBlock.BeginBlock : _scriptBlock.UnoptimizedBeginBlock, AutomationNull.Value, _input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1851,7 +1851,7 @@ namespace System.Management.Automation
|
|||||||
}
|
}
|
||||||
if (_scriptBlock.HasProcessBlock)
|
if (_scriptBlock.HasProcessBlock)
|
||||||
{
|
{
|
||||||
RunClause(_runOptimized ? _scriptBlock.ProcessBlock : _scriptBlock.UnoptimizedProcessBlock, dollarUnder, _input.GetEnumerator());
|
RunClause(_runOptimized ? _scriptBlock.ProcessBlock : _scriptBlock.UnoptimizedProcessBlock, dollarUnder, _input);
|
||||||
_input.Clear();
|
_input.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1865,7 +1865,7 @@ namespace System.Management.Automation
|
|||||||
|
|
||||||
if (_scriptBlock.HasEndBlock)
|
if (_scriptBlock.HasEndBlock)
|
||||||
{
|
{
|
||||||
RunClause(_runOptimized ? _scriptBlock.EndBlock : _scriptBlock.UnoptimizedEndBlock, AutomationNull.Value, _input.ToArray().GetEnumerator());
|
RunClause(_runOptimized ? _scriptBlock.EndBlock : _scriptBlock.UnoptimizedEndBlock, AutomationNull.Value, _input.ToArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1125,7 +1125,8 @@ namespace System.Management.Automation
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var converterInstance = Utils.GetAstToWorkflowConverterAndEnsureWorkflowModuleLoaded(context);
|
var converterInstance = Utils.GetAstToWorkflowConverterAndEnsureWorkflowModuleLoaded(context);
|
||||||
var workflows = converterInstance.CompileWorkflows(scriptBlockAst, context.EngineSessionState.Module, null, out parseErrors);
|
PSLanguageMode? languageMode = (context != null) ? context.LanguageMode : (PSLanguageMode?) null;
|
||||||
|
var workflows = converterInstance.CompileWorkflows(scriptBlockAst, context.EngineSessionState.Module, null, languageMode, out parseErrors);
|
||||||
foreach (var workflow in workflows)
|
foreach (var workflow in workflows)
|
||||||
{
|
{
|
||||||
context.EngineSessionState.SetWorkflowRaw(workflow,
|
context.EngineSessionState.SetWorkflowRaw(workflow,
|
||||||
|
|||||||
@@ -597,7 +597,7 @@
|
|||||||
<value>Cannot define the workflow. The language mode for this session is incompatible with the system-wide language mode.</value>
|
<value>Cannot define the workflow. The language mode for this session is incompatible with the system-wide language mode.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="XamlWorkflowsNotSupported" xml:space="preserve">
|
<data name="XamlWorkflowsNotSupported" xml:space="preserve">
|
||||||
<value>Cannot load the workflow. XAML-based workflows are not supported in the current language mode. Only script-based workflows are supported in this language mode.</value>
|
<value>Cannot load the workflow. Only signed in-box XAML-based workflows or script-based workflows are supported in the current language mode.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CannotDetectNetFrameworkVersion" xml:space="preserve">
|
<data name="CannotDetectNetFrameworkVersion" xml:space="preserve">
|
||||||
<value>Cannot verify the Microsoft .NET Framework version {0} because it is not included in the list of permitted versions.</value>
|
<value>Cannot verify the Microsoft .NET Framework version {0} because it is not included in the list of permitted versions.</value>
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ namespace Microsoft.PowerShell
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace System.Management.Automation
|
namespace System.Management.Automation.Internal
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The SAFER policy associated with this file
|
/// The SAFER policy associated with this file
|
||||||
@@ -118,7 +118,10 @@ namespace System.Management.Automation
|
|||||||
Disallowed = 2
|
Disallowed = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static class SecuritySupport
|
/// <summary>
|
||||||
|
/// Security Support APIs
|
||||||
|
/// </summary>
|
||||||
|
public static class SecuritySupport
|
||||||
{
|
{
|
||||||
#region execution policy
|
#region execution policy
|
||||||
|
|
||||||
@@ -414,7 +417,12 @@ namespace System.Management.Automation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool IsProductBinary(string file)
|
/// <summary>
|
||||||
|
/// Returns true if file has product binary signature
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="file">Name of file to check</param>
|
||||||
|
/// <returns>True when file has product binary signature</returns>
|
||||||
|
public static bool IsProductBinary(string file)
|
||||||
{
|
{
|
||||||
if(String.IsNullOrEmpty(file) || (! IO.File.Exists(file)))
|
if(String.IsNullOrEmpty(file) || (! IO.File.Exists(file)))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user