none
Powershell 4.0 не выполняет команды. RRS feed

  • Вопрос

  • Здравствуйте. У меня возникла проблема - posh не выполняет команды в скрипте. Скрипт работал ранее, никаких изменений в системе (windows server 2012R2, PS 4.0) не было. Была настроена задача по расписанию. Вчера я заметил, что задача не выполняется. Проверил выполнение скрипта на другой машине (windows 7, PS 2.0) - скрипт работает. При отладке через ISE была замечена такое аномальное поведение, что выполнение скрипта останавливается на одном и том же шаге, и при нажатии клавиши F11(вып. след. шаг) подсвечивается не вся строка, а только символ $ у переменной, после следующего нажатия f11 скрипт прекращает свою работу без выдачи ошибок. Код ниже:



    Import-Module ActiveDirectory
    
    try{
    ##Обращение к папке Inbox пользователя, от чьего имени запущен скрипт
      Add-type -assembly "Microsoft.Office.Interop.Outlook" | out-null 
     $olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]  
     $outlook = new-object -comobject outlook.application 
     $namespace = $outlook.GetNameSpace("MAPI") 
     $folder = $namespace.getDefaultFolder($olFolders::olFolderInBox) 
     $folder.items | % {
         if ($_.Subject -eq 'Сменить телефон') 
            {        
      ### инициализация переменных
      $body=$_.Body
      $Sender=$_.SenderName
      #$to=$_.To
      $Subj=$inb.Subject
      $strokaEND=$body.IndexOfAny("↑")
      $strokaEND=[int]$strokaEND
      
      $EOF_table=$body.LastIndexOfAny("↓")
      $EOF_table=[int]$EOF_table + 1
    
      $body=$body.Remove($EOF_table)
      ##цикл получения и обработки строк
      while ($EOF_table -ne $strokaEND)
      {
      echo ""
      echo ""
      echo "Считана строка"
      echo ""
       $body=$body.Remove(0,($strokaEND + 1)) # удаление обработанной строки
       $EOF_table=$body.LastIndexOfAny("↓") # пересчет конца таблицы, после удаления начала таблицы
       $strokaEND=$body.IndexOfAny("↓") # поиск конца строки
       $global:uchetka=$body.Substring(1,($strokaEND - 1)) # получение строки с данными по пользователю
    
    ################Замена символов на другие для удобства написания в коде в дальнейшем (функция "telephone" объявлена выше)
       $global:uchetka=$global:uchetka.Replace("
    ","N") #Возврат каретки 013
       $global:uchetka=$global:uchetka.Replace("
    ","V") #Перевод строки 010
    
      $global:uchetka=$global:uchetka.Replace(" ","P") #пробел 
      $global:uchetka=$global:uchetka.Replace("	","T") #таб
      
     ###########Перенос данных в AD
    $tabel = telephone
    $MainPhone = telephone
    $AdditPhone = telephone
    $CellPhone = telephone 
    
    if (($MainPhone) -or ($AdditPhone) -or ($CellPhone))
    {
       if (!($tabel)) ####Если табельный не указан, значит подразумевается, что информация обновляется для отправителя
    		{        		
                $tabel=Get-ADObject -Filter {Name -eq $Sender} -Properties * | Select -exp employeeID
    		}
       
    
    if ($tabel) ##если значение $tabel пустое, будет ошибка(обработка исключения)
    {
    $tabel = checktab -tabch $tabel
    $tabelSearch=Get-ADObject -filter {employeeID -eq $tabel}
    if (!($tabelSearch))
    	{
    	$er="Учетной записи с табельным "+" "+$tabel+" "+" не существует."	
        sendlog -tab $t -p $path -error $er
    	}
    if ($tabelSearch)
    {
    	if ($tabel -eq '0000') 
    	{
    	$er="Табельный 0!"
        sendlog -tab $t -p $path -error $er
    	}
    	if ($tabel -ne 0) 
    	{   
        #$SAM_tabel=Get-ADObject -Filter {employeeID -eq $tabel} -Properties * | select SamAccountName
        $Sender_tabel=Get-ADObject -Filter {name -eq $Sender} -Properties * | select -exp employeeID
        $Sender_tabel = checktab -tabch $Sender_tabel
        
        if ($tabel -ne $Sender_tabel)### сравниваем табельные отправителя и указанный в текущей строке 
        {
            $SAM_tabel=Get-ADObject -Filter {employeeID -eq $tabel} -Properties * | select SamAccountName
            if ($SAM_tabel.SamAccountName)
                {
                $tabel_name=Get-ADObject -Filter {employeeID -eq $tabel} -Properties * | select -exp name
                 $er="Вы не можете обновить информацию для сотрудника (" + $tabel_name + ") - у вас нет прав!"
                     sendlog2 -SenderName $Sender -error2 $er  
                     continue
                }
        } ##EOF if ($SAM_tabel -ne $SAM_Sender)
        
            $DistName=""## Командлеты *ADObject работают только с DistinguishedName
            $DistName=Get-ADObject -filter {employeeID -eq $tabel} -Properties * | select -exp DistinguishedName
            
            ###Флаги, сигнализирующие, что информация обновлена
            $flagMP=""
            $flagAP=""
            $flagCP=""
            ###Флаги, сигнализирующие, что информация обновлена
           
               ###если значение пустое, то ошибка                
    	if ($MainPhone){                  
            Set-ADObject $DistName -Replace @{title=[int64]$MainPhone}
    		Set-ADObject $DistName -Replace @{telephoneNumber=[int64]$MainPhone}
            $flagMP="Основной телефон"
            }
        if ($AdditPhone){
            Set-ADObject $DistName -Replace @{otherTelephone=[int64]$AdditPhone} 
            $flagAP="Дополнительный телефон"
            }
        if ($CellPhone){
            Set-ADObject $DistName -Replace @{Mobile=[int64]$CellPhone} 
            $flagCP="Мобильный"
            }
            if (($flagMP) -or ($flagAP) -or ($flagCP))
            {sendmail -SenderName2 $Sender -fltab $tabel -flMP $flagMP -flAP $flagAP -flCP $flagCP}
            
           
        } ##EOF if ($tabel -ne 0) 
    }###EOF if ($tabelSearch)
    }###EOF if ($tabel)
    
    }####EOF if (($MainPhone) -or ($AdditPhone) -or ($CellPhone))
    
      }#######EOF While ($EOF_table -ne $strokaEND)
        
            $_.Move($namespace.Folders.Item("netad@gmavtovaz.ru").Folders.Item("ProcessedPhones")) ##перенос обработанного письма в папку для обработанных писем
            }
    }
    
    
    }###EOF try
    catch {
    $t="Табельный "+$tabel
    $er=""
    sendlog -tab $t -p $path -err $er
    }


    30 сентября 2016 г. 11:03

Ответы

  • Данный скрипт использует подключение в Outlook, которое настроено на ПК, где он выполняется.

    Попробуйте запустить Outlook чтобы убедиться, что все работает корреткно. 

    Далее выполните последовательно из PowerShell на сервере, где есть проблема:

    Add-type -assembly "Microsoft.Office.Interop.Outlook" | out-null $olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type] $outlook = new-object -comobject outlook.application $namespace = $outlook.GetNameSpace("MAPI") $folder = $namespace.getDefaultFolder($olFolders::olFolderInBox)

    $folder | SELECT FolderPath ($folder.Idems).Count

    Последние две строки покажут, корректно ли получены данные из Outlook.


    • Изменено Artem RomanchikMVP 3 октября 2016 г. 13:30
    • Помечено в качестве ответа Sergey Dubynin 4 октября 2016 г. 5:21
    3 октября 2016 г. 13:29

Все ответы

  • А где именно выпадает ошибка?

    sendlog - это какое-то ПО, верно?

    30 сентября 2016 г. 11:23
  • Sendlog - это функция, я не стал весь код копировать.

    Проблема возникает на строке

     $folder.items | % {

    . Ошибки никакой нет, просто скрипт прекращает свою работу. На другой машине (Win7 PS 2.0) тот же скрипт работает.

    Я бы приложил скриншоты, на них видно на каком шаге, но моя учетная запись пока "не проверена", и я не могу их приложить.

    Надеюсь в понедельник смогу приложить скриншоты и ссылку на видео.


    30 сентября 2016 г. 12:50
  • А что если ради эксперимента заменить % на foreach?
    30 сентября 2016 г. 13:05
  • Еще предлагаю для дебага вывести содержимое $folder.items
    30 сентября 2016 г. 13:07
  • А что если ради эксперимента заменить % на foreach?

    Не помогло - также подсвечивается не строка, а переменные - сначала $folder.items, а потом  $folderitem :

     #$folder.items | % {
     foreach ($folderitem in $folder.items) {

    Содержимое вывести не могу - скриншот пока я так и не могу приложить.

    Если не боитесь, то скриншоты есть здесь :
    https :// drive.google.com/open?id=0BxhToKb6vyY6NFI1TTJ2UkRpaXc


    3 октября 2016 г. 12:38
  • Данный скрипт использует подключение в Outlook, которое настроено на ПК, где он выполняется.

    Попробуйте запустить Outlook чтобы убедиться, что все работает корреткно. 

    Далее выполните последовательно из PowerShell на сервере, где есть проблема:

    Add-type -assembly "Microsoft.Office.Interop.Outlook" | out-null $olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type] $outlook = new-object -comobject outlook.application $namespace = $outlook.GetNameSpace("MAPI") $folder = $namespace.getDefaultFolder($olFolders::olFolderInBox)

    $folder | SELECT FolderPath ($folder.Idems).Count

    Последние две строки покажут, корректно ли получены данные из Outlook.


    • Изменено Artem RomanchikMVP 3 октября 2016 г. 13:30
    • Помечено в качестве ответа Sergey Dubynin 4 октября 2016 г. 5:21
    3 октября 2016 г. 13:29
  • Данный скрипт использует подключение в Outlook, которое настроено на ПК, где он выполняется.

    Попробуйте запустить Outlook чтобы убедиться, что все работает корреткно. 

    Далее выполните последовательно из PowerShell на сервере, где есть проблема:

    Add-type -assembly "Microsoft.Office.Interop.Outlook" | out-null $olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type] $outlook = new-object -comobject outlook.application $namespace = $outlook.GetNameSpace("MAPI") $folder = $namespace.getDefaultFolder($olFolders::olFolderInBox)

    $folder | SELECT FolderPath ($folder.Idems).Count

    Последние две строки покажут, корректно ли получены данные из Outlook.


    Результат $folder | SELECT FolderPath - верный, выводится путь \\ящик\Inbox

    Результат ($folder.Idems).Count "0".

    И это нормально...

    <quote>Скрипт использует подключение в Outlook, которое настроено на ПК, где он выполняется.</quote>

    Совершенно верно.

    В общем заработало. Я так понимаю помог запуск Outlook клиента. Поясню:
    Скрипт разрабатывался как фоновая задача, естественно запуск outlook вручную не предусматривался. Скрипт обращается к данным Outlook, и при этом он не поднимает клиента.

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

    На моей машине работало, потому что я постоянно перезапускаю Outlook (когда выключаю комп). Хотя перезапуск сервера я уже делал ранее, и это помогло ровно на одно выполнение скрипта. Далее он так же не работал.

    Спасибо большое за помощь!

    4 октября 2016 г. 5:20