11

I have the following code in Powershell

$filePath = "C:\my\programming\Powershell\output.test.txt"

try
{
    $wStream = new-object IO.FileStream $filePath, [System.IO.FileMode]::Append, [IO.FileAccess]::Write, [IO.FileShare]::Read

    $sWriter = New-Object  System.IO.StreamWriter $wStream

    $sWriter.writeLine("test")
 }

I keep getting error:

Cannot convert argument "1", with value: "[IO.FileMode]::Append", for "FileStream" to type "System.IO.FileMode": "Cannot convert value "[IO.FileMode]::Append" to type "System.IO.FileMode" due to invalid enumeration values. Specify one of the following enumeration values and try again. The possible enumeration values are "CreateNew, Create, Open, OpenOrCreate, Truncate, Append"."

I tried the equivalent in C#,

    FileStream fStream = null;
    StreamWriter stWriter = null;

    try
    {
        fStream = new FileStream(@"C:\my\programming\Powershell\output.txt", FileMode.Append, FileAccess.Write, FileShare.Read);
        stWriter = new StreamWriter(fStream);
        stWriter.WriteLine("hahha");
    }

it works fine!

What's wrong with my powershell script? BTW I am running on powershell

Major  Minor  Build  Revision
-----  -----  -----  --------
3      2      0      2237
user1866880
  • 1,437
  • 6
  • 18
  • 26

4 Answers4

23

Another way would be to use just the name of the value and let PowerShell cast it to the target type:

New-Object IO.FileStream $filePath ,'Append','Write','Read'
Shay Levy
  • 121,444
  • 32
  • 184
  • 206
9

When using the New-Object cmdlet and the target type constructor takes in parameters, you should either use the -ArgumentList parameter (of New-Object) or wrap the parameters in parenthesis - I prefer to wrap my constructors with parens:

# setup some convenience variables to keep each line shorter
$path = [System.IO.Path]::Combine($Env:TEMP,"Temp.txt")
$mode = [System.IO.FileMode]::Append
$access = [System.IO.FileAccess]::Write
$sharing = [IO.FileShare]::Read

# create the FileStream and StreamWriter objects
$fs = New-Object IO.FileStream($path, $mode, $access, $sharing)
$sw = New-Object System.IO.StreamWriter($fs)

# write something and remember to call to Dispose to clean up the resources
$sw.WriteLine("Hello, PowerShell!")
$sw.Dispose()
$fs.Dispose()

New-Object cmdlet online help: http://go.microsoft.com/fwlink/?LinkID=113355

Goyuix
  • 23,614
  • 14
  • 84
  • 128
  • You can equally well leave out the parens, because it just expects an object array, optionally preceded by `-ArgumentList`. Your parens just make it a separate expression; is that correct? – mousio Jan 13 '13 at 09:36
  • 7
    Parens around an array in PowerShell is effectively a no-op except to act as a token separator. I avoid this syntax `new-object (arg,arg,...)` because it misleads you into believing this is just a C# constructor when it really isn't. It's actually less typing to use `new-object arg,arg,...`. Sorry for being pedantic but I've answered too many questions about why `MyPowerShellFunctionThatTakesThreeParameters(1,2,3)` doesn't work. :-) – Keith Hill Jan 13 '13 at 21:25
  • 1
    The powershell decision makers are starting to get on my nerves. One day you're not supposed to use parerenthesis. The next day you are. I see you're using commas for constructors too now. They made this more difficult than it needed to be. – Brain2000 Dec 02 '18 at 21:20
5

Yet another way could be to enclose the enums in parens:

$wStream = new-object IO.FileStream $filePath, ([System.IO.FileMode]::Append), `
    ([IO.FileAccess]::Write), ([IO.FileShare]::Read)
mousio
  • 10,079
  • 4
  • 34
  • 43
  • Your way would work if you use parentheses while constructing the FileStream: $wStream = new-object IO.FileStream $filePath([System.IO.FileMode]::Append, [IO.FileAccess]::Write, [IO.FileShare]::Read) – Eyad Aldwaik Apr 12 '19 at 03:45
0

If your goal is to write into a logfile or text file, then you could try the supported cmdlets in PowerShell to achieve this?

Get-Help Out-File -Detailed
HungryHippos
  • 1,473
  • 5
  • 16
  • 24