none
автоочистка home folder юзера после его увольнения? RRS feed

  • Вопрос

  • Ситуация: на контроллере домена (WinServ2003) в AD прописывается путь каждому пользователю на домашнюю папку (допустим диск Z: ) в сети т.е. путь на выделяемое место на файловом сервере вида \\server\home\%username% 

    Вопрос: допустим квота на такую папку 1 Гб. После увольнения юзера и его disable - инфа остается в папке т.е. занимает место на сервере, таких юзеров у меня лично около 1000 и руками удалять папку каждого не хотелось бы. Как быть? Может кто подскажет, как сделать так, чтобы после дисайбла юзера удалялалсь и его папка? Скрипт там или еще чего нибудь полезного?

    Добавлю: т.к. раньше не обращал внимания на эту проблему, то ситуация вышла из-под контролля - домашние папки остались так же тех юзеров, которых в AD уже нет. Наверняка, проблема часто встречается у сисадминов, подскажите как решали...

    Заранее благодарен за ответ.


    27 октября 2008 г. 14:38

Ответы

  •  

    Похожая ситуация.

    Я решил ее следующим образом:

    1) При увольнении админ отключает учетку пользователя.

    2) Раз в месяц админ проверяет отключенные учетки и удаляет их (бывали случаи, что люди увольнялись, потом устраивались обратно) специальным скриптом.

    3) По определеннному рассписанию на файловом сервере запускается скрипт, который каталоги несуществующих пользователей перемещает в долговременное хранилище (бывали случаи, что кое-что требовалось выдернуть задолго после увольнения).

    Скрипты все ниже:

    Code Snippet

    //////////////////////////////////////////////////////////
    // Скрипт отключения пользователя                    //
    // Язык: JScript                                 //
    // Автор: Андрей Мишечкин                          //
    //////////////////////////////////////////////////////////
    var objLDAPUser;
    var objRootDSE = GetObject("LDAP://rootDSE");
    var Args = WScript.Arguments;             //Аргументы коммандной строки

    ////////////////////////////////////////////////////////////////
    //   Создание ADSI объектов пользователя                  //
    ////////////////////////////////////////////////////////////////
    if(Args.length == 1)            //Указано только имя пользователя
    {
       var LoginUserName = Args(0);
    }
    else                 //Неправильные аргументы коммандной строки
    {
       WScript.Echo("Usage: disable[.js] LoginUserName");
       WScript.Quit()
    }
    ////////////////////////////////////////////////////////
    //    Создание ADO-подключения                   //
    ////////////////////////////////////////////////////////
    var objConnection = WScript.CreateObject("ADODB.Connection"); //объект ADO-соединения
    var objCommand = WScript.CreateObject("ADODB.Command");   //объект запроса
    objConnection.Provider = "ADsDSOObject";
    objConnection.Open("Active Directory Provider");
    objCommand.ActiveConnection = objConnection;
    ////////////////////////////////////////////////////////////////////////
    //    Выбор всех имен пользователей из AD c обработкой ошибок   //
    ////////////////////////////////////////////////////////////////////////
    try
    {
      objCommand.CommandText = "SELECT sAMAccountName,distinguishedName from 'LDAP://DC=local,DC=polad,DC=ru' Where objectClass='user' and objectClass<>'computer'";
      var objADCRes = objCommand.Execute;
    }
    catch(e)
    {
      WScript.Echo("ADODB error. " + e.description);
      WScript.Quit(1);
    }
    var IsUserFound = false; //Флаг "Пользователь найден/не найден"
    objADCRes.MoveFirst;   //Переход к первому элементу коллекции выборки учетных записей пользователей
    while(!objADCRes.EOF)   //Цикл перебора всех учетных записей пользователей
    {
     //Получение LDAP-объекта пользователя
     //WScript.Echo(objADCRes.Fields("sAMAccountName").Value);
     //WScript.Echo(objADCRes.Fields("distinguishedName").Value);
      if(objADCRes.Fields("sAMAccountName").Value == LoginUserName)
     {
         objLDAPUser = GetObject("LDAP://" + objADCRes.Fields("distinguishedName").Value);
         IsUserFound = true;
         break;
      }
      else
        objADCRes.MoveNext;
    }
    if(!IsUserFound)
    {
      WScript.Echo("No user found");
      WScript.Quit();
    }
     
    /////////////////////////////////////////////////
    //   Отключение пользователя               //
    ////////////////////////////////////////////////
    var intUAC = objLDAPUser.Get("userAccountControl");
    if(!(intUAC & 2))
    {
        objLDAPUser.Put("userAccountControl", intUAC | 2);
        objLDAPUser.SetInfo();
        WScript.Echo("User "+ LoginUserName +" is disabled");
        Information(LoginUserName);
    }
    else
        WScript.Echo("User " + LoginUserName + " is already disabled");
    ////////////////////////////////////////////////////////////////////////
    //    Перемещение отключенной учетной записи в OU=DisabledAccounts    //
    ////////////////////////////////////////////////////////////////////////
    var strDN = new String(objADCRes.Fields("distinguishedName").Value);
    var reDisabledAccounts = new RegExp("DisabledAccounts","i");
    var MatchResult = strDN.match(reDisabledAccounts);
    //WScript.Echo(MatchResult);
    if(!MatchResult)
    {
      objOU = GetObject("LDAP://OU=DisabledAccounts,OU=UsersOfPolad," + objRootDSE.Get("defaultNamingContext"));
      objOU.MoveHere("LDAP://" + objADCRes.Fields("distinguishedName").Value, "CN="+LoginUserName);
      WScript.Echo("User " + LoginUserName + " is moved to OU=DisabledAccounts");
    }
    else
      WScript.Echo("User " + LoginUserName + " is already present in OU=DisabledAccounts");
    function Information(UserName)
    {
       var WMIServiceObj = GetObject("Winmgmts:");
       var ProcEnumerator = new Enumerator(WMIServiceObj.ExecQuery("Select Handle from Win32_Process WHERE Caption = 'cscript.exe' OR Caption = 'wscript.exe'"));
       var ProcHandle = ProcEnumerator.item().Handle; 
       var objWMIProcess = GetObject("winmgmts:Win32_Process.Handle='" + ProcHandle + "'");
       var wmiOutParams = objWMIProcess.ExecMethod_("GetOwner");
       var AdministratorName = wmiOutParams.User;
       var objCurrentDate = new Date;
       var CurrentDate = objCurrentDate.getDate();
       CurrentDate += "." + (objCurrentDate.getMonth()+1);
       CurrentDate += "." + objCurrentDate.getYear() + " ";
       var CurrentHour = objCurrentDate.getHours();
       if(CurrentHour < 10)
      CurrentDate += "0";
       CurrentDate += CurrentHour + ":";
       var CurrentMinute = objCurrentDate.getMinutes();
       if(CurrentMinute < 10)
      CurrentDate += "0";
       CurrentDate += CurrentMinute;
       var objEmail = WScript.CreateObject("CDO.Message");
       objEmail.From = "\"Disable script\" script@polad.ru";
       objEmail.To = admin1@polad.ru,admin2@polad.ru,admin3@polad.ru;
       objEmail.Subject = UserName +" is disabled";
       objEmail.Textbody = "User " + UserName + " is disabled by " + AdministratorName + " in " + CurrentDate;
       objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2;
       objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "mail.polad.ru";
       objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25;
       objEmail.Configuration.Fields.Update();
       try
       {
          objEmail.Send();
       }
       catch(e)
       {
          WScript.Echo("Mail system error: " + e.description);
       }
    }

     

     

    //////////////////////////////////////////////////////////
    // Скрипт удаления отключенных учетных записей          //
    // в OU=DisabledAccounts                              //
    // Язык: JScript                                 //
    // Автор: Андрей Мишечкин                          //
    //////////////////////////////////////////////////////////
    //Объявление переменных
    var count1 = 0;             //Счетчик общего количества пользователей
    var count2 = 0;             //Счетчик числа увволенных пользователей
    var delUsersList = "";      //Список удаленных пользователей
    var objNTUser;              //ADSI-объект пользователя (используя NTLM)
    var input;                  //переменная ввода символов со стандартного потока
    //Определение полного пути к орг. единце с отключенными учетными записями
    var DisabledAccountsOU = "LDAP://OU=DisabledAccounts,OU=UsersOfPolad,DC=local,DC=polad,DC=ru";
    //var DisabledAccountsOU = "LDAP://OU=TestOU,DC=local,DC=polad,DC=ru";
    //Получение объекта орг. единицы и определение коллекции ее членов с обработкой ошибок
    try
    {
      var objDisabledAccountsOU = GetObject(DisabledAccountsOU);
      var enumDisabledAccountsOU = new Enumerator(objDisabledAccountsOU);
    }
    catch(e)
    {
      WScript.Echo("Can't create the OU object and collection" + e.description);
    }
    //////////////////////////////////////////////////////////////////////
    // Основной цикл перебора элементов коллекции                       //
    //////////////////////////////////////////////////////////////////////
    for(;!enumDisabledAccountsOU.atEnd();enumDisabledAccountsOU.moveNext())
    {
     objOUMember = enumDisabledAccountsOU.item();
     if(objOUMember.Class == "user")
     {
          //Вывод на экран информации о пользователе
          WScript.Echo("Login name: " + GetParam("objOUMember","sAMAccountName"));
          WScript.Echo("Display name: " + GetParam("objOUMember","displayName"));
          WScript.Echo("Description: " + GetParam("objOUMember","Description")); 
          WScript.Echo("Last login time: " + GetParam("objNTUser","LastLogin"));
          if(objOUMember.AccountDisabled == 1)
            WScript.Echo("Account disabled");
         else
            WScript.Echo("Account is not disabled");
        //Выполнение удаления пользователя выполнении условия.
          WScript.Echo("Delete this account ? Y/N");
          for(;;)
          {        
              input = "";
              input = WScript.StdIn.ReadLine();
              if((input == "Y")||(input == "y"))
              {
                  try
                  {
                     objDisabledAccountsOU.Delete("user","cn=" + objOUMember.Get("Name"));
                  }
                  catch(e)
                  {
                     WScript.Echo("Error. Account " + objOUMember.Get("sAMAccountName") + " is not deleted. " + e.description);
                  }
                  WScript.Echo(objOUMember.Get("sAMAccountName") + " is deleted");
                  delUsersList += GetParam("objOUMember","sAMAccountName") + " / " + GetParam("objOUMember","displayName") + "\n";
                  count2++;
                  break;
              }
              else if((input == "N")||(input == "n"))
              {
                  WScript.Echo(objOUMember.Get("sAMAccountName") + " is not deleted");
                  break;
              }
              else 
              {
                  WScript.Echo("Invalid option.");
                  WScript.Echo("Delete this account ? Y/N");
              }  
          }
          WScript.Echo("------------------------------------------------------------");
          count1++;
      }
    }
    WScript.Echo("Total accounts: " + count1);
    WScript.Echo("Deleted accounts: " + count2);
    Information();
    //////////////////////////////////////////////////////////////////
    //  Фукнкция считывания параметров из кэша с обработкой ошибок  //
    //////////////////////////////////////////////////////////////////
    function GetParam(object,ParamName)
    {
     var result;
     if(object == "objOUMember")
        var objUser = objOUMember;
     else if(object == "objNTUser")
        var objUser = GetObject("WinNT://POLAD/" + objOUMember.Get("sAMAccountName") + ",user");
      try
     {
      result = objUser.Get(ParamName);
     }
     catch(e)
     {
      result = "Undefined";
     }
     return result;
    }
    function Information()
    {
       var WMIServiceObj = GetObject("Winmgmts:");
       var ProcEnumerator = new Enumerator(WMIServiceObj.ExecQuery("Select Handle from Win32_Process WHERE Caption = 'cscript.exe' OR Caption = 'wscript.exe'"));
       var ProcHandle = ProcEnumerator.item().Handle; 
       var objWMIProcess = GetObject("winmgmts:Win32_Process.Handle='" + ProcHandle + "'");
       var wmiOutParams = objWMIProcess.ExecMethod_("GetOwner");
       var AdministratorName = wmiOutParams.User;
       var objCurrentDate = new Date;
       var CurrentDate = objCurrentDate.getDate();
       CurrentDate += "." + (objCurrentDate.getMonth()+1);
       CurrentDate += "." + objCurrentDate.getYear() + " ";
       var CurrentHour = objCurrentDate.getHours();
       if(CurrentHour < 10)
      CurrentDate += "0";
       CurrentDate += CurrentHour + ":";
       var CurrentMinute = objCurrentDate.getMinutes();
       if(CurrentMinute < 10)
      CurrentDate += "0";
       CurrentDate += CurrentMinute;
       var objEmail = WScript.CreateObject("CDO.Message");
       objEmail.From = "\"Usrclean script\" script@polad.ru";
       objEmail.To = "admin1@polad.ru,admin2@polad.ru,admin3@polad.ru";
       objEmail.Subject = "Usrclean.js report";
       objEmail.Textbody = "Users:\n" + delUsersList + "was deleted by " + AdministratorName + " in " + CurrentDate;
       objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2;
       objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "mail.polad.ru";
       objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25;
       objEmail.Configuration.Fields.Update();
       try
       {
          objEmail.Send();
       }
       catch(e)
       {
          WScript.Echo("Mail system error: " + e.description);
       }
    }
     
    Code Snippet
    //Необходимые глобальные переменные     
    var objADSIUser                                 //Ссылка на ADSI-объект пользователя
    var objUsersFolder;                              //Ссылка на объект каталога пользователя
    var UserFolderSpec;                                         //Полное имя каталога пользователя
    var OldUsersFolder = "I:\\ODBackup\\OldUsers\\";            //Переменная каталога долговременного хранения
    var enumUserFolders;                             //Коллекция каталогов пользователей
    var NoMove = true;                               //Флаг отмены перемещения каталога пользователя
    var IsError = false;                             //Флаг ошибки
    var WshShell = WScript.CreateObject("WScript.Shell");     //WshShell - используется для выполнения системных комманд 
    ///////////////////////////////////////////////////////////
    //  Создание необходимых объектов файловой системы      //
    ///////////////////////////////////////////////////////////
    var fso = WScript.CreateObject("Scripting.FileSystemObject"); //Объект для файловой системы
    var ReportFile = fso.CreateTextFile("G:\\FileService\\ODLMReports\\" + GetTime() + "_main.txt",true);   //Создание файла отчета и открытие его потока
    try
    {
     objUsersFolder = fso.GetFolder("E:\\Users");              //Попытка получения объекта стартового каталога
      enumUserFolders = new Enumerator(objUsersFolder.SubFolders);  //Создание коллекции для всех подкаталогов текущего каталога
    }
    catch(e)                //Обработка ошибки создания объекта стартового каталога
    {
     ReportFile.Write("Unable to open directory G:\\users or creating subfolders collection. Error: " + e.description);
     ReportFile.Close();
     WScript.Quit();
    }
    ///////////////////////////////////////////////////////////
    //  Считываение каталогов пользователей                //
    ///////////////////////////////////////////////////////////
    while(!enumUserFolders.atEnd())     //Цикл перебора всех подпапок
    {
     objUserFolder = enumUserFolders.item();
     UserName = objUserFolder.Name;
     /////////////////////////////////////////////////////////
     // Получение ссылки на ADSI-объект пользователя        //
     /////////////////////////////////////////////////////////
     try
     {
      objADSIUser = GetObject("WinNT://POLAD/"+UserName+",user");  //ADSI объект текущего пользователя
     }
     catch(e)
     {
      NoMove = false;
     } 
     if(!NoMove)
     {
      /////////////////////////////////////////////////////////////
      // Перемещение каталога                                 //
      ///////////////////////////////////////////////////////////// 
        UserFolderSpec = objUserFolder.Path;
        WScript.Echo("Moving directory " + UserName);
        ReportFile.Write("Moving directory " + UserName + "\n");
        //WScript.Echo("Source = " + UserFolderSpec);
        //WScript.Echo("Destination = " + OldUsersFolder);
      WshShell.Run("robocopy " + UserFolderSpec + " " + OldUsersFolder + "\\" + UserName + " /move /e /copyall /v /LOG:G:\\FileService\\ODLMReports\\" + UserName + ".txt /TEE /R:5 /W:5",1,true);
     }
     enumUserFolders.moveNext();
    }
    ReportFile.Write("odlm.js script is finished.\n");
    ReportFile.Close();       //Закрытие файла отчета
    //////////////////////////////////////////////////////////
    //  Функция получения текущей даты и времени        //
    //////////////////////////////////////////////////////////
    function GetTime()
    {
     var objCurrentDate = new Date;
     var strCurrentTime = objCurrentDate.getDate();
     var CurrentMonth = (objCurrentDate.getMonth()+1);
     if(CurrentMonth<10)
      strCurrentTime +="0";
     strCurrentTime += CurrentMonth;
     strCurrentTime += objCurrentDate.getYear();
     strCurrentTime += "_";
     strCurrentTime += objCurrentDate.getHours();
     strCurrentTime += objCurrentDate.getMinutes();
     strCurrentTime += objCurrentDate.getSeconds();
     return strCurrentTime;
    }

     

     

    • Помечено в качестве ответа Vasily GusevModerator 17 сентября 2009 г. 17:43
    29 октября 2008 г. 12:41

Все ответы

  • Я думаю, надо сначала определиться с критерием удаления: простой запрет пользователя на мой взгляд не достаточное условие, а вот отсутствие в AD в течение, например, месяца уже повод для удаления.

     

    Второе: вопрос больше подходит для раздела скриптов - может перенести?

    27 октября 2008 г. 14:47
    Модератор
  •  sie написано:

    Я думаю, надо сначала определиться с критерием удаления: простой запрет пользователя на мой взгляд не достаточное условие, а вот отсутствие в AD и течение, например, месяца уже повод для удаления.

     

    Второе: вопрос больше подходит для раздела скриптов - может перенести?

    да, конечно можно перенести тему, если считаете нужным...

    27 октября 2008 г. 14:50
  • Ниже пример скрипта на PowerShell.

     

    В скрипте есть функция, которая по имени пользователя возвращает один из 4 статусов: Active, PermanentlyDisabled, TemporarilyDisabled и Unknown.

     

    Active - пользователь включен.

    PermanentlyDisabled - пользователь выключен более или равно чем значение $permanentThreshold дней.

    TemporarilyDisabled  - пользователь выключен менее чем значение $permanentThreshold дней.

    Unknown - нету такого пользователя.

     

    Дальше идёт цикл, пробегающий по все каталогам. У каждого каталога он берет имя и пытается вычислить статус пользователя с таким именем входа. В зависимости от статуса вы можете выполнять различные действия.

     

    В данном привере, в случае если пользователь заблокирован более 200 дней папка удаляется, во всех остальных просто выводится сообщение.

     

    Code Snippet

    Function Get-Status
    {
      param (
        $samAccountName
      )

     

      $permanentThreshold = 200

     

      $adRootDSE   = New-Object DirectoryServices.DirectoryEntry("LDAP://rootDSE")
      $adRootEntry = New-Object DirectoryServices.DirectoryEntry("LDAP://$($adRootDSE.DefaultNamingContext)")
     
      $adSearcher        = New-Object System.DirectoryServices.DirectorySearcher($adRootEntry)
      $adSearcher.Filter = [String]::Format("(&(objectClass=User)(objectCategory=Person)(samAccountName={0}))", $samAccountName)

      [void] $adSearcher.PropertiesToLoad.Add("lastlogontimestamp")

      $adResult          = $adSearcher.FindOne()

      if ($adResult -ne $null) {
        if ([Convert]::ToInt32($adResult.GetDirectoryEntry().PsBase.Properties.userAccountControl.Value) -band 2)
        {
          $userHasBeenDisabled = [DateTime]::Now.Subtract( [DateTime]::FromFileTime( [Int64]::Parse($adResult.Properties["lastlogontimestamp"]) ) )

          if ($userHasBeenDisabled.Days -gt $permanentThreshold)
          {
            return "PermanentlyDisabled"
          }
          else
          {
            return "TemporarilyDisabled"
          }
        }
        else
        {
          return "Active"
        }
      }
      else
      {
        return "Unknown"
      }
    }

     

    Get-ChildItem X:\USERS\HOME | ForEach-Object {
      switch (Get-Status $_.Name) {
        "PermanentlyDisabled" {
          "This user is disabled for good"
          Remove-Item $_
        }
        "TemporarilyDisabled" {
          "This user is disabled temporarily"
        }
        "Active" {
          "This is an active user"
        }
        "Unknown" {
          "Unknown user"
        }
      }
    }

     

     


    • Предложено в качестве ответа Vasily GusevModerator 27 августа 2009 г. 4:57
    28 октября 2008 г. 15:53
  •  

    Похожая ситуация.

    Я решил ее следующим образом:

    1) При увольнении админ отключает учетку пользователя.

    2) Раз в месяц админ проверяет отключенные учетки и удаляет их (бывали случаи, что люди увольнялись, потом устраивались обратно) специальным скриптом.

    3) По определеннному рассписанию на файловом сервере запускается скрипт, который каталоги несуществующих пользователей перемещает в долговременное хранилище (бывали случаи, что кое-что требовалось выдернуть задолго после увольнения).

    Скрипты все ниже:

    Code Snippet

    //////////////////////////////////////////////////////////
    // Скрипт отключения пользователя                    //
    // Язык: JScript                                 //
    // Автор: Андрей Мишечкин                          //
    //////////////////////////////////////////////////////////
    var objLDAPUser;
    var objRootDSE = GetObject("LDAP://rootDSE");
    var Args = WScript.Arguments;             //Аргументы коммандной строки

    ////////////////////////////////////////////////////////////////
    //   Создание ADSI объектов пользователя                  //
    ////////////////////////////////////////////////////////////////
    if(Args.length == 1)            //Указано только имя пользователя
    {
       var LoginUserName = Args(0);
    }
    else                 //Неправильные аргументы коммандной строки
    {
       WScript.Echo("Usage: disable[.js] LoginUserName");
       WScript.Quit()
    }
    ////////////////////////////////////////////////////////
    //    Создание ADO-подключения                   //
    ////////////////////////////////////////////////////////
    var objConnection = WScript.CreateObject("ADODB.Connection"); //объект ADO-соединения
    var objCommand = WScript.CreateObject("ADODB.Command");   //объект запроса
    objConnection.Provider = "ADsDSOObject";
    objConnection.Open("Active Directory Provider");
    objCommand.ActiveConnection = objConnection;
    ////////////////////////////////////////////////////////////////////////
    //    Выбор всех имен пользователей из AD c обработкой ошибок   //
    ////////////////////////////////////////////////////////////////////////
    try
    {
      objCommand.CommandText = "SELECT sAMAccountName,distinguishedName from 'LDAP://DC=local,DC=polad,DC=ru' Where objectClass='user' and objectClass<>'computer'";
      var objADCRes = objCommand.Execute;
    }
    catch(e)
    {
      WScript.Echo("ADODB error. " + e.description);
      WScript.Quit(1);
    }
    var IsUserFound = false; //Флаг "Пользователь найден/не найден"
    objADCRes.MoveFirst;   //Переход к первому элементу коллекции выборки учетных записей пользователей
    while(!objADCRes.EOF)   //Цикл перебора всех учетных записей пользователей
    {
     //Получение LDAP-объекта пользователя
     //WScript.Echo(objADCRes.Fields("sAMAccountName").Value);
     //WScript.Echo(objADCRes.Fields("distinguishedName").Value);
      if(objADCRes.Fields("sAMAccountName").Value == LoginUserName)
     {
         objLDAPUser = GetObject("LDAP://" + objADCRes.Fields("distinguishedName").Value);
         IsUserFound = true;
         break;
      }
      else
        objADCRes.MoveNext;
    }
    if(!IsUserFound)
    {
      WScript.Echo("No user found");
      WScript.Quit();
    }
     
    /////////////////////////////////////////////////
    //   Отключение пользователя               //
    ////////////////////////////////////////////////
    var intUAC = objLDAPUser.Get("userAccountControl");
    if(!(intUAC & 2))
    {
        objLDAPUser.Put("userAccountControl", intUAC | 2);
        objLDAPUser.SetInfo();
        WScript.Echo("User "+ LoginUserName +" is disabled");
        Information(LoginUserName);
    }
    else
        WScript.Echo("User " + LoginUserName + " is already disabled");
    ////////////////////////////////////////////////////////////////////////
    //    Перемещение отключенной учетной записи в OU=DisabledAccounts    //
    ////////////////////////////////////////////////////////////////////////
    var strDN = new String(objADCRes.Fields("distinguishedName").Value);
    var reDisabledAccounts = new RegExp("DisabledAccounts","i");
    var MatchResult = strDN.match(reDisabledAccounts);
    //WScript.Echo(MatchResult);
    if(!MatchResult)
    {
      objOU = GetObject("LDAP://OU=DisabledAccounts,OU=UsersOfPolad," + objRootDSE.Get("defaultNamingContext"));
      objOU.MoveHere("LDAP://" + objADCRes.Fields("distinguishedName").Value, "CN="+LoginUserName);
      WScript.Echo("User " + LoginUserName + " is moved to OU=DisabledAccounts");
    }
    else
      WScript.Echo("User " + LoginUserName + " is already present in OU=DisabledAccounts");
    function Information(UserName)
    {
       var WMIServiceObj = GetObject("Winmgmts:");
       var ProcEnumerator = new Enumerator(WMIServiceObj.ExecQuery("Select Handle from Win32_Process WHERE Caption = 'cscript.exe' OR Caption = 'wscript.exe'"));
       var ProcHandle = ProcEnumerator.item().Handle; 
       var objWMIProcess = GetObject("winmgmts:Win32_Process.Handle='" + ProcHandle + "'");
       var wmiOutParams = objWMIProcess.ExecMethod_("GetOwner");
       var AdministratorName = wmiOutParams.User;
       var objCurrentDate = new Date;
       var CurrentDate = objCurrentDate.getDate();
       CurrentDate += "." + (objCurrentDate.getMonth()+1);
       CurrentDate += "." + objCurrentDate.getYear() + " ";
       var CurrentHour = objCurrentDate.getHours();
       if(CurrentHour < 10)
      CurrentDate += "0";
       CurrentDate += CurrentHour + ":";
       var CurrentMinute = objCurrentDate.getMinutes();
       if(CurrentMinute < 10)
      CurrentDate += "0";
       CurrentDate += CurrentMinute;
       var objEmail = WScript.CreateObject("CDO.Message");
       objEmail.From = "\"Disable script\" script@polad.ru";
       objEmail.To = admin1@polad.ru,admin2@polad.ru,admin3@polad.ru;
       objEmail.Subject = UserName +" is disabled";
       objEmail.Textbody = "User " + UserName + " is disabled by " + AdministratorName + " in " + CurrentDate;
       objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2;
       objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "mail.polad.ru";
       objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25;
       objEmail.Configuration.Fields.Update();
       try
       {
          objEmail.Send();
       }
       catch(e)
       {
          WScript.Echo("Mail system error: " + e.description);
       }
    }

     

     

    //////////////////////////////////////////////////////////
    // Скрипт удаления отключенных учетных записей          //
    // в OU=DisabledAccounts                              //
    // Язык: JScript                                 //
    // Автор: Андрей Мишечкин                          //
    //////////////////////////////////////////////////////////
    //Объявление переменных
    var count1 = 0;             //Счетчик общего количества пользователей
    var count2 = 0;             //Счетчик числа увволенных пользователей
    var delUsersList = "";      //Список удаленных пользователей
    var objNTUser;              //ADSI-объект пользователя (используя NTLM)
    var input;                  //переменная ввода символов со стандартного потока
    //Определение полного пути к орг. единце с отключенными учетными записями
    var DisabledAccountsOU = "LDAP://OU=DisabledAccounts,OU=UsersOfPolad,DC=local,DC=polad,DC=ru";
    //var DisabledAccountsOU = "LDAP://OU=TestOU,DC=local,DC=polad,DC=ru";
    //Получение объекта орг. единицы и определение коллекции ее членов с обработкой ошибок
    try
    {
      var objDisabledAccountsOU = GetObject(DisabledAccountsOU);
      var enumDisabledAccountsOU = new Enumerator(objDisabledAccountsOU);
    }
    catch(e)
    {
      WScript.Echo("Can't create the OU object and collection" + e.description);
    }
    //////////////////////////////////////////////////////////////////////
    // Основной цикл перебора элементов коллекции                       //
    //////////////////////////////////////////////////////////////////////
    for(;!enumDisabledAccountsOU.atEnd();enumDisabledAccountsOU.moveNext())
    {
     objOUMember = enumDisabledAccountsOU.item();
     if(objOUMember.Class == "user")
     {
          //Вывод на экран информации о пользователе
          WScript.Echo("Login name: " + GetParam("objOUMember","sAMAccountName"));
          WScript.Echo("Display name: " + GetParam("objOUMember","displayName"));
          WScript.Echo("Description: " + GetParam("objOUMember","Description")); 
          WScript.Echo("Last login time: " + GetParam("objNTUser","LastLogin"));
          if(objOUMember.AccountDisabled == 1)
            WScript.Echo("Account disabled");
         else
            WScript.Echo("Account is not disabled");
        //Выполнение удаления пользователя выполнении условия.
          WScript.Echo("Delete this account ? Y/N");
          for(;;)
          {        
              input = "";
              input = WScript.StdIn.ReadLine();
              if((input == "Y")||(input == "y"))
              {
                  try
                  {
                     objDisabledAccountsOU.Delete("user","cn=" + objOUMember.Get("Name"));
                  }
                  catch(e)
                  {
                     WScript.Echo("Error. Account " + objOUMember.Get("sAMAccountName") + " is not deleted. " + e.description);
                  }
                  WScript.Echo(objOUMember.Get("sAMAccountName") + " is deleted");
                  delUsersList += GetParam("objOUMember","sAMAccountName") + " / " + GetParam("objOUMember","displayName") + "\n";
                  count2++;
                  break;
              }
              else if((input == "N")||(input == "n"))
              {
                  WScript.Echo(objOUMember.Get("sAMAccountName") + " is not deleted");
                  break;
              }
              else 
              {
                  WScript.Echo("Invalid option.");
                  WScript.Echo("Delete this account ? Y/N");
              }  
          }
          WScript.Echo("------------------------------------------------------------");
          count1++;
      }
    }
    WScript.Echo("Total accounts: " + count1);
    WScript.Echo("Deleted accounts: " + count2);
    Information();
    //////////////////////////////////////////////////////////////////
    //  Фукнкция считывания параметров из кэша с обработкой ошибок  //
    //////////////////////////////////////////////////////////////////
    function GetParam(object,ParamName)
    {
     var result;
     if(object == "objOUMember")
        var objUser = objOUMember;
     else if(object == "objNTUser")
        var objUser = GetObject("WinNT://POLAD/" + objOUMember.Get("sAMAccountName") + ",user");
      try
     {
      result = objUser.Get(ParamName);
     }
     catch(e)
     {
      result = "Undefined";
     }
     return result;
    }
    function Information()
    {
       var WMIServiceObj = GetObject("Winmgmts:");
       var ProcEnumerator = new Enumerator(WMIServiceObj.ExecQuery("Select Handle from Win32_Process WHERE Caption = 'cscript.exe' OR Caption = 'wscript.exe'"));
       var ProcHandle = ProcEnumerator.item().Handle; 
       var objWMIProcess = GetObject("winmgmts:Win32_Process.Handle='" + ProcHandle + "'");
       var wmiOutParams = objWMIProcess.ExecMethod_("GetOwner");
       var AdministratorName = wmiOutParams.User;
       var objCurrentDate = new Date;
       var CurrentDate = objCurrentDate.getDate();
       CurrentDate += "." + (objCurrentDate.getMonth()+1);
       CurrentDate += "." + objCurrentDate.getYear() + " ";
       var CurrentHour = objCurrentDate.getHours();
       if(CurrentHour < 10)
      CurrentDate += "0";
       CurrentDate += CurrentHour + ":";
       var CurrentMinute = objCurrentDate.getMinutes();
       if(CurrentMinute < 10)
      CurrentDate += "0";
       CurrentDate += CurrentMinute;
       var objEmail = WScript.CreateObject("CDO.Message");
       objEmail.From = "\"Usrclean script\" script@polad.ru";
       objEmail.To = "admin1@polad.ru,admin2@polad.ru,admin3@polad.ru";
       objEmail.Subject = "Usrclean.js report";
       objEmail.Textbody = "Users:\n" + delUsersList + "was deleted by " + AdministratorName + " in " + CurrentDate;
       objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2;
       objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "mail.polad.ru";
       objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25;
       objEmail.Configuration.Fields.Update();
       try
       {
          objEmail.Send();
       }
       catch(e)
       {
          WScript.Echo("Mail system error: " + e.description);
       }
    }
     
    Code Snippet
    //Необходимые глобальные переменные     
    var objADSIUser                                 //Ссылка на ADSI-объект пользователя
    var objUsersFolder;                              //Ссылка на объект каталога пользователя
    var UserFolderSpec;                                         //Полное имя каталога пользователя
    var OldUsersFolder = "I:\\ODBackup\\OldUsers\\";            //Переменная каталога долговременного хранения
    var enumUserFolders;                             //Коллекция каталогов пользователей
    var NoMove = true;                               //Флаг отмены перемещения каталога пользователя
    var IsError = false;                             //Флаг ошибки
    var WshShell = WScript.CreateObject("WScript.Shell");     //WshShell - используется для выполнения системных комманд 
    ///////////////////////////////////////////////////////////
    //  Создание необходимых объектов файловой системы      //
    ///////////////////////////////////////////////////////////
    var fso = WScript.CreateObject("Scripting.FileSystemObject"); //Объект для файловой системы
    var ReportFile = fso.CreateTextFile("G:\\FileService\\ODLMReports\\" + GetTime() + "_main.txt",true);   //Создание файла отчета и открытие его потока
    try
    {
     objUsersFolder = fso.GetFolder("E:\\Users");              //Попытка получения объекта стартового каталога
      enumUserFolders = new Enumerator(objUsersFolder.SubFolders);  //Создание коллекции для всех подкаталогов текущего каталога
    }
    catch(e)                //Обработка ошибки создания объекта стартового каталога
    {
     ReportFile.Write("Unable to open directory G:\\users or creating subfolders collection. Error: " + e.description);
     ReportFile.Close();
     WScript.Quit();
    }
    ///////////////////////////////////////////////////////////
    //  Считываение каталогов пользователей                //
    ///////////////////////////////////////////////////////////
    while(!enumUserFolders.atEnd())     //Цикл перебора всех подпапок
    {
     objUserFolder = enumUserFolders.item();
     UserName = objUserFolder.Name;
     /////////////////////////////////////////////////////////
     // Получение ссылки на ADSI-объект пользователя        //
     /////////////////////////////////////////////////////////
     try
     {
      objADSIUser = GetObject("WinNT://POLAD/"+UserName+",user");  //ADSI объект текущего пользователя
     }
     catch(e)
     {
      NoMove = false;
     } 
     if(!NoMove)
     {
      /////////////////////////////////////////////////////////////
      // Перемещение каталога                                 //
      ///////////////////////////////////////////////////////////// 
        UserFolderSpec = objUserFolder.Path;
        WScript.Echo("Moving directory " + UserName);
        ReportFile.Write("Moving directory " + UserName + "\n");
        //WScript.Echo("Source = " + UserFolderSpec);
        //WScript.Echo("Destination = " + OldUsersFolder);
      WshShell.Run("robocopy " + UserFolderSpec + " " + OldUsersFolder + "\\" + UserName + " /move /e /copyall /v /LOG:G:\\FileService\\ODLMReports\\" + UserName + ".txt /TEE /R:5 /W:5",1,true);
     }
     enumUserFolders.moveNext();
    }
    ReportFile.Write("odlm.js script is finished.\n");
    ReportFile.Close();       //Закрытие файла отчета
    //////////////////////////////////////////////////////////
    //  Функция получения текущей даты и времени        //
    //////////////////////////////////////////////////////////
    function GetTime()
    {
     var objCurrentDate = new Date;
     var strCurrentTime = objCurrentDate.getDate();
     var CurrentMonth = (objCurrentDate.getMonth()+1);
     if(CurrentMonth<10)
      strCurrentTime +="0";
     strCurrentTime += CurrentMonth;
     strCurrentTime += objCurrentDate.getYear();
     strCurrentTime += "_";
     strCurrentTime += objCurrentDate.getHours();
     strCurrentTime += objCurrentDate.getMinutes();
     strCurrentTime += objCurrentDate.getSeconds();
     return strCurrentTime;
    }

     

     

    • Помечено в качестве ответа Vasily GusevModerator 17 сентября 2009 г. 17:43
    29 октября 2008 г. 12:41
  • Если я понял правильно. Вам нужно, если учетка Отключена, удалять все файлы из его папки... если у вас имя папки и имя пользователя совпадают, то мне кажется можно решить просто используя dsmod  и т.п. ds-программы. Вы, если еще не разобрались, конкретнее опишите структуру организации папок и на какие события должен реагировать скрипт.
    2 ноября 2008 г. 16:50
  •  Andrey Nepomnyaschih написано:

    Ниже пример скрипта на PowerShell.

     

    В скрипте есть функция, которая по имени пользователя возвращает один из 4 статусов: Active, PermanentlyDisabled, TemporarilyDisabled и Unknown.

     

    Active - пользователь включен.

    PermanentlyDisabled - пользователь выключен более или равно чем значение $permanentThreshold дней.

    TemporarilyDisabled  - пользователь выключен менее чем значение $permanentThreshold дней.

    Unknown - нету такого пользователя.

     

    Дальше идёт цикл, пробегающий по все каталогам. У каждого каталога он берет имя и пытается вычислить статус пользователя с таким именем входа. В зависимости от статуса вы можете выполнять различные действия.

     

    В данном привере, в случае если пользователь заблокирован более 200 дней папка удаляется, во всех остальных просто выводится сообщение.

     

    Code Snippet

    Function Get-Status
    {
      param (
        $samAccountName
      )

     

      $permanentThreshold = 200

     

      $adRootDSE   = New-Object DirectoryServices.DirectoryEntry("LDAP://rootDSE")
      $adRootEntry = New-Object DirectoryServices.DirectoryEntry("LDAP://$($adRootDSE.DefaultNamingContext)")
     
      $adSearcher        = New-Object System.DirectoryServices.DirectorySearcher($adRootEntry)
      $adSearcher.Filter = [String]::Format("(&(objectClass=User)(objectCategory=Person)(samAccountName={0}))", $samAccountName)

      [void] $adSearcher.PropertiesToLoad.Add("lastlogontimestamp")

      $adResult          = $adSearcher.FindOne()

      if ($adResult -ne $null) {
        if ([Convert]::ToInt32($adResult.GetDirectoryEntry().PsBase.Properties.userAccountControl.Value) -band 2)
        {
          $userHasBeenDisabled = [DateTime]::Now.Subtract( [DateTime]::FromFileTime( [Int64]::Parse($adResult.Properties["lastlogontimestamp"]) ) )

          if ($userHasBeenDisabled.Days -gt $permanentThreshold)
          {
            return "PermanentlyDisabled"
          }
          else
          {
            return "TemporarilyDisabled"
          }
        }
        else
        {
          return "Active"
        }
      }
      else
      {
        return "Unknown"
      }
    }

     

    Get-ChildItem X:\USERS\HOME | ForEach-Object {
      switch (Get-Status $_.Name) {
        "PermanentlyDisabled" {
          "This user is disabled for good"
          Remove-Item $_
        }
        "TemporarilyDisabled" {
          "This user is disabled temporarily"
        }
        "Active" {
          "This is an active user"
        }
        "Unknown" {
          "Unknown user"
        }
      }
    }

     

     


    Господа, у меня не отрабатывает данный скрипт. Пробовал разобраться в коде, но ошибок не нашел.

    Мой путь это u:\

    К Remove-Item добавил параметр whatif.

    В результате выполнения скрипта происходит следующее:

    This is an active user
    This user is disabled for good
    Remove-Item : Не удается найти путь "U:\PermanentlyDisabled", так как он не существует.
    В U:\RemoveFolder.ps1:64 знак:18
    + Remove-Item <<<< -Whatif $_
    This is an active user
    Unknown user
    This is an active user
    This is an active user

    Как победить?

    21 ноября 2008 г. 14:36
  • Не проверял ... Smile

     

    Видимо case заменяет $_, буду знать, попробуйте так:

     

    Code Snippet

    Get-ChildItem U:\ | ForEach-Object {

     

      $folderObject = $_

     

      switch (Get-Status $folderObject.Name) {
        "PermanentlyDisabled" {
          "This user is disabled for good"
          Remove-Item $folderObject -WhatIf
        }
        "TemporarilyDisabled" {
          "This user is disabled temporarily"
        }
        "Active" {
          "This is an active user"
        }
        "Unknown" {
          "Unknown user"
        }
      }
    }

     

     

     

     

    • Предложено в качестве ответа Vasily GusevModerator 27 августа 2009 г. 4:58
    21 ноября 2008 г. 19:24
  • Andrey Nepomnyaschih, спасибо! Теперь работает Smile
    24 ноября 2008 г. 8:05
  • Ниже пример скрипта на PowerShell.

     

    В скрипте есть функция, которая по имени пользователя возвращает один из 4 статусов: Active, PermanentlyDisabled, TemporarilyDisabled и Unknown.

     

    Active - пользователь включен.

    PermanentlyDisabled - пользователь выключен более или равно чем значение $permanentThreshold дней.

    TemporarilyDisabled  - пользователь выключен менее чем значение $permanentThreshold дней.

    Unknown - нету такого пользователя.

     

    Дальше идёт цикл, пробегающий по все каталогам. У каждого каталога он берет имя и пытается вычислить статус пользователя с таким именем входа. В зависимости от статуса вы можете выполнять различные действия.

     

    В данном привере, в случае если пользователь заблокирован более 200 дней папка удаляется, во всех остальных просто выводится сообщение.

     

     

    Code Snippet

    Function Get-Status
    {
      param (
        $samAccountName
      )

     

      $permanentThreshold = 200

     

      $adRootDSE   = New-Object DirectoryServices.DirectoryEntry("LDAP://rootDSE")
      $adRootEntry = New-Object DirectoryServices.DirectoryEntry("LDAP://$($adRootDSE.DefaultNamingContext)")
     
      $adSearcher        = New-Object System.DirectoryServices.DirectorySearcher($adRootEntry)
      $adSearcher.Filter = [String]::Format("(&(objectClass=User)(objectCategory=Person)(samAccountName={0}))", $samAccountName)

      [void] $adSearcher.PropertiesToLoad.Add("lastlogontimestamp")

      $adResult          = $adSearcher.FindOne()

      if ($adResult -ne $null) {
        if ([Convert]::ToInt32($adResult.GetDirectoryEntry().PsBase.Properties.userAccountControl.Value) -band 2)
        {
          $userHasBeenDisabled = [DateTime]::Now.Subtract( [DateTime]::FromFileTime( [Int64]::Parse($adResult.Properties["lastlogontimestamp"]) ) )

          if ($userHasBeenDisabled.Days -gt $permanentThreshold)
          {
            return "PermanentlyDisabled"
          }
          else
          {
            return "TemporarilyDisabled"
          }
        }
        else
        {
          return "Active"
        }
      }
      else
      {
        return "Unknown"
      }
    }

     

    Get-ChildItem X:\USERS\HOME | ForEach-Object {
      switch (Get-Status $_.Name) {
        "PermanentlyDisabled" {
          "This user is disabled for good"
          Remove-Item $_
        }
        "TemporarilyDisabled" {
          "This user is disabled temporarily"
        }
        "Active" {
          "This is an active user"
        }
        "Unknown" {
          "Unknown user"
        }
      }
    }

     

    Помогите изменить скрипт так что бы пользовательские каталоги не удалялись с файлового сервера, а перемещались в другой каталог.

    Структура следующая
    Контроллеры домена -DC1, DC2;
    Файловый сервер FS1, FS2
    DFS корень \\company.name\ofice\
    Путь к пользовательски каталогам \\company.name\ofice\userdoc\%username%
    Путь к пользовательским каталогам которые были заблокированы или удалены \\company.name\ofice\NOusers\%username%

     

     

     


    21 августа 2009 г. 10:40
  • Вы бы сделали отдельный топик для своего вопроса со ссылкой на эту тему. Да еще бы оформили более удачно...
    Сазонов Илья http://www.itcommunity.ru/blogs/sie/
    21 августа 2009 г. 12:13
    Модератор