Question

Consider the following code in a powershell script called NewDB.ps1:

param ($i, $d)

Function New-Database 
{
    param ($instance, $name)
    $db = New-Object Microsoft.SqlServer.Management.Smo.Database ($instance, $name) 
    try { $db.Create() }
    catch [Exception] { $_.Exception | Format-list | Out-String ; exit }
    $db.CreateDate.DateTime
    $db.DatabaseOptions.RecoveryModel
    return $db
}

[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | Out-Null
$sqlServer = new-Object Microsoft.SqlServer.Management.Smo.Server($i)
[Microsoft.SqlServer.Management.Smo.Database]$myDB = New-Database $sqlServer $d

I get a type conversion error:

PS C:\Users\moomin\Documents> .\NewDB.ps1 "(local)" "testDB"
Cannot convert the "System.Object[]" value of type "System.Object[]" to type
"Microsoft.SqlServer.Management.Smo.Database".
At C:\Users\moomin\Documents\NewDB.ps1:21 char:1
+ [Microsoft.SqlServer.Management.Smo.Database]$myDB = New-Database $sqlServer $d
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : ConvertToFinalInvalidCastException

How can I return the object back from my function as a Microsoft.SqlServer.Management.Smo.Database object? I need to do more things with it outside the function.

UPDATE Of course, thanks @mjolinor, this works exactly as I want now. BTW it also works fine with New-Database in a separate module (how I have actually implemented it).

param ($i, $d)

Function New-Database 
{
    param ($instance, $name)
    $db = New-Object Microsoft.SqlServer.Management.Smo.Database ($instance, $name) 
    try { $db.Create() }
    catch [Exception] { $_.Exception | Format-list | Out-String ; exit }
    $db
}

[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | Out-Null
$sqlServer = new-Object Microsoft.SqlServer.Management.Smo.Server($i)
$myDB = New-Database $sqlServer $d
$myDB.CreateDate.DateTime
$myDB.DatabaseOptions.RecoveryModel
Was it helpful?

Solution

A function should return only one type of object, and anything it outputs is part of the return, not just what follows the Return keyword, so your return is going to be an array of these 3 objects (this is why it's saying your return type is Object[])

 $db.CreateDate.DateTime
 $db.DatabaseOptions.RecoveryModel
 $db

If you just want $db, only return $db.

OTHER TIPS

The return keyword is really just for syntactical use. If any object is called before the return keyword, they too will be return. So essentially you're returning a list of Objects, which is exactly what the error is telling you.

Let's take this for example. This code will return an array of $y values, but never an $x.

function return-test {
    $x = 1
    $y = 2

    write-host $x  # Console output only
    $x | out-null  # Goes to null
    $x > $null     # Goes to null
    [void] $x      # Goes to null

    $y             # is returned
    return $y      # is returned, but now the return value is an array.
}

So what you need to do is decide what you want to do with $db.CreateDate.DateTime and $db.DatabaseOptions.RecoveryModel. If you just want to display them on the console, then use write-host like so...

function New-Database {
    ...
    write-host $db.CreateDate.DateTime
    write-host $db.DatabaseOptions.RecoveryModel

    # You can use return if you prefer to see it.
    # Either way, you want to return one value.
    #return $db
    $db
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top