So I tried calling the following code with and without credentials.
$username = "user"
$password = "password"
$cred = new-object -argumentlist $username, $password
#Invoke-Command -ComputerName computer -FilePath "C:\Some\Path.ps1" -Credential $cred
Invoke-Command -ComputerName localhost -FilePath "C:\Some\Path.ps1"
after calling in cmd appeared the following lines:
cmdlet New-Object at command pipeline position 1
Supply values for the following parameters:
TypeName:
Since I do not know what this parameters are referring to I type a letter and then the following error occurs:
new-object : Cannot find type [;]: verify that the assembly containing this type is loaded.
At C:\Some\Path.ps1:8 char:9
+ $cred = new-object -argumentlist $username, $password
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand
[localhost] Connecting to remote server localhost failed with the following error message : Access is denied. For more
information, see the about_Remote_Troubleshooting Help topic.
+ CategoryInfo : OpenError: (localhost:String) [], PSRemotingTransportException
+ FullyQualifiedErrorId : AccessDenied,PSSessionStateBroken
I have abs no idea what it means. Can somebody help me please?
Don't fret - PowerShell is a strangely complex language runtime, and the initial learning curve can be quite steep :)
In .NET - the runtime framework on top of which PowerShell is built - all objects have a type - and so you need to specify the type of object you want when creating one.
To find the appropriate type name, let's first take a look at the -Credential
parameter to which you will be passing the object as an argument. We can use Get-Help <commandName> -Parameter <parameterName>
to inspect the parameter definition:
PS ~> Get-Help Invoke-Command -Parameter Credential
-Credential <pscredential>
Required? false
Position? Named
Accept pipeline input? true (ByPropertyName)
Parameter set name ComputerName, Uri, FilePathComputerName, FilePathUri, VMId, VMName, FilePathVMId, FilePathVMName
Aliases None
Dynamic? false
On the first line we see that it expects a value of type pscredential
.
For interactive scripts, the easiest way to construct a pscredential
object is to use the Get-Credential
command - it'll prompt you for a password and return a pscredential
object you can then pass to Invoke-Command
(and re-use later if desirable):
PS ~> $credential = Get-Credential -Username $username # this will prompt you for a password
Enter your credentials.
Password for user asd: ********
PS ~> Invoke-Command {...} -Credential $credential # now we can pass the credential object to the command parameter
Assuming the target computers are all part of the same domain and the credentials you possess have access to connect to the WinRM endpoint on them, you can reuse the same credential object against them all:
foreach ($computerName in $listOfComputerNames) {
Invoke-Command -ComputerName $computerName -ScriptBlock { ... } -Credential $credential
}
... or you can pass all the computer names to Invoke-Command
in one go:
Invoke-Command -ComputerName $listOfComputerNames -ScriptBlock { ... } -Credential $credential
For unattended use however, you might still need to find a way to instantiate a credential object without Get-Credential
.
Let's try passing the correct type name to New-Object
:
PS ~> $cred = New-Object -TypeName pscredential -ArgumentList $username, $password
New-Object : Cannot find an overload for "PSCredential" and the argument count: "2".
At line:1 char:9
+ $cred = New-Object -TypeName pscredential -ArgumentList $username, $p ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
Oh no! The arguments passed to New-Object
doesn't match the constructor parameters defined by the pscredential
type.
The easiest way to inspect all overload signatures for a given type's constructor is to invoke the static new
method on the type, without passing an argument list:
PS ~> [pscredential]::new
OverloadDefinitions
-------------------
pscredential new(string userName, securestring password)
pscredential new(psobject pso)
The constructor with the signature pscredential new(string userName, securestring password)
is probably exactly what we want - but it says it's expecting a securestring
-type object rather than a regular string.
To instantiate a [securestring]
from plain text, we can use the ConvertTo-SecureString
cmdlet:
PS ~> $securePassword = $password |ConvertTo-SecureString -AsPlainText -Force
PS ~> $credential = New-Object pscredential -ArgumentList $username, $securePassword
PS ~> # yay, no more errors!
Ps ~> Invoke-Command {...} -Credential $credential
As an alternative to the New-Object
command, you can also use the static ::new
method we used to discover the constructor signatures earlier:
PS ~> $credential = [pscredential]::new($username, $securePassword)