Learn about Windows PowerShell
Summary: Microsoft Scripting Guy Ed Wilson shows the easy way to use Windows PowerShell to work with the paths to special folders.
Hey, Scripting Guy! I notice that in lots of your sample scripts, you often use a folder named FSO, and it appears off of your C: drive. Why do you do this? Is creating an FSO folder really a best practice?
Microsoft Scripting Guy, Ed Wilson, is here. Last week was an awesome week. The Scripting Wife and I went to two different User Group meetings, and I had several great conference calls. Yep, things were pretty exciting down here in Charlotte, North Carolina in the United States.
One of the cool things about Windows PowerShell 2.0 is that it is nearly 100 percent backward compatible with Windows PowerShell 1.0. This means that things you learned in the first version continue to be useful. In addition, this means that blogs written for earlier versions and scripts written for earlier versions continue to be useful. The one major consideration is that the older materials might not take advantage of newer capabilities. In some cases, this is a non-issue, but for other things, this could be a problem.
EV, the reason I use a folder named FSO goes back a long time ago—a really long time ago. The C:\FSO folder is my scratch folder. It is a folder where I put temporary information, but it is more than simply the TEMP folder because it is a temporary folder I use only for scripts. Therefore, the c:\fso folder is more like my temporary script folder. I put both scripts and output in that folder. The reason it is off the root directory is so that it is easily accessible, and so the path to the folder does not consume a lot of space. This is also the reason for the name FSO, which you can tell is short. I have used a folder named FSO as my scripting temp folder for years. In fact the name FSO itself is a shortcut name that stands for FileSystemObject, which is an object that was often used in VBScript script (but it can be used in other languages, such as in Windows PowerShell) to read and to write to files.
Now, if I did not use a C:\FSO folder to hold files that I use for temporary script input and output, what else could I use? Well, for one thing, I could use a folder that I know will always be available. Luckily, in Windows, there are lots of these types of folders. In fact, they are called special folders. One of the problems with using these special folders is that they have really long paths.
A couple of years ago, during the wrap up for the 2010 Scripting Games, I wrote a blog titled How Can I Query the Contents of a Special Folder on a Windows 7 Computer in which I talked about using the Shell.Application object to list the enumerations and the values of the special folders. It is an excellent blog and you should read it after you read today’s blog.
One easy way to work with special folders in Windows PowerShell is to use the System.Environment.SpecialFolder enumeration. In Windows PowerShell you can easily obtain the path to any special folder by using the GetFolderPath static method from the System.Environment .NET Framework class. This is easier to do than it sounds. Here is the code to obtain the path to the mydocuments special folder.
You can use this value directly. For example, to get a listing of all the files in the mydocuments special folder, use the code that is shown here.
If you decide you want to use the mydocuments folder for your scratch directory, you should consider adding it to your Windows PowerShell profile—both your Windows PowerShell console profile and your Windows PowerShell ISE profile. You should create a short variable name to reference this location. Here is an example of a command that you could add to your profile.
$mytemp = [environment]::getfolderpath("mydocuments")
You could then use it directly as shown here.
If this is something that you do decide to do, you should, perhaps, create a subfolder inside the mydocuments special folder, rather than cluttering up the folder with a bunch of scripts and temporary files. The following image shows my current mydocuments special folder. In this image, note that there are lots of folders, and lots of files (well, you cannot see all the files, but trust me, they are there).
There is a Windows PowerShell folder inside the mydocuments special folder. It contains a number of folders and a few profiles. This folder also holds modules. This would actually be a great place to add a new folder to hold scratch script stuff. The command that follows uses the $mytemp variable created earlier.
New-Item -ItemType directory -Path $mytemp\windowspowershell\ScriptScratch
Now, of course, there is a sort of a problem. I want the new ScriptScratch folder to be my temporary folder, and to be called $mytemp. Also a better name for the current mydocuments location might actually be to call it $mydocuments. Here are the two commands that I use to accomplish this task.
Rename-Item -Path variable:mytemp -NewName mydocuments
$mytemp = "$mydocuments\windowsPowerShell\ScriptScratch"
Now, I check the values of these two variables.
PS C:\> $mytemp
PS C:\> $mydocuments
Cool, it works. I can now add these two commands to my two Windows PowerShell profiles.
$mydocuments = [environment]::getfolderpath("mydocuments")
EV, if you work on multiple computers, and if you are not certain that the ScriptScratch folder exists, you might want to add a test to check for the existence of the folder. For that matter, the WindowsPowerShell folder does not exist in the mydocuments special folder unless specifically created. That is what my Copy-Modules script does. (The Copy-Modules script is shown in my Windows PowerShell ISE profile).
Well, that is all there is to working with scratch directories—at least for now. Join me tomorrow for Windows PowerShell cool stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at firstname.lastname@example.org, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
You forgot the best part. We can know what folders are available on a per OS basis using this:
This will list all special folders available on the current OS.
@JRV that is absolutely correct. Using the GetNames method from the system.enum class is a great way to find out what special folders are available. Thank you for pointing that out.
Sorry for the newb question, but I don't understand the + operator in the context [Environment+SpecialFolder]. I've tried [Environment]::SpecialFolders, but that doesn't seem to work. Can someone please explain to me what the + means in this context and why this works? Thanks!
I think you showed that it is no more complicated to get to special folders in PS than it has been (and is) in VB Script! That's pretty cool!
@jrv: you're perfectly right!
@TanMan: I can't really help you much with this, but this special construct is due to the underlying .Net framework, which is accessed by Reflection methods to get at the enum values of a nested class in this case!
In the blog entry
you'll find the essential statement:
To Get : A parent class and a nested class
Use : Type.GetType("MyParentClass+MyNestedClass")
This is a rare case, and you are not supposed to know that the underlying type is defined in a nested class. Of course, you just have to learn that that's the way you have to go ...
@Klaus, Thanks so much for the explanation and especially the link. I guess I wasn't searching on the right keywords. Down the rabbit hole for me!!!