성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] The Windows Registry Adventure #1: ...
[정성태] systemd for Developers I ; https:/...
[정성태] 엄밀히 object 타입의 인스턴스가 다른 타입으로 형변환 가능...
[정성태] 아래의 글에서 나오는 "Windows Application Pa...
[정성태] The history of calling conventions,...
[정성태] Secure and Deploy .NET Windows Form...
[정성태] Get Started with Milvus Vector DB i...
[정성태] cyberark/PipeViewer - A tool that...
[정성태] WinForms in a 64-Bit world – our st...
[정성태] 예제에서 SELECT_SQL도 내부적으로는 SqlCommand/...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>PowerShell ISE의 스크립트를 복사 후 PPT/Word에 붙여 넣으면 한글이 깨지는 문제</h1> <p> 아는 분이, PowerShell ISE 도구에서 스크립트 내용을 PowerPoint로 복사하면 깨진다고... 하는군요. ^^ 직접 해보니... 다음과 같이, 아주 잘~~~ 깨집니다.<br /> <br /> <img alt='ise_paste_into_ppt_1.png' src='/SysWebRes/bbs/ise_paste_into_ppt_1.png' /><br /> <br /> 혹시 이것을 해결할 수 있는 방법이 없을까요? 마이크로소프트의 경우, "확장(Extension)" 구조를 제공하기로 유명한데 실제로 PowerShell ISE에도 "Add-ons" 메뉴가 있습니다. 그렇다면 아마도 PowerShell ISE에 대한 객체 모델이 있을 것이고 그것을 이용해 사용자가 선택한 텍스트를 "한글이 깨지기 이전의 상태"로 구한다면... 하는 상상을 할 수 있게 만듭니다. ^^<br /> <br /> 다행히 이와 관련해서 검색해 보면 다음의 코드를 발견할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Colorized capture of console screen in HTML and RTF. ; <a target='tab' href='https://devblogs.microsoft.com/powershell/how-to-copy-colorized-script-from-powershell-ise/'>https://devblogs.microsoft.com/powershell/how-to-copy-colorized-script-from-powershell-ise/</a> Copy-Script.zip ; <a target='tab' href='https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/09/31/20/78/Copy-Script.zip'>https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/09/31/20/78/Copy-Script.zip</a> </pre> <br /> 코드에 이미 대부분의 내용이 구현되어 있는데요,<br /> <br /> <pre style='height: 400px; margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ############################################################################################################## # Copy-Script.ps1 # # The script entire contents of the currently selected editor window to system clipboard. # The copied data can be pasted into any application that supports pasting in UnicodeText, RTF or HTML format. # Text pasted in RTF or HTML format will be colorized. # # Create RTF block from text using named console colors. # function Append-RtfBlock ($block, $tokenColor) { $colorIndex = $rtfColorMap.$tokenColor $block = $block.Replace('\','\\').Replace("`r`n","\cf1\par`r`n").Replace("`t",'\tab').Replace('{','\{').Replace('}','\}') $null = $rtfBuilder.Append("\cf$colorIndex $block") } # Generate an HTML span and append it to HTML string builder # function Append-HtmlSpan ($block, $tokenColor) { if ($tokenColor -eq 'NewLine') { $null = $htmlBuilder.Append("<br>") } else { $block = $block.Replace('&','&amp;').Replace('>','&gt;').Replace('<','&lt;') if (-not $block.Trim()) { $block = $block.Replace(' ', '&nbsp;') } $htmlColor = $psise.Options.TokenColors[$tokenColor].ToString().Replace('#FF', '#') $null = $htmlBuilder.Append("<span style='color:$htmlColor'>$block</span>") } } function Copy-Script { if (-not $psise.CurrentOpenedFile) { Write-Error 'No script is available for copying.' return } $text = $psise.CurrentOpenedFile.Editor.Text trap { break } # Do syntax parsing. $errors = $null $tokens = [system.management.automation.psparser]::Tokenize($Text, [ref] $errors) # Set the desired font and font size $fontName = 'Lucida Console' $fontSize = 10 # Initialize HTML builder. $htmlBuilder = new-object system.text.stringbuilder $null = $htmlBuilder.AppendLine("<p style='MARGIN: 0in 10pt 0in;font-family:$fontname;font-size:$fontSize`pt'>") # Initialize RTF builder. $rtfBuilder = new-object system.text.stringbuilder # Append RTF header $null = $rtfBuilder.Append("{\rtf1\fbidis\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 $fontName;}}") $null = $rtfBuilder.Append("`r`n") # Append RTF color table which will contain all Powershell console colors. $null = $rtfBuilder.Append("{\colortbl ;") # Generate RTF color definitions for each token type. $rtfColorIndex = 1 $rtfColors = @{} $rtfColorMap = @{} [Enum]::GetNames([System.Management.Automation.PSTokenType]) | % { $tokenColor = $psise.Options.TokenColors[$_]; $rtfColor = "\red$($tokenColor.R)\green$($tokenColor.G)\blue$($tokenColor.B);" if ($rtfColors.Keys -notcontains $rtfColor) { $rtfColors.$rtfColor = $rtfColorIndex $null = $rtfBuilder.Append($rtfColor) $rtfColorMap.$_ = $rtfColorIndex $rtfColorIndex ++ } else { $rtfColorMap.$_ = $rtfColors.$rtfColor } } $null = $rtfBuilder.Append('}') $null = $rtfBuilder.Append("`r`n") # Append RTF document settings. $null = $rtfBuilder.Append('\viewkind4\uc1\pard\f0\fs20 ') $position = 0 # Iterate over the tokens and set the colors appropriately. foreach ($token in $tokens) { if ($position -lt $token.Start) { $block = $text.Substring($position, ($token.Start - $position)) $tokenColor = 'Unknown' Append-RtfBlock $block $tokenColor Append-HtmlSpan $block $tokenColor } $block = $text.Substring($token.Start, $token.Length) $tokenColor = $token.Type.ToString() Append-RtfBlock $block $tokenColor Append-HtmlSpan $block $tokenColor $position = $token.Start + $token.Length } # Append HTML ending tag. $null = $htmlBuilder.Append("</p>") # Append RTF ending brace. $null = $rtfBuilder.Append('}') # Copy console screen buffer contents to clipboard in three formats - text, HTML and RTF. # $dataObject = New-Object Windows.DataObject $dataObject.SetText([string]$text, [Windows.TextDataFormat]"UnicodeText") $rtf = $rtfBuilder.ToString() $dataObject.SetText([string]$rtf, [Windows.TextDataFormat]"Rtf") $html = $htmlBuilder.ToString() $dataObject.SetText([string]$html, [Windows.TextDataFormat]"Html") [Windows.Clipboard]::SetDataObject($dataObject, $true) 'The script has been copied to clipboard.' } $psise.CustomMenu.Submenus.Add("Copy Script", {Copy-Script}, $null) </pre> <br /> 위의 스크립트를 보면, ISE로부터 현재 열려있는 파일의 텍스트를 가져와서,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > $text = $psise.CurrentFile.Editor.Text </pre> <br /> Token 분해를 한 다음,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > $tokens = [system.management.automation.psparser]::Tokenize($Text, [ref] $errors) </pre> <br /> 이를 바탕으로 RTF(및 HTML) 구문으로 새롭게 구성한 후 클립보드에 복사합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > $dataObject = New-Object Windows.DataObject $dataObject.SetText([string]$text, [Windows.TextDataFormat]"UnicodeText") $rtf = $rtfBuilder.ToString() $dataObject.SetText([string]$rtf, [Windows.TextDataFormat]"Rtf") $html = $htmlBuilder.ToString() $dataObject.SetText([string]$html, [Windows.TextDataFormat]"Html") [Windows.Clipboard]::SetDataObject($dataObject, $true) </pre> <br /> 스크립트에서 한글이 사용된 부분까지의 RTF 텍스트를 출력해 보면 다음과 같이 나옵니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > {\rtf1\fbidis\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 Lucida Console;}} {\colortbl ;\red0\green0\blue0;\red0\green0\blue255;\red0\green0\blue128;\red138\green43\blue226;\red128\green0\blue128;\red139\green0\blue0;\red255\green69\blue0;\red0\green0\blue139;\red0\green191\blue255;\red0\green128\blue128;\red169\green169\blue169;\red0\green100\blue0;} \viewkind4\uc1\pard\f0\fs20 \cf12 #테스트입니다. </pre> <br /> 보는 바와 같이 "#테스트입니다."라는 한글이 문장이 그대로 복사되고 있는데 바로 저 텍스트를 유니코드로 인코딩해서 처리하면 됩니다. 예를 들어, 다음과 같이 해주면 되는 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > {\rtf1\fbidis\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 Lucida Console;}} {\colortbl ;\red0\green0\blue0;\red0\green0\blue255;\red0\green0\blue128;\red138\green43\blue226;\red128\green0\blue128;\red139\green0\blue0;\red255\green69\blue0;\red0\green0\blue139;\red0\green191\blue255;\red0\green128\blue128;\red169\green169\blue169;\red0\green100\blue0;} \viewkind4\uc1\pard\f0\fs20 \cf12 #<span style='color: blue; font-weight: bold'>\u53580?\u49828?\u53944?\u51077?\u45768?\u45796?.</span> </pre> <br /> 따라서 Append-RtfBlock 함수의 구현을 다음과 같이 확장해 주면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > function Append-RtfBlock ($block, $tokenColor) { $colorIndex = $rtfColorMap.$tokenColor $block = $block.Replace('\','\\').Replace("`r`n","\cf1\par`r`n").Replace("`t",'\tab').Replace('{','\{').Replace('}','\}') $wordBuilder = new-object system.text.stringbuilder foreach ($ch in $block.ToCharArray()) { $n = [int]$ch if ($n -ge 255) // 255를 넘는 글자는 무조건 유니코드 인코딩으로 변경해 RTF에 추가 { $nText = $n.ToString() $null = $wordBuilder.Append("\u$($nText)?") } else { $null = $wordBuilder.Append($ch) } } $null = $rtfBuilder.Append("\cf$colorIndex $wordBuilder") } </pre> <br /> 이제부터는 한글이 섞인 스크립트를 복사할 때 Ctrl+C를 누르지 말고 다음과 같이 ".\copy2word.ps1" 스크립트를 실행한 후 PowerPoint/Word에 복사하면 됩니다<br /> <br /> <img alt='ise_paste_into_ppt_2.png' src='/SysWebRes/bbs/ise_paste_into_ppt_2.png' /><br /> <br /> (변경된 전체 소스 코드는 <a target='tab' href='https://github.com/stjeong/psscript/blob/master/copy2word.ps1'>github</a>에 올렸습니다.)<br /> <br /> <hr style='width: 50%' /><br /> <br /> 참고로, 원 소스 코드(Copy-Script.zip)에서는 HTML 포맷으로도 변환해 클립보드에 추가하는 내용이 있는데요, 이상하게 그 코드만 있으면 (워드에는 잘 복사가 되지만) PowerPoint에는 복사가 안 됩니다. 원인을 모르겠군요. ^^ 혹시 아시는 분은 덧글 부탁드립니다.<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1536
(왼쪽의 숫자를 입력해야 합니다.)