PowerShell -Part 6

■ このスレッドは過去ログ倉庫に格納されています
2022/02/13(日) 18:36:12.07ID:LaQ04ZoE
前スレ
PowerShell -Part 5
https://mevius.5ch.net/test/read.cgi/tech/1615994992/

次スレは>>980が立ててね!!
2023/04/23(日) 16:10:27.14ID:n0NMvdBV
>>799
どうやればごみ箱に移動できましょうか?
2023/04/23(日) 16:33:01.94ID:aISPDv4l
>>795
シェル名前空間はバグだか仕様だか判らない所があるから真面目に考えても無駄
もうそういう仕様と考えてファイルは1個1個送れば?
ワイルドカードはgciで展開できるんだし
2023/04/23(日) 17:57:33.46ID:ElcI27v7
>>798
サブスレッドがパイプラインに書き込めば次段が動くんじゃないの?
言い換えると >>792 のfunction targetは実現不可能ということ?
2023/04/24(月) 17:53:43.44ID:cODz6Qqq
>>801
どうもありがとうございます。そうします。
2023/04/25(火) 01:01:33.91ID:q0KJktEO
最近この言語で書くことあるけど関数の呼び出しを最初に書かないとエラー起こすなんて知らなくて問題解決に時間がかかった
多分ほとんどの人が関数はメインの後に書きたいと思うんだけどファイル分けて呼び出したりしてるの?
2023/04/25(火) 07:59:40.97ID:0OU27daL
>>804
> 多分ほとんどの人が関数はメインの後に書きたいと思うんだけど

んなことはない
呼び出される方を前に書かなきゃいけないのは他の言語でも多いぞ
2023/04/25(火) 08:14:10.57ID:Q567y34W
>>805
定義を上書きできる言語なら呼び出し順序に意味があると思うけど、そうじゃないならただの手抜き仕様
2023/04/25(火) 08:17:30.73ID:0OU27daL
>>806
実行速度が速くなる、スコープが明確になる、などのメリットがあって敢えて採用されてるんだよ
JSとかも古くからあるfunction構文は順序関係ないが今推奨されてるアロー関数だと前に書かなきゃだめだ
2023/04/25(火) 08:19:33.10ID:0OU27daL
あとスパゲティを防ぐ効果があるというメリットもあるな
C言語だとそれを目的にプロトタイプを書かない人もいる
2023/04/25(火) 08:27:15.73ID:h+X7r+oZ
関数同士の依存関係が明確で前の関数が後の関数に依存しないなら初めてのコードを読みやすくなるというメリットもあるな
2023/04/25(火) 08:33:08.87ID:TxIkuN+X
ホイスティングってJS以外であるの?
2023/04/25(火) 09:07:53.85ID:qRrW+mkA
Java隆盛くらいの時代には関数はどこに書いても良いのが当たり前として定着したけど
関数型プログラミングでは関数宣言は変数や定数の宣言と同じようなものだからどうしても順序を意識せざるを得ない
順序の扱いを自動でやってくれる仕組みがホイスティングなんだけど、そのルールの分かりにくさやいやらしさが開発者に嫌われてJavaScriptのvarがletとconstに取って代わられた歴史がある
2023/04/25(火) 11:26:54.33ID://VjHWfL
>>804
メインの部分をメイン関数として書いて実行時にメイン関数を呼び出すようにすればよいのでは?PowerShellはシェルとしても動くので実行時に先に関数が定義されていないといけないのは自然な動作のような気もする。
2023/04/25(火) 11:29:40.93ID:Y1VsObgt
vbsは関数後書きでもokだよ
よしvbs使おう
2023/04/25(火) 11:43:20.51ID:Xlw1eETD
>>812
begin process endブロック使いたいときに発狂しそうだな
2023/04/25(火) 21:27:41.00ID:RtJhGNCC
powershellでもclass内なら順序関係なくなるよ
2023/05/04(木) 17:38:09.61ID:spWJYsDj
自分のコード見たら別に後から宣言してても実行できてるんだが
コマンドレットの定義だとホイスティングされるとかある?
2023/05/04(木) 17:56:23.79ID:P088Z0u/
>>816
どういうコード書いてんのよ
818デフォルトの名無しさん
垢版 |
2023/05/04(木) 21:18:57.29ID:FdNSNO1e
>>816
古臭いと言われても、前に書いた方が無駄な混乱をさけられる。
2023/05/05(金) 18:03:31.01ID:gmBJZ0Nw
動的言語は第一級関数のクロージャが多いから、
関数外で宣言したローカル変数が、関数内へ持ち込まれるので、
スコープが広くて、ヤバイ

さらに、JS はホイスティングされるから、超ヤバイ

ただし、Ruby の関数だけは第一級関数のクロージャではなく、
関数外で宣言したローカル変数は、関数内へ持ち込まれない

だから他の言語よりも、圧倒的にバグらないので、初心者向き
2023/06/29(木) 13:26:04.42ID:GLUt9X10
get-childitem select-object Full name,でownerを追加する方法はありますか?ご存知の方、ご教示願います。
2023/06/29(木) 17:48:28.46ID:xt/PffdC
>820
Get-ChildItemだけではowner情報は取れない、Get-Aclで情報取得する必要がある
組み合わせで良ければ以下の様にSelect-Objectでプロパティ追加すれば出来る
Get-ChildItem|Select-Object FullName,@{n="Owner";e={Get-Acl $_.fullname|% {$_.Owner}}}
2023/07/07(金) 19:48:22.82ID:5l+s6JZK
Outlook を起動してメールを送りたいのですが
本文のメールのフォントサイズや色の指定が一切無視されます。
Outlook 側の設定なのか、コードが悪いのかもよくわからず。。。
スレ違いならすいません
===================

$outlook = New-Object -comObject Outlook.Application
$mail = $outlook.CreateItem(0)
$mail.Subject = "件名テスト"
$mail.HTMLBody = "<html><head><style type='text/css'>
body {font-size:11; font-family:Meiryo UI;}
</style></head><body>
ああああ<span style='text-decoration:underline; text-decoration-color:red;'>いいいい</span>ううう<br>
</body></html>"
$inspector = $mail.GetInspector
$inspector.Display()
#$mail.Send()
===================
上記のコードだとメイリオは設定されますが、フォントサイズは8.5になるし下線は黒色になります。
なにとぞご教示お願いします
2023/07/10(月) 00:01:29.03ID:pvSg+WfU
font-sizeの値に単位が無いから無視されてんじゃね
2023/07/10(月) 03:13:05.95ID:ixw20e1S
>>823
試したはず・・・と思いつつも確認したら普通に変更されました!!!
11px で確認したのかもしれません。11pt と書いたら普通に反映されました
ありがとうございます

ただ下線は相変わらず赤色にならず、黒色のままです。
#FF0000 も試したけど変わらず・・・
どうやら text-decoration-color がそもそも使えないようでした。
さささ<span style='text-decoration:underline; color:red;'>ししし</span>すすす<br>
とやったら文字も赤くなりましたが下線も赤くなりました。

Outlook に使える html の仕様との戦いな気がしてきた
これはどこで尋ねたら・・・
2023/07/10(月) 10:11:13.02ID:CzqO5vr+
後はstyle属性をシングルクォーテーションで括ってるのが気になった
全体の括りをシングルにして属性値をダブルに変更で動くと思うよ
2023/07/10(月) 10:51:54.81ID:ixw20e1S
シングルとダブルは変わりませんでした…
実際はPowerShellでメール本文内に変数を当てこむので
シングルのままでいこうと思います

あと下線だけ赤色は私の勘違いでした
赤下線の時は文字も赤くして問題なかったのでとりあえず解決しました

お手数おかけしました
ご助言くださった方ありがとうございました
2023/07/13(木) 11:56:03.10ID:cnmTEsiX
二週間ほど前に自分で調べて書いたのに、どうやって書いて動かしたのか全く思い出せなくて困ってます
自分で自分が信じられないんですが、教えてください。

やりたいこと:Read-Hostで指定したフォルダに存在するフォルダを取得し、各フォルダに指定したファイルをコピーする
引っかかっている点:
1)$input = Read-Host "コピー先フォルダを指定"
たとえばここでcopyと入力。規定のフォルダがC:\作業とする。
入力の結果、c:\作業\copyとして、ここにあるサブフォルダを取得したいので
$inputをc:\作業\copyにしたい。
2)Get-ChildItem でディレクトリ名のみ取得するには?
それでforeachでやってたと思うんですが・・・。
2023/07/13(木) 13:50:42.52ID:K8IsBXo8
Get-ChildItem -LiteralPath ([IO.Path]::Combine("C:\作業", (Read-Host "コピー先フォルダを指定"))) -Directory -Name
2023/07/13(木) 17:51:09.66ID:cnmTEsiX
>>828
わー初見のコード
でもおかげでなんとかできました。ありがとう。
2023/07/14(金) 04:02:22.77ID:vOCFwCnb
多分いままで書いてたコードはこれ

# 規定のフォルダのパスを作成
$parent = join-path 'c:\作業' $input

# 上記パスのサブフォルダ作成
$names = ls -pspath $parent -di | % name

下記はエイリアス(関数の別名)
ls := get-childitem
% := foreach-object
2023/07/14(金) 04:02:59.81ID:vOCFwCnb
# 上記パスのサブフォルダ作成

# 上記パスのサブフォルダ名を取得
832820
垢版 |
2023/07/18(火) 17:12:35.63ID:jBHsPJa3
>>821
遅くなりました。
set-location -pathで場所を指定したら、指定したフォルダのownerを取得できました。ありがとうございます。
get-Childitem -recruse -file ┃select-Object directoryName ,name ,extension ,Length Creationtime, lastACCESStime ,lastwriteTime, fullname ┃Export‐csv ‐Encodeing default xxx.csv
と一緒にできなかったのが悔やまれます。
2023/07/18(火) 18:02:52.05ID:uMqw2ex7
そういう時はadd-memberするんだよ
2023/07/18(火) 20:02:12.51ID:x3+Ehzia
>>821の何がだめで、あるいは何が分からなくて、そのコマンドに組み込めなかったのか分からんな。
起点ディレクトリ自体の情報もCSVに含めたい、って事なのかな。
2023/07/18(火) 22:45:48.56ID:BpIlHiPB
powershellの学習曲線は険しい
本人が納得したならもうそれでいいだろう
836820
垢版 |
2023/07/19(水) 08:31:15.42ID:wWAjwZqt
>>834
そうです。
2023/07/19(水) 15:47:04.50ID:mqKqy4GV
ならこんな感じで。

$dirPath = "起点ディレクトリのフルパス"
[IO.FileInfo]::new($dirPath) | %{$_; $_ | Get-ChildItem -Recurse -File} | Select-Object DirectoryName, Name, Extension, Length, CreationTime, LastAccessTime, LastWriteTime, FullName, @{N="Owner";E={($_ | Get-Acl).Owner};} | Export-Csv -Encoding Default xxx.csv

CSVの出力先がフルパスなら、Set-Locationはいらない。
838820
垢版 |
2023/07/24(月) 18:16:28.42ID:yY3fBN5A
>>837
ありがとうございますm(_ _)m
とりあえずownerを取得できました。列の入れ替えはPowerQueryで対処します。
neme,Extensio,owner,...したかったのですが。
2023/08/02(水) 23:31:49.70ID:8Lc0dkYb
Pythonでやったら楽なのに…と思う処理も他のメンバーに配る可能性を考えると泣く泣くpowershellでやることになる
嫌いな言語ではないけど凝った処理を書こうとすると見た目の癖が強いソースコードになりがち
2023/08/05(土) 08:55:12.86ID:4wFerhHK
Pythonは見た目の癖が強くないとでも?
2023/08/05(土) 09:35:04.11ID:wvUeqD5z
泣く泣くpowershellに草
2023/08/06(日) 22:29:47.72ID:5CExyS7F
質問なのですがパイプラインの結果を関数に渡して先頭からk番目を取り出すには一体どうすればorz
やりたいことはパイプラインの結果を検証する処理をサブルーチン化したい(k番目を取り出すのはその第一歩)

とりあえず書いたがうまく行ってないやつ:
function Test-RegEnt($reg_query_result, $exp_type, $exp_value) {
$reg_query_result | Select-Object -Index 2
}
Write-Output ("Test_A1:" + ($result | Select-Object -Index 2)) # 2行目が意図通りselectされる(" RegisteredOwner REG_SZ Admin")
$result2 = Test-RegEnt($result, 'REG_SZ', 'Admin')
Write-Output ("Test_A2:" + $result2)        # A1と同じ結果になるかと思いきや、'Admin' になる
2023/08/06(日) 22:31:40.76ID:5CExyS7F
先頭3行抜かしましたorz
$result = reg query 'HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion' /v 'RegisteredOwner'
$cnt = 0
$result | ForEach-Object{ "TEST[$cnt}:" + $_; $cnt++ }
この次に>>842のコード。
2023/08/06(日) 22:48:34.72ID:5CExyS7F
んまーなんかこれだとうまく行ったけんども思ってたのと違う……
function Test-RegEnt($exp_type, $exp_value) {
$Input | Select-Object -Index 2
}
$result = reg query 'HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion' /v 'RegisteredOwner'
$cnt = 0
$result | ForEach-Object{ "TEST[$cnt}:" + $_; $cnt++ }
Write-Output ("Test_A1:" + ($result | Select-Object -Index 2))
$result2 = ($result | Test-RegEnt('REG_SZ', 'Admin'))  # パイプラインの結果を引数ではなくパイプで渡す
Write-Output ("Test_A2:" + $result2)

実はパイプラインの結果(オブジェクトの配列)は関数引数に渡せなかったりするので?
つなみにfunctionの引数部分で [array]$reg_query_result としてみてもうまく行かなかった。
2023/08/07(月) 03:16:48.48ID:SSXgsNNw
文法が違う。
Test-RegEnt -reg_query_result $result -exp_type 'REG_SZ' -exp_value 'Admin'
とか
Test-RegEnt $result 'REG_SZ' 'Admin'
とか。
または
function Test-RegEnt {
  Param (
    [Parameter(ValueFromPipeline=$true)]
    [string] $reg_query_result,
    [string] $exp_type,
    [string] $exp_value
  )
  Begin {
    $cnt = 0
  }
  Process {
    $cnt++
    $idx = $cnt - 1
    if ($idx -eq 2) {
      $reg_query_result
      return
    }
  }
}
$result | Test-RegEnt -exp_type 'REG_SZ' -exp_value 'Admin'
2023/08/07(月) 06:50:14.57ID:L1yQ0BJe
>>845
レス㌧クス
$Input利用(>>844)とBegin { } Process { }利用の違いはわかりた
$resultが数億オブジェクトだったりしたら後者の方がパイプラインがスムーズに流れてよさげ(未検証

一方、
>実はパイプラインの結果(オブジェクトの配列)は関数引数に渡せなかったりするので?(>>844)
については関数の呼び出し箇所が
 $result | Test-RegEnt -exp_type 'REG_SZ' -exp_value 'Admin' # (1) OK
 Test-RegEnt -reg_query_result $result -exp_type 'REG_SZ' -exp_value 'Admin' # (2) NG (エラー)
やったから、これは「パイプラインの結果は関数引数には渡せない」((1)のように書くしかない)ということでFA?
2023/08/07(月) 06:54:08.66ID:FZVMVghc
Select-ObjectのSkipとFirst使えばできるのでは?
2023/08/07(月) 06:56:57.16ID:FZVMVghc
関数でやりたいという要件を見落としていた
2023/08/07(月) 07:04:28.71ID:FZVMVghc
>>842
> $result2 = Test-RegEnt($result, 'REG_SZ', 'Admin')

$result2 = Test-RegEnt $result 'REG_SZ' 'Admin'
でやりたいことはできるのではないでしょうか
2023/08/07(月) 22:40:57.49ID:SSXgsNNw
パイプラインと引数のどちらでも動くようにしたいなら
function Test-RegEnt {
  Param (
    [Parameter(ValueFromPipeline=$true)]
    [string[]] $reg_query_result,
    [string] $exp_type,
    [string] $exp_value
  )
  Begin {
    $cnt = 0
  }
  Process {
    foreach ($item in $reg_query_result) {
      $cnt++
      $idx = $cnt - 1
      if ($idx -eq 2) {
        $item
        break
      }
    }
  }
}

あくまでシンプルめのサンプルなんでSelect-Object -Index 2と全く同じ挙動とか期待しないように。
※作りこむならパイプが繋がってるのかチェックして分岐の処理書いたりする。

なお、大量のデータをパイプラインに流すのはお勧めできない。
パイプラインは途中での打ち切りとか難しいし、
結局は普通にループ処理書いた方が速いし制御しやすいし分かりやすい事が多い気がする。
2023/08/10(木) 07:01:52.35ID:3iQsMBl9
レス㌧クス、しかしながら大量データを引数で関数に渡すのはメモリ消費量、応答速度ともに悪くなることがわかったからやめるわサーセン;;;
どういうことかというと、bigfile.txtが(1行何か書いたいた後 Ctrl+A Ctrl+V Ctrl+V を22回反復とかで作った)
4194305行の巨大なテキストファイルだったとして、
  function Test-FileContent([string[]] $lines) { $cnt = 0; foreach ($line in $lines) { $cnt++; Write-Host "cnt=" $cnt } }
  $lines = Get-Content .\bigfile.txt # (1)
  Test-FileContent($lines) # Get-Content完了後の結果を引数で渡す
とするとお、「cnt= 1」が表示される前に(1)で永劫の時間待たされるますが、
  function Test-FileContent() { $cnt = 0; foreach ($line in $Input) { $cnt++; Write-Host "cnt=" $cnt } }
  Get-Content .\bigfile.txt | Test-FileContent  # Get-Contentが読んだら即パイプで渡す
とすると*即座に*「cnt= 1」以降のカウントが始まる
2023/08/10(木) 07:07:45.76ID:3iQsMBl9
つなみに
>$resultが数億オブジェクトだったりしたら後者の方がパイプラインがスムーズに流れてよさげ(>>846)
も検証すた、
>>846のレスポンスが即時のコードと似通っているが関数内でBEGIN { } PROCESS { }でなく$Inputをforeachループで回した場合、
すわなち
  function Test-FileContent() { $cnt = 0; foreach ($line in $Input) { $cnt++; Write-Host "cnt=" $cnt } }
  Get-Content .\bigfile.txt | Test-FileContent
とすると、、「cnt= 1」が表示される前に永劫の時間待たされる、、、

というわけで、パイプライン(の後段まで)に大量のデータを無駄に流すなというのは真やが
生じてしまった大量のデータはむしろパイプラインにしか流さないのが正義……
2023/08/10(木) 07:10:57.08ID:3iQsMBl9
>>851の肝心のところに誤記が合ったスマンヌorz
*即座に*「cnt= 1」以降のカウントが始まるコードは正しくはこれ↓
  function Test-FileContent() { BEGIN { $cnt = 0 } PROCESS { $cnt++; Write-Host "cnt=" $cnt } }
  Get-Content .\bigfile.txt | Test-FileContent
2023/08/11(金) 18:46:06.42ID:I7dwFhkG
パイプの利点は個数を意識しなくて済むことだけど中断が一切できないしデメリットの方が多い
よっぽどの事情でもない限りコマンドレット自作しても遅いだけで良い事なんて1つもない
公式のselect -firstなんかはパイプの流儀に従ってないから似た事をしようとしてもあれ?って自らの間違いに気付くんだよ
powershellの深遠を覗くとそのいい加減さにガッカリするだけ
2023/08/11(金) 19:17:06.70ID:SL3m3m5F
一番の利点はメモリの節約です
2023/08/11(金) 19:30:40.13ID:I7dwFhkG
メモリなんて遅さで相殺される
powershell + 大量データ = 遅くて不採用
2023/08/11(金) 19:42:42.98ID:bAYgNtyZ
>>856
使いどころを履き違えるとそうなる
2023/08/11(金) 19:56:15.04ID:I7dwFhkG
>>857
パイプに希望を見てるのかな
その認識では近く失望させられるだろう
2023/08/11(金) 20:07:52.72ID:PQblbJTG
一番良いのは、Windowsを使わない
これにかぎる
こんなクソなOSを世界中から捨てるべき
2023/08/11(金) 20:09:59.59ID:SL3m3m5F
Windowsは汎用事務処理端末としては競合なしだ
2023/08/11(金) 20:27:11.32ID:SL3m3m5F
メモリ効率とスループットは交換できるようなものではない
手軽さが不要ならPythonでも使っておけばいい
2023/08/11(金) 21:36:23.24ID:55Ub7uv5
いまだにPowerShellがWindows専用だと思ってるアホを真っ先に捨てるべき
2023/08/11(金) 23:05:41.72ID:FP8PIUGD
>>842の質問に戻るのですだが、動かなかったのは単純だが根本的な誤解してたのが原因……
C/C++と同じだろうというつもりで
>$result2 = Test-RegEnt($result, 'REG_SZ', 'Admin')
という呼び出し方に書いたが、これだと「Test-RegEntの第一引数$reg_query_resultに「配列」@($result, 'REG_SZ', 'Admin')を渡す」という意味になる
ので、関数内で
>$reg_query_result | Select-Object -Index 2
とやったら当然そのindex=2の要素 'Admin' が関数の出力となってた、というしくみ
2023/08/11(金) 23:07:08.58ID:FP8PIUGD
正しくは>>845式に
>Test-RegEnt -reg_query_result $result -exp_type 'REG_SZ' -exp_value 'Admin'
またはその省略表記としては
>Test-RegEnt $result 'REG_SZ' 'Admin' # カンマ区切りではなくてスペース区切り
にせねばならなかった
ことがわかったorz
止むにやまれない事情で昨日一日で1500行書いてデバッグしたらその過程でわかった|||。n_
2023/08/11(金) 23:11:54.59ID:FP8PIUGD
あと他のスクリプトをincludeするときの欠き方が気づかないとわかりにくい……
util.ps1 を同じフォルダにある someapp.ps1 からインクルードする場合は
'.\util.ps1'
ではダメで、
.'.\util.ps1'
にしないとutil.ps1で定義した何物も呼び出せないorz
ここで先頭の「.」はutil.ps1のスクリプトスコープを呼び出し元のスコープと同じにするという意味やがちょう紛らわしい……
2023/08/11(金) 23:20:54.21ID:FP8PIUGD
あと関数内においては代入文、[void]にキャストした文、if文とかの条件式 を除く全ての文が出力を持つ、
という仕様のせいで危うく恐ろしいバグを作り込むところやった;;;
function Show-ErrDlg($msg) {
  $wsobj = new-object -comobject wscript.shell
  $wsobj.popup($msg, 0, 'エラー', 0 -bor 16)
}
function Test-Equipment1() {
  $result = (何かのテスト)
  if (!$result) { Show-ErrDlg('何かのテスト failed.') }
  return $result
}
でとするとテストが失敗したときも
2023/08/11(金) 23:25:27.54ID:FP8PIUGD
  if (!(Test-Equipment1) { exit 1 }
  (テスト正常終了の表示処理)
でテスト正常終了の表示が出るorz

これは何でかというと$wsobj.popup($msg, 0, 'エラー', 0 -bor 16) 」がクリックされたボタンの番号を出力する結果、$resultがまたしても配列
 @( (「なんかのテスト」の結果), ($wsobj.popup()でクリックされたボタンの番号) )
となりこれが Test-Equipment1() の戻り値となり、それをif文で評価したら最後の要素
2023/08/11(金) 23:27:54.43ID:FP8PIUGD
(OKボタンのコード6)と評価されるため、!6なので常に偽になるというしくみ、、、、
こう修正すたら直った
function Show-ErrDlg($msg) {
  $wsobj = new-object -comobject wscript.shell
  [void] $wsobj.popup($msg, 0, 'エラー', 0 -bor 16) # [void]付ける
}

わかるかこんなもん……
および原理的にlint的な機械的チェックもできない…… 
2023/08/11(金) 23:35:32.35ID:FP8PIUGD
これはデフォルトで出力無しとして、
なんかの接頭辞を付けた文だけが結果がパイプに出力されるるようにする仕様であるべきだった希ガス
(出力が無いというミスはすぐ気づける
てかWrite-Outputを省略可能としているのがそもその誤り……
※ 個人の感想です

いっぱい連投したがTeamsのつもりでShift+Enterしたら投稿されてしまったせいやスマンヌorz
いじょ
2023/08/12(土) 00:58:59.52ID:H+b+A9qi
============================
function Hoge([int]$num) {
echo "Debug"
return ($num + 1)
}

$a = Hoge(1)
echo $a
============================
こうすると $a には Debug と 2 の2つが入る

============================
function Hoge([int]$num) {
.{
echo "Debug"
} | Out-Null
return ($num + 1)
}

$a = Hoge(1)
echo $a
============================
こうすると $a には 2 の1つしか入らない
不要なところは 「 .{ ~~~ } | Out-Null 」で表示を抑制したら楽になるかも
2023/08/12(土) 01:19:17.04ID:DbL0Mu2X
>>842に言える事はパイプで何番目とかいう考えは捨てた方がいい
パイプは途中で処理を打ち切る機能が欠落してるから何番目だけに用があろうが全ストリームを読み終わるまで終わらない
2023/08/12(土) 08:19:31.33ID:IRt4i0hm
ほぼ誤差だが |Out-Null より $null= で処理した方がパフォーマンスがよく、可読性も高い
2023/08/12(土) 08:23:13.14ID:ueiwXwrP
PowerShell スクリプトのパフォーマンスに関する考慮事項
https://learn.microsoft.com/ja-jp/powershell/scripting/dev-cross-plat/performance/script-authoring-considerations
2023/08/12(土) 22:00:12.59ID:pISu+im0
>>871
わかりた
パイプラインの打ち切りは、実現方法はあるが円満な解決方法はなさげ(どれもこれもなんかしらのミソがつく

パイプで$n番目、というだけならSelect-Objectしたらv3以降ならn+1番目以降を打ち切ってくれる
  $n = 2
  Get-Content .\bigfile.txt | Select-Object -Index $n | Foreach-Object { Write-Output "cnt=${n}: $_" } # bigfile.txtが1億行あっても瞬時に戻って来る
が、これは「Select-Object -Index ~」部分を関数化したら元の木阿弥になる
  function Select-Nth($n) { $Input | Select-Object -Index $n | Foreach-Object { Write-Output "cnt=${n}: $_" } }
  Get-Content .\bigfile.txt | Select-Nth(2) # bigfile.txtを1億行全部読み込んでからおもむろに出力する
構文的に$_を使った関数やフィルタとしては書けない

データを見て条件が成立したら打ち切り、というのになるともっとマンドクセ……
https://winscript.jp/powershell/308
2023/08/12(土) 22:23:22.94ID:pISu+im0
>>870
それな!
ワカル
㌧クス、

>>872
わかりた
function Hoge([int]$num) {
[void].{
echo "Debug"
}
return ($num + 1)
}
$a = Hoge(1)
echo $a
でも逝けた
2023/08/12(土) 22:55:15.75ID:zGmVrirz
関数の出力が意図せず(うっかり)複数個所から行われ分かりにくい点は
バッチとかシェルスクリプトの挙動に合わせすぎた為だろうね。

例えばping.exeを対象2か所に実行するバッチ(.bat)をパイプで繋げたら、
バッチ1つの実行で、ping2回の20行程度がパイプに流れる。

PowerShellスクリプトや関数もこれと同じだと考えればそんな違和感ないはずなんだけど、
元々他の言語なんかで「関数の戻り値は1つ(明示的な1つor関数末尾の1つ)」とか
「明示的に変数格納や出力などしなければ、メソッドや関数の戻り値は捨てられる」
って事に慣れてるし、PowerShellも同じ文法だから同じ挙動を期待しちゃう。

上でも出てるけど、標準ではパイプに流さない仕様とした方が
敬遠される点が減ったと思う。
2023/08/14(月) 13:31:51.80ID:4NX3l0Vm
パイプはスレ違いのバッチスレでドヤ顔ワンライナーするぐらいしか能が無いと言っても過言
2023/08/14(月) 21:15:06.40ID:5teSXOgl
1GiB程度のファイルを処理するときにはパイプは重宝するよ
2023/08/15(火) 05:53:15.07ID:WIzBRZyi
バッチファイルのパイプはメカニズムが違う
あれは実質一時ファイルを作って次段に渡しているだけなので遅い、と言おうと思ったが
"*<CR><LF>" を2^23個書き並べたbigfile.txtに対してコマンドプロンプトで
  type bigfile.txt | find /C "*"
とやったら「瞬時に」
  4194304
と返って来るのに、PowerShellで
  Get-Content .\bigfile.txt | find.exe /C "*"
とやったら永劫の時間待たされた後
  FIND: パラメーターの書式が違います
と言われた後Ctrl+Cにも応答しなくなた……どうなってるのこれ……
2023/08/15(火) 14:11:57.72ID:e55ZiwZ3
そりゃパイプで外部コマンドに送ったら1行ずつfind.exe実行して終了するだろうから
おかしなことにもなるだろうよ
2023/08/15(火) 15:18:16.71ID:qi/dYdNU
> あれは実質一時ファイルを作って次段に渡しているだけなので遅い

それはシングルタスクだったDOS時代の話だろ
NTのcmd.exeには当てはまらない
2023/08/15(火) 15:39:41.88ID:LS4gbGEC
cmd.exeはパイプやfor /Fのコマンドとかワーカースレッドを生成して
別タスク(子環境)としてデータの送り手や受け手を作ってるかな
2023/08/24(木) 22:36:16.57ID:W+JHQ2GG
Get-WinEventでSystem.evtxだかのファイルを処理させるとコマンドレットが終了しても一定時間プロセスがファイル掴みっぱなしになるのどうにかしてくれ
わざわざ別プロセスでGet-WinEvent用のpowershell起動させる間抜けなコードになったぞ
2023/08/25(金) 11:28:27.28ID:WAOpDjEy
処理速度都合なのかな〜って思ってるけど閉じる手段は提供して欲しい。

自分は.NETのクラス使って処理書いちゃった。
2023/09/04(月) 19:42:45.42ID:hSX1x29k
エクスプローラでファイル選択してコピーして

(Get-ClipBoard -Format FileDropList).GetType().ToString()
→ System.Collections.Generic.List`1[System.Management.Automation.PSObject]
うん。

Get-ClipBoard -Format FileDropList | %{$_.GetType().ToString()}
→ System.Collections.Generic.List`1[System.Management.Automation.PSObject]
うn?

foreach( $info in Get-ClipBoard -Format FileDropList ){ $info.GetType().ToString() }
→ System.Collections.Generic.List`1[System.Management.Automation.PSObject]
えぇ…

Get-ClipBoard -Format FileDropList | %{$_} | %{$_.GetType().ToString()}
→ System.IO.FileInfo


[System.IO.FileInfo[]](Get-ClipBoard -Format FileDropList) | %{$_.GetType().ToString()}
→ System.IO.FileInfo
うーん…

$list = Get-ClipBoard -Format FileDropList
$list | %{$_.GetType().ToString()}
→ System.IO.FileInfo
まぁ…

なんか不必要に使いづらい気がするのは自分だけかな。
2023/09/06(水) 19:07:34.39ID:1kNnDW8h
$(Get-ClipBoard -Format FileDropList) | %{$_.GetType().ToString()}
→ System.IO.FileInfo
バッドノウハウの領域だなー
2023/09/12(火) 10:37:58.96ID:EIIMdpOe
隠し属性が設定されたファイルが排他されてるとかで読めない状況のときに
-ForceついたGet-Contentで読もうとすると隠し属性解除されるのは理由あるんだろうか
2023/09/12(火) 13:50:19.66ID:KE5ufRbn
質問で申し訳ない
AccessでエクスポートしたxlsxをPowershellでComObjectを作成してOpenしたいんだけど
破損している云々で発行元を信用しますか?ってダイアログのせいでOpen出来ない

https://learn.microsoft.com/ja-jp/office/vba/api/excel.workbooks.open
ここによると15個目の引数で1を指定(xlRepairFile)すれば良さそうなんだけど
Powershellで実行するとOpenプロパティが無いよって怒られる。

実際のコードはこう
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $True
$fileName = (Get-ChildItem "test.xlsx").FullName
$book = $excel.Workbooks.Open($fileName, [System.Type]::Missing, [System.Type]::Missing, [System.Type]::Missing, [System.Type]::Missing, [System.Type]::Missing, [System.Type]::Missing, [System.Type]::Missing, [System.Type]::Missing, [System.Type]::Missing, [System.Type]::Missing, [System.Type]::Missing, [System.Type]::Missing, [System.Type]::Missing, 1)
2023/09/12(火) 16:40:21.35ID:OgaNelN6
CSVでエクスポートしなよ
2023/09/12(火) 17:47:39.83ID:EIIMdpOe
とりあえずこうすると回避できた。

using namespace Microsoft.Office.Interop.Excel

$excel = New-Object -ComObject Excel.Application
$excel.Visible = $True
$fileName = (Get-ChildItem "test.xlsx").FullName

$param = @([Type]::Missing) * 15
$param[0] = $fileName
$param[14] = [XlCorruptLoad]::xlRepairFile
$workbooks = $excel.Workbooks
$book = $workbooks.Open.Invoke($param)
2023/09/12(火) 18:53:31.49ID:uneKtCE6
>>890
あざす!めっちゃ参考になるます
2023/09/13(水) 02:20:54.13ID:E0UN4wqY
$param = @([Type]::Missing) * 15

$param = @([Type]::Missing) * 0xFF
のほうが人にやさしい気がする
2023/09/13(水) 07:53:07.83ID:mwnND43t
は?
2023/09/13(水) 09:33:15.43ID:ozJmt5GG
ひ?
2023/09/13(水) 23:41:10.61ID:tgD8Mqqk
>>892の後者は配列に255を掛けてるように見えるのだが
人にやさしい部分てどこ?
2023/09/14(木) 03:25:22.93ID:37z8xtDS
マスクしてるのかと思ったわ
ちゃんとソース見てなかった
すまんこ
897デフォルトの名無しさん
垢版 |
2023/09/16(土) 23:53:08.17ID:DkE7QlfD
PowershellのGUI使って簡単な時報を作りたい。
System.Windows.Forms.Timerを使って作ったんだが今何時判定で$Aの数字が毎回リセットされるんでIntervalの回数だけ別ウィンドウが開きまくる。
使い方間違ってるか?教えてくれさい。

$timerTestTick {
【適当に現在時表示】
  if(【指定した時間になったら】-and【$Aがtrueなら】){
  start-prosess 【音楽ファイルを別ウィンドウで再生して処理継続】
  $A = false
}
}
$timerTest.Add_Tick($timerTestTick)
$timerTest.Interval = 200
$timerTest.Enabled = $TRUE
$timerTest.Start()

【適当にフォーム作って表示】
2023/09/17(日) 01:59:03.31ID:ENG0J7cr
>$Aの数字が毎回リセットされるんで
それ$Aを更新しようとする度に毎回スクリプトブロックで別の$Aが生成されるからやね
([ref]$A).Value = $false
と書けば元の$Aを探しにいくから更新できると思う
Powershellのはまりポイントの1つやね
2023/09/17(日) 03:18:20.18ID:LjIc1dUH
powershellでGUIって、c#使えない宗教的理由でもあるの?
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況