- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我遇到了一个奇怪的问题,也许有人可以帮助我。
我正尝试在使用 Windows 10 的机器上使用 C# 从 Active Directory 用户检索终端服务属性。我通过在我的应用程序中运行 PowerShell 脚本来执行此操作,如下所示:
var script = $@"Import-module ActiveDirectory
$user=[ADSI]""LDAP://192.111.222.33:389/CN=SomePerson,DC=Domain,DC=local""
$user.psbase.Username = ""administrator""
$user.psbase.Password = ""adminPassword""
$user.psbase.invokeget(""TerminalServicesProfilePath"")";
using (var runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
using (var pipeline = runspace.CreatePipeline())
{
pipeline.Commands.AddScript(script);
var test = pipeline.Invoke();
Console.WriteLine("Success: ");
return true;
}
}
我遇到了这个异常:
System.Management.Automation.MethodInvocationException: 'Exception calling "InvokeGet" with "1" argument(s): "Unknown name. (Exception from HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME))"'
当我在使用 Windows Server 2012 作为操作系统的机器上的 Visual Studio 2015 中运行上述代码时,它工作得很好!我确保我的 Windows 10 机器也安装了 RSAT。
$user = [ADSI]"LDAP://192.111.222.33:389/CN=SomePerson,DC=Domain,DC=local"
$user.psbase.Username = "administrator"
$user.psbase.Password = "adminPassword"
Write-Output "Terminal Services profile path:"
Write-Output $user.psbase.invokeget("TerminalServicesProfilePath")
这是 PowerShell 的输出:
我还尝试在 Visual Studio 的 PowerShell 交互式窗口中运行该脚本,效果也不错。这是屏幕截图及其输出:
(身份信息已删减)
但是当我使用这些属性名称运行我的脚本时,我没有收到正确的信息。它们似乎不是相同的属性。以下是我的用户在 Active Directory 用户和计算机中的几个屏幕截图:
您可以在上面看到我试图检索的属性。
当我在“属性编辑器”选项卡上查看用户的属性时,您可以看到 msTSProfilePath,它包含一个不同的值:
使用 msTSProfilePath
运行脚本返回在属性编辑器窗口 (????????
) 中看到的属性。
我已经针对两个单独的 Active Directory 域对此进行了测试:
我在另一台 Windows 10 机器上运行这段代码,但问题仍然存在。
谢谢!
最佳答案
这个问题真的困扰了我一生,因为从服务器 2000 开始我就一直在努力寻找获得这个值的方法。我不确定为什么 PowerShell 脚本可以在 Windows 10 上运行(我没有连接到我可以自由查询测试的域的 win10 框)但我确实找到了解决此问题的方法。我知道您一开始不会喜欢它,但您无需执行任何操作,只需复制/粘贴并附加我列出的简短命令列表即可。
我相信您现在已经知道该值隐藏在 userParameters AD 属性中。这是一个编码值。您可以在此处查看取消编码此值的规范(仅当您感兴趣时,不需要获取您的值)https://msdn.microsoft.com/en-us/library/ff635169.aspx
比我更了解这种情况的人确实编写了我的脚本来为我们完成艰苦的工作。此脚本位于此处的第三篇文章中:https://social.technet.microsoft.com/Forums/scriptcenter/en-US/953cd9b5-8d6f-4823-be6b-ebc009cc1ed9/powershell-script-to-modify-the-activedirectory-userparameters-attribute-to-set-terminal-services?forum=ITCG
只需将所有代码复制并粘贴到您的 PowerShell 脚本中。它只构建 1 个名为 TSuserParameters 的对象。您将对从 AD 返回的 userParameters 数据使用一个名为 .UnBlob 的对象方法。在这里,我使用 Get-ADUser 提取此数据:
$TSuserParameters.UnBlob((get-aduser -Identity someuser -Properties userparameters).userparameters)
该对象将解析数据并将其存储在 TSAttributes 属性集合下。该实习生存储 CtxWFProfilePath,其中包含您想要的数据。路径本身存储有元数据(例如,此值的长度是可变宽度。要了解原因,请再次阅读第一个链接中的文档,这与获取数据无关)。因为元数据与对象一起存储,所以您只需要属性数组 [0] 中的第一个对象:
$TSuserParameters.TSAttributes.CtxWFProfilePath[0]
现在您拥有了所需的数据。这应该可以追溯到服务器 2000,因为此编码规范从那时起似乎没有改变。
您还可以使用此对象访问其他 TS 属性。
这是 Stack 愿意让我发布的完整脚本:
$TSuserParameters = New-Object System.Object
$TSuserParameters |Add-Member -membertype NoteProperty -name Types -value @{"CtxCfgPresent" = "Int32"; "CtxCfgFlags1" = "Int32"; "CtxCallBack" = "Int32"; "CtxKeyboardLayout" = "Int32"; "CtxMinEncryptionLevel" = "Int32"; "CtxNWLogonServer" = "Int32"; "CtxWFHomeDirDrive" = "ASCII"; "CtxWFHomeDir" = "ASCII"; "CtxWFHomeDrive" = "ASCII"; "CtxInitialProgram" = "ASCII"; "CtxMaxConnectionTime" = "Int32"; "CtxMaxDisconnectionTime" = "Int32"; "CtxMaxIdleTime" = "Int32"; "CtxWFProfilePath" = "ASCII"; "CtxShadow" = "Int32"; "CtxWorkDirectory" = "ASCII"; "CtxCallbackNumber" = "ASCII"}
$TSuserParameters |Add-Member -membertype NoteProperty -name TSAttributes -value @{}
$TSuserParameters |Add-Member -membertype NoteProperty -name SpecificationURL -value"http://msdn.microsoft.com/en-us/library/cc248570(v=prot.10).aspx"
$TSuserParameters |Add-Member -membertype NoteProperty -name Reserved -value [byte[]]
$TSuserParameters |Add-Member -membertype NoteProperty -name AttributeCount -value [uint16]0
$TSuserParameters |Add-Member -membertype ScriptMethod -name init -value {
$this.TSAttributes = @{}
[byte[]]$this.Reserved = [byte[]]$null
}
$TSuserParameters |Add-Member -membertype ScriptMethod -name UnBlob -value {
Param ($Input)
$this.init()
$ArrayStep = 1
#Add-Type -AssemblyName mscorlib
#A new array for writing things back
[Byte[]] $resultarray = $NULL
#$userInfo.userParameters
$char = [char]1
#The value is a binary blob so we will get a binary representation of it
#$input.length
$userparms = [System.Text.Encoding]::unicode.GetBytes($Input)
#$userparms.count
#$userInfo.userParameters
If ($userparms) #if we have any data then we need to process it
{
#Write-Host "Processing $userparms"
$Valueenum = $userparms.GetEnumerator()
$Valueenum.reset()
$result = $Valueenum.MoveNext()
#Now lets get past the initial reserved 96 bytes as we do not care about this.
Write-Host "skipping reserved bytes"
for ($ArrayStep = 1; $ArrayStep -le 96; $ArrayStep ++)
{
[byte[]]$this.reserved += $Valueenum.current #Store the reserved section so we can add it back for storing
#Write-Host "Step $ArrayStep value $value"
$result = $Valueenum.MoveNext()
}
#Next 2 bytes are the signature nee to turn this into a unicode char and if it is a P there is valid tem services data otherwise give up
#So to combine two bites into a unicode char we do:
Write-Host "Loading signature"
[Byte[]]$unicodearray = $NULL
for ($ArrayStep = 1; $Arraystep -le 2; $ArrayStep ++)
{
$value = $Valueenum.current
#Write-Host "Step $ArrayStep value $value"
[Byte[]]$unicodearray += $Value
$result = $Valueenum.MoveNext()
}
$TSSignature = [System.Text.Encoding]::unicode.GetString($unicodearray)
Write-Host "Signatire is $TSSignature based on $unicodearray"
[uint32] $Value = $NULL
If ($TSSignature -eq "P") # We have valid TS data
{
Write-Host "We have valid TS data so process it"
#So now we need to grab the next two bytes which make up a 32 bit unsigned int so we know how many attributes are in this thing
#We have no such data type so lets improvise by adding the value of the bytes together after multiplying the higer order byte by 256
$Value = [uint16]$Valueenum.current
$result = $Valueenum.MoveNext()
$Value += [uint16]$Valueenum.current * 256
$result = $Valueenum.MoveNext()
write-Host "Found $value TS Attributes in the blob"
$this.AttributeCount = [uint16]$value
For ($AttribNo = 1; $AttribNo -le $value; $AttribNo ++)#For each attribute lets get going
{
#Get the first attribute, 2 bytes for name length, 2 bytes for value length, and 2 bytes for type, followed by the data.
#Grab name length
$NameLength = [uint16]$Valueenum.current
$result = $Valueenum.MoveNext()
$NameLength += [uint16]$Valueenum.current * 256
$result = $Valueenum.MoveNext()
#Grab Value length
$ValueLength = [uint16]$Valueenum.current
$result = $Valueenum.MoveNext()
$ValueLength += [uint16]$Valueenum.current * 256
$result = $Valueenum.MoveNext()
#Grab Type
$TypeValue = [uint16]$Valueenum.current
$result = $Valueenum.MoveNext()
$TypeValue += [uint16]$Valueenum.current * 256
$result = $Valueenum.MoveNext()
#Write-Host "NameLength is $NameLength, ValueLength is $ValueLength, Type is $TypeValue"
#Now we know how many bytes bellong to the following fields:
#Get the name bytes into an array
$NameUnicodeArray = $NULL
for ($ArrayStep = 1; $Arraystep -le $NameLength; $ArrayStep ++)
{
[Byte[]]$NameUnicodeArray += $Valueenum.current
$result = $Valueenum.MoveNext()
}
#Get the attribute value bytes into an array
$ATTValueASCIICodes = ""
for ($ArrayStep = 1; $Arraystep -le $ValueLength; $ArrayStep ++)
{
$ATTValueASCIICodes += [char][byte]$Valueenum.current
$result = $Valueenum.MoveNext()
}
#Grab the name
$AttributeName = [System.Text.Encoding]::unicode.GetString($NameUnicodeArray)
Write-Host "UnBlobing: $AttributeName"
#manipulate the value array as required
#it is sets of two ASCII chars representing the numeric value of actual ASCII chars
$AttributeValue = $NULL
#$TempStr = "" #tem string for the Hex values
#$ValueByteArray | foreach { $TempStr += [char][byte]$_ } #get the bytes into a string as the ASCII chars
#write-host "Temp String = $ATTValueASCIICodes it is $($ATTValueASCIICodes.length)"
switch ($this.Types.$AttributeName)
{
"Int32" {
$AttributeValue = [convert]::toint32($ATTValueASCIICodes,16)
}
"ASCII" {
$AttributeValue = ""
#$ASCIIString = [System.Text.Encoding]::ASCII.GetString($TempStr)# make them into an ascii string
for ($ArrayStep = 0; $Arraystep -lt $ATTValueASCIICodes.length; $ArrayStep += 2)
{
$FinalChar = [char][byte]([convert]::toint16( $ATTValueASCIICodes[($ArrayStep) ] + $ATTValueASCIICodes[$ArrayStep + 1],16)) #Grab the char created by this conversion
$AttributeValue += $FinalChar #add them to the array.
}
}
Default {
$AttributeValue = "Attribute type Not defined"
}
}
If ($this.TSAttributes.containsKey($AttributeName))
{
$this.TSAttributes.$AttributeName = @($AttributeValue,$ATTValueASCIICodes,$NameLength,$ValueLength,$TypeValue)
}
else
{
$this.TSAttributes.add($AttributeName,@($AttributeValue,$ATTValueASCIICodes,$NameLength,$ValueLength,$TypeValue))
}
}
Write-Host "================================"
}
else
{
write-host "Signature is not valid, no TS Data"
}
}
}
$TSuserParameters |Add-Member -membertype ScriptMethod -name Blobify -value {
#Lets build this thing
#Start with the reserved bytes
[byte[]]$result = $this.Reserved
#now add the Signature "P" as we are writing valid data
[byte[]]$result += [System.Text.Encoding]::unicode.GetBytes("P")
#Now for the number of attributes being stored, we need to reverse the bytes in this 16 bit unsigned int
$byte1 = [byte](($this.AttributeCount -band 65280) % 256)
$byte2 = [byte]($this.AttributeCount -band 255)
[byte[]]$result += $byte2
[byte[]]$result += $byte1
#Now for the attributes:
$this.TSAttributes.getenumerator() | foreach {
$Valuearray = $_.value
$attname = $_.key
#Get the reversed bytes for the NameLength field
$byte1 = [byte](($Valuearray[2] -band 65280) % 256)
$byte2 = [byte]($Valuearray[2] -band 255)
[byte[]]$result += $byte2
[byte[]]$result += $byte1
#And again for the ValueLength
$byte1 = [byte](($Valuearray[3] -band 65280) % 256)
$byte2 = [byte]($Valuearray[3] -band 255)
[byte[]]$result += $byte2
[byte[]]$result += $byte1
#And again for the typevalue
$byte1 = [byte](($Valuearray[4] -band 65280) % 256)
$byte2 = [byte]($Valuearray[4] -band 255)
[byte[]]$result += $byte2
[byte[]]$result += $byte1
#Now add the propertyname in plain ASCII text
Write-Host "Blobifying `"$attname`""
#$attnamearray = [System.Text.Encoding]::unicode.GetBytes("$attname")
#Write-Host "Attname array = $($attnamearray.count), valuelength = $($Valuearray[2])"
[byte[]]$result += [System.Text.Encoding]::unicode.GetBytes("$attname")
#write-Host "$($result.count)"
#for ($loopcount = 1; $loopcount -le $attname.length; $loopcount ++)
#{
# [byte[]]$result += [BYTE][CHAR]$attname[$loopcount - 1]
#}
#And finaly add the value to the result using the ASCII conversion
#New array of bytes to add the att value to so we can see how big it is
$HexString = $Valuearray[1]
[byte[]]$attvalbytes = $null
switch ($this.Types.$attname)
{
"ASCII" {
#now for each part of the hex string lets get the value for that ascii char
$HexString.ToCharArray() | foreach {
[byte[]]$attvalbytes += [BYTE][CHAR]($_)
}
}
"Int32" {
#For each char we need to store the byte value
$HexString.ToCharArray() | foreach {
[byte[]]$attvalbytes += [BYTE][CHAR]($_ )
}
}
}
$result += $attvalbytes
write-Host "att value is $($attvalbytes.count) and was $($Valuearray[3])"
Write-Host "NewASCII = $([System.Text.Encoding]::ASCII.GetString($attvalbytes))"
Write-Host "OldASCII = $($Valuearray[1])"
Write-Host "================================"
#[System.Text.Encoding]::unicode.GetString($result)
}
return [System.Text.Encoding]::unicode.GetString($result)
}
$TSuserParameters |Add-Member -membertype ScriptMethod -name AddUpdate -value {
Param ($Attname,$NewAttValue,$TypeValue)
$HexString = ""
switch ($this.Types.$Attname)
{
"ASCII" {
Write-host "ascii"
for ($loopcount = 0; $loopcount -lt $AttValue.length; $loopcount ++)
{
#Lets get the Hex value for this char as a string
$HexString = [convert]::tostring([BYTE][CHAR]($AttValue[$loopcount]),16)
#As the hex conversion drops the leading zero on the first char if we have a less than 10 value add 0 toi the front if we do not have an even number of chars
If (($hexstring.length % 2) -eq 1){ $hexstring = "0" + $hexstring}
}
}
"Int32" {
#convert the int32 to hex
$HexString = [convert]::tostring($AttValue,16)
#As the hex conversion drops the leading zero on the first char if we have a less than 10 value add 0 toi the front if we do not have an even number of chars
If (($hexstring.length % 2) -eq 1){ $hexstring = "0" + $hexstring}
#There is also the special case of the ctX flags value which is always stored as the full 32bits even when there ere empty bits:
if (($attname -eq "CtxCfgFlags1") -and ($hexstring.length -lt 8))
{
$Loopmax = $hexstring.length
for ($loopcount = 1; $loopcount -le (8 - $Loopmax); $loopcount ++) {$HexString = "0" + $HexString ; Write-host "Done"}
}
}
}
$namelenght = ([System.Text.Encoding]::unicode.GetBytes($Attname)).count
#Now change the values in the table:
If ($this.TSAttributes.containsKey($Attname))
{
#If we do not have an type value we can look in the table and get it from there as it is unlikely this attribute will change types
If (-not $TypeValue)#If we are not offered a type value by the user we will assum it is the standard of 1
{
$TypeValue = $this.TSAttributes.$Attname[4]
}
$this.TSAttributes.$Attname = @($NewAttValue,$HexString,$namelenght,$HexString.length,$TypeValue)
}
else
{
If (-not $TypeValue)#If we are not offered a type value by the user we will assum it is the standard of 1
{
$TypeValue = 1
}
$this.TSAttributes.add($Attname,@($NewAttValue,$HexString,$namelenght,$HexString.length,$TypeValue))
}
}
$TSuserParameters |Add-Member -membertype ScriptMethod -name Remove -value {
Param ($Attname)
If ($this.TSAttributes.containsKey($Attname))
{
$test.remove("12")
return $true
}
else
{
return $false
}
}
我知道您的直觉告诉您“但是 PowerShell 有效!”。尽管我无法对此进行测试,但根据我使用 MS Orchestrator 和 PowerShell 1.0 的经验,我可以解决这个问题。我怀疑 IF 本地启动的 PowerShell 实例可以通过您在上面发布的脚本获取此数据,而 C# 中的工作流无法以某种方式获取此数据,那么您应该能够使用 Invoke-Command 来突破受限的 (读取:通过 C# 实例化并以某种方式损坏)版本通过将整个脚本包装在一个变量中并将其传递给“完整”功能版本
invoke-command -computername localhost -scriptblock $yourScriptVar
此逻辑仅在 C# 解释器下执行 invoke-command,然后传递到本地计算机上的新 session ,无论默认值是否就位。在从 Orchestrator 强制进入 PowerShell 1.0 时,我曾经一直这样做。如果它在本地不起作用,您可以更进一步,通过 -computername 直接在域 Controller 上运行命令。
如果事实证明这不起作用,那么我会高度怀疑您在本地使用的脚本依赖于本地系统上缓存的内容。这部分纯粹是一种预感。
关于c# - 在 Visual Studio 中运行 PowerShell 脚本时无法获取 Active Directory 终端服务属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45106182/
SQLite、Content provider 和 Shared Preference 之间的所有已知区别。 但我想知道什么时候需要根据情况使用 SQLite 或 Content Provider 或
警告:我正在使用一个我无法完全控制的后端,所以我正在努力解决 Backbone 中的一些注意事项,这些注意事项可能在其他地方更好地解决......不幸的是,我别无选择,只能在这里处理它们! 所以,我的
我一整天都在挣扎。我的预输入搜索表达式与远程 json 数据完美配合。但是当我尝试使用相同的 json 数据作为预取数据时,建议为空。点击第一个标志后,我收到预定义消息“无法找到任何内容...”,结果
我正在制作一个模拟 NHL 选秀彩票的程序,其中屏幕右侧应该有一个 JTextField,并且在左侧绘制弹跳的选秀球。我创建了一个名为 Ball 的类,它实现了 Runnable,并在我的主 Draf
这个问题已经有答案了: How can I calculate a time span in Java and format the output? (18 个回答) 已关闭 9 年前。 这是我的代码
我有一个 ASP.NET Web API 应用程序在我的本地 IIS 实例上运行。 Web 应用程序配置有 CORS。我调用的 Web API 方法类似于: [POST("/API/{foo}/{ba
我将用户输入的时间和日期作为: DatePicker dp = (DatePicker) findViewById(R.id.datePicker); TimePicker tp = (TimePic
放宽“邻居”的标准是否足够,或者是否有其他标准行动可以采取? 最佳答案 如果所有相邻解决方案都是 Tabu,则听起来您的 Tabu 列表的大小太长或您的释放策略太严格。一个好的 Tabu 列表长度是
我正在阅读来自 cppreference 的代码示例: #include #include #include #include template void print_queue(T& q)
我快疯了,我试图理解工具提示的行为,但没有成功。 1. 第一个问题是当我尝试通过插件(按钮 1)在点击事件中使用它时 -> 如果您转到 Fiddle,您会在“内容”内看到该函数' 每次点击都会调用该属
我在功能组件中有以下代码: const [ folder, setFolder ] = useState([]); const folderData = useContext(FolderContex
我在使用预签名网址和 AFNetworking 3.0 从 S3 获取图像时遇到问题。我可以使用 NSMutableURLRequest 和 NSURLSession 获取图像,但是当我使用 AFHT
我正在使用 Oracle ojdbc 12 和 Java 8 处理 Oracle UCP 管理器的问题。当 UCP 池启动失败时,我希望关闭它创建的连接。 当池初始化期间遇到 ORA-02391:超过
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve
引用这个plunker: https://plnkr.co/edit/GWsbdDWVvBYNMqyxzlLY?p=preview 我在 styles.css 文件和 src/app.ts 文件中指定
为什么我的条形这么细?我尝试将宽度设置为 1,它们变得非常厚。我不知道还能尝试什么。默认厚度为 0.8,这是应该的样子吗? import matplotlib.pyplot as plt import
当我编写时,查询按预期执行: SELECT id, day2.count - day1.count AS diff FROM day1 NATURAL JOIN day2; 但我真正想要的是右连接。当
我有以下时间数据: 0 08/01/16 13:07:46,335437 1 18/02/16 08:40:40,565575 2 14/01/16 22:2
一些背景知识 -我的 NodeJS 服务器在端口 3001 上运行,我的 React 应用程序在端口 3000 上运行。我在 React 应用程序 package.json 中设置了一个代理来代理对端
我面临着一个愚蠢的问题。我试图在我的 Angular 应用程序中延迟加载我的图像,我已经尝试过这个2: 但是他们都设置了 src attr 而不是 data-src,我在这里遗漏了什么吗?保留 d
我是一名优秀的程序员,十分优秀!