Hopefully this answer isn't above me. I've created a custom object with properties and methods. I create several of them on the fly, depending on what the user selects at the beginning.
So for this example, the script might create $PRD1, $PRD2, $TST1 and $TST4.
$PRD1, $PRD2, $TST1 and $TST4 will have some properties like DebugMode, DisableAppsStartTime, DisableAppsStopTime. They'll have some methods like DisableApps(), EnableApps().
How can I find out which variables the script ended up creating? I can use Get-Variable to know the ones it created (plus I DO still have the initial list of names to create). My issue is that I'm having trouble figuring out to call the ones I've created, in a manner that allows me to use the methods and properties, without a ridiculous mash up of nested foreach/if/switch commands.
I certainly hope that made sense.
Thanks in advance,
SS
I DO still have the initial list of names to create
Assuming that $list contains this list, the following creates an (ordered) hash table of those variables that were actually created from that list:
$variableMap = [ordered] #{}
(Get-Variable -ErrorAction Ignore -Scope Local $list).
ForEach({ $variableMap[$_.Name] = $_.Value })
Note: -Scope Local limits the lookup to the current scope[1]; omit it to target all variables visible in the current scope, which includes those from ancestral (parent) scopes.
You can then loop over $variableMap.Keys to process them all, or access one by name selectively, e.g., $variableMap.PRD1 (or $variableMap['PRD1']).
You then use regular dot notation to access properties and methods of these entries; e.g., $variableMap.PRD1.DisableApps().
[1] This includes variables created with the AllScope option, e.g., $HOME, because they are copied to every scope, as the name suggests. You can find all such variables with
Get-Variable | Where-Object Options -match 'AllScope'
I just did this with the where-object cmdlet and the -like operator with an foreach loop.
foreach($var in (get-variable | Where-object {$_.name -like '*PRD*' -or $_.name -like '*TST*'})){
$var
}
Related
$loadbalancer = Get-AzureRmLoadBalancer | select Name,ResourceGroupName
$loadbalancer has two value ILB name and its resource group.
I want call both value in single PS command, Like when I call ILB name its respective resource group should be called.
The problem isn't entirely clear, can you please give an example of the function being used in the next step. I used "get-command" for the examples rather than get-azurermloadbalancer to avoid being package dependent.
To get the propety from $loadbalancer you use a dot and the name.
To get the current row from pipeline you can use $_
$loadbalancer = Get-Command get-* | Select-Object -Property CommandType,Name
#get a particular property
$loadbalancer.CommandType
#Use both properties in one function
$loadbalancer | Where-Object{($_.CommandType -eq "function") -and ($_.Name -match "Token")}
The Exchange PowerShell commands for Mailbox Folder Statistics and Permissions are disjointed and require you to massage data to take statistics and make them usable as variables for removing folder permissions.
I'm trying to use the replace commands in PowerShell to manipulate the values without breaking the array itself.
I've tried various ways of using the -replace command to handle this as it has been unsuccessful.
I'm trying to use code similar to this:
Get-MailboxFolderStatistics -Identity jon#towles.com | Select Identity | ForEach-Object { $_."Identity" -replace '.com','.com:'}
When I use the replace function, it breaks the array so we no longer see headings and cannot use it with stuff like foreach-object {Remove-MailboxFolderPermissions -identity $_.identity -user testuser}
I expect that the replace function will still keep the data layout.
If you want to maintain your psobject structure, you need to avoid dereferencing properties or expanding properties. In your case, you can use a calculated property in your Select-Object command.
Get-MailboxFolderStatistics -Identity user#domain.com |
Select-Object #{Name='Identity';Expression={$_.Identity.Replace('.com','.com:')}}
Your current pipeline object $_ is a psobject with accessible properties. When you use the dereference operator ., you are retrieving a value for one of the properties. $_.Identity produces a different object. Since you do not incorporate that value back into a custom object, the only properties you have available are ones available to its object type, which does not include Identity.
With that said, you don't technically need to maintain your object schema to perform subsequent tasks. Even if you output a string with your first command, you can store that string in a variable and use it in another command. If your plan is to use a Foreach-Object to update all of your objects, you can update the pipelined object for future use within the loop.
Get-MailboxFolderStatistics -Identity user#domain.com | ForEach-Object {
$_.Identity = $_.Identity.Replace('.com','.com:')
Remove-MailboxFolderPermissions -Identity $_.Identity -User testuser
}
I have an example code snippet that suggests using
(Get-Process | Where-Object {$_.WorkingSet64 -gt 20mb}).Count
to return the count of all processess using > 20Mb.
It works, but when typing, neither Intellisense or the "Tab" key shows this property, rather they show the properties of an individual process - which I find misleading.
I understand, that specifying an item property will give me the list of that property only, but is there a way to easily see, in general, what ALL the valid propeties are, including list aggregates etc?
Even assigning to a variable
$processes = Get-Process | Where-Object {$_.WorkingSet64 -gt 20mb}
does not show me "Count" as a valid property of $processes until AFTER the assignment has been actually run and the value assigned - when writing the script it still shows the properties for an individual item.
For me, Intellisense / Tab help that does not cover all the options kind of defeats the purpose ... (not having to remember hundreds objects/functions and their properties / parameters).
Is there any way to improve this situation? Some syntax trick have I missed?
The correct way to find out all of the properties of an object is to pipe the output to Get-Member:
Get-Process | Get-Member
Sometimes there are hidden properties and methods that can only be seen if you add the -force switch:
Get-Process | Get-Member -Force
The count property is an automatic property that is always usable on any collection object but that isn't explicitly listed as a property. Another example of an automatic property is length.
Using #() to force an array type is handy when that is what is wanted.
e.g. $processes = #(Get-Process | Where-Object {$_.WorkingSet64 -gt 20mb}). will show you "Count" and the other array properties.
Other than that, let's say the Intellisense has various limitations / shortcomings that I will just have to learn... sigh.
Is there a way to get only the locally declared variables in a powershell script?
In this snippit, I would want it to return only myVar1, myVar2, anotherVar:
$myVar1 = "myVar1"
$myVar2 = "myVar2"
$anotherVar = "anotherVar"
Get-Variable -Scope Script
But it instead returns a ton of other local script variables.
The problem I'm trying to solve, and maybe you can suggest another way, is that I have many Powershell scripts that have a bunch of misc variable constants declared at the top.
I want to export them all to disk (xml) for import later.
So to call Get-Variable bla* | Export-Clixml vars.xml, I need to know all of the variable names.
So is there a way I can like do
$allVars = {
$myVar1 = "alex"
$myVar2 = "iscool"
$anotherVar = "thisisanotherVar"
}
Get-Variable allVars | Export-Clixml "C:\TEMP\AllVars.xml"
And then later Import-Clixml .\AllVars.xml | %{ Set-Variable $_.Name $_.Value } ?
So that the rest of the script could still use $myVar1 etc without major changes to what is already written?
The issue is there are more variables that are accessible in that scope beyond the ones you already declared. One thing you could do is get the list of variables before you declare yours. Get another copy of all the variables and compare the list to just get yours.
$before = Get-Variable -Scope Local
$r = "Stuff"
$after = Get-Variable -Scope Local
# Get the differences
Compare-Object -Reference $current -Difference $more -Property Name -PassThru
The above should spit out names and simple values for your variables. If need be you should be able to easily send that down the pipe to Export-CliXML. If your variables are complicated you might need to change the -depth for more complicated objects.
Caveat: If you are changing some default variable values the above code currently would omit them since it is just looking for new names.
Also not sure if you can import them exactly in the same means as they were exported. This is largely dependent on your data types. For simple variables this would be just fine
I need to know all of the variable names.
The only other way that I am aware of (I never really considered this) would be to change all of the variable to have a prefix like my_ so then you could just have one line for export.
Get-Variable my_* | Export-Clixml vars.xml
Basically I have this code:
$file = $web.GetFile("Pages/default.aspx")
$file.CheckOut()
and I was wondering if there is anyway to use a pipe and the powershell equivalent of this to rewrite it as:
$web.GetFile("Pages/default.aspx") | $this.CheckOut()
When I try this I get the error:
Expressions are only allowed as the first element of a pipeline.
I also tried using $_ instead of $this but got the same error.
Actually there is a $this in a few cases. You can create a ScriptProperty or ScriptMethod and attach it to an object, and $this will be the original object. You can then define these in types files (I'd recommend using the module EZOut, it makes life much easier) so that any time you see that type, you get that method.
For example:
$Web | Add-Member ScriptMethod EditFile { $this.Checkout() }
Hope this helps
What you're looking for is $_ and it represents the current object in the pipeline. However you can only access $_ in a scriptblock of a command that takes pipeline input e.g.:
$web.GetFile("Pages/default.aspx") | Foreach-Object -Process {$_.Checkout()}
However there are aliases for the Foreach-Object cmdlet {Foreach and %} and -Process is the default parameter so this can be simplified to:
$web.GetFile("Pages/default.aspx") | Foreach {$_.Checkout()}
One other point, the GetFile call appears to return a single file so in this case, the following would be the easiest way to go:
$web.GetFile("Pages/default.aspx").Checkout()
Of course, at this point you no longer have a variable containing the file object.
$_ is the variable for "current object" in powershell.
However, you aren't passing any data, this is just variable assignment. You can only use the pipeline if you manipulate the actual output of a command and use it as input down the pipeline.
I think what you want can be accomplish with nested parentheses:
($web.GetFile("Pages/default.aspx")).CheckOut()
In PS, anything you put inside parentheses gets treated as its own object, and you can apply methods to that inline without variable reassignment.
Assignment does silence the default output, but it does not prevent an object from being further referenced.
($file = $web.GetFile("Pages/default.aspx")).CheckOut()
Of course, it's much more common to either store the return value in a variable and do stuff with it or chain methods/properties/pipes.