Summary: Microsoft Scripting Guy Ed Wilson teaches how to avoid writing blank lines at the end of a file by using Windows PowerShell.
Hey, Scripting Guy! I have a problem with my script. For example, in my script, I build up a variable. Then when I write the variable to a file, I always end up with an extra blank line at the end of the text file. Though many times this is not an issue, it is, on occasion, extremely annoying. These are the times when I am creating a file that will be used to drive another script. For example, if I have a script that collects the names of computers that I need to connect to, and I then write those computer names to a text file so that I can use it with other scripts, I always end up with a blank line at the end of the file. This causes the subsequent scripts to always fail to connect to the blank line, and it therefore causes errors. So far, I have been dealing with this problem by doing a bit of error checking, but that is cumbersome, and it would be easier to avoid the problem all together. You are a wizard when it comes to this sort of stuff, so I know you will be able to solve the problem with something elegant. I remain your biggest fan,
—JN
Hello JN,
Microsoft Scripting Guy Ed Wilson here. Wow, you are my biggest fan! Really? I mean, like the president of the Official Scripting Guys Fan Club? Cool! (Note: One advantage of being a member of the Official Scripting Guys Fan Club is that you do not have to wear round mouselike ear hats. Of course, there is nothing inherently wrong with wearing round mouselike ear hats.)
JN, your problem is that you end up with an extra blank line at the bottom of your text file or at the end of your variable. This problem is shown in the following code?
$count = "count"
for ($i = 0; $i -le 4; $i++)
{
$count += "`r`n" + $i
}
$count > c:\fso\count.txt ; c:\fso\count.txt
When the preceding script runs, the text file contains an additional line at the end of the file. This is shown in the following figure.
One way to solve this problem is to use.NET Framework classes, instead of using redirection arrows or the Out-File cmdlet. To make the change to using the .NET Framework class, you need to make a minimal change to the previous code. The class that I need to use is found in the System.IO namespace, and it is the File class. Therefore, the complete file name is System.IO.File. This class contains a static method called WriteAllText. When writing code, it is permissible to leave off the system portion of the namespace name, because system is the root .NET Framework namespace, and it is assumed that IO would live under the System portion. When I write a script, I will generally use the complete namespace and class name; when working interactively in the Windows PowerShell console, I will generally use the shorter version of the name, and leave off the system portion of the name. The modified script that will not produce an extra blank line at the end of the file is shown here:
$count = "count"
for ($i = 0; $i -le 4; $i++)
{
$count += "`r`n" + $i
}
[system.io.file]::WriteAllText("C:\fso\io.txt", $count)
The text file created by the preceding code is shown in the following figure.
The System.IO.File .NET Framework class documentation is found on MSDN, but I did not need to consult it while writing the above code, not because I have everything memorized, but because I can easily use the Get-Member cmdlet to retrieve information about the WriteAllText static method. There are two ways to use the WriteAllText method. The first way is the way I used in my script: provide the path for the output file, and then provide the text. Here is the line in my script where I did just that:
[system.io.file]::WriteAllText("C:\fso\io.txt", $count)
The double colon indicates that I am calling a static method (one that is always available and does not require an instance of the class upon which to work). The first parameter is the path to the file I want to create. The c:\fso\io.txt path refers to a folder (c:\fso) on my local computer. The content from the script is stored in the $count variable, and this is the text that I write to the file.
The second way to use the WriteAllText static method from the file class in the System.IO namespace is to provide the path, the contents, and the encoding to the method call. The following figure shows the output from the Get-Member cmdlet.
To supply the encoding value to the WriteAllText static method, the third position needs an instance of the System.Text.Encoding enumeration value. The encoding enumerations are all contatined within the System.Text.Encoding class as static properties. It is easy to retrieve them by using the Get-Member cmdlet as shown here:
PS C:\Users\edwils> [system.text.encoding] | get-member -Static -MemberType property
TypeName: System.Text.Encoding
Name MemberType Definition
ASCII Property static System.Text.Encoding ASCII {get;}
BigEndianUnicode Property static System.Text.Encoding BigEndianUnicode {get;}
Default Property static System.Text.Encoding Default {get;}
Unicode Property static System.Text.Encoding Unicode {get;}
UTF32 Property static System.Text.Encoding UTF32 {get;}
UTF7 Property static System.Text.Encoding UTF7 {get;}
UTF8 Property static System.Text.Encoding UTF8 {get;}
Armed with this information, I can revise the script so that I output an ASCII-encoded file. This is shown here:
$count = "count"
for ($i = 0; $i -le 4; $i++)
{
$count += "`r`n" + $i
}
[system.io.file]::WriteAllText("C:\fso\ioascii.txt", $count,[text.encoding]::ascii)
By adding the third parameter, it is the last line that is modified.
Well, JN, that is all about there is to writing to a text file, and ensuring that the output file does not contain any additional spaces or blank lines at the end of the file. Join me tomorrow for more exciting Windows PowerShell goodness.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy