New-Mailbox command does not accept the -Equipment argument - powershell

I'm attempting to create new resources in Exchange Online via a script and it works if I type the line manually but when I run the script, the command New-Mailbox suddenly can't accept the "-Equipment" argument.
Script fails on the following row:
New-Mailbox -Name "$($Resource)" -$($Type)
Error shows following:
A positional parameter cannot be found that accepts argument '-Equipment'.
+ CategoryInfo : InvalidArgument: (:) [New-Mailbox], ParameterBindingException"

PowerShell interprets -$($Type) as a string argument rather than a parameter name. Use splatting to conditionally pass parameters like this:
$extraParams = #{ $Type = $true }
New-Mailbox -Name "$($Resource)" #extraParams
I'm not sure which other types of mailboxes are available in Exchange Online, but you'll probably want to figure that out and apply some input validation:
param(
[string]$Resource,
[ValidateSet('Equipment','Person','Room')]
[string]$Type
)
# do other stuff here
# If someone passed a wrong kind of `$Type`, the script would have already thrown an error
$extraParams = #{ $Type = $true }
New-Mailbox -Name "$($Resource)" #extraParams

Related

How to return an Object from a loaded .dll file in powershell

I'm trying to use a Powershell-script to build a connection with Microsoft Dynamics CRM.
In some others scripts I want to use this connection.
If I export the connection-object, I can't use it as connection-object.
I return the object with:
[Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy] $connection = New-Object Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy($organizationUri,$null,$clientCredentials,$null)
[Microsoft.Xrm.Sdk.Entity] $systemUser = $connection.Retrieve("systemuser", $userId, (New-Object Microsoft.Xrm.Sdk.Query.ColumnSet(#("firstname", "lastname"))))
return $connection
And this is, how I call the script above:
[Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy]$connection = (New-CRMConnection -server $connectionjson.server -organization $connectionjson.organization -domain $connectionjson.domain -user $connectionjson.username -password $connectionjson.password)
But I get this error (I translated it from german, so it's not the exact error-message):
The value "System.Object[]" from type "System.Object[]" cannot be converted to "Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy".
In C:\Users\drieke\Documents\git\SNC-CRM\Solution\Import-CRMSolution.ps1:19 Zeichen:5
+ [Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy]$connection = ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : ConvertToFinalInvalidCastException
How do I correctly return my object?
EDIT
My problem was, that my function returned an array.
The first Object in the array is the object i need.
So my solution is the [1] in following code:
[Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy]$connection = (New-CRMConnection -server $connectionjson.server -organization $connectionjson.organization -domain $connectionjson.domain -user $connectionjson.username -password $connectionjson.password)[1]
The error message means that New-CRMConnection returns an array of objects. Conversion from array into some other non-collection object makes no sense, so Powershell complains.
To debug the scenario, first save New-CRMConnection's return value into a variable and work from there.
$connections = (New-CRMConnection -server $connectionjson.server `
-organization $connectionjson.organization -domain $connectionjson.domain `
-user $connectionjson.username -password $connectionjson.password)
# What kind of object is connections?
$connections.GetType()
# If it was an array, let's see its 1st element
$c = $connections[0]
# What kind of object is the first element?
$c.GetType()
# If it looks sensible, try casting
[Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy]$connection = $c

How to get powershell to throw exception instead of block when missing parameters to cmdlet

Lets say I have a cmdlet:
function Set-Something
{
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string] $SomeValue
)
}
and some automation that calls my cmdlet:
Set-Something
This will make the powershell session halt and write this to screen:
cmdlet Set-Something at command pipeline position 1
Supply values for the following parameters:
SomeValue:
This is downright annoying when doing automation: What we really want is for powershell to not Halt forever expecting user input that will never come, instead we simply want it to throw an exception "Missing parameter in call to Set-Something".
Is this possible?
While removing [Parameter(Mandatory)] as Avshalom suggests works, another solution which will retain the self-documenting benefit, may be to run PowerShell non-interactively.
Use -Noninteractive to launch PowerShell in non-interactive mode. You should then get an error which respects [Parameter(Mandatory)].
Set-Something : Cannot process command because of one or more missing mandatory parameters: SomeValue.
At line:1 char:1
+ Set-Something
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-Something], ParameterBindingException
+ FullyQualifiedErrorId : MissingMandatoryParameter,Set-Something
Just remove the [Parameter(Mandatory)] part and validate it inside the function:
function Set-Something
{
[CmdletBinding()]
param(
[string] $SomeValue
)
if (!$SomeValue)
{
throw "Missing parameter in call to Set-Something"
}
}

positional parameter cannot be found that accepts argument

if ($mbcb1.Checked -eq $true) {$dgr = "-AutoStart"}
if ($mbcb2.Checked -eq $true) {$dgrc = "-AutoComplete"}
if ($mbcb3.Checked -eq $true) {$dgren = "-NotificationEmails"}
New-MigrationBatch -Name $mbnd -SourceEndpoint $mbcx -TargetDeliveryDomain $mbtdd -CSVData ([System.IO.File]::ReadAllBytes("$cmbcsvfile")) $dgr $dgrc $dgren admin#admin.com
Error :
A positional parameter cannot be found that accepts argument '-Autostart'.
+ CategoryInfo : InvalidArgument: (:) [New-MigrationBatch], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,New-MigrationBatch
+ PSComputerName : ps.outlook.com
if i given direct input its working but passing as variable throwing error.
If you want to optionally specify parameters, use splatting:
$OptionalParameters = #{
AutoStart = $mbcb1.Checked
AutoComplete = $mbcb2.Checked
}
if ($mbcb3.Checked) {
$OptionalParameters["NotificationEmails"] = 'admin#admin.com'
}
New-MigrationBatch -Name $mbnd -SourceEndpoint $mbcx -TargetDeliveryDomain $mbtdd -CSVData ([System.IO.File]::ReadAllBytes("$cmbcsvfile")) #OptionalParameters
We simply build a hashtable with the parameter names and their arguments, and then supply it to the cmdlet as an argument (but like #name instead of $name), and then the parser will turn each entry in the hashtable into a named parameter in the form -key:value.
Finally, the $mbcb3.Checked -eq $true comparison is redundant, since Checked (assuming that $mbcb3 is a checkbox) is already either $true or $false
See the about_Splatting help file for more details about parameter splatting

Add bulk credentials in bulk to Password Vault

Overview:
I have created a vault that stores sensitive data, you can see my full sample code in this question:
PowerShell Password Vault
Goal:
I am attempting to make a function that would add credentials in bulk. I am not looking for particular method. However, I did attempt to run a loop that would add creds on each new line. But, my logic is off somewhere, meaning that when I attempt to use the following code, it begins to add credentials in an erroneous manner- please see table below. I am very open to new ideas or suggestions as well.
Exact Code:
function Add-BulkCreds{
param(
[string]$ID,
[string]$Key,
[string]$URL
)
$vaultAssembly
do{
Write-Host 'AddCreds)' -ForegroundColor Yellow -NoNewline
$x = Read-Host
$first,$second,$third = $x -split '\s',3
$vault = New-Object Windows.Security.Credentials.PasswordVault
$cred = New-Object Windows.Security.Credentials.PasswordCredential($second, $third, $first)
$vault.Add($cred)
}while($x)
}
Example input:
PS > Add-BulkCreds
AddCreds)test1c1 test1c2 test1c3
test2c1 test2c2 test2c3
test3c1 test3c2 test3c3
AddCreds)
New-Object : Exception calling ".ctor" with "3" argument(s): "The parameter is incorrect.
Cannot create credential"
At C:\Users\getcred.ps1:83 char:13
+ $cred = New-Object Windows.Security.Credentials.PasswordCredential($second, ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
Output:
ID Key Endpoint
-------- ------ -----------
test1c3... test1c1 test1c2
Closer Look at ID column:
PS > $credexample.id | Where-Object {$_.key -eq 'test1c1'}
test1c3
test2c1 test2c2 test2c3
test3c1 test3c2 test3c3
Observation:
As you can see the following part of my input was added to my ID column:
test1c3
test2c1 test2c2 test2c3
test3c1 test3c2 test3c3
Whereas....
test1c1 was added to Key
test1c2 was added to endpoint
Question:
Given my goal and overview, how can I create a simple, yet efficient function for adding credentials in bulk? And, does my logic work?
Additionally:
I am realizing that the original parameters aren't even needed since I am splitting the variable below with $x.
param(
[string]$ID,
[string]$Key,
[string]$URL
)

Microsoft DacServices Powershell error on constructor when calling new-object

I have the following Powershell script I am trying to run:
add-type -path "C:\Program Files (x86)\Microsoft SQL Server\110\DAC\bin\Microsoft.SqlServer.Dac.dll";
$d = new-object Microsoft.SqlServer.Dac.DacServices "server=localhost"
# Load dacpac from file & deploy to database named pubsnew
$dp = [microsoft.sqlserver.dac.dacpackage]::load("c:\deploy\MyDbDacPac.dacpac")
$d.deploy($dp, "MyDb", $true)
However, when it runs, I am getting the following error:
New-Object : Exception calling ".ctor" with "1" argument(s): "The type initializer for 'Microsoft.SqlServer.Dac.DacServices' threw an exception."
At C:\Scripts\DeployDacPac.ps1:3 char:16
+ $d = new-object <<<< Microsoft.SqlServer.Dac.DacServices "server=localhost"
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : Cons tructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
I am trying to run this for an automated database deploy but cannot get past this weird error.
I have already set my execution policy to remotesigned and updated my runtime version for Powershell to .NET 4.0. Can't figure out what else could be wrong.
Any help would be greatly appreciated!
The problem here is that the default authentication method is SQL Server authentication which expects a username and password. You will need to either supply those parameters or explicitly specify that Windows authentication should be used. You can do this by replacing your connection string argument with the following.
"server=localhost;Integrated Security = True;"
Alternatively, you could use the following function to encapsulate this logic. Note that the default parameter set is 'WindowsAuthentication' which does not include the UserName or Password parameters. If you supply either of these, Powershell will use the 'SqlServerAuthentication' parameter set and the $PSCmdlet.ParameterSetName variable will be set appropriately.
function Get-DacServices()
{
[CmdletBinding(DefaultParameterSetName="WindowsAuthentication")]
Param(
[string]$ServerName = 'localhost',
[Parameter(ParameterSetName='SqlServerAuthentication')]
[string]$UserName,
[Parameter(ParameterSetName='SqlServerAuthentication')]
[string]$Password
)
$connectionString = "server=$serverName;";
if($PSCmdlet.ParameterSetName -eq 'SqlServerAuthentication')
{
$connectionString += "User ID=$databaseUsername;Password=$databasePassword;";
}
else
{
$connectionString += "Integrated Security = True;";
}
$result = new-object Microsoft.SqlServer.Dac.DacServices $connectionString;
return $result;
}