I have a Powershell script working perfectly fine when executed from Visual Studio Code powershell terminal.
When I try to run the same script from c# code, or trying to Run as PowerShell from Windows explorer, I get the following error:
New-Object : Cannot find type [Microsoft.SqlServer.Management.Common.ServerConnection]: verify that the assembly
containing this type is loaded.
At line:32 char:18
+ return @(& $origNewObject @psBoundParameters)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand
[...]
Script code is as follow:
try {
Add-Type -AssemblyName "Microsoft.SqlServer.Smo, Version=15.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"
Start-Sleep -Seconds 5
}
catch {
Write-Output "Failed to load the SMO assembly. Error: $($_.Exception.Message)"
return
}
$SMOServerConn = new-object ("Microsoft.SqlServer.Management.Common.ServerConnection")
$SMOServerConn.ServerInstance="xxx.xxx.xxx.xxx"
$SMOServerConn.LoginSecure=$false
$SMOServerConn.Login='xxxxxx'
$SMOServerConn.Password='xxxxxxxxxxxxxxxxxxxxxxxxxxxx'
$SMOserver = new-object ("Microsoft.SqlServer.Management.Smo.Scripter") #-argumentlist $server
$srv = new-Object Microsoft.SqlServer.Management.Smo.Server($SMOServerConn)
$srv.ConnectionContext.ApplicationName="MySQLAuthenticationPowerShell"
$db = New-Object Microsoft.SqlServer.Management.Smo.Database
$db = $srv.Databases.Item('xxxxx')
$maxAttempts = 10
$attempt = 0
# Loop until the connection is established or the maximum number of attempts is reached
while ($db.ConnectionContext.IsOpen -eq $false -and $attempt -lt $maxAttempts) {
$attempt++
Write-Output "Attempt $($attempt): Connecting to database..."
# Wait for a short duration before attempting the next connection check
Start-Sleep -Seconds 1
}
$scripter = new-object ("$SMOserver") $srv
$line="[cccauth].[spGetTrxReconSummary]"
$line = $line.replace('[','').replace(']','')
$splitline =$line.Split(".")
$Objects = $db.storedprocedures[$splitline[1], $splitline[0]]
Write-Host "Extracting stored procedure $($line)"
Write-Host "--------------------------------"
$sp_extracted+=$Scripter.Script($Objects)
$sp_extracted=$sp_extracted.replace("SET QUOTED_IDENTIFIER ON", "SET QUOTED_IDENTIFIER ON `r`nGO`r`n")
Write-Host $sp_extracted -ForegroundColor Green
Write-Host "Scripting DB Finished... Press any key..."
[void][System.Console]::ReadKey($true)
If I implement the logic to connect to a second server/database on the script, then this second connection is working.
Does anyone know what is wrong here?
Thank you in advance.
It's not clear what kind of C# project you created or whether you're using .NET or .NET Framework. Also, I'm not familiar with VS Code, but the following may be helpful.
According to Global assembly cache APIs are obsolete:
According to Differences between Windows PowerShell 5.1 and PowerShell 7.x:
According to PowerShell Add-Type:
If using .NET 5+, it seems that one should specify -Path instead of -AssemblyName. If using .NET Framework one can use either Path or AssemblyName (if the DLL is in the global assembly cache).
If using .NET Framework, to check if Microsoft.SqlServer.Smo exists in the global assembly cache, open a cmd window and type:
When specifying a path, no matter how one attempts to run the PowerShell script, the path to
Microsoft.SqlServer.Smo.dllneeds to be known. If one desires to run the script in Windows Explorer, one can specify the fully-qualified path to the assembly, or may be able to add the path to the Windows Path environment variable.Where are the DLLS? When one installs SQL Server Express, the DLLs are installed in
%ProgramFiles%\Microsoft SQL Server\100\SDK\Assemblies. If one adds theMicrosoft.SqlServer.SqlManagementObjectsNuGet package to one's project, the DLLs will be downloaded to%UserProfile%\.nuget\packages\microsoft.sqlserver.sqlmanagementobjects\<version>\lib\<version>. Then when the project is compiled, they'll be copied to the project output folder (ex: bin\Debug\net5.0-windows).For C#, add the Microsoft.SqlServer.SqlManagementObjects NuGet package to the project.
Create a new
Window Forms App(for Framework, choose.NET 6)Add the following NuGet packages to your project:
Add the following using directives
Specifying the version of
Microsoft.SqlServer.Smo.dllshouldn't be necessary. Try the following:Script:
RunPowerShell
Also see: