Войти

Показать полную графическую версию : Открытие окна свойства УЗ


Aynyuh
28-02-2012, 13:09
Добрый день!
Для поиска учётной записи используется оснастка "Active Directory -- Пользователи и группы", через кнопку найти (меню Действие-Найти...).
При двойном клике по найденной записи или вызове пункта контекстного меню "Свойства" появляется диалог свойств учётной записи.

Можно ли автоматизировать действие поиска, таким образом, чтобы скрипт (не важно на чём: PowerShell, VBS и т.д. В принципе могу и на каком-нибудь языке написать программу) вызывал окно свойств к отдельной учётке?
После неудачных поисков, решил что можно сделать через MMC Automation Object Model, но из-за скудности примеров пока испытываю трудности, да и не совсем уверен что это лучший путь.
Система: Windows 7 x64 Ent
Буду рад любым мыслям и наводкам по данному вопросу.

Iska
28-02-2012, 16:13
Aynyuh, ну, а если будет найдено несколько подходящих объектов?

И — смысл?! Лишний щёлчок мышки убрать?

Aynyuh
28-02-2012, 16:21
Это уже зависит от параметров поиска. В принципе, в скрипт можно передавать уникальный параметр -- имя пользователя. Что делать с результатами я уже, думаю, смогу разобраться, мне бы понять как вызвать диалог свойств для какого-либо объекта это оснастки...

Но это же не один щелчёк. К тому же ещё приходится вводить вручную (или копировать) данные пользователя. Каждый раз приходится запускать оснастку, запускать поиск, вводить логин пользователя или фамилию/имя. Я согласен делать эти операции при нестандартном поиске, но в 99% поиск однообразен и включает в себя все эти шаги. Напрягает, когда приходится это делать помногу раз на дню.

Kazun
28-02-2012, 16:49
Как вызвать свойства для определенной учетной записи на PowerShell:

$path = "contoso.com/Human Resources/Human Resources Users" -split "/"
$user = "Kazun"

$guid = "{E355E538-1C2E-11D0-8C37-00C04FD8FE93}"
$mmc = New-Object -ComObject MMC20.Application
$mmc.Document.SnapIns.Add($guid)

$view = $mmc.Document.Views.Item(1)
$view.ActiveScopeNode = $view.ListItems.Item(1)

foreach ($i in $path)
{
$view.ActiveScopeNode = $view.ListItems | Where {$_.Name -eq $i}
}

$usernode = $mmc.Document.ActiveView.ListItems | Where {$_.Name -eq $user}
$mmc.Document.ActiveView.Select($usernode)
$mmc.Document.ActiveView.ExecuteSelectionMenuItem("_PROPERTIES")

Aynyuh
28-02-2012, 17:45
Kazun, это прекрасно!
Хотя бы становится понятно каким образом можно с этим работать.
Подскажите, должны ли быть установлены какие-то компоненты чтобы этот скрипт работал?
При запуске пишет:
New-Object : Сбой при получении производства объектов класса COM для компонента с CLSID {49B2791A-B1AE-4C90-9B8E-E860BA07F8 89} в результате следующей ошибки: 800702e4. C:\Users\denis\AppData\Local\Temp\0768b3c6-a38e-4dca-85ac-8e47b47580c5.ps1:5 знак:18 + $mmc = New-Object <<<< -ComObject MMC20.Application + CategoryInfo : ResourceUnavailable: (:) [New-Object], COMException + FullyQualifiedErrorId : NoCOMClassIdentified,Microsoft.PowerShell.Commands.NewObjectCommand

Kazun
28-02-2012, 17:57
Требуется повышение привилегий(для запуска PowerShell - Run As Administrator).

Я думаю для вашей задачи лучше использовать командлеты -http://www.quest.com/powershell/activeroles-server.aspx или использовать командлеты в RSAT для управления AD. Это гораздо облегчит работу.

Aynyuh
02-03-2012, 19:02
Kazun, к сожалению командлеты тут не нужны, т.к. ничего конкретного с учётной записью проделывать не нужно.
Благодаря вашему примеру мне стало понятно как работать с консолью MMC, и вот что у меня получилось:

Option Explicit

'################################################################################################### #######
' Скрипт открывает окно свойств для пользователя. В домене test.local.
' Поиск производится по имени пользователя (логину)
' При запуске требует передачи параметра user: prop.vbs /user:<UserName> через коммандную строку,
' либо в самом скрипте при его запуске с пустым параметром /user
'################################################################################################### #######

Dim colNamedArguments, strParamUser
Set colNamedArguments = WScript.Arguments.Named
If colNamedArguments.Count > 0 Then
strParamUser = colNamedArguments.Item("user")
Else
Dim mb
mb = MsgBox("Usage: prop.vbs /user:UserName" & Chr(&HD&) & "Do you want enter the user login name manually?", vbInformation + vbYesNo, "Don't specify parameter ""user""")
If mb = vbYes Then
Dim strInput
strInput = InputBox("Enter login (domain: DC=test.local):")
If Trim(strInput) <> "" Then
strParamUser = strInput
End If
Else
WScript.Quit
End If
End If

' находим объект УЗ по имени пользователя -- samAccountName
Function GetDistinguishedFromLDAP(samAccountName)
Const C_SRCH_FIELD = "(samAccountName="
Const C_OUT_FIELDS = "samAccountName,displayName,distinguishedName;"
Const C_SRCH_METHOD = "subtree"

Dim objConnection
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open "Provider=ADsDSOObject;"

Dim objCommand
Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection

objCommand.CommandText = _
"<LDAP://DC=test,DC=local>;(&(objectCategory=person)" & _
C_SRCH_FIELD & samAccountName & "));" & _
C_OUT_FIELDS & _
C_SRCH_METHOD

Dim objRecordSet
Set objRecordSet = objCommand.Execute

If objRecordset.RecordCount > 0 Then
objRecordSet.MoveFirst
GetDistinguishedFromLDAP = objRecordSet.Fields(2).Value
End If

objConnection.Close
End Function

' преобразуем ldap-путь в обычный путь
Function DistinguishedToPath(s)
Dim distpath, path, pathDC, e

distpath = Split(s, ",")
For Each e In distpath
Select Case Left(e, 2)
Case "OU", "CN" path = Right(e, Len(e) - InStr(e, "=")) & "/" & Path
Case "DC" pathDC = pathDC & "." & Right(e, Len(e) - InStr(e, "="))
End Select
Next

If Right(path, 1) = "/" Then path = Left(path, Len(path) - 1)
If Left(pathDC, 1) = "." Then pathDC = Right(pathDC, Len(pathDC) - 1)

DistinguishedToPath = pathDC & "/" & path
End Function

' ###################### Открытие MMC и добавление объекта
Dim objMMC
Set objMMC = Wscript.CreateObject("MMC20.Application")
Dim objDoc
Set objDoc = objMMC.Document
objDoc.SnapIns.Add("{E355E538-1C2E-11D0-8C37-00C04FD8FE93}")

Dim oV
Set oV = objDoc.Views.Item(1)
oV.ActiveScopeNode = oV.ListItems.Item(1)

Dim aPath
aPath = Split(DistinguishedToPath(GetDistinguishedFromLDAP(strParamUser)), "/")

Dim p
' открывает нужные ветки в соответствии с путём объекта
For Each p In aPath
Dim i
For i = 1 To oV.ListItems.Count
If oV.ListItems.Item(i).Name = p Then
'MsgBox oV.ListItems.Item(i).Name

' перемещаемся по дереву, в соответствии с местоположением найденного объекта (УЗ)
If oV.ListItems.Item(i).IsScopeNode Then
oV.ActiveScopeNode = oV.ListItems.Item(i)
End If
Exit For
End If
Next
Next

Dim oActiveView, oUserNode
Set oActiveView = objDoc.ActiveView

For Each p In oActiveView.ListItems
If p.Name = aPath(UBound(aPath)) Then
Set oUserNode = p
Exit For
End If
Next

objDoc.ActiveView.Select(oUserNode)
objDoc.ActiveView.ExecuteSelectionMenuItem("_PROPERTIES")

Dim WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Popup "Click Ok", 10, "Job done!", vbInformation
'MsgBox "Click Ok", vbInformation, "Job done!"

Скрипт ищет заданный логин и выводит окно свойств для этого пользователя. Но есть новая проблема, и поэтому я снова здесь :)
Проблема в том, что окно свойств появляется ЗА окном программы, которая его вызывает. А также, если после метода ExecuteSelectionMenuItem не показывать сообщение или не делать Wait секунды на 3-5, то окно свойств не появляется вообще.

Каким образом можно заставить появляться его на первом плане?

Aynyuh
05-03-2012, 14:53
Пока что вышел из ситуации таким образом. Скрипт в зависимости от локализации системы (русская или английская) пытается активировать окно свойств, передавая заголовок окна, до тех пор пока данное окно не активируется, либо цикл не отработает 11 раз:
For i = 0 To 10
' с окном свойств какая-то шняга, оно то появляется на переднем плане, то нет
' пока не разобрался, вот такой костыль будет
If GetLocale = 1049 Then
' Russian — ru — 0x0419 — 1049
If WshShell.AppActivate("Свойства: " & aPath(UBound(aPath))) Then Exit For
Else
If WshShell.AppActivate(aPath(UBound(aPath))) Then Exit For
End If
WScript.Sleep 1000
Next

DmitriiV
06-03-2012, 07:55
Aynyuh, пара советов по коду сценария из сообщения #7.

1. В функции DistinguishedToPath() нет необходимости, т.к. значение, которое Вы называете "обычный путь",- это значение атрибута Canonical-Name. Его легко получить непосредственно в ADO-запросе.
Пример:

Const C_OUT_FIELDS = "samAccountName,displayName,distinguishedName,canonicalName;"
objCommand.CommandText = _
"<LDAP://DC=test,DC=local>;(&(objectCategory=person)" & _
C_SRCH_FIELD & samAccountName & "));" & _
C_OUT_FIELDS & _
C_SRCH_METHOD
Dim objRecordSet
Set objRecordSet = objCommand.Execute
If objRecordset.RecordCount > 0 Then
objRecordSet.MoveFirst
If IsArray(objRecordSet.Fields(3)) Then
arrTemp = objRecordSet.Fields(3)
MsgBox "Каноническое имя: " & arrTemp(0)
Else
MsgBox "Каноническое имя: " & objRecordSet.Fields(3)
End If
End If

2. Имя текущего домена в формате DistinguishedName можно получить с помощью объекта RootDSE.
Пример:

Set objRootDSE = GetObject("LDAP://RootDSE")
strDomain = objRootDSE.Get("defaultNamingContext")
Set objRootDSE = Nothing
'...
objCommand.CommandText = _
"<LDAP://" & strDomain & ">;(&(objectCategory=person)" & _
C_SRCH_FIELD & samAccountName & "));" & _
C_OUT_FIELDS & _
C_SRCH_METHOD




© OSzone.net 2001-2012