PowerShell」カテゴリーアーカイブ

マウントしているPSTファイル一覧をPowerShellで出力

OutlookでPSTファイルを使用している環境で、
ユーザーがどの程度使用しているか実態を把握したい場合があります。

この場合、以下のPowerShellコマンドで出力可能です。

$Olk = New-Object -comObject Outlook.Application;
$Olk.Session.Stores | where{($_.FilePath -like '*.pst')} | ft DisplayName,FilePath -Autosize;

ログオンスクリプトなどに組み込んで共有ファイルサーバーにテキスト出力するなどすれば
ユーザーに紐づいて情報が入手できます。

Outlookのキャッシュファイルを自動削除

OutlookをExchange環境でする場合、
キャッシュモードでの使用が推奨されています。

キャッシュモードが有効だと、Exchangeメールボックスの容量に応じて
クライアントローカルにキャッシュファイルが保存されるのですが
複数人で使用するクライアントですとHDDを圧迫しかねません。

グループポリシーのスタートアップスクリプトに組み込むことで
一定日数が経過したキャッシュファイルを削除してくれるスクリプトを書いてみました。

# 変数定義
$OST_Path01 = "C:\Users\";
$OST_Path02 = "\AppData\Local\Microsoft\Outlook\";
$File_Extension = "*.ost";
$Number_Of_Days = 30;

# メイン
$Folder_List = Get-ChildItem -Path $OST_Path01;

foreach($tmp01 in @(Get-ChildItem -Path $OST_Path01)){
    $File_Path = $OST_Path01 + $tmp01.Name + $OST_Path02;

    if(Test-Path -Path $File_Path){
        foreach($tmp02 in @(Get-ChildItem -Path $File_Path -Recurse -Force -Include $File_Extension)){
            $Item_Property = Get-ItemProperty -Path $tmp02.FullName;
            if(((Get-Date) - $Item_Property.LastWriteTime).days -gt $Number_Of_Days){
                Write-EventLog -LogName Application -Source Application -EventID 999 -EntryType Information -Message "PowerShell Script Run.";
                Remove-Item -Path $tmp02.FullName -Force;
            }
        }
    }
}

スクリプトではデフォルトパスを想定し、30日以上更新がないOSTファイル(キャッシュファイル)を
自動的に削除します。この際、削除されたことがわかりにくいのでアプリケーションログに書き込んでいます。
Windowsのユーザープロファイルも含め、使用するには環境に応じたカスタマイズが必要かもしれません。

PowerShellでローカルプロファイルを削除

不特定多数者が使用する端末などですと、
知らぬ間にローカルプロファイルでディスクが一杯に・・・なんてこともありがちです。
PowerShellで条件を設定しながら削除することが可能です。
スクリプトを作成してスタートアップスクリプトなり、タスクスケジューラに
設定してあげるとシステム管理者が幸せになれるかもしれません。

Get-CIMInstance win32_userProfile -verbose | where{$_.LastuseTime -let $(Get-Date).Date.AddDays(-90)} | Remove-CIMInstance -Verbose;

上記コマンドでは、「LastUseTime」(GUI画面だと変更日)を軸としてコマンドの実行日から90日以上更新がないプロファイルを削除します。
数値を変更することで、期間は柔軟に変更可能です。
所謂「既定のプロファイル」はアクセスが拒否されますので削除される恐れはありません。
このままだとエラーが表示されてしまうので、除外したほうがスマートですね。

Get-CIMInstance win32_userProfile -verbose | where{($_.LastuseTime -let $(Get-Date).Date.AddDays(-90)) -and ($_.SID -ne "S-1-5-18")} | Remove-CIMInstance -Verbose;

これで綺麗に削除されるはずです。

PowerShellでFSMO移動

普段はGUIやコマンドプロンプトから実施することが多いのですが、
PowerShellでのやり方を調べてみました。

1. ActiveDirectory向けモジュールを読み込む

Import-Module ActiveDirectory;

2. FSMOを転送する

Move-ADDirectoryServerOperationMasterRole -Identity 移動先ADサーバー -OperationMasterRole 0,1,2,3,4 -Confirm:$False; 
    # OperationMasterRole
    # 0:PDCEmulator
    # 1:RIDMaster
    # 2:InfrastructureMaster
    # 3:SchmeMaster
    # 4:DomainNamingMaster

「OperationMasterRole」の指定で転送する操作マスタ選択できます。
また、「-Confirm:$False」を入れることで実行確認メッセージをスキップしています。

上記例では数字で指定していますが、明示的に機能名で指定することも可能です。

Move-ADDirectoryServerOperationMasterRole -Identity 移動先ADサーバー -OperationMasterRole InfraStructureMaster,RIDMaster,PDCEmulator,DomainNamingMaster,SchemaMaster -Confirm:$False;

なお、「-Force」オプションを加えることで、AD同士の疎通が取れない中でのFSMO強制転送が可能です。

Move-ADDirectoryServerOperationMasterRole -Identity 移動先ADサーバー -OperationMasterRole 0,1,2,3,4 -Force -Confirm:$False; 

PowerShellでメール送信

PowerShellではVer2.0から標準的なコマンドで
SMTPメールを送信することができます。

Send-MailMessage
※ 使用頻度の高いオプションのみ記載
-Attachments : 添付ファイルを指定
-Bcc : Bccのメールアドレスを指定
-Body : 本文内容
-Cc : Ccのメールアドレスを指定
-Encoding : 本文と件名に使用されるエンコード形式を指定
-From : 送信元メールアドレスを指定
-SmtpServer : メールを送信するSMTPサーバーを指定
-Subject : メッセージの件名を指定
-To : 宛先のメールアドレスを指定

使用例としては、以下のような形です。

Send-MailMessage -From admin@example.co.jp -To test@example.co.jp -Subject TestMessage -Body "Hello" -SmtpServer "smtpserver.example.co.jp";

日本語が含まれるメールを送信する場合は、Encodingオプションを指定しないと文字化けする可能性が高いです。
基本的にUTF8を指定すれば大概は大丈夫なイメージです。

Send-MailMessage -From admin@example.co.jp -To test@example.co.jp -Subject TestMessage -Body "ハロー" -SmtpServer "smtpserver.example.co.jp" -Encoding UTF8;

宛先やCcなどに複数のメールアドレスを指定する場合は、配列形式にして渡してあげれば大丈夫です。

$To = @("test@example.co.jp","test2@example.co.jp")
Send-MailMessage -From admin@example.co.jp -To $To -Subject TestMessage -Body "Hello" -SmtpServer "smtpserver.example.co.jp";

作業で時間を要するスクリプトを実行することも多いため、
スクリプトが終了したときに携帯電話へ完了メッセージを送るなどして活用しています。
送信に活用できるSMTPサーバーがある環境ならば、是非活用してください。

Exchangeでメールボックス内のメールを検索/削除する その1

Exchangeを運用するにあたりメール検索/監査、あるいは削除などを目的として
メールボックス内のアイテムを検索することを求められたりします。

色々条件などはつきますが、「Search-Mailbox」というコマンドを利用することで対応ができます。
https://technet.microsoft.com/ja-jp/library/dd298173(v=exchg.160).aspx

コマンド実行には、操作するアカウントに以下のRoleが必要です。
通常の管理者アカウントでは、コマンド自体が実行できません。
「Mailbox Search」
「Mailbox Import Export」

監査などの業務だと、所謂システム部門ではなく監査部門が対応する場合もありますので
権限の分割が可能です。(手順連携などは複雑でしょうけれども・・・・)

私のところに来た依頼としては、特定のメールボックスの予定表登録内容を削除したいというものでした。
コマンドのオプション「-SearchQuery」を使用して取得するアイテムを限定できるのですが、
クエリ設定の情報が少ないため検証に苦慮しました・・・・。
今回のように”予定表アイテムのみ”を指定したい場合は、下記クエリ設定で可能です。
-SearchQuery “Kind:meetings”

なお、オプション「-DeleteCcontent」を指定することで問答無用で削除可能です。

依頼内容を反映すると、以下のようなコマンドでしょうか。

Search-Mailbox -Identity "対象のメールアドレス" -SearchQuery "Kind:meetings" -DeleteContent

対象メールボックスの予定表アイテムにしぼり、問答無用で削除します。
上記コマンドだけではログに残りませんので、必要に応じてオプション調整が必要です。

Search-Mailbox -Identity "対象のメールアドレス" -SearchQuery "Kind:meetings" -TargetMailbox administrator -TargetFolder SearchResult -LogLevel Full -LogOnly

「-LogLevel」オプションをつけることで、クエリを投げた結果が「-Targetmailbox」で指定したメールボックスに保存されます。
「-LogOnly」オプションは、アイテムのコピーや削除を実行せず、あくまでクエリ結果のみを出力するオプションです。

ひとまずログを出力させてから実際の操作を行う方が丁寧かなと。

制限としては、クエリに対する結果が10,000件以上あると使用できないようです。
抵触した場合、大容量の検索実行は別コマンド「」が推奨される旨が表示されます。
別コマンドで実行しても良いのですが、残念ながらアイテム削除オプションは無いようです。

あくまで予定表フォルダ内の予定表アイテムを強制的に削除しているだけですので、
会議開催通知などで予定を共有している場合はメンバー全員への対応が必要です。
仮に会議主催者の予定を削除しても会議参加者の予定はそのままです。

PowerShellでファイル圧縮

PowerShellのVer5.0以降では、専用のコマンドとしてZip圧縮がサポートされています。
確認してみると、2つのコマンドが確認できます。

  • Compress-Archive(ファイル/フォルダ圧縮)
  • Expand-Archive(ファイル/フォルダ解凍)

<< Compress-Archive >>
ファイル/フォルダの圧縮を実行できます。

Compress-Archive -Path 圧縮元ファイル/フォルダ -DestinationPath 圧縮先指定(ファイル名も可)

試してみたところ、圧縮元が空フォルダである場合は圧縮ファイルは作成されないようです。
1つでも中身があれば正常に圧縮することができました。
ちなみに圧縮元ファイル/フォルダはワイルドカードが使用できる模様です。

Compress-Archive -Path C:\Test\* -DestinationPath C:\ArchiveTest.zip

「-CompressionLevel」オプションを使用することで、圧縮レベルを調整することができるようです。

  • Fastest:圧縮は高速だが、圧縮後のサイズは大きくなる。
  • NoCompression:圧縮はせず、ファイル/フォルダをまとめるだけ。
  • Optimal:(既定)ファイルサイズに応じて自動的に調整する。

圧縮対象が大量にある場合は変化があるかもしれませんが、通常はわざわざ変更する恩恵を受けられないかも・・・。

「-Update」オプションを使用することで、既存zipファイルにファイル/フォルダを追加できます。

Compress-Archive -Path C:\Test2 -Update -DestinationPath C:\ArchiveTest.zip

便利ですが機能上パスワードは設定できず、現在2GBまでのファイルしか圧縮できないようです。
ログローテーションなどに使用する分には十分な機能かと思います。

<< Expand-Archive >>
ファイル/フォルダの展開を実行できます。

Expand-Archive -Path C:\ArchiveTest.zip -DestinationPath C:\ExpandDirectory

こちらは単純に展開するだけですね。
残念ながら、こちらもパスワード付きzipには対応していません。
より高度な機能を使用するなら、専用のアーカイバーをインストールしてしまったほうが良いようです。

PowerShellでCDトレイを開く

読んで字の如く、あくまでお遊び的なコマンドです。
作業用のスクリプトに取り込んでおくと、メディアの置き忘れ防止に良いかも。

(New-Object -com WMPlayer.OCX.7).cdromCollection.Item(0).Eject();

今のところ、試したPCではすべて動きました。

Windowsでダミーファイル作成

インフラの検証をしている際に、よく任意のサイズでダミーファイルが必要になります。
よくコマンドを忘れてしまうのでメモメモ・・・。

fsutil file createnew ファイル名 サイズ

コマンドプロンプトで実行可能です。
サイズ指定はバイト単位のため、1MBのファイルを作成する際はこうなります。

fsutil file createnew C:\test.txt 1048576

ちなみにコマンドはPowerShellでも実行可能です。
PowerShellだとMBやGBなどの単位を解釈してくれるので便利。
さきほどのコマンドもこうなります。

fsutil file createnew C:\test.txt (1MB)

こっちの方が直感的に使用できますね。
まとまった数を作りたい場合はこんな感じで。

# ダミーファイルを作成したい個数
$Count = 100;

for($i = 0;$i -lt $Count;$i++){
    fsutil file createnew "testfile$i" (1MB);
}