getfolderpath & Program Data - powershell

I have been successfully using [environment]::getfolderpath("ProgramFiles") to get the path to program Files, but now I have a need to also access Program Data, and it looks from this enumeration like ProgramData is not available with this method. Is that true, or am I missing something here?

$env: to access environmental variables
$env:ProgramData

The quickest way is to use $env:ProgramData as BenH already pointed out in your question comments.
Using the .net Specialfolder, you would have needed to use the CommonApplicationData
Instead of using a string though such as your initial example:
[Environment]::GetFolderPath('CommonApplicationData')
I'd suggest using the enumeration as you will get the possible enumeration values directly into the intellisense while developping.
[Environment]::GetFolderPath([System.Environment+SpecialFolder]::CommonApplicationData)
Finally, because you knew the path you were looking for but not the corresponding variable, you could have listed them all neatly using something like:
$SpecialFolders = New-Object -TypeName psobject
[Environment+SpecialFolder]::GetNames([Environment+SpecialFolder]) | sort |
foreach {Add-Member -InputObject $SpecialFolders -Type NoteProperty -Name
($_) -Value ([Environment]::GetFolderPath($_)) }
$SpecialFolders | fl
Using that snippet, you could have determined that c:\programdata was a special folder path belonging to CommonApplicationData.
The enumeration can still be handy if a specified folder is not in the $env scope (example: My documents special folder).

Related

See metadata variable names on files (Windows 10)

I am having a hard time defining this issue, but basically what I would like to know is "what are the symbolic variable names connected to files' metadata (preferably on a Windows installation)".
For example, taking a .mp3 file, checking its properties yields a Title, Bit Rate, Folder Path etc. descriptions. What I want to know is the name of the fields seen by programs (i.e. Title->title, Bit Rate->bit_rate etc.) if it makes any sense, as I've been trying to index some files and I'd like to gather as much info on them as possible.
I'm not convinced that there is such a thing as "symbolic names" for the metadata, especially not in relation to PowerShell. I suspect that Windows maintains support for a certain number of popular formats, and offers functionality through Explorer to view and sometimes edit them. I haven't found a source to prove this theory, but research implicitly supports it: there's several dozen search results about how to retrieve a file's metadata in PowerShell, and they all seem to suggest roughly the same approach (for example this blog post): using a Shell object to gather the information.
Since you tagged this PowerShell, here's my take on boiling it down to the essentials:
$path = 'C:\temp\file.txt' # pick a path
$parent = Split-Path -Parent $path # get the directory
$shell = New-Object -ComObject Shell.Application # get ourselves a shell
$folder = $shell.NameSpace($parent) # get a "folder namespace"
$file = $Folder.Items() | where { $_.Path -eq $path } # get the file itself from the folder
$count = 0 # zero our iterator
$object = New-Object PSObject # make a fresh object to hold our output
While ($folder.GetDetailsOf($folder.Items, $count) -ne "") { # iterate over the available metadata tags for the folder, and for each one get the value from the file
$object | Add-Member -Force NoteProperty ($folder.GetDetailsOf($folder.Items, $count)) ($folder.GetDetailsOf($file, $count))
$count += 1
}
Write-Output $object
Note that the attributes available for a given file are obviously not all of the attributes that could possibly be supported for any file, and additionally are not necessarily "symbolic names". I suspect that the process of querying the shell object causes it to examine the files in a folder and extract metadata that Windows recognizes--it might even do this based on the view type selected for the folder (Photos, Music, Documents, etc.).
As for writing the information, this might be possible through the same shell object, but I haven't explored that option. It's likely dependent on the specific format: for mp3 you probably want a library for viewing/editing mp3-specific metadata.

Use a variable returned by Get-Variable

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
}

How to enumerate all locally declared script variables?

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

PowerShell Set-ItemProperty vs. dot to set a property

I'm trying to set a property of for example an ApplicationPool with PowerShell (version 2).
(I've a Windows 7 64 bit machine if that matters)
I see that this example uses Set-ItemProperty and this example uses a dot . to set a property of an object / element:
$pool | Set-ItemProperty -Name "managedRuntimeVersion" -Value "v4.0"
versus:
$pool.managedRuntimeVersion = "v4.0"
So what's the difference? I think that the second one is much more readable, but I don't know what the implications are.
EDIT:
I noticed that (at least in this case) there is a difference, the Set-ItemProperty does save the value of the property directly, while the other method does set the value (while debugging) but does not save it afterwards. I've not found out yet why this happens. (Do you need to call something like save or commit?) See #moonstom's answer, for Powershell 2.0 Set-ItemProperty is the only way or $pool | Set-Item for Powershell 3+ (see sample).
You're working on a representation of that app pool. If you check the type of that object, you'll get a configuration element. So after setting it up, you need to push your settings back with $pool | Set-Item, available in PS 3.0 and above. Otherwise your only alternative is Set-ItemProperty
There is no difference. In the first one you pass the object to the Set-ItemProperty commandlet via the pipe and the commandlet setting the object property.
The second one you're setting it directly on the object. But they are functionally the same. With the second one you could also retrieve the property's value like this:
$value = $pool.managedRuntimeVersion

Powershell - Get Data of Registry Value Saved to a Variable

I need to save a single data item in a registry key to a variable. I've tried the following without any luck:
$dxVersion = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\DirectX").GetValue("Version",$null)
I want JUST the version number saved to the variable, nothing else. Not the name, just the data.
Thanks in advance for your help!
You almost had it. Try:
$dxVersion = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\DirectX").Version
Get-ItemProperty returns a PSCustomObject with a number of properties -- Version among them. This sort of dotted notation as I used above allows you to quickly access the value of any property.
Alternatively, so long as you specify a scalar property, you could use the ExpandProperty parameter of Select-Object:
$dxVersion = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\DirectX") | Select-Object -ExpandProperty Version