<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title type="html"><![CDATA[Серый форум &mdash; WSH: блокировка учетных записей, неактивных более 30 дней]]></title>
	<link rel="self" href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=859&amp;type=atom" />
	<updated>2007-12-06T10:29:45Z</updated>
	<generator>PunBB</generator>
	<id>https://forum.script-coding.com/viewtopic.php?id=859</id>
		<entry>
			<title type="html"><![CDATA[Re: WSH: блокировка учетных записей, неактивных более 30 дней]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=6726#p6726" />
			<content type="html"><![CDATA[<p>Случайно наткнулся на еще один вариант скрипта выполняющий эту функцию (проверял, работает как надо, системные учетные записи не блокируются)&nbsp; взят отсюда <a href="http://www.codeproject.com/KB/vbscript/Disable_Stale_AD_Users.aspx">http://www.codeproject.com/KB/vbscript/ … Users.aspx</a></p><div class="codebox"><pre><code> &#039;set up some varaibles
bDisable = 0                            &#039;do you want to disable and move the accounts?
strFileName = &quot;c:\users.txt&quot;                    &#039;the file where the tab delimited results are saved

strUserDN = &quot;domaincontroller/OU=All Users, dc=yourdomain, dc=com&quot;      &#039;initial OU where the users are located
strNewParentDN = &quot;OU=Inactive Users, dc=yourdomain, dc=com&quot;      &#039;location where disabled users are moved to
strDomain = &quot;yourdomain.com&quot;                &#039;FQDN
iDayThreshold = 180                        &#039;number of days without logging in

strOut = &quot;&quot;                            &#039;tmp string
strOut2 = &quot;&quot;                        &#039;another tmp string
Main()

Sub Main()
&#039;get the initial data then ask some questions
    EnumOUs(&quot;LDAP://&quot; &amp; strUserDN)

    &#039;yes=6, no=7, cancel=2
    answer = MsgBox(strOut &amp; vbCrLf &amp; &quot;Disable and move these users?&quot;, vbYesNoCancel)
    If answer=2 Then
        Exit Sub
    ElseIf answer=6 Then
        bDisable = 1
        EnumOUs(&quot;LDAP://&quot; &amp; strUserDN)
    End If

    answer = MsgBox(&quot;Save the data to &quot; &amp; strFileName &amp; &quot;?&quot;, vbYesNoCancel)

    If answer = 6 Then
        strOut = &quot;username&quot; &amp; vbTab &amp; &quot;Name&quot; &amp; vbTab &amp; &quot;Last Logon&quot; &amp; vbTab &amp; &quot;Days&quot; &amp; vbCrLf &amp; strOut
        strOut2 = &quot;These users have never logged in:&quot; &amp; vbCRLF _
                &amp; &quot;username&quot; &amp; vbTab &amp; &quot;Name&quot; &amp; vbTab &amp; &quot;Creation Date&quot; &amp; vbCRLF &amp; strOut2
        strOut = strOut &amp; vbCRLF &amp; vbCRLF &amp; strOut2
        SaveToFile strOut
    End If
End Sub

Function EnumOUs(sADsPath)
&#039;recursively finds all of the OU&#039;s and users in the given AD path

    Set oContainer = GetObject(sADsPath)
    oContainer.Filter = Array(&quot;OrganizationalUnit&quot;)
    For Each oOU in oContainer
        EnumUsers(oOU.ADsPath)
        EnumOUs(oOU.ADsPath)
    Next
End Function

Function EnumUsers(sADsPath)
&#039;finds all of the users&#039; last login time

    Set oContainer = GetObject(sADsPath)
    oContainer.Filter = Array(&quot;User&quot;)
    For Each oADobject in oContainer
        Set objLogon = oADobject.Get(&quot;lastLogon&quot;)
        intLogonTime = objLogon.HighPart * (2^32) + objLogon.LowPart 
        intLogonTime = intLogonTime / (60 * 10000000)
        intLogonTime = intLogonTime / 1440
        intLogonTime = intLogonTime + #1/1/1601#
        inactiveDays = Fix(Now() - intLogonTime)

        &#039;adds a list of people who have never logged on.
        If intLogonTime = &quot;1/1/1601&quot; Then strOut2 = strOut2 &amp; oADobject.sAMAccountName &amp; vbTab &amp; oADobject.DisplayName &amp; vbTab &amp; oADobject.whencreated &amp; vbCRLF
        
        &#039;if they are beyond the threshhold, it will add them to the output string
        If inactiveDays &gt; iDayThreshold And intLogonTime &lt;&gt; &quot;1/1/1601&quot; Then
            strOut = strOut &amp; oADobject.sAMAccountName _
                &amp; vbTab &amp; oADobject.displayName _
                &amp; vbTab &amp; intNewTime _
                &amp; vbTab &amp; intLogonTime _
                &amp; vbTab &amp; intMaxTime _
                &amp; vbTab &amp; inactiveDays &amp; vbCRLF

            &#039;if disabling was requested, it will move them to a new folder and disable the account
            If bDisable = 1 Then
                If strNewParentDN &lt;&gt; &quot;&quot; Then MoveUser oADobject.Name, oADobject.ADsPath
                Set objUser = GetObject(&quot;WinNT://&quot; &amp; strDomain &amp; &quot;/&quot; &amp; oADobject.sAMAccountName)
                objUser.AccountDisabled = True
                objUser.SetInfo
            End If
        End If
    Next
End Function

Sub MoveUser(sName, sPath)
&#039;moves the user from the given OU to a new OU
    Set objUser = GetObject(&quot;LDAP://&quot; &amp; strNewParentDN)
    objUser.MoveHere sPath, sName
End Sub

Sub SaveToFile(strData)
&#039;writes the given data to a text file
    Dim objFSO
    Set objFSO = CreateObject(&quot;Scripting.FileSystemObject&quot;) 
    If objFSO.FileExists(strFileName) Then
        Set objTextStream = objFSO.OpenTextFile(strFileName, 2)
        
        objTextStream.Write strData
        objTextStream.Close
        Set objTextStream = Nothing
    Else
        Set objTextStream = objFSO.CreateTextFile(strFileName, True)        
        objTextStream.Write strData
        objTextStream.Close
        Set objTextStream = Nothing
    End If
End Sub</code></pre></div>]]></content>
			<author>
				<name><![CDATA[dmitry_a]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=5879</uri>
			</author>
			<updated>2007-12-06T10:29:45Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=6726#p6726</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: блокировка учетных записей, неактивных более 30 дней]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=6702#p6702" />
			<content type="html"><![CDATA[<p>Спасибо! Эту тему открепляю, а дополнять <a href="http://forum.script-coding.com/viewtopic.php?id=920">тему в Коллекции</a> в любое время новыми мыслями, естественно, не возбраняется.</p>]]></content>
			<author>
				<name><![CDATA[The gray Cardinal]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=2</uri>
			</author>
			<updated>2007-12-06T07:29:27Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=6702#p6702</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: блокировка учетных записей, неактивных более 30 дней]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=6599#p6599" />
			<content type="html"><![CDATA[<p>Мне пока нечего сказать, поскольку болен, ergo нет возможности опробовать, что было выложено <strong>delpher</strong> под конец, как собирался. Вариант js от <strong>delpher</strong>, на мой взгляд, достаточен (после перехода на ADO вроде бы должны отслеживаться все учётные записи) для Коллекции. Остальное — тонкости в разных подходах к кодированию. Оклемаюсь, опробую, переложу на VBS.</p>]]></content>
			<author>
				<name><![CDATA[alexii]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=1844</uri>
			</author>
			<updated>2007-12-04T13:27:21Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=6599#p6599</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: блокировка учетных записей, неактивных более 30 дней]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=6595#p6595" />
			<content type="html"><![CDATA[<p>Ну если у <strong>alexii</strong> сказать больше нечего (замечания исходили только от него:) ), то выложу последний свой JS вариант, только причешу его и сочиню аннотацию к нему, поскольку, как выяснилось, он не вполне универсален.<br />[off] 2 <strong>The gray Cardinal</strong>: нас не почешешь, так мы и не похрюкаем <img src="//forum.script-coding.com/img/smilies/smile.png" width="15" height="15" /> [/off]</p>]]></content>
			<author>
				<name><![CDATA[delpher]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=6992</uri>
			</author>
			<updated>2007-12-04T12:36:11Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=6595#p6595</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: блокировка учетных записей, неактивных более 30 дней]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=6573#p6573" />
			<content type="html"><![CDATA[<p>Уважаемые господа Разработчики!<br />Неужели в этой теме вообще нет ни одной строки кода, которую можно было бы поместить в Коллекцию? Могу предположить только две причины этого:<br />а) Вся тема - сплошной флуд.<br />б) Проблема блокировки учетных записей, неактивных более 30 дней, с помощью скрипта - это проблема, принципиально нерешаемая на современном уровне развития IT-технологий.<br /><img src="//forum.script-coding.com/img/smilies/wink.png" width="15" height="15" /></p>]]></content>
			<author>
				<name><![CDATA[The gray Cardinal]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=2</uri>
			</author>
			<updated>2007-12-04T09:23:39Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=6573#p6573</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: блокировка учетных записей, неактивных более 30 дней]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=6483#p6483" />
			<content type="html"><![CDATA[<div class="quotebox"><cite>alexii пишет:</cite><blockquote><p>P.S. Мне, собственно, не нравилось (из первых вариантов скриптов) не очень корректное отслеживание через обработку ошибок try/on error. Судя даже по предпоследнему варианту, работает и с lastLogon = &lt;Not Set&gt;, и с == 0.</p></blockquote></div><p>Ну самый последний вариант разделяет 0 и &lt;Not Set&gt; вроде корректно и без try catch. Другое дело, что определить системность учетной записи это в общем случае не помогает.</p>]]></content>
			<author>
				<name><![CDATA[delpher]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=6992</uri>
			</author>
			<updated>2007-11-29T03:40:55Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=6483#p6483</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: блокировка учетных записей, неактивных более 30 дней]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=6480#p6480" />
			<content type="html"><![CDATA[<p>Домен Windows 2000 основной режим; 2DC; оба, соответственно, Windows 2000 Server SP4 UP1; один узел, один лес. Когда я поднимал его, помнится, некоторое время держал в смешанном (был переход с домена NT 4.0). А может и нет, уже не помню. Домен делал свеженький, со старым, на время перехода, устанавливались доверительные отношения. Возможно, что-то поменялось в политике партии.<br /></p><div class="quotebox"><cite>delpher пишет:</cite><blockquote><p>Но у меня аккаунты с lastLogon = &lt;Not Set&gt; отсутствуют вообще.</p></blockquote></div><p>Похоже, что мои учётные записи с lastLogon = &lt;Not Set&gt; создавались ещё до появления SP1.</p><p>В общем, как всегда, завтра попробую.</p><p>OFF:<br />===============================================================<br />P.S. Мне, собственно, не нравилось (из первых вариантов скриптов) не очень корректное отслеживание через обработку ошибок try/on error. Судя даже по предпоследнему варианту, работает и с lastLogon = &lt;Not Set&gt;, и с == 0.</p><p>P.P.S. Честно говоря, тяжко идёт java, тяжко; собственно, не само чтение/понимание, а отладка/изменение, дабы что-то проверить. Порою мне быстрее на VBS перевести и там проверять, нежели листать документацию в попытке найти то, чего ещё и сам не знаешь.</p><p>P.P.P.S. Посмотрев на Ваш вариант с перебором контроллеров, подумал — зачем? Хотел уже написать, что сие лишнее. Лишь заметно позже вспомнил, что lastLogon по умолчанию не реплицируется.<br />===============================================================</p>]]></content>
			<author>
				<name><![CDATA[alexii]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=1844</uri>
			</author>
			<updated>2007-11-28T20:58:13Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=6480#p6480</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: блокировка учетных записей, неактивных более 30 дней]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=6451#p6451" />
			<content type="html"><![CDATA[<div class="quotebox"><cite>alexii пишет:</cite><blockquote><p>Возможно, загвоздка вот в этом куске:<br /></p><div class="codebox"><pre><code>if ( RSUsers.Fields(&quot;lastLogon&quot;).Value ) {</code></pre></div><p>Тех, у которых lastLogon &lt;&gt; 0 идёт отбирает.<br /></p><div class="quotebox"><blockquote><p>XXXXSERVER: Администратор&nbsp; &nbsp; &nbsp;Age: 7&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Last logon: вторник, 20 ноября 2007 года 13:20:48</p></blockquote></div><p>Тех, у которых lastLogon = 0 отбирает.<br /></p><div class="quotebox"><blockquote><p>XXXXSERVER: Гость&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Age: 148619&nbsp; &nbsp; Last logon: понедельник, 1 января 1601 года 0:00:00</p></blockquote></div><p>Тех, у которых lastLogon = &lt;not set&gt; не отбирает.</p><p>P.S. В запрос они попадают. Я вставлял вывод strDC+&quot;: &quot;+RSUsers.Fields(&quot;sAMAccountName&quot;).Value перед if ( RSUsers.Fields(&quot;lastLogon&quot;).Value ) {</p></blockquote></div><p>Ко всему выдает, есть ли у атрибута значение, или оно &lt;Not Set&gt;, проверьте.<br /></p><div class="codebox"><pre><code>var Stdout = WScript.Stdout;
var Stdin  = WScript.Stdin;
var objDict = new ActiveXObject(&quot;Scripting.Dictionary&quot;);
var objConnection = new ActiveXObject(&quot;ADODB.Connection&quot;);
var objCommand = new ActiveXObject(&quot;ADODB.Command&quot;);
var oRoot = GetObject(&quot;LDAP://rootDSE&quot;);
var sDomain = oRoot.Get(&quot;defaultNamingContext&quot;);

var strLDAP  = &quot;LDAP://OU=Domain Controllers,&quot; + sDomain;
var ADS_SCOPE_SUBTREE = 2;
var space = &#039;                                                                                                                                       &#039;;
var strDC, temp, arr

// Формируем запрос на поиск всех серверов домена ========================
objConnection.Provider = &quot;ADsDSOObject&quot;;
objConnection.Open(&quot;Active Directory Provider&quot;);

objCommand.ActiveConnection = objConnection;
objCommand.Properties(&quot;Page Size&quot;) = 500;
objCommand.Properties(&quot;Searchscope&quot;) = ADS_SCOPE_SUBTREE;
objCommand.Properties(&quot;Sort On&quot;) = &quot;sAMAccountName&quot;;
objCommand.CommandText = &quot;SELECT sAMAccountName,adsPath FROM &#039;&quot; + strLDAP + &quot;&#039; WHERE objectCategory=&#039;computer&#039;&quot;;
// =======================================================================

// Выполняем запрос
var objRSServers = objCommand.Execute;

// Перебираем все найденные серверы и добавляем юзеров в глобальный
// для сценария словарь objDict (в функции GetUsers)
while ( !objRSServers.EOF ) {
   strDC = objRSServers.Fields(&quot;sAMAccountName&quot;).Value;
   GetUsers(strDC.substr(0, strDC.length-1 ));
   objRSServers.moveNext()
}

// сортируем логины по алфавиту
arr = (new VBArray(objDict.Keys())).toArray();
for (var i = arr.length - 1; i&gt;=0; i--) {
   for (var j= 0; j&lt;i; j++) {
      if ( arr[j]&gt;arr[j+1] ) {
         temp=arr[j+1];
         arr[j+1]=arr[j];
         arr[j]=temp;
      }
   }
}

// Перебираем всех найденных юзверей
var name, lastLogon, age, comment, Item
for (var usr in arr)
{
   name = arr[usr];
   Item = objDict(name);
   lastLogon = Item[0];
   comment = Item[1];

   age = (new Date() - lastLogon)/(86400*1000);
   Stdout.WriteLine( (name+space).substr(0,30) +
                     &quot;Age: &quot;+(age.toFixed(0)+space).substr(0,10)+
                     &quot;Last logon: &quot; +(lastLogon.toLocaleString()+space).substr(0,32)+
                     &quot;Comment: &quot; +comment );
}

Stdout.WriteLine (&quot;\nPress Enter&quot;);
Stdin.ReadLine ();


//
// FUNCTIONS
//


// Выбирает всех пользователей на заданном сервере домена в ассоциативный массив
function GetUsers( strDC ) {
var dLastLogin;
var Conn = new ActiveXObject(&quot;ADODB.Connection&quot;);
var RSUsers = new ActiveXObject (&quot;ADODB.Recordset&quot;);
var query = &quot;SELECT sAMAccountName, lastLogon FROM &#039;LDAP://&quot; + strDC + &quot;&#039; WHERE objectCategory=&#039;user&#039;&quot;

   Stdout.WriteLine(&quot;Working on &quot; + strDC);

   Conn.Provider = &quot;ADsDSOObject&quot;;
   Conn.Open(&quot;Active Directory Provider&quot;);
   RSUsers.ActiveConnection = Conn;

   for ( RSUsers.Open (query); !RSUsers.EOF; RSUsers.moveNext() ) {

      // Для уникальности имени добавляем к нему имя DC
      sAMAccountName = strDC+&quot;: &quot;+RSUsers.Fields(&quot;sAMAccountName&quot;).Value;

      if ( dLastLogin = RSUsers.Fields(&quot;lastLogon&quot;).Value ) {
          // сюда попадаем, когда у атрибута есть значение (любое)
          dLastLogin     = getLast(dLastLogin);
         AddToDict(sAMAccountName, dLastLogin, &#039;   Success&#039;)
      } else {
         // сюда попадаем, когда атрибута нет значения (&lt;Not Set&gt;)
         AddToDict(sAMAccountName, new Date(1900,0,1,0,0,0), &#039;&lt;Not Set&gt;&#039;)
      }
   }
}


// добавляет в ассоциативный массив значение с примечанием
function AddToDict(name, value, comment) {
   if (!objDict.Exists (name) ) {
      objDict.Add ( name, [value, comment] );
   } else {
      if (objDict(name)[0] &lt; value ) {
         objDict(name) = [value, comment];
      }
   }
}

// конвертирует lastLogon, возвращенный запросом к LDAP в удобоваримую дату
// возвращает массив - дату как Date() и дату как число
function getLast( last ) {
var res,
    intLastLogonTime = last.HighPart* (4294967296) + last.LowPart;

   res = intLastLogonTime / 10000;
   res = res - Math.abs((new Date(1601,0,1)).getTime());

   return (new Date(res));
}</code></pre></div><p>Но у меня аккаунты с lastLogon = &lt;Not Set&gt; отсутствуют вообще. Т.е., что у системных, что у ручных - если входа не было, то lastlogon = 0 (что равноценно дате 01.01.1601). Так что универсального способа отделить ручных мух от системных котлет все еще нету (если это кому-то критично).</p><p>Кстати, посмотрите, какой у Вас режим работы домена: &#039;Windows 2000 (основной режим)&#039;, &#039;Windows 2000 (смешанный режим)&#039; или &#039;Windows Server 2003&#039;? И вообще, что за ось на контроллере домена? У меня 2003-я и домен поднят в режиме &#039;Windows 2000 (смешанный режим)&#039; (поднимал не я).</p>]]></content>
			<author>
				<name><![CDATA[delpher]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=6992</uri>
			</author>
			<updated>2007-11-28T09:51:01Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=6451#p6451</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: блокировка учетных записей, неактивных более 30 дней]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=6434#p6434" />
			<content type="html"><![CDATA[<p>Возможно, загвоздка вот в этом куске:<br /></p><div class="codebox"><pre><code>if ( RSUsers.Fields(&quot;lastLogon&quot;).Value ) {</code></pre></div><p>Тех, у которых lastLogon &lt;&gt; 0 идёт отбирает.<br /></p><div class="quotebox"><blockquote><p>XXXXSERVER: Администратор&nbsp; &nbsp; &nbsp;Age: 7&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Last logon: вторник, 20 ноября 2007 года 13:20:48</p></blockquote></div><p>Тех, у которых lastLogon = 0 отбирает.<br /></p><div class="quotebox"><blockquote><p>XXXXSERVER: Гость&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Age: 148619&nbsp; &nbsp; Last logon: понедельник, 1 января 1601 года 0:00:00</p></blockquote></div><p>Тех, у которых lastLogon = &lt;not set&gt; не отбирает.</p><p>P.S. В запрос они попадают. Я вставлял вывод strDC+&quot;: &quot;+RSUsers.Fields(&quot;sAMAccountName&quot;).Value перед if ( RSUsers.Fields(&quot;lastLogon&quot;).Value ) {</p>]]></content>
			<author>
				<name><![CDATA[alexii]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=1844</uri>
			</author>
			<updated>2007-11-27T14:33:19Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=6434#p6434</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: блокировка учетных записей, неактивных более 30 дней]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=6408#p6408" />
			<content type="html"><![CDATA[<div class="quotebox"><cite>delpher пишет:</cite><blockquote><p>Создал тестового пользователя. Запустил оба скрипта (из #11 и #21) с numDays=0.<br />На обоих скриптах что ручной, что системный пользователь - без разницы - если входа не было, то выдается ошибка доступа к lastLogin:<br /></p><div class="quotebox"><cite>js пишет:</cite><blockquote><p>test&nbsp; &nbsp; !!! - Mon Nov 26 11:01:25 2007 - -2147463155 - Свойства службы каталогов не могут быть найдены в кэше.</p></blockquote></div><div class="quotebox"><cite>vbs пишет:</cite><blockquote><p>test, Тест, Not found attribute, Not calculated</p></blockquote></div><p>Т.е. разницы, кем был создан пользователь - системой или человеком - нету.</p></blockquote></div><p>Попробуйте посмотреть через ADSI Edit, Active Directory Administration Tool или Active Directory Explorer; у меня, например, для IUSR_XXXX — lastLogon: Value not set, для ручного XXXX — lastLogon: 0. Так что, какая-то разница есть <img src="//forum.script-coding.com/img/smilies/smile.png" width="15" height="15" />.<br /></p><div class="quotebox"><cite>delpher пишет:</cite><blockquote><p>Так что гарантированного способа отличить их я не вижу.</p></blockquote></div><p>Я тоже. Вылетает с одинаковой ошибкой на тех, и на тех. Ну, и что с ними делать? Есть какой-либо атрибут, что ли, чтобы отличить встроенные системные учётные записи от ручных? Может, просто смотреть, если группа == Users, то считать эти учётки == системные? Криво как-то...</p><div class="quotebox"><cite>delpher пишет:</cite><blockquote><div class="quotebox"><cite>alexii пишет:</cite><blockquote><p>VBS: Некоторые учётные записи вообще не попали в обработку.</p></blockquote></div><p>Что значит? Не были отобраны совсем?</p></blockquote></div><p>Угу. Раскомментировал bTrace = True и смотрел. Попробую завтра поразбираться.<br /></p><div class="quotebox"><cite>delpher пишет:</cite><blockquote><p>Мой косяк. Исправил:<br />...</p></blockquote></div><p>Тоже завтра погляжу.</p>]]></content>
			<author>
				<name><![CDATA[alexii]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=1844</uri>
			</author>
			<updated>2007-11-26T14:53:05Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=6408#p6408</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: блокировка учетных записей, неактивных более 30 дней]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=6392#p6392" />
			<content type="html"><![CDATA[<div class="quotebox"><cite>alexii пишет:</cite><blockquote><p>Скажем, так: создайте учётную запись и, не входя под ней, прогоните Ваш (а если можно, то попутно и мой — для контроля) скрипт (задав numDays = 0). Попадёт ли она в отбор? У меня и на Вашем варианте и на переведённом — такие учётные записи в отбор не попадают.</p></blockquote></div><p>Создал тестового пользователя. Запустил оба скрипта (из #11 и #21) с numDays=0.<br />На обоих скриптах что ручной, что системный пользователь - без разницы - если входа не было, то выдается ошибка доступа к lastLogin:<br /></p><div class="quotebox"><cite>js пишет:</cite><blockquote><p>test&nbsp; &nbsp; !!! - Mon Nov 26 11:01:25 2007 - -2147463155 - Свойства службы каталогов не могут быть найдены в кэше.</p></blockquote></div><div class="quotebox"><cite>vbs пишет:</cite><blockquote><p>test, Тест, Not found attribute, Not calculated</p></blockquote></div><p>Т.е. разницы, кем был создан пользователь - системой или человеком - нету. Так что гарантированного способа отличить их я не вижу. </p><div class="quotebox"><cite>alexii пишет:</cite><blockquote><p>VBS: Некоторые учётные записи вообще не попали в обработку.</p></blockquote></div><p>Что значит? Не были отобраны совсем?</p><div class="quotebox"><cite>alexii пишет:</cite><blockquote><p>JS:<br />Вылетело на строке<br />Код:<br />if (objDict(sAMAccountName) &lt; dLastLogin ) {<br />C:\Temp\0000\84.js(95, 16) Ошибка выполнения Microsoft JScript: Объект не поддерживает это свойство или метод</p></blockquote></div><p>Мой косяк. Исправил:</p><br /><div class="codebox"><pre><code>var Stdout = WScript.Stdout;
var Stdin  = WScript.Stdin;
var objDict = new ActiveXObject(&quot;Scripting.Dictionary&quot;);
var objConnection = new ActiveXObject(&quot;ADODB.Connection&quot;);
var objCommand = new ActiveXObject(&quot;ADODB.Command&quot;);
var oRoot = GetObject(&quot;LDAP://rootDSE&quot;);
var sDomain = oRoot.Get(&quot;defaultNamingContext&quot;);

var strLDAP  = &quot;LDAP://OU=Domain Controllers,&quot; + sDomain;
var ADS_SCOPE_SUBTREE = 2;
var space = &#039;                                                                                                                                       &#039;;
var strDC, temp, arr

// Формируем запрос на поиск всех серверов домена ========================
objConnection.Provider = &quot;ADsDSOObject&quot;;
objConnection.Open(&quot;Active Directory Provider&quot;);

objCommand.ActiveConnection = objConnection;
objCommand.Properties(&quot;Page Size&quot;) = 500;
objCommand.Properties(&quot;Searchscope&quot;) = ADS_SCOPE_SUBTREE;
objCommand.Properties(&quot;Sort On&quot;) = &quot;sAMAccountName&quot;;
objCommand.CommandText = &quot;SELECT sAMAccountName,adsPath FROM &#039;&quot; + strLDAP + &quot;&#039; WHERE objectCategory=&#039;computer&#039;&quot;;
// =======================================================================

// Выполняем запрос
var objRSServers = objCommand.Execute;

// Перебираем все найденные серверы и добавляем юзеров в глобальный
// для сценария словарь objDict (в функции GetUsers)
while ( !objRSServers.EOF ) {
   strDC = objRSServers.Fields(&quot;sAMAccountName&quot;).Value;
   GetUsers(strDC.substr(0, strDC.length-1 ));
   objRSServers.moveNext()
}

// сортируем логины по алфавиту
arr = (new VBArray(objDict.Keys())).toArray();
for (var i = arr.length - 1; i&gt;=0; i--) {
   for (var j= 0; j&lt;i; j++) {
      if ( arr[j]&gt;arr[j+1] ) {
         temp=arr[j+1];
         arr[j+1]=arr[j];
         arr[j]=temp;
      }
   }
}

// Перебираем всех найденных юзверей
var name, lastLogon, age
for (var usr in arr)
{
   name = arr[usr];
   lastLogon = objDict(name);

   // Если дата последнего входа не указана, то можно пропустить их,
   // раскомментировав следующую строку
   //if (lastLogon[1] != 0)
   {
      age = (new Date() - lastLogon[0])/(86400*1000);
      Stdout.WriteLine( (name+space).substr(0,30) +
                        &quot;Age: &quot;+(age.toFixed(0)+space).substr(0,10)+
                        &quot;Last logon: &quot; +lastLogon[0].toLocaleString() );
   }
}

Stdout.WriteLine (&quot;\nPress Enter&quot;);
Stdin.ReadLine ();


//
// FUNCTIONS
//


// Выбирает всех пользователей на заданном сервере домена
function GetUsers( strDC ) {
var dLastLogin;
var Conn = new ActiveXObject(&quot;ADODB.Connection&quot;);
var RSUsers = new ActiveXObject (&quot;ADODB.Recordset&quot;);
var query = &quot;SELECT sAMAccountName, lastLogon FROM &#039;LDAP://&quot; + strDC + &quot;&#039; WHERE objectCategory=&#039;user&#039;&quot;

   Stdout.WriteLine(&quot;Working on &quot; + strDC);

   Conn.Provider = &quot;ADsDSOObject&quot;;
   Conn.Open(&quot;Active Directory Provider&quot;);
   RSUsers.ActiveConnection = Conn;

   for ( RSUsers.Open (query); !RSUsers.EOF; RSUsers.moveNext() ) {
      if ( RSUsers.Fields(&quot;lastLogon&quot;).Value ) {

         // Для уникальности имени добавляем к нему имя DC
         sAMAccountName = strDC+&quot;: &quot;+RSUsers.Fields(&quot;sAMAccountName&quot;).Value;
         dLastLogin     = RSUsers.Fields(&quot;lastLogon&quot;).Value;

         dLastLogin = getLast(dLastLogin);

         if (!objDict.Exists (sAMAccountName) ) {
            objDict.Add ( sAMAccountName, dLastLogin );
         } else {
            if (objDict(sAMAccountName) &lt; dLastLogin ) {
               objDict(sAMAccountName) = dLastLogin;
            }
         }
      }
   }
}

// конвертирует lastLogon, возвращенный запросом к LDAP в удобоваримую дату
// возвращает массив - дату как Date() и дату как число
function getLast( last ) {
var res,
    intLastLogonTime = last.HighPart* (4294967296) + last.LowPart;

   res = intLastLogonTime / 10000;
   res = res - Math.abs((new Date(1601,0,1)).getTime());

   return [(new Date(res)), intLastLogonTime]; // возвращаем массив
}</code></pre></div>]]></content>
			<author>
				<name><![CDATA[delpher]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=6992</uri>
			</author>
			<updated>2007-11-26T05:05:28Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=6392#p6392</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: блокировка учетных записей, неактивных более 30 дней]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=6342#p6342" />
			<content type="html"><![CDATA[<div class="quotebox"><cite>alexii пишет:</cite><blockquote><p>Подождём до следующей недели его подтверждения на мой вопрос четырьмя постами выше?</p></blockquote></div><p>Да, конечно.</p>]]></content>
			<author>
				<name><![CDATA[The gray Cardinal]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=2</uri>
			</author>
			<updated>2007-11-23T13:47:46Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=6342#p6342</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: блокировка учетных записей, неактивных более 30 дней]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=6340#p6340" />
			<content type="html"><![CDATA[<div class="quotebox"><cite>The gray Cardinal пишет:</cite><blockquote><p>В таком случае просьба сделать резюме этой темы в Коллекции, с отражением всех вменяемых вариантов решения проблемы.</p></blockquote></div><p>Я пока не вижу полноценного решения задачи. Если первый вариант хоть и делает не всё, что нужно, так хотя бы внятно работает; последний же вариант с перебором всех КД и работает горррраздо медленнее и кое-что пропускает по совершенно непонятным пока для меня причинам.</p><p>P.S. В принципе, можно запостить старый вариант <strong>delpher</strong>&#039;а (через провайдер WinNT://), и мою трансляцию его скрипта на VBS; только с обязательным упоминанием, что в обработку не попадают учётные записи, под которыми не было ни одного входа (как встроенные типа IUSR_XXXX, так и обычные). Подождём до следующей недели его подтверждения на мой вопрос четырьмя постами выше?</p>]]></content>
			<author>
				<name><![CDATA[alexii]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=1844</uri>
			</author>
			<updated>2007-11-23T13:01:51Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=6340#p6340</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: блокировка учетных записей, неактивных более 30 дней]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=6339#p6339" />
			<content type="html"><![CDATA[<p>По варианту VBS:<br /></p><div class="quotebox"><blockquote><p>User account:Гость&nbsp; last login at 01.01.1601<br />User account:XXXXXXX&nbsp; last login at 01.01.1601</p></blockquote></div><p>Некоторые учётные записи вообще не попали в обработку.</p><p>JS:<br />Вылетело на строке<br /></p><div class="codebox"><pre><code>if (objDict(sAMAccountName) &lt; dLastLogin ) {</code></pre></div><p>C:\Temp\0000\84.js(95, 16) Ошибка выполнения Microsoft JScript: Объект не поддерживает это свойство или метод</p><p>P.S. Чтобы есть, нужно быть уверенным, что не отравишься <img src="//forum.script-coding.com/img/smilies/big_smile.png" width="15" height="15" />. Игрушки с доменом дорого обходятся.</p>]]></content>
			<author>
				<name><![CDATA[alexii]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=1844</uri>
			</author>
			<updated>2007-11-23T12:45:37Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=6339#p6339</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: WSH: блокировка учетных записей, неактивных более 30 дней]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=6338#p6338" />
			<content type="html"><![CDATA[<div class="quotebox"><cite>delpher пишет:</cite><blockquote><p>По-моему уже тему истрепали до самого не хочу и вариантов столько, что чем хочешь, тем и ешь. <img src="//forum.script-coding.com/img/smilies/smile.png" width="15" height="15" /></p></blockquote></div><p>В таком случае просьба сделать резюме этой темы в Коллекции, с отражением всех вменяемых вариантов решения проблемы.</p>]]></content>
			<author>
				<name><![CDATA[The gray Cardinal]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=2</uri>
			</author>
			<updated>2007-11-23T12:19:40Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=6338#p6338</id>
		</entry>
</feed>
