#author("2024-10-23T01:24:02+09:00","default:admin","admin")
#author("2024-10-23T01:41:51+09:00","default:admin","admin")
#navi(../)
#Contents
------------------------

*Powershell [#cbb330d1]

** モジュール関連 [#td02f412]

*** モジュールをインストール [#qce43968]

インストールされているモジュールをインストールする方法
 PS> Install-Module -Name <モジュール名>

*** モジュールを表示 [#ifb92fb8]

インストールされているモジュールを表示
 PS> Get-Module

*** モジュールをインポート [#k1a7f368]

モジュールをインポートする方法
 PS> Import-Module <module-name>

*** モジュールを削除 [#u9980c89]

モジュールを削除する方法

 PS> Remove-Module <module-name>

** hoge [#c3111dbc]
 cd D:\script
 
 $TargetFile = "D:\script\wrk\production\dat\product\product_20201001\wiki-001.zip"
 
 D:\script\wrk\deveroper\dat\product\product_20201001\wiki
 
 "D:\script\bin\7z.exe" e -y -o
 
 $filelist = (Get-ChildItem D:\script\wrk\production\dat\ -Recurse | ? { ! $_.PSIsContainer }).fullname
 $TargetFile = New-Object PSObject | Select-Object drive, folder1, folder2, folder3, folder4, folder5, folder6, file
 $Data = @()
 
 foreach ( $file in $filelist ) {
 
     $TargetFile = ($file).split("\")
 
     $Data += $TargetFile
     echo $TargetFile
     echo ---
 
 }
 
 $Data


*** ディスク容量を確認する関数 [#ba7cade9]

 関数:
 function Global:Get-DirSize() {
 
    Param( [string]$TargetDir )
 
    if ( $TargetDir.Length -eq 0 ) {
 
       $Host.UI.WriteErrorLine( "Usage: Get-DirSize <path>" )
       return
 
    }
 
    write-output ( "---------------------------------------------------------------------------------------------------" )
    write-output ( "TargetDirectory : ${TargetDir}" )
    write-output ( "---------------------------------------------------------------------------------------------------" )
 
    set-location ${TargetDir}
 
    Get-ChildItem | Select-Object FullName, @{ name = "Size(MB)"; expression = { [math]::round((Get-ChildItem $_.FullName -Recurse -Force | Measure-Object Length -Sum ).Sum /1MB ) } }
 
 }

 関数実行:
 PS C:\> Get-DirSize C:\

 実行結果:
 ---------------------------------------------------------------------------------------------------
 TargetDirectory : C:\
 ---------------------------------------------------------------------------------------------------
 
 FullName         Size(MB)
 --------         --------
 C:\Autodesk          4997
 C:\BUFFALO            101
 C:\ESD                  0
 C:\Intel                0
 C:\PerfLogs             0
 C:\Program Files     3256
 C:\Program Fi...     7851
 C:\Users           257541
 C:\VNTApp               0
 C:\Windows          27189
 
 PS C:\>

*** バッテリー情報収集 [#l4f68f36]

 #####################################################################
 # システム情報
 #####################################################################
 function QueryServerInfo(){
     $ReturnData = New-Object PSObject | Select-Object HostName,Manufacturer,Model,SN,CPUName,PhysicalCores,Sockets,MemorySize,DiskInfos,OS
 
     $Win32_BIOS = Get-WmiObject Win32_BIOS
     $Win32_Processor = Get-WmiObject Win32_Processor
     $Win32_ComputerSystem = Get-WmiObject Win32_ComputerSystem
     $Win32_OperatingSystem = Get-WmiObject Win32_OperatingSystem
 
     # ホスト名
     $ReturnData.HostName = hostname
 
     # メーカー名
     $ReturnData.Manufacturer = $Win32_BIOS.Manufacturer
 
     # モデル名
     $ReturnData.Model = $Win32_ComputerSystem.Model
 
     # シリアル番号
     $ReturnData.SN = $Win32_BIOS.SerialNumber
 
     # CPU 名
     $ReturnData.CPUName = @($Win32_Processor.Name)[0] 
 
     # 物理コア数
     $PhysicalCores = 0
     $Win32_Processor.NumberOfCores | % { $PhysicalCores += $_}
     $ReturnData.PhysicalCores = $PhysicalCores
     
     # ソケット数
     $ReturnData.Sockets = $Win32_ComputerSystem.NumberOfProcessors
     
     # メモリーサイズ(GB)
     $Total = 0
     Get-WmiObject -Class Win32_PhysicalMemory | % {$Total += $_.Capacity}
     $ReturnData.MemorySize = [int]($Total/1GB)
     
     # ディスク情報
     [array]$DiskDrives = Get-WmiObject Win32_DiskDrive | ? {$_.Caption -notmatch "Msft"} | sort Index
     $DiskInfos = @()
     foreach( $DiskDrive in $DiskDrives ){
         $DiskInfo = New-Object PSObject | Select-Object Index, DiskSize
         $DiskInfo.Index = $DiskDrive.Index              # ディスク番号
         $DiskInfo.DiskSize = [int]($DiskDrive.Size/1GB) # ディスクサイズ(GB)
         $DiskInfos += $DiskInfo
     }
     $ReturnData.DiskInfos = $DiskInfos
     
     # OS 
     $OS = $Win32_OperatingSystem.Caption
     $SP = $Win32_OperatingSystem.ServicePackMajorVersion
     if( $SP -ne 0 ){ $OS += "SP" + $SP }
     $ReturnData.OS = $OS
     
     return $ReturnData
 }


 powercfg /batteryreport

|項目|説明|h
|Installed batteries|バッテリー状態|
|Recent usage|最近の使用状態(過去3日間)|
|Battery usage|バッテリーの使用状態(過去3日間の電池残量)|
|Usage history|使用状態履歴|
|Battery capacity history|バッテリーキャパシティ履歴|
|Battery life estimates|使用状況から推測したバッテリー稼働可能時間|

**連想配列(Hashtable)メモ [#l902aa22]

*** 配列作成 [#l20c9713]

System.Collections.Hashtableのインスタンスを作成

 $RadioButtons = @{}

*** 連想配列(代入) [#o1e3c315]
 PS C:> $RadioButtons = @{
     1 = "AAA";
     2 = "BBB";
     3 = "CCC";
 }

*** 連想配列(表示) [#o14c06ce]
 PS C:> for($i=0; $i -le 3; $i++) {
     $RadioButtons.${i} = "AAA${i}"
 }


 PS C:> $RadioButton = ""

 PS C:> foreach ($RadioButton in $RadioButtons) {
 
     $RadioButton
 
 }
 
 Name                           Value                                                                                                    
 ----                           -----                                                                                                    
 3                              AAA3                                                                                                     
 2                              AAA2                                                                                                     
 1                              AAA1                                                                                                     
 0                              AAA0 

*** 繰り返し処理[#k4696ce0]

foreachでループ処理するとき。ValuesプロパティにValueのコレクション、KeysプロパティにKeyのコレクションが入っている。

 PS C:> $RadioButtons.Values | foreach { $_ }
 
 AAA3
 AAA2
 AAA1
 AAA0

*** 繰り返し処理2[#s343141a]

Valueを連想配列にして、値を取得する例。

 PS C:> $dialog1 = @{
     "Text" = "Dialog1";
     "Size" = @{
        "Width" = 600;
        "Height" = 400;
     };
 }

 PS C:> $dialog1.Size.Width
 
 600

 PS C:> $dialog1.Values | foreach { $_ }
 
 Dialog1
 
 Name                           Value                                                                                                    
 ----                           -----                                                                                                    
 Height                         400                                                                                                      
 Width                          600                                                                                                      


 PS C:> $dialog1.Keys | foreach { $_ }
 
 Text
 Size

-フォルダーサイズ一覧~
[[フォルダーサイズ一覧>FrontPage/IT/Script/Windows/Powershell/FolderSize]]

-ログイン状態確認
 # ログファイルのパスを設定
 $logFilePath = "C:\Logs\UserLogonStatus.log"
 
 # ログファイルが存在しない場合は作成
 if (-Not (Test-Path $logFilePath)) {
     New-Item -Path $logFilePath -ItemType File -Force
 }
 
 # 現在ログオンしているユーザーを取得
 $loggedOnUsers = Get-WmiObject -Class Win32_ComputerSystem | Select-Object -ExpandProperty UserName
 
 # ログオン状態をログファイルに出力
 $timeStamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
 if ($loggedOnUsers) {
     $logEntry = "$timeStamp - Logged on user: $loggedOnUsers"
 } else {
     $logEntry = "$timeStamp - No users logged on"
 }
 
 Add-Content -Path $logFilePath -Value $logEntry

-administrator~
「Administrator」でログインしている場合に「No users logged on」と表示される問題は、Win32_ComputerSystemクラスを使用しているためです。このクラスは「インタラクティブなユーザーセッション」を取得しますが、Administratorのセッションは特別なセキュリティコンテキストにあるため、正しく検出できない場合があります。~
~
この問題を解決するには、別の方法でログオンユーザーを取得することが必要です。以下の方法を試してみてください。~
~
修正版スクリプト
qwinstaコマンドを使用して、ログオンしているすべてのセッションを取得し、ユーザー名を判別する方法です。これにより、ローカルにログインしているすべてのユーザーを確認でき、Administratorも含まれます。~

 powershell
 # ログファイルのパスを設定
 $logFilePath = "C:\Logs\UserLogonStatus.log"
 
 # ログファイルが存在しない場合は作成
 if (-Not (Test-Path $logFilePath)) {
     New-Item -Path $logFilePath -ItemType File -Force
 }
 
 # qwinstaコマンドを実行してセッション情報を取得
 $sessionInfo = qwinsta | Select-String "Active" | ForEach-Object {
     ($_ -split "\s+")[1]
 }
 
 # ログオンしているユーザーを取得
 $loggedOnUsers = $sessionInfo -join ", "
 
 # ログオン状態をログファイルに出力
 $timeStamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
 if ($loggedOnUsers) {
     $logEntry = "$timeStamp - Logged on users: $loggedOnUsers"
 } else {
     $logEntry = "$timeStamp - No users logged on"
 }
 
 # ログファイルに出力
 Add-Content -Path $logFilePath -Value $logEntry

スクリプトの説明
-qwinstaは、Windows上で現在アクティブなセッションをリストするコマンドです。このコマンドは、インタラクティブなユーザー(例:Administratorを含む)のセッションも取得します。~
-Select-String "Active"で、アクティブなセッションのみをフィルタリングしています。~
-その後、ユーザー名を抽出し、それをログファイルに記録しています。~
手順
+上記の修正版スクリプトをPowerShellスクリプトファイル(例:CheckUserLogon.ps1)として保存します。~
+タスクスケジューラで、このスクリプトを定期的に実行するタスクを設定します(前述の手順を参考にしてください)。~
これで、Administratorでログインしている場合でも正しくログオンユーザーが取得され、ログに記録されるはずです。
-パート2
qwinstaコマンドを使うと、リモートデスクトップ(RDP)セッションでログインしているユーザーが「rdp-tcp#6」のように表示されることがあります。これは、RDPセッションに割り当てられたセッションIDが表示されるためで、具体的なユーザー名ではありません。このようなセッションIDから実際のユーザー名を取得するためには、quserコマンドやGet-WmiObjectなどを組み合わせて使う方法があります。~
~
解決策: quser コマンドを使用してユーザー名を取得する~
quserコマンドを使うと、現在ログオンしているユーザーとそのセッションのリストを取得でき、rdp-tcpのセッションでもユーザー名を確認できます。~
~
以下は、RDPセッションやローカルセッションも含めて正確にログオンユーザーを取得するスクリプトの例です。~
~
修正版スクリプト~
 powershell
 # ログファイルのパスを設定
 $logFilePath = "C:\Logs\UserLogonStatus.log"
 
 # ログファイルが存在しない場合は作成
 if (-Not (Test-Path $logFilePath)) {
     New-Item -Path $logFilePath -ItemType File -Force
 }
 
 # quserコマンドでセッション情報を取得
 $sessionInfo = quser | ForEach-Object {
     # 行を分割し、ユーザー名を取得
     ($_ -split "\s+")[1]
 }
 
 # ユーザーがログオンしているか確認
 $loggedOnUsers = $sessionInfo | Where-Object { $_ -ne "USERNAME" } # "USERNAME" ヘッダーを除外
 
 # ログオン状態をログファイルに出力
 $timeStamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
 if ($loggedOnUsers) {
     $logEntry = "$timeStamp - Logged on users: $($loggedOnUsers -join ', ')"
 } else {
     $logEntry = "$timeStamp - No users logged on"
 }
 
 # ログファイルに出力
 Add-Content -Path $logFilePath -Value $logEntry

スクリプトのポイント
+quserコマンド:~
quserコマンドは、現在ログオンしているすべてのユーザーとそのセッション情報を表示します。この出力から、実際のユーザー名を抽出します。~
~
+ForEach-Objectでユーザー名の抽出:~
出力行を空白で分割し、必要なユーザー名部分だけを取得します。~
~
+ヘッダーを除外:~
quserコマンドの出力には「USERNAME」というヘッダー行があります。この行を除外して、実際のユーザー名だけを取り出します。~
~
使い方~
+スクリプトをファイルとして保存(例:CheckRDPUserLogon.ps1)。~
+前述のタスクスケジューラの設定方法に従い、定期的に実行するよう設定します。~
これにより、RDPセッションも含め、正しくログオンユーザー(Administratorやその他のユーザー)が取得され、ログファイルに出力されるようになります。
~
結果例~
ログファイルには以下のように記録されます:~
~
bash~
コードをコピーする~
2024-10-18 12:30:00 - Logged on users: Administrator, JohnDoe~
これで、RDPセッションで「rdp-tcp#6」などの表示ではなく、実際にログオンしているユーザー名が表示されるようになります。~

**GUI ツール [#l0f7168a]

***リモートサーバへスクリプトを設置するGUIプログラム [#l1ad7878]

 Add-Type -AssemblyName System.Windows.Forms
 Add-Type -AssemblyName System.Drawing
 
 # フォームの作成
 $form = New-Object System.Windows.Forms.Form
 $form.Text = "リモート接続とファイル設置"
 $form.Size = New-Object System.Drawing.Size(400,300)
 $form.StartPosition = "CenterScreen"
 
 # ラベルとテキストボックス
 $labelHost = New-Object System.Windows.Forms.Label
 $labelHost.Text = "ホスト名:"
 $labelHost.Location = New-Object System.Drawing.Point(10,20)
 $form.Controls.Add($labelHost)
 
 $textHost = New-Object System.Windows.Forms.TextBox
 $textHost.Location = New-Object System.Drawing.Point(120,20)
 $textHost.Width = 250
 $form.Controls.Add($textHost)
 
 $labelUser = New-Object System.Windows.Forms.Label
 $labelUser.Text = "ユーザー名:"
 $labelUser.Location = New-Object System.Drawing.Point(10,60)
 $form.Controls.Add($labelUser)
 
 $textUser = New-Object System.Windows.Forms.TextBox
 $textUser.Location = New-Object System.Drawing.Point(120,60)
 $textUser.Width = 250
 $form.Controls.Add($textUser)
 
 $labelPassword = New-Object System.Windows.Forms.Label
 $labelPassword.Text = "パスワード:"
 $labelPassword.Location = New-Object System.Drawing.Point(10,100)
 $form.Controls.Add($labelPassword)
 
 $textPassword = New-Object System.Windows.Forms.TextBox
 $textPassword.Location = New-Object System.Drawing.Point(120,100)
 $textPassword.Width = 250
 $textPassword.UseSystemPasswordChar = $true
 $form.Controls.Add($textPassword)
 
 $labelFile = New-Object System.Windows.Forms.Label
 $labelFile.Text = "ファイル選択:"
 $labelFile.Location = New-Object System.Drawing.Point(10,140)
 $form.Controls.Add($labelFile)
 
 $textFile = New-Object System.Windows.Forms.TextBox
 $textFile.Location = New-Object System.Drawing.Point(120,140)
 $textFile.Width = 180
 $form.Controls.Add($textFile)
 
 $buttonBrowse = New-Object System.Windows.Forms.Button
 $buttonBrowse.Text = "参照..."
 $buttonBrowse.Location = New-Object System.Drawing.Point(310,140)
 $buttonBrowse.Add_Click({
     $openFileDialog = New-Object System.Windows.Forms.OpenFileDialog
     if ($openFileDialog.ShowDialog() -eq 'OK') {
         $textFile.Text = $openFileDialog.FileName
     }
 })
 $form.Controls.Add($buttonBrowse)
 
 # 接続ボタン
 $buttonConnect = New-Object System.Windows.Forms.Button
 $buttonConnect.Text = "接続"
 $buttonConnect.Location = New-Object System.Drawing.Point(150,180)
 $form.Controls.Add($buttonConnect)
 
 # 終了ボタン
 $buttonExit = New-Object System.Windows.Forms.Button
 $buttonExit.Text = "終了"
 $buttonExit.Location = New-Object System.Drawing.Point(250,180)
 $buttonExit.Add_Click({
     $form.Close()
 })
 $form.Controls.Add($buttonExit)
 
 $buttonConnect.Add_Click({
     $hostName = $textHost.Text
     $userName = $textUser.Text
     $password = $textPassword.Text | ConvertTo-SecureString -AsPlainText -Force
     $credential = New-Object System.Management.Automation.PSCredential ($userName, $password)
 
     # リモートセッションの作成
     try {
         $session = New-PSSession -ComputerName $hostName -Credential $credential
         if ($session -ne $null) {
             [System.Windows.Forms.MessageBox]::Show("接続成功しました!")
             
             # ファイル転送処理
             $filePath = $textFile.Text
             if (Test-Path $filePath) {
                 Copy-Item -Path $filePath -Destination "C:\RemotePath" -ToSession $session
                 [System.Windows.Forms.MessageBox]::Show("ファイルを転送しました。")
             } else {
                 [System.Windows.Forms.MessageBox]::Show("ファイルが見つかりません。")
             }
 
             # セッションの終了
             Remove-PSSession -Session $session
         } else {
             [System.Windows.Forms.MessageBox]::Show("セッション確立に失敗しました。")
         }
     } catch {
         [System.Windows.Forms.MessageBox]::Show("エラー: $_")
     }
 })
 
 $form.Topmost = $true
 $form.Add_Shown({$form.Activate()})
 [void]$form.ShowDialog()


**参考資料 [#je7bc608]
-[[ChatGPT>https://chatgpt.com/]]

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS