tech.guitarrapc.cóm

Technical updates

PowerShellでWorkGroup環境のWindows Userユーザーフラグを変更する

WorkGroup環境でPowerShellを使ってWindows Userのユーザーフラグを変更するのはADSIを参照する必要があります。 今回は、 既存ユーザーのユーザーフラグを指定したものに変更する方法です。

これでAD環境じゃなくてユーザー管理がということも少し減るとうれしいです。

ユーザーフラグとは

コンピュータの管理 > ユーザーとグループ > ユーザーのプロパティにあるオプションです。

今回のコードはWindows Server 2012で検証してあります。

サンプルコード

guitarrapc/PowerShellUtil - ADSI-Cmdlets | GitHub

以下のコードは、指定したユーザー以外のOSに存在するユーザー情報を取得して、そのユーザーフラグをPassword Never Expiredに変更するものです。

$excludeuser = "Administrator","Guest"
$HostPC = [System.Environment]::MachineName

# PowerShell 3.0 では cim から取得可能
$users = (Get-CimInstance -ClassName Win32_UserAccount | where Name -notin $excludeuser).Name

foreach ($user in $users)
{
    $targetuser = [ADSI]("WinNT://{0}/{1}, user" -F $HostPC, $user)
    Write-Warning "Setting user [$($targetuser.name)] as password not expire."
    $userFlags = $targetuser.Get("UserFlags")
    $userFlags = $userFlags -bor 0x10000 # 0x10040 will "not expire + not change password"
    $targetuser.Put("UserFlags", $userFlags)
    $targetuser.SetInfo()
}

解説

ユーザーの取得

PowerShell 3.0にはCIMコマンドレットがあるので、これを使うと簡単です。 ユーザーアカウントを取得して、絞ります。

$excludeuser = "Administrator","Guest"
$HostPC = [System.Environment]::MachineName

# PowerShell 3.0 では cim から取得可能
$users = (Get-CimInstance -ClassName Win32_UserAccount | where Name -notin $excludeuser).Name

PowerShell 2.0にはCIMコマンドレットがないため、WMIか以下のコードで取得します。 ここでは、ADSI型にしてPSBaseプロパティの全子要素をなめ、PSBase.SchemaClassNameからUserに該当するもの = ユーザー名を取得しています。 下は、AdministratorとGuestユーザーを除外しています。

$HostPC = [System.Environment]::MachineName
$adsi = [ADSI]("WinNT://" + $HostPc)
$users = ($adsi.psbase.children | where {$_.psbase.schemaClassName -match "user"} | where Name -notin "Administrator","Guest").Name

除外する対象を先に定義しておいてもいいでしょう。

$excludeuser = "Administrator","Guest"
$HostPC = [System.Environment]::MachineName
$adsi = [ADSI]("WinNT://" + $HostPc)
$users = ($adsi.psbase.children | where {$_.psbase.schemaClassName -match "user"} | where Name -notin $excludeuser).Name

各ユーザーのadsiパス取得とユーザーフラグ設定

対象のユーザー名を取得出来たら、ADSIパスを出してユーザーフラグを設定します。 先のやり方では、ユーザ一覧を取得した時Doman|WorkGroupがパスに紛れてしまいそのままでは利用できないので、ADSIパスをユーザー毎に取得しなおしています。

foreach ($user in $users)
{
    $targetuser = [ADSI]("WinNT://{0}/{1}, user" -F $HostPC, $user)

ここでユーザーフラグを取得しています。

    $userFlags = $targetuser.Get("UserFlags")

ここで、任意のユーザーフラグを設定します。 サンプルでは0×10000 (ADS_UF_DONT_EXPIRE_PASSWD)としています。

    $userFlags = $targetuser.Get("UserFlags")
    $userFlags = $userFlags -bor 0x10000 # 0x10040 will "not expire + not change password"

ユーザーフラグ一覧はMSDNで公開されています。

ADS_USER_FLAG_ENUM enumeration.aspx)

設定したいフラグをbitを組み合わせて下さい。

ADS_UF_SCRIPT                                  = 1,        // 0x1
  ADS_UF_ACCOUNTDISABLE                          = 2,        // 0x2
  ADS_UF_HOMEDIR_REQUIRED                        = 8,        // 0x8
  ADS_UF_LOCKOUT                                 = 16,       // 0x10
  ADS_UF_PASSWD_NOTREQD                          = 32,       // 0x20
  ADS_UF_PASSWD_CANT_CHANGE                      = 64,       // 0x40
  ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED         = 128,      // 0x80
  ADS_UF_TEMP_DUPLICATE_ACCOUNT                  = 256,      // 0x100
  ADS_UF_NORMAL_ACCOUNT                          = 512,      // 0x200
  ADS_UF_INTERDOMAIN_TRUST_ACCOUNT               = 2048,     // 0x800
  ADS_UF_WORKSTATION_TRUST_ACCOUNT               = 4096,     // 0x1000
  ADS_UF_SERVER_TRUST_ACCOUNT                    = 8192,     // 0x2000
  ADS_UF_DONT_EXPIRE_PASSWD                      = 65536,    // 0x10000
  ADS_UF_MNS_LOGON_ACCOUNT                       = 131072,   // 0x20000
  ADS_UF_SMARTCARD_REQUIRED                      = 262144,   // 0x40000
  ADS_UF_TRUSTED_FOR_DELEGATION                  = 524288,   // 0x80000
  ADS_UF_NOT_DELEGATED                           = 1048576,  // 0x100000
  ADS_UF_USE_DES_KEY_ONLY                        = 2097152,  // 0x200000
  ADS_UF_DONT_REQUIRE_PREAUTH                    = 4194304,  // 0x400000
  ADS_UF_PASSWORD_EXPIRED                        = 8388608,  // 0x800000
  ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION  = 16777216 // 0x1000000

最後に、ユーザーフラグを確定させます。

    $targetuser.SetInfo()
}

以上で、WorkGroup環境でも任意のユーザーのユーザーフラグを変更できます。 マウス/キーボードでGUIからやるなどというリスクの高い操作が減らせるのはいいですね。