0

我正在开发一个基于 GUI 的 Powershell 工具,以帮助用户轻松找出他们的 AD 密码何时到期。由于 Covid 的限制,大多数用户并没有在现场,而是依靠 VPN 连接到 AD。这样做的一个副产品是,许多人看不到 Windows 中的自动弹出窗口来提醒他们尽快设置新密码。那些在现场的人看到通知 OK。这不是一个组策略问题。该工具将以两种不同的语言推出——一种代表“母语”(通常不说英语)和所有其他国家的英语。

一些(大部分)东欧国家使用类似“dMyyyy”的短日期格式。- 根据设置菜单更改 Windows 中的“区域”设置。

该工具计算今天和到期数据之间的差异,并将天数输出到文本字段。实际到期时间在其自己的文本字段中正确显示。

这一切背后的一些源代码......

$thisUser = [Environment]::UserName

#make string
"net user " + $thisUser + " /domain"

#make cmd string
$fetch_net_user = "net user " + $thisUser + " /domain"

#execute command and store to variable
$net_user_data_array = Invoke-Expression $fetch_net_user

#Gets password expiry date (with header)
$password_expiry_with_header = $net_user_data_array[11]

#extracts only the date and assigns to new variable (the hours and minutes) can be ignored)
$password_expiry_as_string = $password_expiry_with_header.Split(' ')[-2]

# Home countries - works OK
try{
    $password_expiry_as_dateTime = [datetime]::ParseExact($password_expiry_as_string, 'dd.MM.yyyy', $null)
}

# Others - works OK
catch{
    $password_expiry_as_dateTime = [datetime]::ParseExact($password_expiry_as_string, 'dd/MM/yyyy', $null)

 # where problem occurs
 catch{
 $password_expiry_as_dateTime = [datetime]::ParseExact($password_expiry_as_string, 'd.M.yyyy.', $null)
 }

finally{
#show GUI error window...
 }

#fetch date... converted to yesterday to fix an off-by-one bug!
$today = Get-Date
$rightNow = $today.AddDays(-1)

#calc days left
$daysRemaining = (New-TimeSpan -Start $rightNow -End $password_expiry_as_dateTime).Day

# some other code follows, manipulating date values etc. Works with most date formats. 

执行脚本时会抛出几个错误。

第一个是...

Exception calling "ParseExact" with "3" argument(s): "String was not recognized as a valid  DateTime."

其他人将遵循,例如

You cannot call a method on a null-valued expression.

由于无法计算今天与到期日之间的差异。

有什么简单的解决方法吗?我宁愿避免为每个国家/文化写一长串“如果”陈述。谢谢!

我确信代码可以更优雅一点,这将在以后的版本中解决。现在,让它在一些更晦涩的日期格式上工作是我的首要任务。

我应该强调的其他一点是,该工具以“只读”能力工作。不使用“Set-Item”命令。

问候,

WL

4

1 回答 1

2

你有2个问题:

  • 可互换使用的多种日期格式
  • 一些字符串上的尾随点

第一个问题可以通过传递多个格式字符串来解决ParseExact()- 它会按顺序尝试每个,直到成功解析输入字符串(或到达列表末尾):

[datetime]::ParseExact($password_expiry_as_string, [string[]]@('dd.MM.yyyy', 'dd/MM/yyyy', 'dd.M.yyyy', 'd.M.yyyy'), $null, [System.Globalization.DateTimeStyles]::None)

第二个问题可以通过修剪尾随点来解决:

[datetime]::ParseExact($password_expiry_as_string.TrimEnd('.'), [string[]]@('dd.MM.yyyy', 'dd/MM/yyyy', 'dd.M.yyyy', 'd.M.yyyy'), $null, [System.Globalization.DateTimeStyles]::None)
于 2022-02-03T11:03:12.627 回答