質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

PowerShell

Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

Q&A

2回答

4291閲覧

powershell関数での値渡し

satousan

総合スコア10

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

PowerShell

Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

0グッド

0クリップ

投稿2016/07/29 08:11

編集2016/08/01 04:40

##質問
powershellで、関数の値渡しを行おうとしているのですが、
以下エラーが出てしまいます。

##やろうとしていること
複数の宛先端末(windows)にpingを打って、生きていたらpsexecでゴニョゴニョ

###発生している問題・エラーメッセージ
引数の型をSystem.voidにすることはできません。
発生場所 C:sourcepath**.ps1:33 文字7

  • $out=mypsexec($myarg)

###該当のソースコード

$pinfo = New-Object System.Diagnostics.ProcessStartInfo $pcname = (Get-Content list.txt) -as [string[]] function mypsexec($in){ $pinfo.FileName ="PsExec.exe" $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.CreateNoWindow = $True $pinfo.Arguments = $in $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo [void]$p.Start() | Out-Null $stdout="" while (!$p.HasExited){ $line = $p.StandardOutput.ReadLine() $stdout += $line + "`n" } [void]$p.WaitForExit() [void]$p.Close() [void]$p.Dispose() return $stdout } for($i = 0; $i -lt $pcname.Count; $i++) { $pingAlive = @(Test-Connection -ComputerName $pcname[$i] -Quiet -count 1 ) if ($pingAlive -eq $True) { Write-Host ($pcname[$i] ) $myarg="` \\" + $pcname[$i] + "` -u` admin` -p` ****** cmd.exe` /c` type` %windir%\system32\drivers\etc\hosts" $out=mypsexec($myarg) if ([String]::IsNullOrEmpty($out) -eq $True){ echo "can not get hosts. nothing to do" }else{ //ゴニョゴニョ } } } }

###試したこと
デバッガーを起動しステップ実行。$myargに文字は入っている。
gettypeを実行したところ$myargはsystem.objectになっている

###補足情報(言語/FW/ツール等のバージョンなど)
os:windows7 SP1
psversion:3.0

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

何をしているのかわからない PsExec.exe が出てきたり、Get-Content があるのに cmd を使って type していたりと、かなり無駄があるように見受けられます。
無駄のあるソースにはバグがあり、インデントのないソースのデバッグは困難です。

管理者権限でメモ帳を開いてhostsを編集するコマンド を参考に書き直してみてください。もしかしたら二、三行にすっきり収まるかもしれませんよ。
###追記
色々制約があるので(にしては PsExec は OK だったり UAC を無効にしていたりポートを開いたりしているようですが)、こうなりましたが、これできちんと動作することを確認しました。
Test-Admin および Start-ScriptAsAdmin は スクリプトを管理者権限で実行するから頂戴しました。
これらを別のスクリプトファイルに分ければ見やすくなると思います。

PowerShell

1$computerNames = '...\list.txt' 2$psexec = '...\psexec' 3 4function Test-Admin 5{ 6 ( 7 [Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]:: 8 GetCurrent() 9 ).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) 10} 11 12function Start-ScriptAsAdmin 13{ 14 param( 15 [string] 16 $ScriptPath, 17 [object[]] 18 $ArgumentList 19 ) 20 if(!(Test-Admin)) 21 { 22 $list = @($ScriptPath) 23 if($null -ne $ArgumentList) 24 { 25 $list += @($ArgumentList) 26 } 27 Start-Process powershell -ArgumentList $list -Verb RunAs 28 } 29} 30 31Start-ScriptAsAdmin $PsCommandPath $Args 32Get-Content $computerNames | Foreach-Object { 33 if (Test-Connection -ComputerName $_ -Quiet -count 1) { 34 Write-Host ($_) 35 $out = &$psexec "\\$_\" cmd /c "type %WINDIR%\System32\drivers\etc\hosts" 36 $out 37 } 38}

投稿2016/08/01 03:03

編集2016/08/02 04:52
Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2016/08/01 03:11 編集

ちなみに %WINDIR% は ${ENV:windir} と表せます。
satousan

2016/08/02 01:27

powershellはglue言語と認識しています。質問は、windows環境にて環境の制約に合わせ、その隙間を埋めるために、標準入出力経由でのデータのやり取りが基本になると考え行っています。 >何をしているのかわからない hosts fileの走査とこれによる後段処理の分岐です。ただこれは、質問の趣旨ではなく、詳しくは書いていません。標準入出力経由でのデータのやり取り関数作成が主題です >Get-Content があるのに cmd を使って type していたり 走査対象pcはドメイン外にあり容易にポリシー変更が出来ず、全端末においてpowershellが使えるわけではありません。故に、対象pc上でget-contentを実行することは出来ないと認識していますが、この様な制約下においても、powershellだけで、目的達成が可能なのでしょうか。psexecについては、対応するpowershell関数等があるのかもしれませんが、現状は存じておりません。2行程度で完結できるのであればぜひともご教授ねがいたいです
Zuishin

2016/08/02 02:10

PowerShell にはリモート機能がありますが、権限の変更ができないというのであれば仕方がありません。 psexec の中身がわからないので断定はできませんが、状況から見て psexec のバグの可能性は高いと思います。別のファイルを表示しているのではないですか?
Zuishin

2016/08/02 02:20

psexec は自作のものかと思っていました。今調べて違うことを知りました。 そうであればバグは別のところかもしれません。 せっかくソース表示にしていただいたので読んでみます。
satousan

2016/08/08 04:15

遅くなりすみません。コマンド実行部分の「&」演算子等を調べていますがはっきりしたものがなくよく分かっていません。 ``` $out = &$psexec "\\$_\" cmd /c "type %WINDIR%\System32\drivers\etc\hosts" 「&」の直後に実行ファイルパス格納変数を置き、その後に、引数文字列を置くのでしょうか。cmd /c部分は、文字列扱い?なのでしょうか。よろしくお願いいたします。
Zuishin

2016/08/08 04:44

そうですね。& の直後に文字列や変数やスクリプトブロックを置くと、その内容を実行します。そして引数の文字列はクォーテーションしなくて済む場合はしなくていいというルールがあります。 & Call operator Runs a command, script, or script block. The call operator, also known as the "invocation operator," lets you run commands that are stored in variables and represented by strings. Because the call operator does not parse the command, it cannot interpret command parameters. C:\PS> $c = "get-executionpolicy" C:\PS> $c get-executionpolicy C:\PS> & $c AllSigned
guest

0

コードは三連バッククォート ( ```)で括ってください。

エラーの方は関数内の

powershell

1[void]$p.Start() | Out-Null

ps

1$p.Start() | Out-Null

としたらうまくいきませんか?

投稿2016/07/29 14:25

flied_onion

総合スコア2604

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

satousan

2016/08/01 01:13

引数の型をSystem.voidになるエラーは解消しました。ありがとうございました。 が、stdoutの文字列が途中で切れてしまい、 全てを取得できない状況です。具体的には、上記コードにも記載している %windir%\system32\drivers\etc\hosts" のtext情報が、以下の様に、途中で切れた状態になってしまいます。 #Copyright (c) 1993-2009 Microsoft Corp. # #This is a sample HOSTS file used 該当端末で当該hostファイルをtypeすると、 当然used以降も表示されます。何か制限等があるのでしょうか。
flied_onion

2016/08/01 02:28

とりあえずコードブロックを見やすい形に直してください。
satousan

2016/08/01 05:39

とりあえず、コード部分を囲みました。よろしくお願いいたします
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問