嗨,我正在创建一个软件,它应该注销除当前登录的Windows 10系统中的用户之外的所有内容。 我可以在powershell中使用powershell命令登录。在下面查找命令:
quser | Select-String "Disc" | ForEach{logoff ($_.toString() -split ' +')[2]}
上面的命令非常适合Powershell控制台。
当它添加到我的代码 c# 中并调用该命令时,它不起作用。请在下面找到代码。
string logOff = "quser | Select-String "Disc" | ForEach{logoff ($_.toString() -split ' +')[2]}";
PowerShell psExec = PowerShell.Create();
psExec.AddScript(logoff);
Collection<PSObject> results;
results = psExec.Invoke();
我也尝试过通过生成电源外壳的子进程。请检查以下代码:
processInfo = new ProcessStartInfo
{
UseShellExecute = false,
FileName = "powershell.exe",
Arguments = "quser | Select-String "Disc" | ForEach{logoff ($_.toString() -split ' +')[2]}"
}
Console.WriteLine("Starting child process...");
using (var process = Process.Start(processInfo))
{
process.WaitForExit();
}
我也尝试了如下:
using (PowerShell ps = PowerShell.Create())
{
ps.AddScript("C:\Users\vijay.rm\Desktop\test.ps1");
Collection<PSObject> PSOutput = ps.Invoke();
foreach (PSObject item in PSOutput)
{
if (item == null)
{
Console.WriteLine(item.BaseObject.ToString());
Console.WriteLine("Done");
}
}
}
其中 test.ps1 脚本包含:
quser | Select-String "Disc" | ForEach{logoff ($_.toString() -split ' +')[2]}
我还通过将其更改为 x86 和 x64 来检查构建,但结果是相同的。
我没有得到任何例外。
但我也没有让用户注销。
我还尝试了具有管理权限的控制台应用程序。
我希望在运行 c# 代码时,除登录计算机的用户之外的所有用户都应该注销。 为了检查用户是否注销的天气,请在powershell中运行以下命令:
Get-WMIObject -class Win32_UserProfile
你会得到如下的结果:
__GENUS : 2
__CLASS : Win32_UserProfile
__SUPERCLASS :
__DYNASTY : Win32_UserProfile
__RELPATH : Win32_UserProfile.SID="S-1-5-21-329068152-1454471165-1417001333-8355646"
__PROPERTY_COUNT : 29
__DERIVATION : {}
__SERVER : BDC3-LX-G5N6QQ2
__NAMESPACE : rootcimv2
__PATH : \BDC3-LX-G5N6QQ2rootcimv2:Win32_UserProfile.SID="S-1-5-21-329068152-1454471165-14
17001333-8355646"
AppDataRoaming : System.Management.ManagementBaseObject
Contacts : System.Management.ManagementBaseObject
Desktop : System.Management.ManagementBaseObject
Documents : System.Management.ManagementBaseObject
Downloads : System.Management.ManagementBaseObject
Favorites : System.Management.ManagementBaseObject
HealthStatus : 3
LastAttemptedProfileDownloadTime :
LastAttemptedProfileUploadTime :
LastBackgroundRegistryUploadTime :
LastDownloadTime :
LastUploadTime :
LastUseTime : 20190917044128.412000+000
Links : System.Management.ManagementBaseObject
Loaded : True
LocalPath : C:Usersvijay.rm
Music : System.Management.ManagementBaseObject
Pictures : System.Management.ManagementBaseObject
RefCount :
RoamingConfigured : False
RoamingPath :
RoamingPreference :
SavedGames : System.Management.ManagementBaseObject
Searches : System.Management.ManagementBaseObject
SID : S-1-5-21-329068152-1454471165-1417001333-8355646
Special : False
StartMenu : System.Management.ManagementBaseObject
Status : 0
Videos : System.Management.ManagementBaseObject
PSComputerName : BDC3-LX-G5N6QQ2
当我们运行脚本或代码时,加载的属性应该为 false。
提前谢谢。
最有可能失败的是调用外部程序,quser.exe
和logoff.exe
(可能是后者 - 我强烈怀疑您需要运行管理权限才能注销其他用户的会话(。
外部程序输出的 stderr 消息显示在 PowerShell 的错误流中,但它们不会导致异常,因此代码会以静默方式运行和失败。
(同样,报告非零退出代码的外部程序不会导致 PowerShell 执行任何操作。
要查看出了什么问题,您必须检查psExec.Streams.Error
,即在呼叫期间收集的错误消息。
在评论中,您指出在检查错误流时,您发现那里的错误消息抱怨quser
找不到作为命令(The term 'quser' is not recognized as the name of a cmdlet, function, script file, or operable program. ...
(。
这表明了两个可能的原因之一(结果是(a((:
(a(:您的System32文件夹(通常为
C:WindowsSystem32
(莫名其妙地未列在您的Path
环境变量($env:Path
(中,但这是非常不寻常的,值得进一步调查。- 作为同时的解决方法:虽然您可以尝试引用
quser.exe
并按其完整路径logoff.exe
,但它使您可以更灵活地将 System32 文件夹作为第一个命令添加到$env:PATH
。
- 作为同时的解决方法:虽然您可以尝试引用
string logOff = "$env:PATH += ";$env:windir\System32"; quser.exe | Select-String "Disc" | ForEach{logoff.exe ($_.toString() -split ' +')[2]}";
或 (b(:C# 代码使用 32 位版本的 PowerShell SDK,并且在32 位应用程序视为
C:WindowsSystem32
的不同目录中(实际上是C:WindowsSysWow64
(,quser.exe
也不存在logoff.exe
。- 您可以尝试调用64 位版本,方法是通过虚拟目录[1]
C:WindowsSysNative
显式引用它们(仅对 32 位应用程序可见(:
- 您可以尝试调用64 位版本,方法是通过虚拟目录[1]
string logOff = "C:\Windows\SysNative\quser.exe | Select-String "Disc" | ForEach{C:\Windows\SysNative\logoff.exe ($_.toString() -split ' +')[2]}";
[1] 注意:我假设您的 Windows 安装的根目录是C:Windows
; 即使它位于不同名称的目录中,也可以可靠地引用它的方法是使用$env:windir
而不是文字C:Windows
。