locked
Is there any static variable in powershell? RRS feed

  • General discussion

  • hi,

    I have a script, I need to have a variable say $a which is initialised as $a= "" first time I run the scriptb Then later in the code it is assigned a value after some manipulation. Now I want that the previous value should be retained when I run the script next time and not initialized with "". In other programming languages we have static to that. What can be the solution here.

    Thanks

    Wednesday, August 24, 2011 6:38 AM

All replies

  • Create a script with this line:

    New-Variable -Name a -Value 1 -Scope "Global"
    

    Open a Powershell and run the script.

    Then, at the prompt, type

    $a

    You will see that the variable $a has retained its value after the script is finished, because you declared it as a Global variable.


    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"
    Wednesday, August 24, 2011 8:01 AM
  • It's impossible to tell from the information given, but depending on how the code is written this may or may not be a scope issue.  If all invocations of the script are being done in the same scope, then using a global scope won't help. 

    New-Variable -Name a -Value 1 -Scope "Global" -option ReadOnly
    

    will create the variable in the global scope, and prevent any subsequent invocation of the script from re-initializing it.


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "
    Wednesday, August 24, 2011 10:29 AM
  • Hi mj, this subject is new to me (scopes in Powershell), but I've been playing around a bit, and this is what I found:  I have two scripts, for demo purposes, one called newvar.ps1, and one called checkvar.ps1:

     

    # NewVar.ps1
    Remove-Variable -Name a -Force -ea silentlycontinue
    Remove-Variable -Name b -Force -ea silentlycontinue
    New-Variable -Name a -Value 1 -Scope "Global"
    New-Variable -Name b -Value 2 -Scope "Local" 
    "A new global variable was created called `$a, with the value of $a"
    "A new local variable was created, called `$b, with the value of $b"
    

    # CheckVar.ps1
    "The global variable `$a is found to be $a"
    "The local variable `$b is found to be $b"
    

    Now this seems to demonstrates to me quite neatly how global variables can be used between scripts, not necessarily read-only.  But I'm sure it's not a simple as that, is it?

     


    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"
    Wednesday, August 24, 2011 11:29 AM
  • It is indeed as simple as that, with the caveat that using global variables has a high potential for unintended consequences if you inadvertently use the same global variable name for different purposes, in different scripts and manage to run those scripts at the same time. 

    Using global variables is generally considered bad practice, and to be avoided if possible.


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "
    Wednesday, August 24, 2011 12:59 PM
  • Yes, I think the OP want's to tack together some scripts, but maybe is overwhelmed by the idea of consolidating them into a logical program.
    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"
    Wednesday, August 24, 2011 1:03 PM
  • Tanyatcs_Blue, is this still part of the 'apples' file and 'apples' control file comparing program we were dicussing last week?
    [string](0..9|%{[char][int](32+("39826578840055658268").substring(($_*2),2))})-replace "\s{1}\b"
    Wednesday, August 24, 2011 1:09 PM
  • mj, will this help me to retain the previous value of the variable without re-initializing it if i run my script after first invocation.
    Wednesday, August 24, 2011 2:52 PM
  • If the value was set using the -option ReadOnly, then the attempt to reinitialize it in subsequent scripts will fail, unless it was initialized using the -force option.  Since you aren't using that in your script it will help you retain that value once it has been set.

    The variable will not persist in the system if you log off, or if the system is restarted, and will need to be re-initialized.


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "
    Wednesday, August 24, 2011 3:14 PM
  • Well I brought this up in another thread, but just for completeness I will express my opinion that monkeying around with scope and global variables is the wrong way to solve this. What I think the OP wants is data persistence between script executions. To get that I think the best solution is to serialize the data that you want to persist and save it at the end of each run then reload it at the start of the next run. I have suggested in the other thread that Export-CLIXML and Import-CLIXML is the best way to go about this.
    Wednesday, August 24, 2011 3:14 PM
  • Agreed.  I've started off by warning that using global variables is bad practice.
    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "
    Wednesday, August 24, 2011 3:21 PM
  • There are also operating system environment variables that can be used
    to store persisting information.
     
    [Environment]::SetEnvironmentVariable("myVar", "valueofmyVar", "User")
    [Environment]::GetEnvironmentVariable("myVar", "User")
     
     
    More information about these environment variables at
     
    Wednesday, August 24, 2011 4:00 PM
  • Persistence between script executions is best handled through the use of files but I suspect that is not what you're really after. Also, 2011 is long gone but somebody may have the same question so...

    As for "static" variables, the use of the global scope has risks and is considered bad practice accordingly (read as don't do it). Using the script scope and encapsulating the code into a module also suffer the same risk, each to an increasing lesser extent. A solution which I'm using is to declare the variable with the AllScope option such as below which then results in the variable being copied into each child scope:

    Function Recurse ([Int]$MaxDepth) {

      Get-Variable -Name CrntDepth -ErrorAction SilentlyContinue | Out-Null

      If (!$?) { New-Variable -Name CrntDepth -Value 1 -Option AllScope } else { ++CrntDepth }

      If ($CrntDepth -lt $MaxDepth) { Recurse $MaxDepth }

      Write-Host "Current depth = $CrntDepth"

      $CrntDepth--

    }

    Recurse 5

    Thursday, September 4, 2014 3:35 AM