如何从网络用户帐户中过滤主目录位置?

How to filter Home Directory location from net user accounts?

有命令 net user 列出所有 用户帐户
命令的输出是这样的:

Administrator            Guest                    asroot
1psaadm                  2satish                  3shyam                    
4sushil                  5sysuser_8               6sysuser_b                
tcuser                   test1                    test11 
...

如果我运行这个命令

net user shyam

输出是:

Workstations allowed         All
Logon script                 
User profile                 
Home directory               C:\Inetpub\vhosts\example.com
Last logon                   6/5/2021 4:57:17 AM

Logon hours allowed          All

我只想要来自所有 user accountsHome Directory 路径。所以我希望所有用户帐户 只有这条路径 C:\Inetpub\vhosts\example.com

我试图用这个命令得到想要的数据,但是没有输出

for /f "tokens=* skip=1" %a in ('wmic UserAccount get Name') do net user %a | findstr /c:"Home directory"

如何获取所有用户帐户的所有路径列表?

注意:如果你的cmd中没有Home directory路径那么你可以尝试列出:

Logon hours allowed      ALL

WMIC 的输出始终是 Unicode 输出,编码 UTF-16 LE (little endian) with BOM (byte order mark) which is a problem in this case because of the Windows command processor cmd.exe is designed for processing text data with a character encoding 每个字符仅使用一个字节。 CMD 将以十六进制字节值 0D 00 0A 00(回车 return + 换行)结尾的 UTF-16 LE 编码行错误解释为 0D 0D 0A 和因此,从捕获的输出中进一步处理的每一行在删除以 0D 0A.

结尾的行后,末尾都有一个回车符 return

命令行还有一个问题:

wmic UserAccount get Name

WMIC 追加到尾随 space 的所有行,以便每个输出行具有相同数量的字符。这是有问题的,因为用户名也可以包含一个或多个 spaces,因此默认字符串定界符正常 space 和水平制表符不能用于删除不需要的尾随 spaces . tokens=* 的使用导致仅删除所有前导 spaces/tabs,但尾随 space 保留。

使用以下命令行会发生什么情况?

for /f "tokens=* skip=1" %a in ('wmic UserAccount get Name') do

已将一个用户帐户名一个接一个地分配给指定的循环变量 a,尾随 spaces 并在末尾有一个回车符 return,因此下一个命令未能按预期工作。

在命令提示符中可以使用window:

for /F "skip=2 tokens=1* delims==" %G in ('%SystemRoot%\System32\wbem\wmic.exe USERACCOUNT GET Name /VALUE 2^>nul') do @for /F "eol=| delims=" %I in ("%H") do @for /F "tokens=2*" %J in ('%SystemRoot%\System32\net.exe user "%I" 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Home directory"') do @echo Home directory for "%I" is: "%K"

在批处理文件中可以使用:

for /F "skip=2 tokens=1* delims==" %%G in ('%SystemRoot%\System32\wbem\wmic.exe USERACCOUNT GET Name /VALUE 2^>nul') do for /F "eol=| delims=" %%I in ("%%H") do for /F "tokens=2*" %%J in ('%SystemRoot%\System32\net.exe user "%%I" 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Home directory"') do echo Home directory for "%%I" is: "%%K"

这个长命令行最适合在上面发布的批处理文件中使用,但可读性更好的是:

for /F "skip=2 tokens=1* delims==" %%G in ('%SystemRoot%\System32\wbem\wmic.exe USERACCOUNT GET Name /VALUE 2^>nul') do (
    for /F "eol=| delims=" %%I in ("%%H") do (
        for /F "tokens=2*" %%J in ('%SystemRoot%\System32\net.exe user "%%I" 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Home directory"') do (
            echo Home directory for "%%I" is: "%%K"
        )
    )
)

带有选项 /F 和包含在 ' 中的字符串的第一个命令 FOR 在后台启动另一个带有选项 /c 的命令进程使用完全限定文件名及其四个参数执行 WMIC 重定向 2>nul 重定向来自句柄 STDERR 的可能错误消息(标准错误)到设备 NUL。因此在后台执行,Windows 安装到 C:\Windows 命令:

C:\Windows\System32\cmd.exe /c C:\Windows\System32\wbem\wmic.exe USERACCOUNT GET Name /VALUE 2>nul

阅读有关 Using command redirection operators 的 Microsoft 文档,了解 2>nul 的解释。重定向运算符 > 必须在 FOR 命令行上使用脱字符 ^ 进行转义,以便在 Windows 命令解释器处理此命令时将其解释为文字字符执行命令 FOR 之前的行,它在后台启动的单独命令进程中执行嵌入式 wmic 命令行。

WMIC 在这种情况下使用 Microsoft 记录的 Win32_UserAccount class

最后带有选项 /VALUEWMIC 的输出与没有此选项的输出不同。输出现在针对每个用户帐户名称:

  • 两个空行和
  • 一行 Name= 和附加的用户帐户名 没有 尾随 spaces,这是使用选项 /VALUE 的原因之一。

WMIC.

在这种情况下最后多输出了两行空行

FOR分别cmd.exe处理批处理文件等待started的自终止cmd.exe然后处理捕获的文本数据输出处理后台命令进程的STDOUT(标准输出)。

FOR 选项 /F 总是忽略空行。但是 WMIC 的 Unicode 编码输出不幸地没有被 cmd.exe 正确处理,因此有些行只包含一个回车 return 和以 [= 开头的行35=] 和一个用户帐户名以及末尾的错误回车 return。所以无法直接处理捕获的输出。

选项skip=2 tokens=1* delims==的使用导致

  • 跳过始终为空行的前两行捕获,
  • 将每行分成两个子字符串,等号作为字符串定界符在帐户名称感兴趣的行Name之后总是存在一次,
  • 使用默认的行尾字符 ; 这在这里没有问题,因为感兴趣的行总是以 Name
  • 开头
  • 并分配给指定的循环变量 G 错误处理的空行上的回车 return 或具有用户帐户名的行上的 Name 和下一个循环变量 H 根据 ASCII table 要么空行上根本没有字符串,要么用户帐户名称末尾有不需要的回车 return。

注意:以一个或多个等号开头的用户帐户名非常不常见,此代码无法正确处理该用户帐户名开头的所有等号也被 FOR 删除。

第二个 FOR 再次使用选项 /F 现在只处理分配给循环变量 H 的字符串。因此,根本没有要处理的字符串分配给 H,因为空行被错误地解释为带有单个回车 return 的行,因此第二个 FOR 循环过滤器出空行。

对于具有用户帐户名称的行,末尾带有不需要的回车符 return 的名称分配给循环变量 H 由第二个 FOR[=220 处理=] 删除换行符回车 return 并将其余部分分配给指定的循环变量 I ,这是所需的用户帐户名。此处使用选项 eol=| 来避免以一个或多个分号开头的不寻常名称被第二个 FOR 忽略。任何用户帐户名称都不能包含竖线,因为这是 file/folder 名称不允许的字符。

第三个 FOR 循环再次使用选项 /F 运行s 在后台再次执行一个命令进程 NET,输出首先重定向到 FINDSTR,以过滤掉除以 Home directory 区分大小写的行之外的所有行。 NET 输出每个字符编码一个字节的文本数据,从而可以使用 FINDSTR 过滤输出并通过 [=156 处理捕获的输出=]FOR 更容易。后台执行的命令是:

C:\Windows\System32\cmd.exe /c C:\Windows\System32\net.exe user "%%I" 2>nul | C:\Windows\System32\findstr.exe /B /L /C:"Home directory"

第三个 FOR 必须始终只处理以 Home directory 开头的一行,十五个 space 用于对齐,也许仅此而已或主目录为用户帐户定义的路径。使用选项 tokens=2* 使用默认 space/tab 作为行分隔符拆分行,以将单词 directory 分配给指定的循环变量 J 和整个主目录到下一个但一个循环变量 K 的路径,它也可以包含一个或多个 space 或者是一个空字符串,就像在我的 Windows 计算机上的所有帐户一样。

第三个FOR最终执行命令ECHO输出消息,用户账户名由第二个[=156]确定=]FOR 和由第三个 FOR 确定的主目录路径(如果根本没有主目录路径的话)。


Compo suggested to use WMIC with the Win32_NetworkLoginProfile class 通过使用:

%SystemRoot%\System32\wbem\WMIC.exe NetLogin Get Caption,HomeDirectory

那个class有账户名和家目录路径作为成员所以想要的数据可以直接用WMIC.

名称列表在两个 classes 之间是不同的,因为可以在命令提示符 运行ning 两个 WMIC 命令中看到 window 并仔细阅读两个 class 的 属性 Name 的描述,由此 属性 Caption 的字符串 Win32_NetworkLoginProfile class 也不同于此 class 属性 Name 的字符串。 Caption 的字符串只是真实用户帐户的帐户名称,而 Name 的字符串对于本地帐户是 ComputerName\AccountNameDomain\AccountName 对于域帐户。

但是,也许可以在批处理文件中使用此 class 的数据和以下代码:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "skip=2 tokens=1* delims==" %%G in ('%SystemRoot%\System32\wbem\wmic.exe NETLOGIN GET Caption^,HomeDirectory /VALUE 2^>nul') do (
    if "%%G" == "Caption" (
        set "AccountName="
        for /F "eol=| tokens=1,2 delims=\" %%I in ("%%H") do if "%%J" == "" set "AccountName=%%I"
    ) else if "%%G" == "HomeDirectory" (
        set "HomeDirectory="
        for /F "eol=| delims=" %%I in ("%%H") do set "HomeDirectory=%%"
        if defined AccountName (
            setlocal EnableDelayedExpansion
            echo Home directory for "!AccountName!" is: "!HomeDirectory!"
            endlocal
        )
    )
)
endlocal

再次出现选项 /VALUE 否则,如果帐户完全没有主目录路径输出,则主目录路径后将再次尾随 spaces 而不是这种情况在我的 Windows 电脑上。

编写代码是为了忽略 Caption 中包含反斜杠的帐户,例如 NT AUTHORITY\SYSTEMNT AUTHORITY\LOCAL SERVICENT AUTHORITY\NETWORK SERVICE,这些帐户很可能根本不感兴趣。那么,也可以使用 if not "%%I" == "NT AUTHORITY" 而不是 if "%%J" == "" 来过滤掉不感兴趣的帐户,因为它们不是真实用户帐户。

此解决方案的优点是 cmd.exe 仅在后台启动一次 运行 wmic.exe 并获取所有感兴趣的数据。所以这个解决方案更快。


为了了解使用的命令及其工作原理,请打开 command prompt window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。

  • cmd /?
  • echo /?
  • endlocal /?
  • for /?
  • if /?
  • net /?
  • net user /?
  • set /?
  • setlocal /?
  • wmic /?
  • wmic netlogin /?
  • wmic netlogin get /?
  • wmic useraccount /?
  • wmic useraccount get /?