Hatena::Groupsubtech

ういはるかぜの化学

Saturday, December 08, 2012

Windows RTでもPowerShellしたい 00:22 Windows RTでもPowerShellしたい - ういはるかぜの化学 を含むブックマーク はてなブックマーク - Windows RTでもPowerShellしたい - ういはるかぜの化学

こんにちは。今日はPowerShell Advent Calendar 2012ということでWindows RTでPowerShellを動かすことについてちょっと書いてみたいと思います。

Windows RTとPowerShellってなに

まあこのエントリを読みつつそのような疑問を持たれるかたも少ないのではないかという気もしますが簡単に説明しておきます。

Windows RTというのはWindows 8の姉妹OSで簡単にいうところARMCPUに対応してWindows 8から機能を削って、Windows ストアアプリしかインストールできないようにしたタブレット向けOSです。Windows ストアアプリしかインストールできませんがOfficeInternet Explorerなどといったものが動く従来のデスクトップが存在しています。ですので見た目上にはほとんど変わりありません。

次にPowerShellですがこちらはWindowsのコマンドシェルというかまあバッチ処理用スクリプト言語、といった感じです。どちらかといえばシステム管理者向けのものという感じです。

.NET Frameworkの上に構築された仕組みなので.NET Frameworkのライブラリを使うことができたりします。

どうしてWindows RTでPowerShell

Windows RTでもPowerShellをという話なのですがどうして動かしたいのかという話を簡単に。

先ほどWindows RTの説明でも少し触れましたがWindows RTというのはWindows 8に見えるのにデスクトップアプリケーションをインストール・起動できないという制限があります。デスクトップアプリケーションというのはいわゆるEXEファイルです。これを持って行っても動かすことはできないようになっています(プラットフォーム非依存な.NETなバイナリであってもです

ですがまあ何か自作のものを動かしたくなるというのが人というもの。自作のものを動かす環境として実行ファイル以外に何があるか考え思いつく方法は以下のものがあります。

この中で一番強そうなのは.NET Frameworkパワーを使えるPowerShellです。.NETのアセンブリを読み込めたら何でもできそうです。ということでPowerShellを使うことができるのかなと夢が膨らみます。

Windows RTにPowerShellはあるの?

そもそもWindows RTにPowerShellはインストールされているの?という話がありますがインストールされています。

ちゅきさんがまとめてくださっていますがWindows RTでもPowerShell ISEはないもののコマンドプロンプトでの利用はできるようになっています。

Surface(Windows RT)でPowerShell

スタートに表示しなくても普通にエクスプローラからも開くことができますね。

Windows RTのPowerShellはどこまでできるの?

Windows RTにもPowerShellが入っていることがわかりました。ということでいろいろできそうな予感がしてきました。

アセンブリは読み込めるの?

まずはアセンブリを読み込めるかどうかです。初めにSystem.Windows.Forms.dllを読み込んでみます。Windows Forms使えればいろいろ作れそうですよね。

PS C:\Users\Tomoyo\Desktop> Add-Type -AssemblyName "System.Windows.Forms"
PS C:\Users\Tomoyo\Desktop> [System.Windows.Forms.Form]

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    Form                                     System.Windows.Forms.ContainerControl

おお、特にエラーもなく動いたようです。では自作のアセンブリはどうでしょうか。適当にコンパイルしたものを置いてみます。

PS C:\Users\Tomoyo\Desktop> Add-Type -Path .\MyAssembly.dll
Add-Type : Could not load file or assembly 'file:///C:\Users\Tomoyo\Desktop\MyAssembly.dll' or one of its dependencies.
 Windows cannot verify the digital signature for this file. A recent hardware or software change might have installed a file that is signed incorrectly or damaged, or that might be malicious software from an unknown source. (Exception from HRESULT: 0x80070241)
At line:1 char:1
+ Add-Type -Path .\MyAssembly.dll
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Add-Type], FileLoadException
    + FullyQualifiedErrorId : System.IO.FileLoadException,Microsoft.PowerShell.Commands.AddTypeCommand

うーむ。エラーが出ました。署名して証明書を入れてもダメなのでどうしてもダメそうです。ちなみにTraceListenerにしてしれっと読み込まれるようにしたらどうかと思いましたがそれもダメでした。

まあWindows Formsのアセンブリを読み込めたのでよしとします。

Add-Typeでコードを追加して型を定義する

PowerShellにはAdd-Typeというコマンドがありまして、このコマンドではC#などのコードを流しこんで型を作ることができるという裏技チックなことができます。

ということはこれを使えばアセンブリ読み込まなくてもC#のコードを動かせるのでは!?と思うのも当然という感じです。というわけでさっそく呼んでみましょう。

PS C:\Users\Tomoyo\Desktop> Add-Type -TypeDefinition "public class Hauhau {}"
Add-Type : Cannot add type. Definition of new types is not supported in this language mode.
At line:1 char:1
+ Add-Type -TypeDefinition "public class Hauhau {}"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (:) [Add-Type], PSNotSupportedException
    + FullyQualifiedErrorId : CannotDefineNewType,Microsoft.PowerShell.Commands.AddTypeCommand

なんかエラーがでました。この言語モードでは型を追加するのがサポートされていない、ということのようです。なんというがっかり。

読み込んだアセンブリのクラスを作る

というわけで自作のアセンブリを読み込むことはできず、C#のコードで型を定義することもできない、こうなったらPowerShellのスクリプトで頑張るしかないのです。

ということでWindows FormsでFormを作ってみましょう。

PS C:\Users\Tomoyo\Desktop> New-Object System.Windows.Forms.Form
New-Object : Cannot create type. Only core types are supported in this language mode.
At line:1 char:1
+ New-Object System.Windows.Forms.Form
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (:) [New-Object], PSNotSupportedException
    + FullyQualifiedErrorId : CannotCreateTypeConstrainedLanguage,Microsoft.PowerShell.Commands.NewObjectCommand

oh…エラー…どうもコアタイプのみNew-Objectできるようです。コアタイプというのはInt32とかそういういかにもコアな型のようです。

PS C:\Users\Tomoyo\Desktop> New-Object System.Int32
0
読み込んだアセンブリのクラスのメソッドを呼ぶ

まさかクラスからオブジェクトを作りだすことが禁止されているとは…という感じですがめげずに次の手を考えます。

とりあえずオブジェクトを作るだけならActivatorクラスのCreateInstanceメソッドを呼んだらよさそうな気がします。

PS C:\Users\Tomoyo\Desktop> [System.Activator]::CreateInstance([System.Windows.Forms.Form])
Cannot invoke method. Method invocation is supported only on core types in this language mode.
At line:1 char:1
+ [System.Activator]::CreateInstance([System.Windows.Forms.Form])
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodInvocationNotSupportedInConstrainedLanguage

この言語モードではコアタイプのメソッドのみがーというエラーが…まさかのメソッド呼び出しにも制限が。

PS C:\Users\Tomoyo\Desktop> [System.Windows.Forms.MessageBox]::Show("Hauhau")
Cannot invoke method. Method invocation is supported only on core types in this language mode.
At line:1 char:1
+ [System.Windows.Forms.MessageBox]::Show("Hauhau")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodInvocationNotSupportedInConstrainedLanguage

デスヨネー…。

リモート接続はできるのかどうか?(クライアントとして)

自作の何かを動かす話からちょっと変わりますが、PowerShellにはリモート接続する機能が備わっていますがこれは使えるのでしょうか?

ということで試してみます。まずはSurface RTからWindows 8に対して接続してみます。

PS C:\Users\Tomoyo\Desktop> set-item wsman:/localhost/Client/TrustedHosts -Value *

WinRM Security Configuration.
This command modifies the TrustedHosts list for the WinRM client. The computers in the TrustedHosts list might not be
authenticated. The client might send credential information to these computers. Are you sure that you want to modify
this list?
[Y] Yes  [N] No  [S] Suspend  [?] Help (default is "Y"): y
PS C:\Users\Tomoyo\Desktop> enter-pssession -computername Anies -Credential Anies\Tomoyo
[Anies]: PS C:\Users\Tomoyo\Documents>

おお、なんか普通に接続できました。

リモート接続はできるのかどうか?(サーバーとして)

では逆にWindows 8からSurface RTに接続できるのかどうか。とりあえずEnable-PSRemotingしてみます。

PS C:\Users\Tomoyo\Desktop> Enable-PSRemoting

WinRM Quick Configuration
Running command "Set-WSManQuickConfig" to enable remote management of this computer by using the Windows Remote
Management (WinRM) service.
 This includes:
    1. Starting or restarting (if already started) the WinRM service
    2. Setting the WinRM service startup type to Automatic
    3. Creating a listener to accept requests on any IP address
    4. Enabling Windows Firewall inbound rule exceptions for WS-Management traffic (for http only).

Do you want to continue?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"):
WinRM has been updated to receive requests.
WinRM service type changed successfully.
WinRM service started.

WinRM has been updated for remote management.
Created a WinRM listener on HTTP://* to accept WS-Man requests to any IP on this machine.
WinRM firewall exception enabled.
Configured LocalAccountTokenFilterPolicy to grant administrative rights remotely to local users.


Confirm
Are you sure you want to perform this action?
Performing operation "Set-PSSessionConfiguration" on Target "Name: microsoft.powershell SDDL:
O:NSG:BAD:P(A;;GA;;;BA)(A;;GA;;;RM)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD). This will allow selected users to remotely run
Windows PowerShell commands on this computer".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"):

Confirm
Are you sure you want to perform this action?
Performing operation "Set-PSSessionConfiguration" on Target "Name: microsoft.powershell.workflow SDDL:
O:NSG:BAD:P(A;;GA;;;BA)(A;;GA;;;RM)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD). This will allow selected users to remotely run
Windows PowerShell commands on this computer".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"):
PS C:\Users\Tomoyo\Desktop> enter-pssession -computername localhost
[localhost]: PS C:\Users\Tomoyo\Documents> dir


    Directory: C:\Users\Tomoyo\Documents


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        2012/11/06      3:23            OneNote Notebooks

とりあえずEnable-PSRemotingできて、localhostでの接続はできました。ということで続けてWindows 8から接続してみます。

PS C:\Users\Tomoyo\Desktop> Enter-PSSession -ComputerName Honeycomb -Credential (略)
[Honeycomb]: PS C:\Users\Tomoyo\Documents> Get-WmiObject Win32_ComputerSystem


Domain              : WORKGROUP
Manufacturer        : Microsoft
Model               : Surface with Windows RT
Name                : HONEYCOMB
PrimaryOwnerName    : Windows User
TotalPhysicalMemory : 2087518208

おお、接続できました。何が嬉しいのかわかりませんが管理できそうですね。ちなみにちゃんと制限言語モードになっているので大したことはできません。

まとめ

ということでまとめるとWindows RTのPowerShellでできることこんな感じです。

  • アセンブリはMicrosoftによって署名されているものを読み込める
  • インスタンスを作れるクラスはコアタイプとして認識されている一部のクラスに限られている
  • メソッドやプロパティなどの呼び出しもコアタイプとして認識されているクラスに限られている
  • リモート接続はサーバーとしてもクライアントとしても一応動く

なんという使い物にならなさ...。まあリモート接続はできるのでシステム管理者のような方はWindows ServerやOffice 365のメンテができてうれしいですね。

とはいえコアタイプにWebClientとかもあるので実際何があるのか、というのは調べてみる価値はあるかもしれません(時間切れ)。

トラックバック - http://subtech.g.hatena.ne.jp/mayuki/20121208