none
Функция:глобальные параметры RRS feed

  • Вопрос

  • Есть вопрос по поводу глобального параметра функции - зачем он нужен. Сначала думал, что объявив функцию глобальной можно использовать все переменные в её теле, но ничего не получилось, пришлось объявлять сами переменные глобальными. Объясните пожалуйста где и зачем нужно использовать глобальные функции.

    Спасибо

    11 июня 2011 г. 8:56

Ответы

  • Для доступа к переменным внутри функции их надо объявлять глобальным ($global:variable,$script:variable),либо использовать dot-sourcing.

    1) про dot-sourcing можно прочитать:

    http://rkeithhill.wordpress.com/2007/06/16/quick-test-for-powershell-dot-source-library-scripts/

    http://technet.microsoft.com/en-us/library/ee176949.aspx#ECAA

    http://poshoholic.com/2008/03/18/powershell-deep-dive-using-myinvocation-and-invoke-expression-to-support-dot-sourcing-and-direct-invocation-in-shared-powershell-scripts/

    2)Использование global.

    Один из примеров представлен в справке get-help about_Functions

     

    Область функции
      Функция существует в пределах области, в которой она была создана. 
    
      Если функция является частью скрипта, эта функция доступна в 
      инструкциях в этом скрипте. По умолчанию функции в скрипте не 
      доступны в командной строке. 
    
      Область функции можно задать. Например, в следующем примере функция 
      добавляется в глобальную область: 
    
     
       function global:get-dependentsvs { get-service |
        where {$_.dependentservices} }
    
    
      Если функция принадлежит к глобальной области, ее можно 
      использовать в скриптах, в функциях и в командной строке.
    
      Обычно функции образуют собственную область. Элементы, 
      создаваемые внутри функции, например переменные, существуют 
      только в пределах области этой функции.
    
      Дополнительные сведения об областях в Windows PowerShell см в 
      разделе about_Scope.
    
    

     


    Еще как пример вызывать объявленные функции из другого скрипта,если он слишком большой,то для простоты все их вынести.

     

    Скрипт 1
    
    function global:get-dependentsvs { get-service |
        where {$_.dependentservices} }
    
    Скрипт 2
    
    "Hello, i'm script 2 and run function from script 1"
    С:\service.ps1
    get-dependentsvs
    
    
    Вывод:
    
    Hello, i'm script 2 and run function from script 1
    
    Status Name    DisplayName
    ------ ----    -----------
    Running AudioEndpointBu... Windows Audio Endpoint Builder
    Running BFE    Base Filtering Engine
    Running CryptSvc   Cryptographic Services
    Running Dhcp    DHCP Client
    Stopped EapHost   Extensible Authentication Protocol
    Running eventlog   Windows Event Log
    Running EventSystem  COM+ Event System


     


    • Помечено в качестве ответа Tualantin 11 июня 2011 г. 10:18
    • Снята пометка об ответе Tualantin 13 июня 2011 г. 9:40
    • Помечено в качестве ответа Tualantin 13 июня 2011 г. 12:56
    11 июня 2011 г. 9:35
    Отвечающий
  • Если пишет в stderr, то почему от туда и не взять?

    $ver_sig = pgp --verify $a 2>&1

    • Помечено в качестве ответа KazunEditor 13 июня 2011 г. 14:33
    13 июня 2011 г. 11:47

Все ответы

  • Для доступа к переменным внутри функции их надо объявлять глобальным ($global:variable,$script:variable),либо использовать dot-sourcing.

    1) про dot-sourcing можно прочитать:

    http://rkeithhill.wordpress.com/2007/06/16/quick-test-for-powershell-dot-source-library-scripts/

    http://technet.microsoft.com/en-us/library/ee176949.aspx#ECAA

    http://poshoholic.com/2008/03/18/powershell-deep-dive-using-myinvocation-and-invoke-expression-to-support-dot-sourcing-and-direct-invocation-in-shared-powershell-scripts/

    2)Использование global.

    Один из примеров представлен в справке get-help about_Functions

     

    Область функции
      Функция существует в пределах области, в которой она была создана. 
    
      Если функция является частью скрипта, эта функция доступна в 
      инструкциях в этом скрипте. По умолчанию функции в скрипте не 
      доступны в командной строке. 
    
      Область функции можно задать. Например, в следующем примере функция 
      добавляется в глобальную область: 
    
     
       function global:get-dependentsvs { get-service |
        where {$_.dependentservices} }
    
    
      Если функция принадлежит к глобальной области, ее можно 
      использовать в скриптах, в функциях и в командной строке.
    
      Обычно функции образуют собственную область. Элементы, 
      создаваемые внутри функции, например переменные, существуют 
      только в пределах области этой функции.
    
      Дополнительные сведения об областях в Windows PowerShell см в 
      разделе about_Scope.
    
    

     


    Еще как пример вызывать объявленные функции из другого скрипта,если он слишком большой,то для простоты все их вынести.

     

    Скрипт 1
    
    function global:get-dependentsvs { get-service |
        where {$_.dependentservices} }
    
    Скрипт 2
    
    "Hello, i'm script 2 and run function from script 1"
    С:\service.ps1
    get-dependentsvs
    
    
    Вывод:
    
    Hello, i'm script 2 and run function from script 1
    
    Status Name    DisplayName
    ------ ----    -----------
    Running AudioEndpointBu... Windows Audio Endpoint Builder
    Running BFE    Base Filtering Engine
    Running CryptSvc   Cryptographic Services
    Running Dhcp    DHCP Client
    Stopped EapHost   Extensible Authentication Protocol
    Running eventlog   Windows Event Log
    Running EventSystem  COM+ Event System


     


    • Помечено в качестве ответа Tualantin 11 июня 2011 г. 10:18
    • Снята пометка об ответе Tualantin 13 июня 2011 г. 9:40
    • Помечено в качестве ответа Tualantin 13 июня 2011 г. 12:56
    11 июня 2011 г. 9:35
    Отвечающий
  • Все понятно, кроме того почему данная функция корректно работает при запуске через script editor, но через консоль выдаёт неправильный результат

    #Функции

    function sigver($a,$b,$c){

    pgp --verify $a ; [string]$sig = $error["$c"].exception ; $ver_sig = $sig -join "" ;

    if ( $ver_sig -match "$b" -and $ver_sig -match "good signature" ) {

    $global:ver_res="ok"} else { $global:ver_res="bad" }}

     

    Помогите разобраться.

    13 июня 2011 г. 9:42
  • Все понятно, кроме того почему данная функция корректно работает при запуске через script editor, но через консоль выдаёт неправильный результат

    #Функции

    function sigver($a,$b,$c){

    pgp --verify $a ; [string]$sig = $error["$c"].exception ; $ver_sig = $sig -join "" ;

    if ( $ver_sig -match "$b" -and $ver_sig -match "good signature" ) {

    $global:ver_res="ok"} else { $global:ver_res="bad" }}

     

    Помогите разобраться.

    Во-первых вы даже не удосужились привести,что именно не так и какие возникают проблемы.С чего такая уверенность,что $error["$c"].exception -вообще будет существовать или в ней содержится требуемая ошибка?
    13 июня 2011 г. 9:47
    Отвечающий
  • Ну я же сказал что когда запускаю функцию в скрипт editor-е всё прекрасно работает, все переменные досупны вне функции и т.д. Согласен, что данная переменная может и не существовать и судя по всему не существует, но почему в editor она есть а в консоли её нет. Да и как мне по другому вытащить ошибку из стороннего cmd-лета?!

    13 июня 2011 г. 10:04
  • Ну я же сказал что когда запускаю функцию в скрипт editor-е всё прекрасно работает, все переменные досупны вне функции и т.д. Согласен, что данная переменная может и не существовать и судя по всему не существует, но почему в editor она есть а в консоли её нет. Да и как мне по другому вытащить ошибку из стороннего cmd-лета?!

    $error существует всегда,по умолчанию не содержит объектов.О каком командлете идет речь,когда его здесь нет. Pgp я думаю пишет в стандартный поток ошибок и что вы собираетесь вытащить из $error ,я не понимаю.

    Вывод покажите $error в script editor,который можно перенаправить в файл и  вывод $error в консоле.


    13 июня 2011 г. 10:22
    Отвечающий
  • Я под командлетом подразумеваю как раз pgp. Из $error я и пытаюсь вытащить ошибки выдаваемые pgp.

    вывод в scripteditor

     

     

    info.sig:verify (0:verify complete)

    info.sig:verify (3038:signing key 0xxxxx xxx2011 <xxxx@xxx.com>)

    info.sig:verify (3040:signature created 2011-06-10T15:42:56+05:00)

    info.sig:verify (3170:signature hash SHA-256)

    info.sig:verify (3035:good signature)

    info.sig:verify (3177:message signed by key ID xxxx)

    info:verify (1082:detached signature target file)

    a00xxx07.104.sig:verify (3038:signing key 0xxxxxx xxx2011 <xxxx@xxx.com>)

    a00xxx07.104.sig:verify (3040:signature created 2011-06-10T15:42:56+05:00)

    a00xxx07.104.sig:verify (3170:signature hash SHA-256)

    a00xxx07.104.sig:verify (3035:good signature)

    a00xxx07.104.sig:verify (0:verify complete)

     

     

    а в консоли $error пустой.

    13 июня 2011 г. 10:44
  • function sigver($a,$b,$c){
    	$ver_sig = pgp --verify $a
    	if ( $ver_sig -match "$b" -and $ver_sig -match "good signature" ) {
    	$global:ver_res="ok"} else { $global:ver_res="bad" }
    }
    
    Укажите полный путь к pgp(C:\pgp.exe) и есть ли проблемы с запуском в консоли,просто pgp --verify $a,если нет,то посмотреть содержимое $ver_sig = pgp --verify $a.
    13 июня 2011 г. 10:51
    Отвечающий
  •  такой вариант не прокатит ($ver_sig = pgp --verify $a). Переменная просто выполнит команду и останется нулевой. pgp пишет только в поток ошибок. В консоли pgp запускается нормально т.е. 100% работает. проблему вижу именно в переменной $error т.к.  перенаправил внутри функции переменную $error в файл и как результат через консоль файл пустой а через едитор он забит ошибками.

    13 июня 2011 г. 11:19
  • Если пишет в stderr, то почему от туда и не взять?

    $ver_sig = pgp --verify $a 2>&1

    • Помечено в качестве ответа KazunEditor 13 июня 2011 г. 14:33
    13 июня 2011 г. 11:47
  • Или используя класс Proccess:

     

    $info = New-Object System.Diagnostics.ProcessStartInfo -Property @{
    			"FileName" = "pgp"
    			"Arguments" = "--verbose $a"
    			"UseShellExecute" = $false
    			"RedirectStandardError" = $true
    			}
    
    $pr = New-Object System.Diagnostics.Process
    $pr.StartInfo = $info
    [void]$pr.Start()
    $sig_verif = $pr.StandardError.ReadToEnd()


     


    13 июня 2011 г. 12:00
    Отвечающий
  • Это слишком увеличивает объем скрипта. Тема мало что говорить о сути проблемы поэтому попробую открыть новую.
    13 июня 2011 г. 12:56