PowerShell -Part 7
キモいpython処理www キモいのはpowershellじゃぼけww >>32 たしかにpowershellもキモいと言えばそうだがpythonとはキモさのベクトルが違うんだよ >>30 にはいい事も書いてある >PowerShell チームに対して、これらの Python ライブラリをネイティブ PowerShell パッケージの一部として直接実装するよう求めているのであれば、私は同意しなければなりません。 いずれこういう俺と同じ考えを持つ輩がpythonライブラリのぶっこ抜きに成功し キモいpython処理系が駆除された明るい未来を創り上げてくれる事に期待している $null | %{'hoge'+$_} これでなんでhogeが出力されるんですか? Nullになるかとおもったんですが 型を合わせるために、NULLが空文字に変換されるから。 そこでNULLを期待するのはRDBとかの場合だね。(RDBにもよるけど。) >>35 なるほど ありがとうございます ためしに $null | %{$_+$hoge} にしたらNullになりました +演算子の左辺の型に合わせて右が型変換されるんですね …PowerShellは難しい PowerShellでファイルの詳細なプロパティを編集することってできますか? 評価とかタグとか下のurlに載っている300種類ぐらいの拡張プロパティです Windows プロパティ - Win32 apps | Microsoft Learn https://learn.microsoft.com/ja-jp/windows/win32/properties/props プロパティの取得だけなら $shell = New-Object -COMObject Shell.Application $folder = Split-Path $path $file = Split-Path $path -Leaf $Getfolder = $shell.Namespace($folder) $Getfile = $Getfolder.ParseName($file) $Getfile.ExtendedProperty("System.SimpleRating") これでできたんですけど プロパティの編集方法は色々調べてみたんですがわかりませんでした >>40 インストールでちょっとつまづいちゃいましたが やりたいことができました ありがとうございます! 中見たら7時代のWindows-API-Code-Packとやらを拾ってきて使うのか 本来シェル名前空間からやれそうな事なのにWritePropertyへ辿りつくまでかなり遠回りしたな ps1ファイルをユーザーに手軽に実行してもらう方法ってないですかね batだと単にダブルクリックするだけでいいところが、 ps1だとショートカット作って↓↓をくっつけてと、とても運用に耐えられないんですが 「powershell.exe -ExecutionPolicy Unrestricted 」 >>44 ググればバッチファイルにPowerShellスクリプトを埋め込む方法が見つかるよ >>46 ps1単独で解決できないものか 将来性を考えて、ps1使ってみようと思ったが、 バッチやvbsの助けがないと使いにくいんじゃイマイチだな ps1はコード署名して、グループポリシーで証明書配付しよう >>48 そこまでするなら、スクリプトよりexe作った方が早・・・ 埋め込むやつって結局iex経由の特殊環境だから一部の変数とか使えなくて困る 無理に使わなくていいよ 横からすみません >>40 のインストールにチャレンジしたのですが、管理者権限のPowerShellでInstall-ModuleをしたのにImport-Moduleでdllが無いみたいなエラーが出て使えません どなたかアドバイス頂けないでしょうか >>52 下のURLの2つのnupkgをダウンロードして、ファイル名の後ろの拡張子を.zipに変更する https://www.nuget.org/api/v2/package/Microsoft-WindowsAPICodePack-Core/1.1.4 https://www.nuget.org/api/v2/package/Microsoft-WindowsAPICodePack-Shell/1.1.4 ↓ microsoft-windowsapicodepack-core.1.1.4.nupkg.zip microsoft-windowsapicodepack-shell.1.1.4.nupkg.zip この2つのzipを適当なフォルダに解凍して、libフォルダその他が作成される事を確認。ここで必要なのはlib配下の*.dllのみ libフォルダ内の自分のpowershell環境と適合する.NETのバージョンのフォルダから*.dllを取り出してカレントディレクトリに配置 でいけるんじゃないかな $PROFILE ってなんなのでしょうか $PROFILE.GetType() だと String のようですが $PROFILE | Select-Object * で AllUsersAllHosts などが出てくるのがわかりません $PROFILE | Select-Object * で何が起きているのでしょうか PowerShellはAdd-Memberでオブジェクトにプロパティやメソッドを追加できる https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.utility/add-member $PROFILE | Get-Member を実行してみればわかるけど AllUsersAllHostsとかは$PROFILEに追加されたNotePropertyって種類のプロパティ >>54 中身がPSCustomObjectでない変数にもNotePropertyを設定できる ただしその変数に他の値を代入するとNotePropertyの情報は消えてしまうから用途は限定される $a = "aaa" $a = $a | Add-Member -PassThru "Value" "xxx" $a = $a | Add-Member -PassThru "Value2" "yyy" $a # aaa $a.Value # xxx $a.Value2 # yyy $a | select * $a = "bbb" $a.Value # $null ('str' | Add-Member -type NoteProperty -Name 'wao' -Value 'Wao!' -passThru).wao → Wao! (123 | Add-Member -type NoteProperty -Name 'wao' -Value 'Wao!' -passThru).wao → Wao! 理解した >>56 Add-Member は変数ではなくオブジェクトにメンバーを追加する "aaa" と "bbb" は違うオブジェクトなんだから "aaa" に追加したメンバーが "bbb" に無いのは当たり前 ネイティブコマンドの出力ってPowerShell界に入るとString列になるけど Stringのそれぞれにプロパティで元のバイナリ付けて欲しい バイナリが通るようになったのは 「ネイティブからネイティブ」と「PowerShellからネイティブ」だけ 「ネイティブからPowerShell」に手軽にバイナリ通したい バイナリ出力ネイティブ | バイナリ入力ネイティブ として使うバイナリ入力ネイティブ用にラッパーが書きたいのに今は書けない 自分には必要ないから触れなかったけど バイナリ出力ネイティブのラッパーも書けない 引数に -i を複数回指定したいので param() を使わずに function を書いています get-help で SYNTAX に使い方を表示するにはどうすれば良いのでしょうか about_Comment_Based_Help ttps://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_comment_based_help?view=powershell-7.4 このページの中の項目で スクリプト モジュールでのコメント ベースのヘルプの構文 コメントベースのヘルプ キーワード 関数のコメント ベースのヘルプ 関数構文でのパラメーターの説明 スクリプトのコメントベースのヘルプ あたりが参考になるかも paramを使わずにSYNTAXを表示する方法を尋ねたのはそこを見たからでして 方法がありましたら具体的にご教示くださいませ そもそもなんで -i を複数回指定したいんだろう 引数$i の型を配列にするのとは違うの? ffmpeg.exeに毎回付けたいオプションがありまして オプション付きエイリアス代わりのfunctionが欲しかったのです ffmpeg -f aac -i audio.bin -f hevc -i video.bin -c copy out.mp4 のようにffmpeg.exeと同じ使い方だと嬉しい ちなみにValueFromRemainingArgumentsで受けようとしても ffmpeg: Parameter cannot be processed because the parameter name 'i' is ambiguous. Possible matches include: -InformationAction -InformationVariable. と怒られます 指定する対象はaudioとvideoと決まってるんだから -aiや-viにすりゃいい 変態的なffmpegのオナニーに付き合う必要はない いやaudioとvideoに限らんし個数も不定なのよ audioが言語別複数で、videoはチャプターごとに分かれて、字幕もあったり 結局ffmpegと同じ使い方ができるようにするのが面倒ない ffmpegはシーケンスが意味を持つ引数になってるのよね どういう順で記述するかによって適用される範囲が異なってくる なら引数は$argsで受け取って好きなように解釈したらええがな だからそうしてるのが理解できないのかな paramを使わないというのは $args を自分で解釈するということ その上でparamを使わない場合のget-helpの出力について相談したんだが 聞いた相手が想像を超えたバカだったたようだ 邪魔したな PowerShellにはPowerShellの流儀があるわけで それに合わないことをやろうとすれば苦労するのは当たり前 C言語で関数型プログラミングをしたいって騒いでるのと同レベル ・質問者がget-helpのやり方をスレで質問 ・そもそもこうすればいいんじゃね?と別解について疑問があがる ・さほど適した別解はないことが判明 ・質問者に対して怒り出す 別に苦労したと文句たれてるわけでもないのに質問者がウザ絡みされて気の毒すぎる 助言・回答者に対しキレ散らかすパターン多いな。同一人物か? PowerShellよりdoskeyのマクロにしたほうが簡単そう get-helpでヘルプを表示させる コメントベースのヘルプを記述する param()を使わない という条件だったら単純にスクリプトの先頭にコメントベースで .SYNOPSIS または .DESCRIPTION に「-iが複数使える」旨を書けばいいのでは もしくは param()を使わず$Argsを自前で解釈しなきゃいけないので 引数の解釈を構築するついでに $Args.Countがゼロもしくは -help -h -? /h /? あたりの引数で独自のヘルプを表示させちゃうとか まぁ普通に考えたらこうならね? XMLヘルプファイル用意して参照させればParam()のないfunctionに対し「構文」部分を書ける。 PowerShell標準から外れた「引数に -i を複数回指定」みたいな内容を書けるかは知らん。 国内公式からLenovoのノートPC買ったら何故かISEが英語環境になって意味わからん。 どこに言語設定あるの?当然OSは日本語設定にしてるし、他のアプリも日本語になってる。 これまでLenovoのPCは5台くらい買ってきたのにISEだけ英語になるの初めてなんだが。 https://i.imgur.com/H4NVkKH.png そういうのsurfaceでもあったな OSセットアップ時の国設定が半端に適用された状態だから入れ直した方が早いかも >>85 Windowsは英語版を日本語に切り替えると日本語にならないところがある だから日本語版でインストールした方がいい ちなみにいまどきISEを使っているのもよくわからない powershell iseってのを知らなかったけど起動したらUIシンプルで美しいな VSCodeもこれくらいシンプルになってくれんかな カスタマイズしてシンプルにすればいいと思うよ 俺はどちらかというとVSCodeのほうが機能美を感じる デフォルトで万人の感性にフィットするモノは存在しない カスタマイズも嫌なら自分で作るか作らせるか Class C { $a = '失敗' } function f { Param([ref]$r); $r.Value = '成功' } $o = [C]::new() f ([ref]$o.a) $o.a $t = '失敗' f ([ref]$t) $t こんなの聞いてないよ 何が言いたいのかわからないw コードを実行した結果が書かれてないので 何を言いたいのか知るにはこのコードを実行しなきゃならない めんどくさいw $o | Get-Member を実行してみれば分かるけど$o.aはフィールドじゃなくてプロパティだからな $o.aのgetter( $o.get_a() )の戻り値を関数に渡しても$o.aの値は変わらない パワーシェルすげえな 仕事がどんどん片付いていくよ 2つのCSV(どちらも同じヘッダー)で両方に一致するデータ行があった場合にその行を2つのCSVから取り除きたいんだけどどうしたらいいの? ヘッダーがDate,Shop,Sales だとしてユニークな項目がなく全く同じデータが1つ目のCSVに1行、2つ目のCSVに2行あった場合に2つ目のCSVは1行だけ消したい Where-object だと2行とも消えちゃう 2つのCSVをどうやってwhere-objectに渡してんだよ その2行が消える間抜けコード晒してみなよ # CSVファイルを読み込む $csv1 = Import-Csv -Path 'csv1.csv' $csv2 = Import-Csv -Path 'csv2.csv' # CSV1の各行について foreach ($row1 in $csv1) { # CSV2の中で一致する行を探す $match = $csv2 | Where-Object { $_.Date -eq $row1.Date -and $_.Shop -eq $row1.Shop -and $_.Sales -eq $row1.Sales } # 一致する行が見つかった場合 if ($match) { # CSV1とCSV2から一致する行を削除 $csv1 = $csv1 | Where-Object { $_ -ne $row1 } $csv2 = $csv2 | Where-Object { $_ -ne $match[0] } } } # 結果を出力 $csv1 | Export-Csv -Path 'csv1.csv' -NoTypeInformation $csv2 | Export-Csv -Path 'csv2.csv' -NoTypeInformation わーいできたー $csv1=gc csv1.csv $csv2=csv2.csv #どうせ全一致ならテキストのまま比較すりゃいいだろ $i=0 foreach($row in $csv1){ $csv2|%{ $j=$k=0 }{ if($_ -eq $row -and $i -eq 0){ $csv1[$i]=$csv2[$j]=$null $k=1 } $j++ } $i++ } $csv1|sc csv1.csv $csv2|sc csv2.csv $i1 = "csv1.csv" $i2 = "csv2.csv" $o1 = "csv1_out.csv" $o2 = "csv2_out.csv" gc $i1, $i2 | group readcount | ?{$_.group[0] -ne $_.group[1]} | foreach{$_.group[0] | ac $o1; $_.group[1] | ac $o2; $_.group[0].readcount} 段階を踏まないのは謎だよな ファイルをコピーする概念もなさそう これで良かったわ $csv1=gc csv1.csv $csv2=gc csv2.csv $compare=compare $csv1 $csv2 $compare|?{$_.SideIndicator -eq "<="}|% InputObject|sc csv1.csv $compare|?{$_.SideIndicator -eq "=>"}|% InputObject|sc csv2.csv CSVファイルに想定外のデータがあることを考慮しないのか わ仕事早い… csv1の方はDateがYYYY/MM/DDの10桁固定で csv2の方はDateがYYYY/M/Dで8〜10桁になってて 日付としてみれば同じなんですが1行を文字ででみると違う可能性があります… 後出しですいません またShopはだいたい一致してるのですが 「ローソン札幌店」と「ローソン札幌」や「ローソンサッポロ」みたいな内容が異なることがあってそこを必ず自前のfunctionの変換リストかましてから比較する予定でした 私の想定を超えるプログラムでfunctionを挟むこともできない カラムの曖昧さとかは全く興味沸かないなあ自分でやんな 昨日の少し試しましたが $compare=compare $csv1 $csv2 $compare|?{$_.SideIndicator -eq "<="}|% InputObject|sc csv1.csv $compare|?{$_.SideIndicator -eq "=>"}|% InputObject|sc csv2.csv でうまくいきそうです ありがとうございます 自分でつけてる家計簿からクレジットで相殺してる項目だけ出力したcsvと 三井住友のVpassの明細(ファイルの日付的には翌月)を突き合わせを自動でやって7割ぐらい減ってくれたらいいなと思って AIにプログラム書かせたらすぐにできるかなと思ったけどAIもまだまだアホでした 土日に頑張ります 目的よりも手段にこだわっていると思われる テキストファイルとPowerShellだけで、イレギュラーなデータがあるかもしれないデータを操作をするのは、かなり面倒なやり方だぞ。 >>110 はキャラクタセットも気にしてなさそうなんだよな 行比較が出来るようになれば対象が何だろうが応用できるだろ 話はとっくに終わってんのよ >目的よりも手段にこだわっていると思われる これまんまお前のことじゃね? そんなに複雑なら、シェルの範囲を超えている。 Ruby など動的言語の出番 >>106 RubyのCSV では、コンバーターで変換器を自作する Ruby では、2024-01-01 のみ、Date 型へ変換できる。 2024/1/1,2024/01/01,2024-1-1 は変換できない。 以下のように、自分で変換器・コンバーターを定義すれば変換できる でも表記揺れは別の処理として、最初に一括して変換した方が安全 require 'csv' input_csv = <<"EOT" 2024/1/1,2024-1-2 2024/02/01,2024-02-02 EOT # Date 型へ変換する proc = Proc.new do |field, field_info| case field_info.index when 0 then Date.strptime( field, "%Y/%m/%d" ) # 0列目 when 1 then Date.strptime( field, "%Y-%m-%d" ) # 1列目 else field # 処理なし end end options = { :converters => proc } p CSV.parse( input_csv, options ) 出力 [ [#<Date: 2024-01-01>, #<Date: 2024-01-02>], [#<Date: 2024-02-01>, #<Date: 2024-02-02>] ] PowerShellだと何も考えずにDateTime変換できるのに、Rubyだとそんなに手間かかるのか もうそんな言語使うの止めて大人しくPowerShell使ったら? すいません初心者でとんちんかんな質問だったらごめんなさい PowerShellからarduinoにデータを送ってOLEDで表示するセンサーモニターを作ってます CPU・GPUの使用率や温度は取り出せて表示できたのですが FPSってどこからか取り出す方法ってありますか? 使用率や温度と違うのでPresentMonやAfterburnerからGet-Counterで取得する? とか考えて調べてるのですが分からなくて とんちんかんなこと言ってたらすいません できるできない含めて教えてください 基本的に、Go でも、こういうのしかない 2024-01-01 2024-01-01 15:01:01 それか、RFC 3339, RFC 3339 Nano これら以外を使っているシステムは、バグるからダメ! >>117 FPSて。要するにモニタのリフレッシュレートが欲しいんじゃろ? ほれ $RefreshRate = Get-WmiObject -Class:Win32_videocontroller | Select-Object -ExpandProperty CurrentRefreshRate >>119 返事ありがとうございます 言葉足らずですいません 頂いた情報は現在設定しているリフレッシュレートが表示されるようです 欲しいデータはGeForce ExperienceやMSI Afterburnerで画面上でオーバーレイさせて 表示しているリアルタイムのFPSとして表示されている数値なんです FPSやフレームレートで検索してましたがリフレッシュレートでも探してみます >>119 返事ありがとうございます 言葉足らずですいません 頂いた情報は現在設定しているリフレッシュレートが表示されるようです 欲しいデータはGeForce ExperienceやMSI Afterburnerで画面上でオーバーレイさせて 表示しているリアルタイムのFPSとして表示されている数値なんです FPSやフレームレートで検索してましたがリフレッシュレートでも探してみます 連投してましたすいません 引き続き皆さんの知恵を貸してください まずそれらがfps値返すようなAPI持ってるか調べなよ 無いなら値として取得は無理だろうね fps表示部分が単色ならそのエリアをキャプチャして数字認識でもした方が早そう >>123 ヒントありがとうございます APIを調べてみたらNVIDIAにNVAPIと言うのがありました ここからどうやって取り出すか調べてます もし良かったらもう少し何かヒントをください もうpowershell関係ないがPresentMon64に計測対象のPID渡せばfps取得できるみたいね >>125 はいPresentMonでもFPSを取れるみたいなのは調べました ただ、今arduinoㇸpowarshellからCPUGPUのデータを 受け取ってたのでそこと一緒に入れる方法が見つけられなくて Add-Type -AssemblyName System.Windows.Forms function ConvertShopName([string]$shopName) { switch -Wildcard ($shopName) { "ファミリーマート*" { $shopName2 = [regex]::Replace($shopName, "(ファミリーマート)([ ]*)(.*)(店)", { $args.groups[1].value + " " + $args.groups[3].value }) } "ローソン*" { $shopName2 = [regex]::Replace($shopName, "(ローソン)([ ]*)(.*)", { $args.groups[1].value }) } "セブンイレブン*" { $shopName2 = "セブンイレブン" } "マクドナルド*" { $shopName2 = "マクドナルド" } "すき家*" { $shopName2 = "すき家" } "Amazonで注文" { $shopName2 = "AMAZON.CO.JP" } default { $shopName2 = $shopName } } return $shopName2 } if ($Args.Count -eq 0) { [System.Windows.Forms.MessageBox]::Show("引数にファイルを指定してください", "エラー") return 0 } # 家計簿から抽出した csv ファイルを読み込む $excelData = Import-Csv $Args[0] -Encoding Default -Header "Date", "Shop", "Amount" | Select-Object @{ label = 'Date'; expression = { [DateTime]$_.Date} }, Shop, @{ label = 'Amount'; expression = { [int]$_.Amount } } # 引数で指定されたファイルをフォルダパスとファイル名(拡張子なし)に分離する $baseName = [System.IO.Path]::GetFileNameWithoutExtension($Args[0]) $folderPath = [System.IO.Path]::GetDirectoryName($Args[0]) # ファイル名から日付に変換する $targetDate = [DateTime]::ParseExact($baseName + "01日","yyyy年MM月dd日", $null) # 引数と同じフォルダにある Vpass からダウンロードした csv ファイル(ファイル名は翌月) を読み込む $vpassFile = $folderPath + "\" + $targetDate.AddMonths(1).ToString("yyyyMM") + ".csv" $vpassData = Import-Csv $vpassFile -Encoding Default -Header "Date", "Shop", "TotalAmount", "Type", "Count", "PaymentAmount", "ShopDetail" | Select-Object @{ label = 'Date'; expression = { [DateTime]$_.Date } }, Shop, @{ label = 'TotalAmount'; expression = { [int]$_.TotalAmount } }, Type, Count, @{ label = 'PaymentAmount'; expression = { [int]$_.PaymentAmount } }, ShopDetail echo "実行します . . ." # 家計簿データの Shop が "自動引き落とし" で Amount がプラスのデータを削除する $excelDataList = [System.Collections.ArrayList]$excelData | Where-Object { $_.Shop -ne "自動引き落とし" -and $_.Amount -lt 0 } # 家計簿データの 2項目目が空のデータ行を削除する $excelDataList = [System.Collections.ArrayList]$excelData | Where-Object { ![string]::IsNullOrEmpty($_.Shop) } # 家計簿のマイナスになっている消し込みデータをプラスに変換し、店名をクレジット明細側に変換する foreach($data in $excelDataList) { $data.Amount = $data.Amount * -1 $data.Shop = ConvertShopName($data.Shop) } # vpass データの Type, Count, PaymentAmount, ShopDetail が null のデータを削除する $vpassData2 = $vpassData | Where-Object { ![string]::IsNullOrEmpty($_.Type) -or ![string]::IsNullOrEmpty($_.Count) -or ![string]::IsNullOrEmpty($_.PaymentAmount) -or ![string]::IsNullOrEmpty($_.ShopDetail) } # vpass の Date, Shop, TotalAmount, Type, Count, Count, ShopDetail が null のデータを削除する $vpassData3 = $vpassData2 | Where-Object { ![string]::IsNullOrEmpty($_.Date) -or ![string]::IsNullOrEmpty($_.Shop) -or ![string]::IsNullOrEmpty($_.TotalAmount) -or ![string]::IsNullOrEmpty($_.Type) -or ![string]::IsNullOrEmpty($_.Count) -or ![string]::IsNullOrEmpty($_.ShopDetail) } # 抽出後のデータを格納するための変数 [System.Collections.ArrayList]$vpassDataList = @() [System.Collections.ArrayList]$unknownhDataList = @() # vpass データのデータを必要な項目のみにする foreach($data in $vpassData3) { if ( $data.Type -eq "1" -and $data.Count -eq "1" -and $data.TotalAmount -eq $data.PaymentAmount -and $data.ShopDetail -eq "" ) { $temp = $data | Select-Object Date, Shop, @{ label = 'Amount'; expression = { [int]$_.TotalAmount } } $vpassDataList += $temp } elseif ( $data.Type -eq "1" -and $data.Count -eq "1" -and $data.TotalAmount -eq $data.PaymentAmount -and $data.ShopDetail -ne $null ) { $temp = $data | Select-Object Date, @{ label = 'Shop'; expression = { $_.ShopDetail } }, @{ label = 'Amount'; expression = { [int]$_.TotalAmount } } $vpassDataList += $temp } else { $unknownhDataList += $data } } # 重複するオブジェクトを探す $commonObjects1 = Compare-Object -ReferenceObject $excelDataList -DifferenceObject $vpassDataList -Property Date, Shop, Amount -IncludeEqual | Where-Object { $_.SideIndicator -eq '<=' } $commonObjects2 = Compare-Object -ReferenceObject $excelDataList -DifferenceObject $vpassDataList -Property Date, Shop, Amount -IncludeEqual | Where-Object { $_.SideIndicator -eq '=>' } Add-Content $Args[0] "`r`n`r`n--------`r`n`r`n" Add-Content $Args[0] $unknownhDataList Add-Content $Args[0] "`r`n`r`n" Add-Content $Args[0] $commonObjects1 Add-Content $Args[0] "`r`n`r`n" Add-Content $Args[0] $commonObjects2 echo "終了しました。続行するには何かキーを押してください . . ." $host.UI.RawUI.ReadKey() ----- とりあえず形にはなりました。ありがとうございました! それだけプログラミングできるなら、 データベースもある、Ruby on Rails で稼げ PowerShell では稼げないだろ 無償のRDBに取り込んで操作すれば楽なのにな SQL Server ExpressもSQLもわからないのかもしれないが read.cgi ver 07.5.1 2024/04/28 Walang Kapalit ★ | Donguri System Team 5ちゃんねる