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

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

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

Q&A

解決済

1回答

1221閲覧

PC起動時に管理者権限でbatファイルを実行させたい

takokaina

総合スコア8

0グッド

0クリップ

投稿2024/05/30 04:52

編集2024/06/03 04:45

実現したいこと

社内でWindows11にアップロードが進行中。
バージョンアップ後、社内のネットワーク(Wi-Fi)への接続チェックも併せて行います。
何台か社内のネットワークにつながりにくいPCがいました。
起動時につながりにくい
途中で切れる
症状はいくつかあるのですが、固定IPで再設定して、現在手動でその問題を解消しています。

利用者がPC起動時したときにipアドレスを書き替えることを実現したい

発生している問題・分からないこと

batファイルは走るが、
ipは書き込まれていない。

エラーメッセージ

error

1赤い字が見えるので、エラーが出ているようなのですが、そのままスンって終わってしまうためエラーメッセージは未確認

イメージ説明

修正後実行エラー
イメージ説明

@powershell "$s=[scriptblock]::create((gc %~f0|?{$_.readcount -gt 1})-join\"`n\");&$s" %*&goto:eof if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole("Administrators")) { Start-Process powershell.exe "-File `"$PSCommandPath`"" -Verb RunAs; exit } $adapter = Get-NetAdapter | Where-Object {$_.InterfaceAlias -eq "Wi-Fi"} # アダプターのコンフィグを取得 $conf = $adapter | Get-NetIPConfiguration # IPアドレスが設定されている場合 If ($conf.IPv4Address.IPAddress) { # その設定を削除する $adapter | Remove-NetIPAddress -AddressFamily "IPv4" -Confirm:$false } # デフォルトゲートウェイが設定されている場合 If ($conf.Ipv4DefaultGateway) { # その設定を削除する $adapter | Remove-NetRoute -AddressFamily "IPv4" -Confirm:$false } $adapter | New-NetIPAddress ` -AddressFamily "IPv4" ` -IPAddress "XXX.XX.X.XXX" ` -PrefixLength 24 ` -DefaultGateway "XXX.XX.X.XXX" $adapter | Set-DnsClientServerAddress -ServerAddresses "2XX.1XX.XX.XX,2XX.1XX.XX.1XX"

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

@powershell "$s=[scriptblock]::create((gc %~f0|?{$_.readcount -gt 1})-join"`n");&$s" %*&goto:eof

についてはテラテイルや別の解説もあり。
のURLを載せておきます。
https://teratail.com/questions/254067
https://gist.github.com/newgami/de924220b8241561203b902557b83ed8
要するに「ps1ファイルをbatファイル化」して実行する

if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole("Administrators")) { Start-Process powershell.exe "-File "$PSCommandPath"" -Verb RunAs; exit }

はpowershellで管理者権限で実行させたい場合に使う
https://qiita.com/sakekasunuts/items/63a4023887348722b416

ここからは実際に手動でpowershell管理者権限で実行させると最後終わり、きちんとipが書き換えられてpowershellも実行結果をきちんと出してくれます。

$adapter = Get-NetAdapter | Where-Object {$_.InterfaceAlias -eq "Wi-Fi"}

アダプターのコンフィグを取得
$conf = $adapter | Get-NetIPConfiguration

IPアドレスが設定されている場合
If ($conf.IPv4Address.IPAddress) {

# その設定を削除する $adapter | Remove-NetIPAddress -AddressFamily "IPv4" -Confirm:$false

}

デフォルトゲートウェイが設定されている場合
If ($conf.Ipv4DefaultGateway) {

# その設定を削除する $adapter | Remove-NetRoute -AddressFamily "IPv4" -Confirm:$false

}

$adapter | New-NetIPAddress -AddressFamily "IPv4"
-IPAddress "XXX.XX.X.XXX" -PrefixLength 24
-DefaultGateway "XXX.XX.X.XXX"

$adapter | Set-DnsClientServerAddress -ServerAddresses "2XX.1XX.XX.XX,2XX.1XX.XX.1XX"

実行処理後の結果を表示して終えてくれる状態です。

補足

特になし

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

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

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

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

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

poto568

2024/05/30 06:34

とりあえず何か処理が終わるたびに pause を書いておけば状況が確認できるかもしれません。
takokaina

2024/05/30 08:35

ありがとうございます。やってみます
bsdfan

2024/05/30 12:22

batファイルを実行 → batファイルからpowershellのスクリプトを生成してpowershellで実行→powershellスクリプトから管理者権限でそのpowershellスクリプト($PSCommandPath)を実行、という流れなんだと思いますが、2回目のpowershellで $PSCommandPath を実行しようとしているのがうまくいかないんじゃないでしょうか。 $PSCommandPath がどんな値になっているか確認できますか?元の batファイルを指している?
takokaina

2024/05/31 00:47

bsdfanさんのおっしゃる通り Start-Process powershell.exe "-File `"$PSCommandPath`"" -Verb RunAs; exit でエラーが発生しており、 中身は"C:\Users\******\AppData\Roming\Start Menu\Programs\Startup になっているようです。
takokaina

2024/05/31 00:48

朝出た画像はエラーメッセージに掲載させていただきました。
takokaina

2024/05/31 01:44

あと自分では管理者権限で立ち上げているつもりなんですが、 「要求された操作には、権限の昇格が必要です・・・」とあるので管理者権限で実行されていない模様。 if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole("Administrators")) { Start-Process powershell.exe "-File `"$PSCommandPath`"" -Verb RunAs; exit } のコードも有効ではないのでしょうか?
takokaina

2024/05/31 05:17

9:48に出したコメントと10:44分に出したコメントは別の新たなバッチファイルを作っていて出てきたエラメッセージに対するコメントでした。 失礼しました。 poto568さんのアドバイス通りpauseを挿入して手動で実行してみたら新たにエラメッセージがでてとまりました。 エラーメッセージ1:”1”個の引数を指定して"Create"を呼び出し内に例外が発生しました。:”発生場所 行:2 文字:3” + %*&goto:eof アンパサンド("&")文字は許可されていません。&演算子は、今後使用するために予約されています。アンパサンドを2重引用符で囲み(”&”)文字列の一部としてお渡しください" 上記のようにあるのはなぜでしょうか? powershell エイリアス アンパサンドと検索すると 「アンパサンドとシングルクオート用いて、exeファイルの実行を行うことができます」 https://qiita.com/Kirito1617/items/df46899f8d28701da03b ↑出展 とありました。 &'$s'とする必要があるのでしょうか? いったん検索結果をもと実行してみます。→結果だめでした。 エラーメッセージ2:パイプライン要素内で'&'の後にある式が無効なオブジェクトを作成しました。コマンド名、スクリプト ブロックまたはCommandInfoオブジェクトになる必要があります。 これも先ほどにエラー1に関連した変数$sに関してシングルコーテーションをつけたがダメでした
takokaina

2024/06/03 04:59

コメントありがとうございます。⚪︎⚪︎を試しましたがまだ解決できていません。 試した結果を質問に追記しました。 だめでした。というのはきちんと現実を羽石ていないのでお伝えさえていただきますと、 スタートアップフォルダで実行 次のエラーのため実行できませんでした。指定ファイルが見つかりません。 ※上の黄色下線部 デスクトップに置いてダブルクリック実行した際は、 管理者権限が実行しているためこのアプリがデバイスに変更を加えることを許可しますか?が聞かれ、肺をおすと、 次に「続行するにはEnterキーを押してください。。。」 きちんと」IPしてくれます。 質問①この実行の違いは階層の深さなのでしょうか? ご教示ただケルトと幸いです。 質問2 上記質問がYesの場合、起動時に実行というのはむずあかっしいことになりますでしょうか? ※いったん自分ではスケジューラで管理しないといかね猪飼と考え調べています。
bsdfan

2024/06/03 05:32 編集

回答を修正しましたの確認ください。 (回答へのコメントは回答のほうにお願いします。あと誤字、誤記が多く怪文書っぽくなっているので修正するほうがベターかと思います) パスの途中にスペースがある場合に問題が発生しています。cmd用とpowershell用で二重でクォートしておくほうが良さそうです。
guest

回答1

0

ベストアンサー

バッチファイルをpowershellとして実行するときに、結構トリッキーな技を使っているので、それを管理者権限で実行しなおすというのが困難になっているように見えます。

順番として、

  1. バッチファイルを実行
  2. そのバッチファイルを管理者権限で実行
  3. (管理者権限を持ったまま)そのバッチファイルを powershell で実行

という流れにするほうが良いと思います。

<# : @echo off openfiles >nul 2>&1 if errorlevel 1 ( powershell start-process "'%~f0'" -verb runas goto :EOF ) powershell -noprofile -command "invoke-expression (get-content '%~f0' -raw)" goto :EOF #> # 以下 powershell スクリプト $adapter = Get-NetAdapter | Where-Object {$_.InterfaceAlias -eq "Wi-Fi"} (省略・・・)

簡単に説明すると、

  • <# : はpowershellにとってはコメントの開始ですが、cmd にとっては何も実行されない行になります。
  • openfiles は管理者で実行すると成功しますが、非管理者の場合はエラーになって errorlevel が 1 になります。
  • 次段の if で errorlevel を判定し、非管理者の場合に powershell start-process "'%~f0'" -verb runas で同じバッチファイルを管理者権限で実行します。
  • powershell -noprofile -command ... の行で、バッチファイルの内容を powershell で実行しています。このとき<# から #>まではコメントとして扱われるので、cmd で実行する部分は powershell では評価されません。

追記

<# : について

<# : がバッチファイルで何も実行されない行になる理由は、正直よくわからないところがあります。
: はバッチファイルではラベルを表す記号なので、特別に扱われているのかもしれません。

< は cmd では標準入力のリダイレクトなので <# は 「#」という名前のファイルから入力を読み込むという意味です。実際 <# more を実行すると「#」という名前のファイルの中身が表示されますし、ファイルがない場合はエラーになります。(通常リダイレクトは、コマンドの後ろに書きますが、前に書くこともできます)

一方で、バッチファイルの外のコマンドラインで <# : を実行すると、「#」という名前のファイルがあってもなくてもエラーになります。(異なるエラーになります)
なぜか : <# だとエラーになりません。
UNIX の sh などでは : は何もしないコマンドとして存在しているのですが、cmd で : がバッチ外ではどういう扱いなのか、よくわかっていません。(正式な記載がどこかにあったら教えて欲しいです)

投稿2024/05/31 07:57

編集2024/06/11 04:51
bsdfan

総合スコア4899

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

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

takokaina

2024/06/03 22:18

回答ありがとうございます。 試したところ問題が解決しました! ベストアンサーに選ばせていただきました。 初学でいきなり難しいことに取り組んでしまって最初は、どうしようと思っていましたが、bsdfan様のような親切な方がいらっしゃってとても助かりました。 せっかく学べたのでさらにこの学んだことから深く学んでまいりたいと思います。 ありがとうございました。
takokaina

2024/06/11 02:36

<# #>はpowershellで複数行にわたるコメントと調べて分かったのですが、 <# :/~~~~~~cmd にとっては何も実行されない行になります。とあるのですが、 調べてもコマンドが無効になるような記述はみつかりませんでした。 あと何もしないとなるとこのコマド自信を開くコードになっているはずなので、 <#: #>除いた部分でコマンド実行されている認識でよいですか?
bsdfan

2024/06/11 04:54

> あと何もしないとなるとこのコマド自信を開くコードになっているはず ちょっとここの意味がよくわかりません。 バッチファイルも、powershellも上から順に実行していくだけです。 そのときにバッチファイルとしては、<# : の行は何もせず、goto :EOF 以降は実行されないということと、powershell では <# ~ #> はコメントとして実行されないということです。
takokaina

2024/06/11 08:28

なるほど <# : のこの1行だけということなのですね。すみません。私の勝手な解釈で次の行も含めておりました。 自分のなかでの疑問ははれました。 bsdfanは1行目まで 私はそれ以降もふくめて なので齟齬がおこっていたようです。 すみません。 理解いたしました。
takokaina

2024/06/13 07:00

もう一つ疑問があります。 powershell -noprofile -command "invoke-expression (get-content '%~f0' -raw)" get-content '%~f0' -rawこのファイ自身の中身を丸ごととってきて invoke-expressionでこのファイルの中身を実行する「# 以下 powershell スクリプト $adapter = Get-NetAdapter | Where-Object {$_.InterfaceAlias -eq "Wi-Fi"} (省略・・・)」を実行となるのですが、(そのために<##>コメント化が必要なのですね) powershellはパワーシェルの実行 nonprofileは環境設定を読み込まずに実行だと思うのですが、 -commandは何の働きをしていますか?
takokaina

2024/06/15 08:01

get-contentでとってきたそのファイル自身(%~f0)のコマンドを全て(-raw)1読み込ん(get-content)でそみ込んだ文字列をinvoke-expressionに入れ、「その後のすべての引数が実行するコマンドの一部として解釈されるため」とあるのでコマンドとして読み込んで、powershell管理者権限で実行と理解して良いでしょうか?
bsdfan

2024/06/15 10:16

-command 以降の文字列 "invoke-expression (get-content '%~f0' -raw)" をpowershell で実行すると言う意味です。 get-content でファイルを読み込んで、invoke-expression でそこに書かれていることを実行しています。
takokaina

2024/06/17 05:39

理解がふかまりました。 ありがとうざいます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問