I can't seem to pass $outputStream as Stream to StreamWritter constructor. It gets passed as string and then it invokes wrong constructor that expects string not stream.
$tcpClient = New-Object System.Net.Sockets.TCPClient
$connect = $tcpClient.BeginConnect("localhost", 8080, $null, $null)
$success = $connect.AsyncWaitHandle.WaitOne($testTimeoutMs, $true)
[System.Net.Sockets.NetworkStream]$outputStream = $tcpClient.GetStream()
$writer = New-Object System.IO.StreamWriter -ArgumentList $outputStream, [System.Text.Encoding].ASCII
I want to invnoke this (https://msdn.microsoft.com/en-us/library/3aadshsx(v=vs.110).aspx) constructor but it invokes one with string parameters instead of Stream.
This results in this error:
New-Object : Exception calling ".ctor" with "2" argument(s): "The process cannot access the file 'C:\Users\Maciej\System.Net.Sockets.NetworkStream' because it is being used by anothe
r process."
At line:1 char:12
+ $writer = New-Object System.IO.StreamWriter -ArgumentList $outputStr ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
How to force to pass this parameter as Stream not as string?
Your problem is trying to access the [Encoding] class's static member with the wrong syntax:
[Text.Encoding].ASCII
In PowerShell, you access type static members with the following syntax:
[Text.Encoding]::ASCII
This object has the type [System.Text.ASCIIEncoding] according to .GetType() which inherits from [System.Text.Encoding] and should resolve the constructor errors you're receiving:
$tcpClient = New-Object -TypeName 'System.Net.Sockets.TCPClient'
$connect = $tcpClient.BeginConnect('localhost', 8080, $Null, $Null)
$success = $connect.AsyncWaitHandle.WaitOne($testTimeoutMs, $True)
$outputStream = $tcpClient.GetStream()
$writer = New-Object -TypeName 'System.IO.StreamWriter' -ArgumentList #($outputStream, [System.Text.Encoding]::ASCII)
As a side-note, in v5+, you can natively call the constructor method:
$streamWriter = [IO.StreamWriter]::new($outputStream, [Text.Encoding]::ASCII)
Related
I'm trying to use .net's MoveFileEx function from Powershell but DllImport seems to require casting all parameters to a certain type.
I have this code thanks to http://poshcode.org/2196:
$MOVEFILE_DELAY_UNTIL_REBOOT = 0x00000004
$memberDefinition = #'
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
public static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, int dwFlags);
'#
$type = Add-Type -Name MoveFileUtils -MemberDefinition $memberDefinition -PassThru
To MOVE a file at boot time, this works fine:
$result = $type::MoveFileEx($Path, $destination, $MOVEFILE_DELAY_UNTIL_REBOOT)
To DELETE a file at boot time, I thought this would work.
$result = $type::MoveFileEx($Path, $null, $MOVEFILE_DELAY_UNTIL_REBOOT)
But I get this error:
You cannot call a method on a null-valued expression.
At line:2 char:1 + $result = $type::MoveFileEx($Path, $null, $MOVEFILE_DELAY_UNTIL_REBOOT) +
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
CategoryInfo : InvalidOperation: (:) [], RuntimeException +
FullyQualifiedErrorId : InvokeMethodOnNull
This is because lpNewFileName is cast as string in the DllImport line above
Is there a way to rework the $memberDefinition (aka the c# code) to NOT cast lpNewFileName as string?
Or to import the MoveFileEx function twice, one with lpNewFileName cast as string and the second with lpNewFileName cast as null?
Update 1: I tried this
$NullValue = [NullString]::Value
$result = $type::MoveFileEx($Path, $NullValue, $MOVEFILE_DELAY_UNTIL_REBOOT)
and got this error:
You cannot call a method on a null-valued expression.
At line:4 char:6
+ $result = $type::MoveFileEx($Path, $NullValue, $MOVEFILE_DELAY_UNTIL_REBOOT ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Looks like I will need to write a wrapper function in c# to call the same MoveFileEx depending if I want to move or delete a file. Yay!
Update 2 As requested: fully self-contained code to demonstrate the problem.
$Path = "C:\ProgramData\DeleteMe.txt"
Set-Content -Path $Path -Value "Test file for you!"
$memberDefinition = #'
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
public static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, int dwFlags);
'#
$type = Add-Type -Name MoveFileUtils -MemberDefinition $memberDefinition -PassThru
[Int32]$MOVEFILE_DELAY_UNTIL_REBOOT = 0x00000004
$NullValue = [NullString]::Value #I read that c# may not like $null b/c c# sees $null as an object. (Stay buggy MS)
$result = $type::MoveFileEx($Path, $NullValue, $MOVEFILE_DELAY_UNTIL_REBOOT)
#If successful, PendingFileRenameOperations value is created at:
# [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager]
$Destination = "C:\ProgramData\DeleteMe.new"
$result = $type::MoveFileEx($Path, $Destination, $MOVEFILE_DELAY_UNTIL_REBOOT)
Now problem has disappeared! No more errors.
WTH..Thank you?!
It seems the [NullString]::Value is the key but it failed the first time I tried it.
I'm trying to create a nuget package from my class libary. So far I managed to create and install the package in a test project, but I also want to create a package manager command. My NuGet package is created with the NuGet Package Explorer.
NuGet Package structure
NuGet files content
init.ps1
param($installPath, $toolsPath, $package)
Import-Module (Join-Path $toolsPath MyNuGetCommands.psm1)
MyNuGetCommands.psm1
function Hello($name, $city)
{
Write-Host (‘Hello ‘ + $name + ‘. See you soon in ‘ + $city + ‘.’)
$lib = [Reflection.Assembly]::LoadFile("\\lib\EF.XML.dll")
$obj = new-object Parser
$result = $obj.UpdateXml()
}
Export-ModuleMember Hello
Register-TabExpansion ‘Hello’ #{
‘name’ = { "MSFTees", "MVPs", "My friends" };
‘city’ = { "Redmond", "Seattle", "Bellevue", "Duvall" };
}
I found the Hello function on the net and it worked in my project so I thougt lets add some lines found here to call my C# method. When I call the Hello function in my test project I get this errors:
Error 1
Exception calling "LoadFile" with "1" argument(s): "Cannot find the network path. (Exception from HRESULT: 0x80070035)" At
\svr\redirectedfolders\Stage\my documents\visual studio
2015\Projects\Test\packages\XML.EF.1.0.0\tools\MyNuGetCommands.psm1:5
char:43
+ $lib = [Reflection.Assembly]::LoadFile <<<< ("\lib\EF.XML.dll")
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Error 2
New-Object : Cannot find type [Parser]: make sure the assembly
containing this type is loaded. At
\svr\redirectedfolders\Stage\my documents\visual studio
2015\Projects\Test\packages\XML.EF.1.0.0\tools\MyNuGetCommands.psm1:6
char:22
+ $obj = new-object <<<< Parser
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand
Error 3
You cannot call a method on a null-valued expression. At
\svr\redirectedfolders\Stage\my documents\visual studio
2015\Projects\Test\packages\XML.EF.1.0.0\tools\MyNuGetCommands.psm1:7
char:29
+ $result = $obj.UpdateXml <<<< ()
+ CategoryInfo : InvalidOperation: (UpdateXml:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
So I think in the above errors obj is null but how can I fix this (I am not sure if LoadFile path is correct)? I did run set-executionpolicy RemoteSigned in Powershell.
Parser.cs file structure in EF.XML.dll
public class Parser
{
public void UpdateXml()
{
//code
}
}
This is the code to I use to call the method from a .cs file (which works but I want to call this from my Powershell Module:
var parser = new EF.XML.Parser();
parser.UpdateXml();
I'm trying to call a web service method from my PowerShell script but it's failing. Here is the C# code:
public MyTable InsertRow(MyTable data)
{
var dataContext = new MyEntities();
dataContext.MyTables.AddObject(data);
dataContext.SaveChanges();
return data;
}
This is how I call it in PowerShell:
$uri = "http://localhost/MyWcfService/MyService.svc?wsdl"
$svc = New-WebServiceProxy -Uri $uri -UseDefaultCredential
$t = $svc.GetType().Namespace
$attributes = New-Object($t + ".MyTable")
$attributes.Name = "Project X"
$attributes.Comment = "This is a test"
$resp = $svc.InsertRow($attributes)
$resp
And this is the error that I get:
Cannot find an overload for "InsertRow" and the argument count: "1". At line:1 char:1
+ $resp = $svc.InsertRow($attributes)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
What am I doing wrong?
Update:
This is the built-in .NET type when I call $attributes.GetType():
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True MyTable Microsoft.PowerShell.Commands.NewWebserviceProxy.AutogeneratedTypes.WebServiceProxy1WcfService_MyService_s...
I gave up on trying to call my RESTful Web service in PowerShell. I used this tutorial to create entity data in a data service and then used this sample code to consume the service using C#. This I have not yet tried, but I should be able to use the C# code in PowerShell script (this being my project's requirement).
Following is my powershell script,
function hello()
{
$dllpath = "C:\\Documents and Settings\\raj\\pstest\\testlib.dll";
[Reflection.Assembly]::LoadFrom($dllpath) | out-null;
$obj = New-Object testlib.TestClass;
$obj.print();
}
hello
Following is the TestClass in testlib which i am trying t access in powershell
using System;
namespace testlib
{
class TestClass
{
public TestClass()
{
}
public void print()
{
Console.WriteLine("Hi");
}
}
}
But i am getting error like below,
New-Object : Cannot find type [testlib.TestClass]: make sure the assembly conta
ining this type is loaded.
At C:\Documents and Settings\raj\pstest\script1.ps1:5 char:19
+ $obj = New-Object <<<< testlib.TestClass;
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentExcepti
on
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewOb
jectCommand
You cannot call a method on a null-valued expression.
At C:\Documents and Settings\raj\pstest\script1.ps1:6 char:12
+ $obj.print <<<< ();
+ CategoryInfo : InvalidOperation: (print:String) [], RuntimeExce
ption
+ FullyQualifiedErrorId : InvokeMethodOnNull
I have tried using add-type cmddlet but it is also giving the same response.
I guess the dll is getting loaded properly into the powershell but I am not able to instantiate the object of TestClass. Please tell me what I am doing wrong.
If i remove out-null following is the output im getting,
GAC Version Location
--- ------- --------
False v2.0.50727 C:\Documents and Settings\553566\pstest\testlib.dll
New-Object : Cannot find type [testlib.TestClass]: make sure the assembly conta
ining this type is loaded.
At C:\Documents and Settings\raj\pstest\script1.ps1:5 char:19
+ $obj = New-Object <<<< testlib.TestClass;
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentExcepti
on
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewOb
jectCommand
You cannot call a method on a null-valued expression.
At C:\Documents and Settings\raj\pstest\script1.ps1:6 char:12
+ $obj.print <<<< ();
+ CategoryInfo : InvalidOperation: (print:String) [], RuntimeExce
ption
+ FullyQualifiedErrorId : InvokeMethodOnNull
Try this:
[code]$dll = $($env:userprofile + '\pstest\testdll.dll')
And then try to invoke some static method from your library. For example:
$dll = $($env:userprofile + '\pstest\test.dll')
[void][Reflection.Assembly]::LoadFile($dll)
[MyNamespace.MyClass]::Print()
OOPS my bad .........
The TestClass should be a public one :(
After that modification its working
Hi I have written new functionality in the existing webservice.
I am copying the proxy file when rebuilding and copying to the specific location
i am using powershell but its not working .i get the following error.
**The term 'wsdl.exe' is not recognized as the name of a cmdlet, function, script
file, or operable program. Check the spelling of the name, or if a path was in
cluded, verify that the path is correct and try again.
At C:\[path edited for security]\RebuildProxy.ps1:30 char:9
+ wsdl.exe <<<< /fields "/l:CS" "/n:$namespace" "/out:$outCSFile" "/urlkey:Tes
tEndpoint" "$wsdlUrl";
+ CategoryInfo : ObjectNotFound: (wsdl.exe:String) [], CommandNot
FoundException
+ FullyQualifiedErrorId : CommandNotFoundException**
After rebuild i get the message the file has been modified outside the source editor[ the generated proxy file already there in the location]
could you please help me on this
posted below the powershell code
param (
[string]$webServiceProjFile = $(throw "webServiceProjFile paramter is required." ),
[string]$serviceFile = $(throw "serviceFile parameter is required."),
[string]$outCSFile = $(throw "outCSFile paramter is required." )
)
if (! [IO.File]::Exists($webServiceProjFile))
{
throw "$webServiceProjFile note found.";
}
if (! [IO.File]::Exists($outCSFile))
{
throw "$outCSFile note found.";
}
# read the project file into an XML document.
$projectFileXml = [xml] (Get-Content $webServiceProjFile );
# access the configured IIS URL
$serviceWsdlUrl = [string]::Concat($projectFileXml.Project.ProjectExtensions.VisualStudio.FlavorProperties.WebProjectProperties.IISUrl.Trim(), '/', $serviceFile);
$namespace = "";
# Read the namespace for the proxy from the proxy C# file
Get-Content $outCSFile | ForEach-Object { if ($_ -match "^\s*namespace\s+([A-Za-z._]+)\s+{\s*$") { $namespace = $matches[1] }};
$wsdlUrl = [string]::Concat("$serviceWsdlUrl", '?wsdl');
# Regenerate the proxy using WSDL.exe
wsdl.exe /fields "/l:CS" "/n:$namespace" "/out:$outCSFile" "/urlkey:TestEndpoint" "$wsdlUrl";
# Update the generated C# file so the proxy class interits from WSE2 base class.
(Get-Content $outCSFile) |
ForEach-Object { $_ -replace "\s+\:\s+System\.Web\.Services\.Protocols\.SoapHttpClientProtocol", " : Microsoft.Web.Services2.WebServicesClientProtocol" } |
Set-Content $outCSFile ;
$projectDirectory = [IO.Path]::GetDirectoryName($outCSFile);
$appConfigFilePath = [IO.Path]::Combine($projectDirectory, "App.config");
(Get-Content $appConfigFilePath) |
ForEach-Object { $_ -replace '<add\s+key="TestEndpoint"\s+value="[^"]*"\s+/>', "<add key=""TestEndpoint"" value=""$serviceWsdlUrl"" />" } |
Set-Content $appConfigFilePath ;
WSDL.EXE is not in the path. On my computer it comes with the visual studio.
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools\x64\wsdl.exe