ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

Windows PowerShellコミュのPowerShell質問箱

  • mixiチェック
  • このエントリーをはてなブックマークに追加

コメント(62)

状況がよく分かりませんが、
コマンドプロンプトで同様の操作をしてログインできますか?
できないならPowerShell側の問題ではありません。
PowerShellスクリプトでtelnetサーバにつないでLinuxサーバ側にログインしてLinuxサーバをコントロールしたい…ということなんでしょうか?

それとも単にtelnetコマンドの使い方がわからないと言うことなんでしょうか?
説明不足で申し訳ございません。

>それとも単にtelnetコマンドの使い方がわからないと言うこ
>となんでしょうか?

こちらは問題ありません。

>PowerShellスクリプトでtelnetサーバにつないでLinuxサー
>バ側にログインしてLinuxサーバをコントロールしたい…と
>いうことなんでしょうか?

こちらになります。
telnetでサーバに繋いだ後、ユーザ名、パスワードをPowerShell
のスクリプトから送る方法が分りません。

申し訳ございませんが、宜しくお願いします。
そのやり方ですと、telnet実行した段階で、
telnetのプロンプトに切り替わってしまうので、
下記は無理ではないでしょうか。

> telnetでサーバに繋いだ後、ユーザ名、パスワードをPowerShell
> のスクリプトから送る方法が分りません。

代替案として、
System.Net.Sockets.TcpClientクラスを利用する方法があります。

サンプル作ったので載せておきますね。
これを拡張してみてください。
#$hostname、$port、$user、$passは
#適切な値に変えてください。

==================================================================
function ReadLine()
{
$reader.ReadLine()
}

function SendLine([String]$str)
{
$bytes = [Byte[]]([Text.Encoding]::ASCII.GetBytes($str + "`r`n"))
$stream.Write($bytes, 0, $bytes.Length)
}

$hostname="サーバ名"
$port=23
$user="ユーザ名"
$pass="パスワード"

$client = New-Object Net.Sockets.TcpClient($hostname,$port)
$stream = $client.getstream()
$reader = New-Object IO.StreamReader($stream,[Text.Encoding]::ASCII)

$reader.ReadLine()

SendLine("USER $user")
$reader.ReadLine()

SendLine("PASS $pass")
$reader.ReadLine()

SendLine("PWD")
$reader.ReadLine()

SendLine("QUIT")
$reader.ReadLine()

$stream.close()
$client.close()
==================================================================
>newpopsさん

いつもアドバイスありがとうございます。

早速拡張して試してみたのですが、最初の「$reader.ReadLine() 」を
実行したところで固まってしまいます。相手から受け取るデータがなく
待ち状態になっているようにも思えます。(TelnetではなくFTPだと、
FTPサーバからのレスポンスをreadできています。) もし、そうなので
あればデーターが無い場合、どのような処理を追加すればよいのでしょ
うか?

申し訳ございませんが、宜しくお願いします。
>TelnetではなくFTPだと、FTPサーバからのレスポンスをreadできています。

失礼しました。
実は、LINUXにtelnet(23)できる環境がなかったので、
FTP(21)で確認したサンプルでした。(^^;

telnetの場合、コネクト後のネゴシエーション部分を
実装してあげる必要があるのだと思います。
#すみません。このあたりは詳しくありません。
>newpopsさん

ありがとうございます。
後は、パケットをとるなりして頑張ってみます。
お世話になっています。takuです。

いつも質問ばかりで申し訳ないのですが、エクセルの
プロセスが残る件で質問させて下さい。

下記の様なエクセルのブックを開いて閉じているだけの
ものですが、閉じた後もタスクマネージャーのプロセス
画面で確認するとエクセルのタスクが残ったままになっ
ています。

「$excelworkbook.Close()、$excelapp.Quit()」だけで
は閉じないのでしょうか? Get-Processでプロセスを止
める必要があるのでしょうか?

すみませんが、アドバイス宜しくお願いします。

-----------------------------------------------------
$excelapp = New-Object -ComObject Excel.Application
$excelworkbook = $excelapp.Workbooks.Open("D:\Book1.xls")

$excelworkbook.Close()
$excelapp.Quit()
えー、このケースでしたら
$excelapp=$excelworkbook=$null
[GC]::Collect()
で、execl.exeが終了すると思います。
簡単にまとめると、Excelのobjectを参照している変数をnullにして、ガベージコレクタを動作させるという方法です。
追記します。お手軽にガベージコレクタを動作させましたが、GC以外の方法であれば、Excelオブジェクトを参照している各変数に対して、ReleaseComObjectメソッドを呼びます。
[Runtime.InteropServices.Marshal]::ReleaseComObject($excelworkbook)
[Runtime.InteropServices.Marshal]::ReleaseComObject($excelapp)
というものです。
はじめまして

2バイト文字でのSortの昇順と、
文字列の比較時のコードの大小について教えて下さい。

SortはSJISで、比較のときはUnicodeで
処理されてしまうようなのですが、
何処かにコードの指定するとこありませんか?

やりたいことは、ディレクトリィのメンバーを名前でソートして、二つのディレクトリィ間で比較したいのです。
Sort-Objectをどのように指定されていますか? PowerShell自体は内部でUTF-16で動作していると思うのですけど。Sort-Objectは、デフォルトで-CaseSensitiveでないので。
後は、配列を作って自分で[Array]::Sortメソッドを呼んで処理する方法などもありますけどね。
ありがとうございます。

Get-Childitem|Sort Fullname
みたいな感じで使いたいです。

とりあえずは、自分でソートロジック入れて
Sortは、外してます。

実際に、新と現の文字でトラブりました。

PS C:\>
PS C:\> $a ="新","現"
PS C:\> $a
新
現
PS C:\> ($a[0] -lt $a[1])
True
PS C:\> $b = $a|sort $_
PS C:\> $b
現
新
PS C:\> ($b[0] -lt $b[1])
False
PS C:\> $c = $a|sort $_ -caseSensitive
PS C:\> $c
現
新
PS C:\> ($c[0] -lt $c[1])
False
PS C:\>
えーっと。確認しました。文字列のままでsort-objectを使うと確かに、変わんないですね。このケースだとcharを使うことで上手くいきましたが、全てのケースで大丈夫かは別の問題です。
PS C:\ >$a = "新","現"
PS C:\ >$b = @()
PS C:\ >foreach ( $i in $a) { $b += [char] $i}
PS C:\ >$b
新
現
PS C:\ >$c = $b |sort
PS C:\ >$c
新
現
PS C:\ >$c[0] -lt $c[1]
True
PS C:\ >$a[0] -lt $a[1]
True
PS C:\ >$a|sort
現
新

なので文字列比較は、charで行っているのではないかと。sort-objectが違いそうですね。ソートロジックを作られていて、問題がないのならそのまま使う方が良いのでは、ないでしょうか。
>kazaさん

ありがとうございます。

自宅ではPowerShellの環境がないので、
火曜日にいじってみます。

とりあえず、いまの仕組みでやるしかにのかな?

sort-objectつかえると、
簡潔でいいのですが…

逆に、文字列比較をSort-Objectにあわせられれば…
質問です。

パラメータの
ValueFromPipelineByPropertyName
がTrueになっている場合、具体的にどういうことが可能になるのでしょうか?MSDNを見たのですがコマンドレットの実装について書いてあるのみで実際にどういう動きをするかについてはよくわかりません。

ValueFromPipelineはパイプを渡ってきたオブジェクトがそのままパラメータに渡されるということで理解できるのですが…

あとValueFromRemainingArgumentsもいまいち意味がわかりません。

どなたかご教示願えると幸いです。
# ヘルプを眺めただけなので、正しくない可能性が十分にあります。叩き台にでもしてください。

ValueFromPipelineByPropertyNameは、COMのIPropertyBagとIPersistPropertyBagの対のような働きではないかとみています。
入ってくるPipelineを既定(?)のフォーマットで区切り、そこに複数のオブジェクトを流し込んで、それをCmdlet側で復元して、更に事前に用意したプロパティに代入しておいてくれる、というものだと思います。

それに対してValueFromPipelineでは、入ってくるPipelineをより直接的に使えるようにする、というのかも知れません。

ValueFromRemainingArgumentsはParamArrayのようなものではないか、と思います。
ValueFromPipelineByPropertyNameは、SDKによるとプロパティで値が渡されたかどうかを示すとあります。でAdding Parameters that Process Pipeline Inputには「名前でPowerShellランタイムがチェックする」とあります。
ValueFromRemainingArgumentsは、SDKでは未指定の引数をすべて受け取ったかどうかを示すとあります。つまり$argsで受け取ったかどうかという意味でしょうかねー。
>K.J.K.さん
なんとなくですがちょっとわかった気になりました、ありがとうございます。ただ実例がちょっと思い浮かばないですね。

>kazaさん
ありがとうございます。
http://msdn2.microsoft.com/en-us/library/ms714597.aspx
http://msdn2.microsoft.com/en-us/library/system.management.automation.parameterattribute.valuefrompipelinebypropertyname.aspx
ですね。
でも意味がよくわからないんです(汗
具体例がどこかにあるといいんですが・・・

ValueFromRemainingArgumentsについては分かった気がします。
えーと、何となくですがValueFromPipelineByPropertyNameですが、実用性があるかどうかは別として、以下のような記述ができます。
$a = Dir a*
$a | Dir
この時の$aは、FileInfoとDirectoryInfoを含んだ配列です。このオブジェクトのプロパティから値を取り出したかをPowerShellランタイムがチェックするという意味だと思います。Dirの実態のGet-ChildItemでは、PathとLiteralPathパラメータにValueFromPipelineByPropertyNameが指定されています。
ありがとうございます。
うーん、あと一歩で理解できそうなんですが。
パイプを通った時、FileInfoオブジェクトのPSPathプロパティがLiteralPathパラメータに渡る、ということでしょうか?
LiteralPathはエイリアスとしてPSPathがあるのはそういう意味だったのかな?(まだ誤解している可能性あり)
でもPathプロパティはFileInfoオブジェクトにないですしそういう意味じゃないのかも・・・
やっぱりその理解で正しかったようです。
もしPathプロパティがあったらちゃんとそれが-pathパラメータに渡ります。

PS C:\script> $a = "hoge"
PS C:\script> $a = $a | add-member noteproperty Path "a*" -passthru
PS C:\script> $a.path
a*
PS C:\script> $a|dir


ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\script


Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2007/07/20 18:33 0 a.txt
-a--- 2007/07/21 16:17 8826 about_Alias.help.txt
ですね。私も同じことを試していました。
私の場合は、psobjectを使っていました。
$a = new-object psobject
$a | add-member noteproperty path "a*" -passthru
$a | dir
get-childitemのパラメータ属性をReflctorで調べのは内緒っと。
あ、ちょっとうそでした。$aじたいが文字列だとだめですね。それが渡ってしまう。実際は$a=1ってやってました。
http://blogs.wankuma.com/mutaguchi/archive/2007/07/21/86361.aspx

ブログのネタにさせていただきましたー
psobjectのほうが素直なのでそちらを採用しました。
久し振りなんですが、「&」オペレータに関して気がついたことを少しまとめます。
ご存知のように「&」オペレータを使うとスクリプトブロックを実行することができます。が、色々と試していくとコマンド実行オペレータという表現が私には、しっくりきます。具体的には、以下のような記述ができるからです。
function test { "Test Function" }
test # 関数呼び出し
&test # 同じく関数呼び出し
"Test Script File" > "test1.ps1"
.\test1 # スクリプトファイルの実行
&.\test1 # 同じくスクリプトファイルの実行
$a = "Get-ChildItem"
&$a # Get-ChildItemの実行
Invoke-Expression $a # Get-ChildItemの実行

この結果を見ると、「&」オペレータで実行できるのはコマンドであるということが理解できます。変数にコマンドを文字列として設定した場合は、引数を文字列の中に入れられないのですけど(例えば、 &$a -recurse という感じです)。
何気にInvoke-Expressionしないで使える点が、気にいっています。
皆さんは、如何でしょうか。
WMIでWin32_Productクラスを使おうとしたら、Windows Vistaではエラーになりました。どうもVistaのWMIのバグらしいです。このためWindows InstallerのCOMを使おうと思ったら、このCOMのタイプライブラリにはcoclassの定義がありません。このためNew-Object -comでは、プロパティやメソッドをマップできないようです。
結局、Typeオブジェクトのインスタンスを取得して、Invokeでプロパティを呼び出すはめになりました。
Windows InstallerのProgIDは「WindowsInstaller.Installer」なのですが、環境によってはProgIDが登録されていないOSもあるようです。WSHのサンプルなどを探すと、Windows Installer 2.0あたりからProgIDは登録されているようなんですが、皆様の環境では如何でしょうか。
coclassの記述がないとVB6などではnewできないだけで、ProgIDがあればVBScriptなどではCreateObjectでインスタンスが作成できます。
# ちなみに、CLSIDとIIDが同一値なので、標準のTLBコンパイラではcoclassは無理のようです。

で、私の環境(XP)で、ですが、例えばインターフェースInstallerが、標準では、
HKEY_CLASSES_ROOT\Interface\{000C1090-0000-0000-C000-000000000046}
で存在しますが、
HKEY_CLASSES_ROOT\Interface\{000C1090-0000-0000-C000-000000000046}\TypeLib
のキーが存在していませんでした。

そこで、
[HKEY_CLASSES_ROOT\Interface\{000C1090-0000-0000-C000-000000000046}\TypeLib]
@="{000C1092-0000-0000-C000-000000000046}"
"Version"="1.0"
を登録してみるとどうなるのでしょうか?
Version=1.0は、値ですよね。
{000C1090-0000-0000-C000-000000000046}には、TypeLibとVersionが登録されているんですよ。
TypeLibのキーが存在するとProgIdが存在するのかしら。
どうもいじりすぎてたようです。RegSvr32でmsi.dllを登録するときちんと入っていますね。という訳で先ほどのは撤回します。

Installerオブジェクトの挙動で妙なところは、
1,OLEViewでインスタンスを作成し、そこからタイプライブラリのソースを表示させようとすると、LoadRegTypeLibで失敗した、というエラーが出る。
2,VB6でObject型としてインスタンスを得て、TLI.InterfaceInfoFromObjectでInterfaceInfoを得ようとすると失敗する。
があることを確認しています。
あらら...
ということはProgIdは標準的にあると考えて良いのかな。
coclassがない点とCLSIDとIIDが同じであるという点が、new-objectコマンドレットでは、メンバーをマップできないと考えて良いのかも知れません。
まだ確認はしていませんが、おそらくInstallerオブジェクトのIDispatch::GetTypeInfoが有効なITypeInfoのインスタンスを返さないのだと思います。
それで、メンバーメソッドの逆引きができないのかと。

VB6やVBScriptだと、この過程をスキップして、IDispatch::GetIDsOfNamesとInvokeだけで済ましているので、特に問題は起きないのではないかと。

そういう意味では、VB6のObject型やVBSと同様にIDispatchをそのまま処理する仕組みがあると楽かも知れません。
# でも、そのまま入れるのはそぐわない気がします。
有難うございます。
COM側の実装の問題ですね。そういう類のCOMをPowerShellから扱おうとすると、面倒な手間がかかるということになるんですね。
VistaにおけるWMIのWin32_Productクラスですが、Vista SP1 RC1で試したところ、問題が解消されていました。Get-WmiObjectで普通に使えます。
SP1じゃない環境では、エラーになりますのでご注意くださいませ。
こんにちは。

Add-MemberでNotePropertyを付加し、変数に代入すると
NotePropertyが引き継がれない、という事がありアドバイス頂きたい次第です。

実際にやりたい内容は下記のような感じです。
$host1 = get-host
$host1 | add-member noteproperty prop "test"
$host1.prop -eq $null ←?
$array = new-object system.collections.arraylist
[void]$array.add($host1)
$array[0].prop -eq $null ←?

?はFalse、?はTrueになります。

$host1 = get-host
$host1 | add-member noteproperty prop "test"
$host1.prop -eq $null ←?
$host2 = $host1
$host2.prop -eq $null ←?

?、?いずれもTrueになります。

2つの結果からオブジェクト型の相違に原因があるような気がするのですが、、
アドバイス下さい。よろしくお願いします。
$host1 = get-host
$host1 | add-member noteproperty prop "test"
$host1.prop -eq $null ←?
$host2 = $host1
$host2.prop -eq $null ←?

?、?いずれもFalseの誤りです。
失礼しました。。
あまり時間が無くこの場で質問させて下さい。
バッチファイルで%1を変数に代入する場合「set HOGE=%1」等、UNIXシェルスクリプトでは「export HOGE=$1」とするが、Powershellで同等のことが出来なく困っております。

お手数ですがご教授願います。

ログインすると、残り25件のコメントが見れるよ

mixiユーザー
ログインしてコメントしよう!

Windows PowerShell 更新情報

Windows PowerShellのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。