diff --git a/assets/files.wxs b/assets/files.wxs
index 5869628e0cd..86baf9f5d09 100644
--- a/assets/files.wxs
+++ b/assets/files.wxs
@@ -1331,9 +1331,6 @@
-
-
-
@@ -1643,6 +1640,9 @@
+
+
+
@@ -3919,6 +3919,7 @@
+
diff --git a/src/Microsoft.PowerShell.Commands.Management/Microsoft.PowerShell.Commands.Management.csproj b/src/Microsoft.PowerShell.Commands.Management/Microsoft.PowerShell.Commands.Management.csproj
index cd84d055c08..26f8f161a51 100644
--- a/src/Microsoft.PowerShell.Commands.Management/Microsoft.PowerShell.Commands.Management.csproj
+++ b/src/Microsoft.PowerShell.Commands.Management/Microsoft.PowerShell.Commands.Management.csproj
@@ -18,14 +18,12 @@
-
-
@@ -38,7 +36,6 @@
-
@@ -46,7 +43,6 @@
-
diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Clipboard.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Clipboard.cs
new file mode 100644
index 00000000000..95f276f792b
--- /dev/null
+++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Clipboard.cs
@@ -0,0 +1,386 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace Microsoft.PowerShell.Commands.Internal
+{
+ internal static class Clipboard
+ {
+ private static bool? _clipboardSupported;
+
+ // Used if an external clipboard is not available, e.g. if xclip is missing.
+ // This is useful for testing in CI as well.
+ private static string _internalClipboard;
+
+ private static string StartProcess(
+ string tool,
+ string args,
+ string stdin = "" )
+ {
+ ProcessStartInfo startInfo = new ProcessStartInfo();
+ startInfo.UseShellExecute = false;
+ startInfo.RedirectStandardInput = true;
+ startInfo.RedirectStandardOutput = true;
+ startInfo.RedirectStandardError = true;
+ startInfo.FileName = tool;
+ startInfo.Arguments = args;
+ string stdout;
+
+ using (Process process = new Process())
+ {
+ process.StartInfo = startInfo;
+ try
+ {
+ process.Start();
+ }
+ catch (System.ComponentModel.Win32Exception)
+ {
+ _clipboardSupported = false;
+ return string.Empty;
+ }
+
+ if (!string.IsNullOrEmpty(stdin))
+ {
+ process.StandardInput.Write(stdin);
+ process.StandardInput.Close();
+ }
+
+ stdout = process.StandardOutput.ReadToEnd();
+ process.WaitForExit(250);
+
+ _clipboardSupported = process.ExitCode == 0;
+ }
+
+ return stdout;
+ }
+
+ public static string GetText()
+ {
+ if (_clipboardSupported == false)
+ {
+ return _internalClipboard ?? string.Empty;
+ }
+
+ string tool = string.Empty;
+ string args = string.Empty;
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ string clipboardText = string.Empty;
+ ExecuteOnStaThread(() => GetTextImpl(out clipboardText));
+ return clipboardText;
+ }
+ else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+ {
+ tool = "xclip";
+ args = "-selection clipboard -out";
+ }
+ else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ {
+ tool = "pbpaste";
+ }
+ else
+ {
+ _clipboardSupported = false;
+ return string.Empty;
+ }
+
+ return StartProcess(tool, args);
+ }
+
+ public static void SetText(string text)
+ {
+ if (string.IsNullOrEmpty(text))
+ {
+ return;
+ }
+
+ if (_clipboardSupported == false)
+ {
+ _internalClipboard = text;
+ return;
+ }
+
+ string tool = string.Empty;
+ string args = string.Empty;
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ ExecuteOnStaThread(() => SetClipboardData(Tuple.Create(text, CF_UNICODETEXT)));
+ return;
+ }
+ else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+ {
+ tool = "xclip";
+ args = "-selection clipboard -in";
+ }
+ else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ {
+ tool = "pbcopy";
+ }
+ else
+ {
+ _clipboardSupported = false;
+ return;
+ }
+
+ StartProcess(tool, args, text);
+ if (_clipboardSupported == false)
+ {
+ _internalClipboard = text;
+ }
+ }
+
+ public static void SetRtf(string plainText, string rtfText)
+ {
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ return;
+ }
+
+ if (s_CF_RTF == 0)
+ {
+ s_CF_RTF = RegisterClipboardFormat("Rich Text Format");
+ }
+
+ ExecuteOnStaThread(() => SetClipboardData(
+ Tuple.Create(plainText, CF_UNICODETEXT),
+ Tuple.Create(rtfText, s_CF_RTF)));
+ }
+
+ private const uint GMEM_MOVEABLE = 0x0002;
+ private const uint GMEM_ZEROINIT = 0x0040;
+ private const uint GHND = GMEM_MOVEABLE | GMEM_ZEROINIT;
+
+ [DllImport("kernel32.dll")]
+ private static extern IntPtr GlobalAlloc(uint flags, UIntPtr dwBytes);
+
+ [DllImport("kernel32.dll")]
+ private static extern IntPtr GlobalFree(IntPtr hMem);
+
+ [DllImport("kernel32.dll")]
+ private static extern IntPtr GlobalLock(IntPtr hMem);
+
+ [DllImport("kernel32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool GlobalUnlock(IntPtr hMem);
+
+ [DllImport("kernel32.dll", ExactSpelling = true, EntryPoint = "RtlMoveMemory", SetLastError = true)]
+ private static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
+
+ [DllImport("user32.dll", SetLastError = false)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool IsClipboardFormatAvailable(uint format);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool OpenClipboard(IntPtr hWndNewOwner);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool CloseClipboard();
+
+ [DllImport("user32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool EmptyClipboard();
+
+ [DllImport("user32.dll", SetLastError = true)]
+ private static extern IntPtr GetClipboardData(uint format);
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr SetClipboardData(uint format, IntPtr data);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ private static extern uint RegisterClipboardFormat(string lpszFormat);
+
+ private const uint CF_TEXT = 1;
+ private const uint CF_UNICODETEXT = 13;
+ private static uint s_CF_RTF;
+
+ private static bool GetTextImpl(out string text)
+ {
+ try
+ {
+ if (IsClipboardFormatAvailable(CF_UNICODETEXT))
+ {
+ if (OpenClipboard(IntPtr.Zero))
+ {
+ var data = GetClipboardData(CF_UNICODETEXT);
+ if (data != IntPtr.Zero)
+ {
+ data = GlobalLock(data);
+ text = Marshal.PtrToStringUni(data);
+ GlobalUnlock(data);
+ return true;
+ }
+ }
+ }
+ else if (IsClipboardFormatAvailable(CF_TEXT))
+ {
+ if (OpenClipboard(IntPtr.Zero))
+ {
+ var data = GetClipboardData(CF_TEXT);
+ if (data != IntPtr.Zero)
+ {
+ data = GlobalLock(data);
+ text = Marshal.PtrToStringAnsi(data);
+ GlobalUnlock(data);
+ return true;
+ }
+ }
+ }
+ }
+ catch
+ {
+ // Ignore exceptions
+ }
+ finally
+ {
+ CloseClipboard();
+ }
+
+ text = string.Empty;
+ return false;
+ }
+
+ private static bool SetClipboardData(params Tuple[] data)
+ {
+ try
+ {
+ if (!OpenClipboard(IntPtr.Zero))
+ {
+ return false;
+ }
+
+ EmptyClipboard();
+
+ foreach (var d in data)
+ {
+ if (!SetSingleClipboardData(d.Item1, d.Item2))
+ {
+ return false;
+ }
+ }
+ }
+ finally
+ {
+ CloseClipboard();
+ }
+
+ return true;
+ }
+
+ private static bool SetSingleClipboardData(string text, uint format)
+ {
+ IntPtr hGlobal = IntPtr.Zero;
+ IntPtr data = IntPtr.Zero;
+
+ try
+ {
+ uint bytes;
+ if (format == s_CF_RTF || format == CF_TEXT)
+ {
+ bytes = (uint)(text.Length + 1);
+ data = Marshal.StringToHGlobalAnsi(text);
+ }
+ else if (format == CF_UNICODETEXT)
+ {
+ bytes = (uint)((text.Length + 1) * 2);
+ data = Marshal.StringToHGlobalUni(text);
+ }
+ else
+ {
+ // Not yet supported format.
+ return false;
+ }
+
+ if (data == IntPtr.Zero)
+ {
+ return false;
+ }
+
+ hGlobal = GlobalAlloc(GHND, (UIntPtr)bytes);
+ if (hGlobal == IntPtr.Zero)
+ {
+ return false;
+ }
+
+ IntPtr dataCopy = GlobalLock(hGlobal);
+ if (dataCopy == IntPtr.Zero)
+ {
+ return false;
+ }
+
+ CopyMemory(dataCopy, data, bytes);
+ GlobalUnlock(hGlobal);
+
+ if (SetClipboardData(format, hGlobal) != IntPtr.Zero)
+ {
+ // The clipboard owns this memory now, so don't free it.
+ hGlobal = IntPtr.Zero;
+ }
+ }
+ catch
+ {
+ // Ignore failures
+ }
+ finally
+ {
+ if (data != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(data);
+ }
+
+ if (hGlobal != IntPtr.Zero)
+ {
+ GlobalFree(hGlobal);
+ }
+ }
+
+ return true;
+ }
+
+ private static void ExecuteOnStaThread(Func action)
+ {
+ const int RetryCount = 5;
+ int tries = 0;
+
+ if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
+ {
+ while (tries++ < RetryCount && !action())
+ {
+ // wait until RetryCount or action
+ }
+
+ return;
+ }
+
+ Exception exception = null;
+ var thread = new Thread(() =>
+ {
+ try
+ {
+ while (tries++ < RetryCount && !action())
+ {
+ // wait until RetryCount or action
+ }
+ }
+ catch (Exception e)
+ {
+ exception = e;
+ }
+ });
+
+ thread.SetApartmentState(ApartmentState.STA);
+ thread.Start();
+ thread.Join();
+
+ if (exception != null)
+ {
+ throw exception;
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/GetClipboardCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/GetClipboardCommand.cs
index f033b13100b..7dda142c2eb 100644
--- a/src/Microsoft.PowerShell.Commands.Management/commands/management/GetClipboardCommand.cs
+++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/GetClipboardCommand.cs
@@ -3,72 +3,20 @@
using System;
using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.ComponentModel;
-using System.Diagnostics.CodeAnalysis;
-using System.Drawing;
-using System.Globalization;
-using System.IO;
-using System.Linq;
using System.Management.Automation;
-using System.Media;
-using System.Runtime.InteropServices;
-using System.Windows.Forms;
+using Microsoft.PowerShell.Commands.Internal;
namespace Microsoft.PowerShell.Commands
{
- ///
- /// Defines the different type supported by the clipboard.
- ///
- public enum ClipboardFormat
- {
- /// Text format as default.
- Text = 0,
-
- /// File format.
- FileDropList = 1,
-
- /// Image format.
- Image = 2,
-
- /// Audio format.
- Audio = 3,
- };
-
///
/// Defines the implementation of the 'Get-Clipboard' cmdlet.
/// This cmdlet get the content from system clipboard.
///
- [Cmdlet(VerbsCommon.Get, "Clipboard", HelpUri = "https://go.microsoft.com/fwlink/?LinkId=526219")]
+ [Cmdlet(VerbsCommon.Get, "Clipboard", HelpUri = "https://go.microsoft.com/fwlink/?LinkId=2109905")]
[Alias("gcb")]
- [OutputType(typeof(string), typeof(FileInfo), typeof(Image), typeof(Stream))]
+ [OutputType(typeof(string))]
public class GetClipboardCommand : PSCmdlet
{
- ///
- /// Property that sets clipboard type. This will return the required format from clipboard.
- ///
- [Parameter]
- public ClipboardFormat Format { get; set; }
-
- ///
- /// Property that sets format type when the return type is text.
- ///
- [Parameter]
- [ValidateNotNullOrEmpty]
- public TextDataFormat TextFormatType
- {
- get { return _textFormat; }
-
- set
- {
- _isTextFormatTypeSet = true;
- _textFormat = value;
- }
- }
-
- private TextDataFormat _textFormat = TextDataFormat.UnicodeText;
- private bool _isTextFormatTypeSet = false;
-
///
/// Property that sets raw parameter. This will allow clipboard return text or file list as one string.
///
@@ -79,76 +27,38 @@ public SwitchParameter Raw
set
{
- _isRawSet = true;
_raw = value;
}
}
private bool _raw;
- private bool _isRawSet = false;
///
/// This method implements the ProcessRecord method for Get-Clipboard command.
///
protected override void BeginProcessing()
{
- // TextFormatType should only combine with Text.
- if (Format != ClipboardFormat.Text && _isTextFormatTypeSet)
- {
- ThrowTerminatingError(new ErrorRecord(new InvalidOperationException(
- string.Format(CultureInfo.InvariantCulture, ClipboardResources.InvalidTypeCombine)),
- "FailedToGetClipboard", ErrorCategory.InvalidOperation, "Clipboard"));
- }
-
- // Raw should only combine with Text or FileDropList.
- if (Format != ClipboardFormat.Text && Format != ClipboardFormat.FileDropList && _isRawSet)
- {
- ThrowTerminatingError(new ErrorRecord(new InvalidOperationException(
- string.Format(CultureInfo.InvariantCulture, ClipboardResources.InvalidRawCombine)),
- "FailedToGetClipboard", ErrorCategory.InvalidOperation, "Clipboard"));
- }
-
- if (Format == ClipboardFormat.Text)
- {
- this.WriteObject(GetClipboardContentAsText(_textFormat), true);
- }
- else if (Format == ClipboardFormat.Image)
- {
- this.WriteObject(Clipboard.GetImage());
- }
- else if (Format == ClipboardFormat.FileDropList)
- {
- if (_raw)
- {
- this.WriteObject(Clipboard.GetFileDropList(), true);
- }
- else
- {
- this.WriteObject(GetClipboardContentAsFileList());
- }
- }
- else if (Format == ClipboardFormat.Audio)
- {
- this.WriteObject(Clipboard.GetAudioStream());
- }
+ this.WriteObject(GetClipboardContentAsText(), true);
}
///
/// Returns the clipboard content as text format.
///
- ///
- ///
- private List GetClipboardContentAsText(TextDataFormat textFormat)
+ /// Array of strings representing content from clipboard.
+ private List GetClipboardContentAsText()
{
- if (!Clipboard.ContainsText(textFormat))
+ var result = new List();
+ string textContent = null;
+
+ try
{
- return null;
+ textContent = Clipboard.GetText();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ ThrowTerminatingError(new ErrorRecord(new InvalidOperationException(ClipboardResources.UnsupportedPlatform), "FailedToGetClipboardUnsupportedPlatform", ErrorCategory.InvalidOperation, "Clipboard"));
}
- List result = new List();
-
- // TextFormat default value is Text, by default it is same as Clipboard.GetText()
- string textContent = Clipboard.GetText(textFormat);
if (_raw)
{
result.Add(textContent);
@@ -161,54 +71,5 @@ private List GetClipboardContentAsText(TextDataFormat textFormat)
return result;
}
-
- ///
- /// Returns the clipboard content as file info.
- ///
- ///
- private List GetClipboardContentAsFileList()
- {
- if (!Clipboard.ContainsFileDropList())
- {
- return null;
- }
-
- List result = new List();
- foreach (string filePath in Clipboard.GetFileDropList())
- {
- FileInfo file = new FileInfo(filePath);
- result.Add(WrapOutputInPSObject(file, filePath));
- }
-
- return result;
- }
-
- ///
- /// Wraps the item in a PSObject and attaches some notes to the
- /// object that deal with path information.
- ///
- ///
- ///
- ///
- private PSObject WrapOutputInPSObject(
- FileInfo item,
- string path)
- {
- PSObject result = new PSObject(item);
-
- // Now get the parent path and child name
- if (path != null)
- {
- // Get the parent path
- string parentPath = Directory.GetParent(path).FullName;
- result.AddOrSetProperty("PSParentPath", parentPath);
-
- // Get the child name
- string childName = item.Name;
- result.AddOrSetProperty("PSChildName", childName);
- }
-
- return result;
- }
}
}
diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/SetClipboardCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/SetClipboardCommand.cs
index bce2f7ec14e..3aed047f443 100644
--- a/src/Microsoft.PowerShell.Commands.Management/commands/management/SetClipboardCommand.cs
+++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/SetClipboardCommand.cs
@@ -3,17 +3,11 @@
using System;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Collections.Specialized;
-using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
-using System.IO;
-using System.Linq;
using System.Management.Automation;
using System.Text;
-using System.Text.RegularExpressions;
-using System.Windows.Forms;
+using Microsoft.PowerShell.Commands.Internal;
namespace Microsoft.PowerShell.Commands
{
@@ -21,20 +15,17 @@ namespace Microsoft.PowerShell.Commands
/// Defines the implementation of the 'Set-Clipboard' cmdlet.
/// This cmdlet gets the content from system clipboard.
///
- [Cmdlet(VerbsCommon.Set, "Clipboard", DefaultParameterSetName = "String", SupportsShouldProcess = true, HelpUri = "https://go.microsoft.com/fwlink/?LinkId=526220")]
+ [Cmdlet(VerbsCommon.Set, "Clipboard", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.Medium, HelpUri = "https://go.microsoft.com/fwlink/?LinkId=2109826")]
[Alias("scb")]
public class SetClipboardCommand : PSCmdlet
{
private List _contentList = new List();
- private const string ValueParameterSet = "Value";
- private const string PathParameterSet = "Path";
- private const string LiteralPathParameterSet = "LiteralPath";
///
/// Property that sets clipboard content.
///
- [Parameter(ParameterSetName = ValueParameterSet, Position = 0, Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
- [AllowNull]
+ [Parameter(Position = 0, Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
+ [System.Management.Automation.AllowNull]
[AllowEmptyCollection]
[AllowEmptyString]
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
@@ -46,41 +37,6 @@ public class SetClipboardCommand : PSCmdlet
[Parameter]
public SwitchParameter Append { get; set; }
- ///
- /// Property that sets Path parameter. This will allow to set file formats to Clipboard.
- ///
- [Parameter(ParameterSetName = PathParameterSet, Mandatory = true, ValueFromPipelineByPropertyName = true)]
- [ValidateNotNullOrEmpty]
- [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
- public string[] Path { get; set; }
-
- ///
- /// Property that sets LiteralPath parameter. This will allow to set file formats to Clipboard.
- ///
- [Parameter(ParameterSetName = LiteralPathParameterSet, Mandatory = true, ValueFromPipelineByPropertyName = true)]
- [Alias("PSPath")]
- [ValidateNotNullOrEmpty]
- [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
- public string[] LiteralPath { get; set; }
-
- ///
- /// Property that sets html parameter. This will allow html content rendered as html to clipboard.
- ///
- [Parameter]
- public SwitchParameter AsHtml
- {
- get { return _asHtml; }
-
- set
- {
- _isHtmlSet = true;
- _asHtml = value;
- }
- }
-
- private bool _asHtml;
- private bool _isHtmlSet = false;
-
///
/// This method implements the BeginProcessing method for Set-Clipboard command.
///
@@ -94,26 +50,10 @@ protected override void BeginProcessing()
///
protected override void ProcessRecord()
{
- // Html should only combine with Text content.
- if (Value == null && _isHtmlSet)
- {
- ThrowTerminatingError(new ErrorRecord(new InvalidOperationException(
- string.Format(CultureInfo.InvariantCulture, ClipboardResources.InvalidHtmlCombine)),
- "FailedToSetClipboard", ErrorCategory.InvalidOperation, "Clipboard"));
- }
-
if (Value != null)
{
_contentList.AddRange(Value);
}
- else if (Path != null)
- {
- _contentList.AddRange(Path);
- }
- else if (LiteralPath != null)
- {
- _contentList.AddRange(LiteralPath);
- }
}
///
@@ -121,27 +61,15 @@ protected override void ProcessRecord()
///
protected override void EndProcessing()
{
- if (LiteralPath != null)
- {
- CopyFilesToClipboard(_contentList, Append, true);
- }
- else if (Path != null)
- {
- CopyFilesToClipboard(_contentList, Append, false);
- }
- else
- {
- SetClipboardContent(_contentList, Append, _asHtml);
- }
+ SetClipboardContent(_contentList, Append);
}
///
/// Set the clipboard content.
///
- ///
- ///
- ///
- private void SetClipboardContent(List contentList, bool append, bool asHtml)
+ /// The content to store into the clipboard.
+ /// If true, appends to clipboard instead of overwriting.
+ private void SetClipboardContent(List contentList, bool append)
{
string setClipboardShouldProcessTarget;
@@ -150,7 +78,7 @@ private void SetClipboardContent(List contentList, bool append, bool asH
setClipboardShouldProcessTarget = string.Format(CultureInfo.InvariantCulture, ClipboardResources.ClipboardCleared);
if (ShouldProcess(setClipboardShouldProcessTarget, "Set-Clipboard"))
{
- Clipboard.Clear();
+ Clipboard.SetText(string.Empty);
}
return;
@@ -159,15 +87,7 @@ private void SetClipboardContent(List contentList, bool append, bool asH
StringBuilder content = new StringBuilder();
if (append)
{
- if (!Clipboard.ContainsText())
- {
- WriteVerbose(string.Format(CultureInfo.InvariantCulture, ClipboardResources.NoAppendableClipboardContent));
- append = false;
- }
- else
- {
- content.AppendLine(Clipboard.GetText());
- }
+ content.AppendLine(Clipboard.GetText());
}
if (contentList != null)
@@ -175,7 +95,6 @@ private void SetClipboardContent(List contentList, bool append, bool asH
content.Append(string.Join(Environment.NewLine, contentList.ToArray(), 0, contentList.Count));
}
- // Verbose output
string verboseString = null;
if (contentList != null)
{
@@ -198,230 +117,8 @@ private void SetClipboardContent(List contentList, bool append, bool asH
if (ShouldProcess(setClipboardShouldProcessTarget, "Set-Clipboard"))
{
- // Set the text data
- Clipboard.Clear();
- if (asHtml)
- Clipboard.SetText(GetHtmlDataString(content.ToString()), TextDataFormat.Html);
- else
- Clipboard.SetText(content.ToString());
- }
- }
-
- ///
- /// Copy the file format to clipboard.
- ///
- ///
- ///
- ///
- private void CopyFilesToClipboard(List fileList, bool append, bool isLiteralPath)
- {
- int clipBoardContentLength = 0;
- HashSet dropFiles = new HashSet(StringComparer.OrdinalIgnoreCase);
-
- // Append the new file list after the file list exists in the clipboard.
- if (append)
- {
- if (!Clipboard.ContainsFileDropList())
- {
- WriteVerbose(string.Format(CultureInfo.InvariantCulture, ClipboardResources.NoAppendableClipboardContent));
- append = false;
- }
- else
- {
- StringCollection clipBoardContent = Clipboard.GetFileDropList();
- dropFiles = new HashSet(clipBoardContent.Cast().ToList(), StringComparer.OrdinalIgnoreCase);
-
- // we need the count of original files so we can get the accurate files number that has been appended.
- clipBoardContentLength = clipBoardContent.Count;
- }
- }
-
- ProviderInfo provider = null;
- for (int i = 0; i < fileList.Count; i++)
- {
- Collection newPaths = new Collection();
-
- try
- {
- if (isLiteralPath)
- {
- newPaths.Add(Context.SessionState.Path.GetUnresolvedProviderPathFromPSPath(fileList[i]));
- }
- else
- {
- newPaths = Context.SessionState.Path.GetResolvedProviderPathFromPSPath(fileList[i], out provider);
- }
- }
- catch (ItemNotFoundException exception)
- {
- WriteError(new ErrorRecord(exception, "FailedToSetClipboard", ErrorCategory.InvalidOperation, "Clipboard"));
- }
-
- foreach (string fileName in newPaths)
- {
- // Avoid adding duplicated files.
- if (!dropFiles.Contains(fileName))
- {
- dropFiles.Add(fileName);
- }
- }
- }
-
- if (dropFiles.Count == 0)
- return;
-
- // Verbose output
- string setClipboardShouldProcessTarget;
- if ((dropFiles.Count - clipBoardContentLength) == 1)
- {
- if (append)
- {
- setClipboardShouldProcessTarget = string.Format(CultureInfo.InvariantCulture, ClipboardResources.AppendSingleFileToClipboard, dropFiles.ElementAt(dropFiles.Count - 1));
- }
- else
- {
- setClipboardShouldProcessTarget = string.Format(CultureInfo.InvariantCulture, ClipboardResources.SetSingleFileToClipboard, dropFiles.ElementAt(0));
- }
- }
- else
- {
- if (append)
- {
- setClipboardShouldProcessTarget = string.Format(CultureInfo.InvariantCulture, ClipboardResources.AppendMultipleFilesToClipboard, (dropFiles.Count - clipBoardContentLength));
- }
- else
- {
- setClipboardShouldProcessTarget = string.Format(CultureInfo.InvariantCulture, ClipboardResources.SetMultipleFilesToClipboard, dropFiles.Count);
- }
- }
-
- if (ShouldProcess(setClipboardShouldProcessTarget, "Set-Clipboard"))
- {
- // Set file list formats to clipboard.
- Clipboard.Clear();
- StringCollection fileDropList = new StringCollection();
- fileDropList.AddRange(dropFiles.ToArray());
- Clipboard.SetFileDropList(fileDropList);
+ Clipboard.SetText(content.ToString());
}
}
-
- ///
- /// Generate HTML fragment data string with header that is required for the clipboard.
- ///
- /// The html to generate for.
- /// The resulted string.
- private static string GetHtmlDataString(string html)
- {
- // The string contains index references to other spots in the string, so we need placeholders so we can compute the offsets.
- // The "<<<<<<<<1,<<<<<<<<2, etc" strings are just placeholders. We'll back-patch them actual values within the header location afterwards.
- const string Header = @"Version:0.9
-StartHTML:<<<<<<<<1
-EndHTML:<<<<<<<<2
-StartFragment:<<<<<<<<3
-EndFragment:<<<<<<<<4
-StartSelection:<<<<<<<<3
-EndSelection:<<<<<<<<4";
-
- const string StartFragment = "";
- const string EndFragment = @"";
-
- var sb = new StringBuilder();
- sb.AppendLine(Header);
- sb.AppendLine(@"");
-
- // if given html already provided the fragments we won't add them
- int fragmentStart, fragmentEnd;
- int fragmentStartIdx = html.IndexOf(StartFragment, StringComparison.OrdinalIgnoreCase);
- int fragmentEndIdx = html.LastIndexOf(EndFragment, StringComparison.OrdinalIgnoreCase);
-
- // if html tag is missing add it surrounding the given html
- // find the index of " 0 ? html.IndexOf('>', htmlOpenIdx) + 1 : -1;
- // find the index of " 0 ? html.IndexOf('>', bodyOpenIdx) + 1 : -1;
-
- if (htmlOpenEndIdx < 0 && bodyOpenEndIdx < 0)
- {
- // the given html doesn't contain html or body tags so we need to add them and place start/end fragments around the given html only
- sb.Append("");
- sb.Append(StartFragment);
- fragmentStart = GetByteCount(sb);
- sb.Append(html);
- fragmentEnd = GetByteCount(sb);
- sb.Append(EndFragment);
- sb.Append("");
- }
- else
- {
- // insert start/end fragments in the proper place (related to html/body tags if exists) so the paste will work correctly
- // find the index of "