Convertissez les fichiers Get-Clipboard et Set-Clipboard PowerShell de Keith Hill en script PSM1

Je voudrais convertir l’implémentation C # de Get-Clipboard et Set-Clipboard en Keith Hill en PowerShell pur sous forme de fichier .PSM1.

Existe-t-il un moyen de créer un thread STA dans PowerShell comme il le fait dans son applet de commande lors de l’utilisation du Presse-papiers?

Le blog post
Le code

TextBox ne nécessite pas de commutateur -STA.

function Get-ClipBoard { Add-Type -AssemblyName System.Windows.Forms $tb = New-Object System.Windows.Forms.TextBox $tb.Multiline = $true $tb.Paste() $tb.Text } function Set-ClipBoard() { Param( [Parameter(ValueFromPipeline=$true)] [ssortingng] $text ) Add-Type -AssemblyName System.Windows.Forms $tb = New-Object System.Windows.Forms.TextBox $tb.Multiline = $true $tb.Text = $text $tb.SelectAll() $tb.Copy() } 

Reportez-vous à la section inférieure pour connaître le module multi-édition et multiplate-forme offrant une prise en charge du texte du presse-papier dans PowerShell Core et dans Windows PowerShell v2 – v4.

Tentative de synthèse de la situation et des options de Windows PowerShell v5.1 / PowerShell Core v6.1.0 :

  • Windows PowerShell version 5.0 + : utilisez les applets de commande Get-Clipboard et Set-Clipboard intégrées.

  • Windows PowerShell v4.0- (v1 – v4.0): aucune applet de commande intégrée pour interagir avec le Presse-papiers , mais il existe des solutions de contournement :

    • Utilisez les extensions de communauté PowerShell (PSCX; http://pscx.codeplex.com/ ), fournies avec plusieurs cmdlets liées au Presse-papiers, qui vont au-delà du traitement de texte.
    • Pipe vers l’ utilitaire de ligne de commande standard clip.exe (W2K3 + côté serveur, Vista + côté client) [1]:

      • Remarque: Outre les problèmes d’encodage abordés ci-dessous, ... | clip.exe ... | clip.exe ajoute invariablement une nouvelle ligne de fin à l’entrée; le seul moyen d’éviter cela consiste à utiliser un fichier temporaire dont le contenu est fourni via la redirection d’entrée < cmd - reportez Set-ClipboardText fonction Set-ClipboardText ci Set-ClipboardText dessous.

      • Si seul le support de caractères ASCII (7 bits) est requirejs: fonctionne par défaut.

      • Si seule la prise en charge du codage OEM (8 bits) (par exemple, IBM437 aux États-Unis) est nécessaire, exécutez d'abord les tâches suivantes:

        • $OutputEncoding = [System.Text.Encoding]::GetEncoding([System.Globalization.CultureInfo]::CurrentCulture.TextInfo.OEMCodePage)
      • Si un support complet Unicode est requirejs, un codage UTF-16 LE sans nomenclature doit être utilisé; lancez d'abord le suivant:

        • $OutputEncoding = New-Object System.Text.UnicodeEncoding $false, $false # UTF-16 encoding *without BOM*
        • Exemple à tester (la console PS affiche les caractères asiatiques sous la forme "??", mais les gère toujours correctement - vérifiez le contenu du Presse-papiers dans le Bloc-notes, par exemple):

          • "I enjoyed Thomas Hübl's talk about 中文" | clip # should appear as is on the clipboard
      • Remarque: L'atsortingbution à $OutputEncoding comme ci-dessus fonctionne $OutputEncoding dans l'étendue globale , mais pas autrement, comme dans une fonction , en raison d'un bogue de Windows PowerShell version 5.1 / PowerShell Core v6.0.0-rc.2 - voir https: //github.com/PowerShell/PowerShell/issues/5763

        • Dans un contexte non global, utilisez (New-Object ...).psobject.BaseObject pour contourner le bogue ou - dans PSv5 + - utilisez plutôt [...]:new() .
      • Note: clip.exe comprend apparemment 2 formats:

        • la page de codes OEM actuelle du système (par exemple, IBM 437)
        • UTF-16 LE ("Unicode")
        • Malheureusement, clip.exe traite toujours une nomenclature en tant que données , d'où la nécessité d'utiliser un codage sans nomenclature.
        • Notez que les codages ci-dessus ne sont importants que pour la détection correcte de l' entrée ; une fois dans le presse - papiers , la chaîne d'entrée est disponible dans tous les encodages suivants: UTF-16 LE, "ANSI" et OEM.
    • Utilisez une solution basée sur PowerShell avec utilisation directe des classes .NET :

      • Notez que l'access au Presse-papiers ne peut se produire qu'à partir d'un thread en mode STA (single-threaded apartment) - par opposition à MTA (multi-threaded apartment):

        • v3: STA est la valeur par défaut (le mode MTA peut être -mta powershell.exe avec le commutateur -mta ).
        • v2 et v1: MTA est la valeur par défaut ; Le mode STA peut être -sta powershell.exe avec le commutateur -sta .
        • Ergo: Les fonctions robustes devraient pouvoir accéder au presse-papiers à partir de sessions dans l'un ou l'autre mode.
  • PowerShell Core (multiplate-forme), à compter de la v6.1.0 , n’a pas d’applet de commande intégré pour l’interaction avec le Presse-papiers , même lorsqu’il est exécuté sous Windows .

    • La solution consiste à utiliser des utilitaires ou des API spécifiques à la plate-forme (voir ci-dessous).

Le module My ClipboardText fournit des fonctions "polyfill" Get-ClipboardText et Set-ClipboardText pour obtenir et définir du texte à partir du presse-papiers . ils fonctionnent sur Windows PowerShell v2 + ainsi que sur PowerShell Core (avec des limitations, voir ci-dessous).

Dans le cas le plus simple (PSv5 + ou v3 / v4 avec les modules de gestion de paquet installés), vous pouvez l' installer à partir de la galerie PowerShell à partir d'une session surélevée / sudo comme suit :

 Install-Module ClipboardText 

Pour plus d'informations, y compris sur les prérequirejs et les instructions d'installation manuelle, voir le référentiel .

  • Remarque: À proprement parler, les fonctions ne sont pas des tâches multiples , étant donné que leurs noms diffèrent des applets de commande intégrées. Cependant, le suffixe de nom Text a été choisi de manière à indiquer explicitement que ces fonctions traitent uniquement du texte.

  • Le code s'appuie sur des informations provenant de différents sites, notamment la réponse de @ hoge ( https://stackoverflow.com/a/1573295/45375 ) et http://techibee.com/powershell/powershell-script-to-copy-powershell- commande-sortie-vers-presse-papiers / 1316

  • Sous Windows PowerShell v5 + en mode STA :

    • Les cmdlets intégrées ( Get-Clipboard / Set-Clipboard ) sont appelées en arrière-plan.
      Notez que le mode STA (un modèle de thread COM) est le mode par défaut depuis la v3, mais vous pouvez choisir de passer en mode MTA (mode multithread) avec l'option de ligne de commande -MTA .
  • Dans tous les autres cas (Windows PowerShell v4 et / ou en mode MTA, PowerShell Core sur toutes les plateformes sockets en charge):

    • Les utilitaires natifs sont appelés en coulisse
      • Windows: clip.exe pour définir le texte et une solution WSH / JScript pour obtenir du texte.
      • macOS: pbcopy et pbpaste
      • Linux: xclip , si disponible et installé ;
        par exemple, sur Ubuntu, utilisez sudo apt-get xclip pour installer.
  • Set-ClipboardText peut accepter n'importe quel type d'object (s) en tant qu'entrée (qui est / est ensuite convertie en texte de la même manière que dans la console), directement ou à partir du pipeline.

  • Appelez avec -Verbose pour voir quelle technique est utilisée en coulisse pour accéder au presse-papiers.


[1] Une version antérieure de cette réponse affirmait à tort que clip.exe :
- ajoute toujours un saut de ligne lors de la copie dans le presse-papier (PAS)
- gère correctement les nomenclatures UTF-16 LE dans les fichiers redirigés vers stdin via < vs lorsque l'entrée est acheminée via | ( clip.exe copie également toujours la nomenclature dans le presse-papiers).

Vous devriez d’abord vérifier votre hôte. ISE exécute déjà STA, il n’est donc pas nécessaire de créer un autre thread ou un autre shell (optimisation figurant dans ma liste de tâches pour PSCX). Pour l’invite de la console, qui est MTA, alors je voudrais passer au code binary comme le montre Oisin ou utiliser une simple petite application C # comme:

 using System; using System.Runtime.InteropServices; using System.Windows.Forms; class OutClipboard { [STAThread] static void Main() { Clipboard.SetText(Console.In.ReadToEnd()); } } 

Et pour obtenir le contenu du presse-papiers, Vista et les versions ultérieures ont clip.exe.

Je ne pense pas que même les fonctions avancées 2.0 soient prêtes à laisser les gens faire la fête avec leurs propres threads .NET dans un script.

Jetez un coup d’œil à la recette de Lee Holme dans PowerShell Cookbook: Set-Clipboard . Vous pouvez utiliser at comme Set-Clipboard.ps1 ou simplement déposer le code dans une fonction PowerShell ( voici un exemple tiré de mon profil PowerShell).

Le script vous permettra d’obtenir la sortie complète de la tuyauterie dans le presse-papiers, par exemple:

 dir | Set-Clipboard 

J’ai initialement appris la solution de Lee Holme grâce à cette réponse .