GUI and PSRemoting in Powershell CLI - winforms

Recently, I created a script that utilizes GUI's such as Out-GridView and Winforms and puts that module on a remote Windows 2012 server. This was to allow users to establish remote PSSessions and execute scripts from a centralized location.
For Example:
1. When attempting to call a winform I get the following error:
Exception calling "ShowDialog" with "0" argument(s): "Showing a modal dialog box or form when the application is not running in UserInteractive mode is not a valid operation. Specify the ServiceNotification or DefaultDesktopOnly style
to display a notification from a service application."
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : InvalidOperationException
+ PSComputerName : servera
2.
When attempting to place results into an Out-GridView I get the following error:
Out-GridView does not work in a remote session.
+ CategoryInfo : InvalidOperation: (Microsoft.Power...GridViewCommand:OutGridViewCommand) [Out-GridView], NotSupportedException
+ FullyQualifiedErrorId : RemotingNotSupported,Microsoft.PowerShell.Commands.OutGridViewCommand
+ PSComputerName : servera
Question:
Are there any workarounds that would allow me to utilize OGV and Winforms?
Side note:
I am open to allowing the user to export the module to their physical workstation to let them use these options if need be - OGV and Winforms - only if there is an effective/secure means to do it.On the other hand, I am open to different suggestions.

You need to use the UI on your local machine, not the remote one. Retrieve data remotely, display locally.
For instance:
Invoke-Command -ComputerName RemoteServer -Scriptblock { Get-Process } | Out-Gridview
Using the gridview inside the scriptblock will attempt to launch the UI on RemoteServer and give you the error you mentioned.

Invoke-Command I think would be better here because you are telling the remote computer what to do instead of asking to interact directly with the remote computer using Enter-PSSessionor New-PSSession.

Related

Powershell error running Get-dbaDatabase searching for missing backups

I am getting the following error when running this command:
Get-dbaDatabase -sqlinstance server01 -NoFullBackup
Error:
Compare-DbaCollationSensitiveObject : Cannot bind argument to parameter 'Value' because it is null.
At C:\Program Files\WindowsPowerShell\Modules\dbatools\1.1.76\allcommands.ps1:22322 char:109
+ ... bject -Property Name -In -Value $lastCopyOnlyBackups.Database -Collat ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Compare-DbaCollationSensitiveObject], ParameterBindingValidationExcept
ion
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Compare-DbaCollationSensitiveObject
This happens on multiple versions of dbatools, I don't think it is related to dbatools at all. When I run this on another account that has a profile created long ago I get no errors. New account profiles seem to have this error show up. I am thinking it may be related to a setting in PowerShell but I am not sure what it could be.
On an older account profile the command just returns nothing, basically a blank line. The newer accounts all return this error. I have run this command on machines ranging from Windows Server 2012 through Windows Server 2019.
I did try to use an account that worked on an older server on a new server and in that case I do get the error above. It seems to be related to when the profile was created, which makes me think there is some default setting or behavior that is being set at the group policy or machine policy level.
PowerShell version is 5.1.
I am hoping there are some PowerShell experts out there that can point me in the right direction.
Thanks!
This has been acknowledged as a bug in the function by the dbatools team. This is fairly new functionality that was implemented in late 2021. This should get fixed in a future update to dbatools.

Unable to invite user to Azure Active Diretory

Im trying to invite guest users to my AAD without success. I get the message "Unable to invite user" and when I check the error details I get the following
{"errorCode":"B2BError","localizedErrorDetails":null,"operationResults":null,"timeStampUtc":"2017-05-12T23:48:31.5694549Z","clientRequestId":"xxxxxxxxxxx","internalTransactionId":"xxxxxxxxxxx","upn":"xxxxxxxxxxx","tenantId":"xxxxxxxxxxx","userObjectId":"xxxxxxxxxxx"}
I was able to invite users without problems a few weeks ago. But today Im receiving this error. I tried with a different tenant and it's working fine.
I also tried via powershell, using the New-AzureADMSInvitation cmdlet from Azure Active Directory V2 Preview Module. The same happens: one tenant works and the other doesnt. The error that I get on powershell is
New-AzureADMSInvitation : Error occurred while executing NewAzureADMSInvitation
Code: Forbidden
Message: Generic authorization exception.
InnerError:
RequestId: xxxxxxxxxxx
DateTimeStamp: Fri, 12 May 2017 20:43:52 GMT
HttpStatusCode: Forbidden
HttpStatusDescription: Forbidden
HttpResponseStatus: Completed
At line:1 char:15
+ ... nvitation = New-AzureADMSInvitation -InvitedUserEmailAddress teste2#p ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [New-AzureADMSInvitation], ApiException
+ FullyQualifiedErrorId : Microsoft.Open.MSGraphBeta.Client.ApiException,Microsoft.Open.MSGraphBeta.PowerShell.NewAzureADMSInvitation
I even enabled the Premium trial to check if it had something to do with the free plan, but the problem persists
Does anybody know whats going on?
According to your error message, maybe we should check your Azure AD configure settings, like the screenshot:
Also we can use admin account of Azure AD to invite user.

Memory usage for bacpac restore to SQL server

I have just restored a .bacpac file into a local SQL server instance (64b v12.0.4213), the backup is from an azure sql instance.
It failed a few times with an OOM exception. I switched off everything on my machine and by the end of the restore the SQL server service instance was consuming 13GB of memory from a 700MB file!
The restore luckily finished, but it seems the memory is not being freed up/garbage collected. It's still sitting at 12GB as I write this.
Is it a known issue? Is there any way I can restore a .bacpac and select a table to ignore? You can to do this with a normal data restore, the most offensive table was a dbo.[Logs] table, obvs.
I had the same issue; amending the memory available to the server had no impact.
For me the resolution was to use the command line (PowerShell) to perform the import.
[string]$myBacpac = 'c:\temp\myBacpac123.bacpac'
[string]$connectionString = 'Data Source=.;Initial Catalog=MyNewCatalog; Integrated Security=true;'
[string]$action = 'Import'
[string[]]$commandParameters = #(
"/Action:`"$action`""
"/SourceFile:`"$myBacpac`""
"/TargetConnectionString:`"$connectionString`""
)
[string]$LatestSqlPackage = Get-Item 'C:\*\Microsoft SQL Server\*\DAC\bin\sqlpackage.exe' | %{get-command $_}| sort version -Descending | select -ExpandProperty source -First 1
if ($LatestSqlPackage) {
Write-Verbose "Found: $LatestSqlPackage"
& $LatestSqlPackage $commandParameters
} else {
Write-Error "Could not find SqlPackage.exe"
}
On my first attempt I received an error regarding an unsupported model version:
Importing to database 'MyNewCatalog' on server '.'. Creating deployment plan
Initializing deployment SqlPackage.exe : * Error importing
database:Could not read schema model header information from package.
At line:1 char:1
+ & $sqlPackage /Action:Import /SourceFile:"c:\temp\myBacpac123.bacpac" /T ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (* Error impor...n from package.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError The model version '3.5' is not supported.
For that error I followed the guidance here: https://stackoverflow.com/a/40541210/361842; i.e. installed Microsoft SQL Server Data-Tier Application Framework (16.4). On rerunning all was successful.
To configure SQL Server's use of memory, open SQL Server Management Studio, connect to the server, right-click on the server in the Object Explorer window, click properties, and then click on the Memory tab of the Server Properties window.
As for the bacpac, you can't select which tables to restore during an import operation, but you can select which tables are exported. You can use SqlPackage.exe's export command with the /p:TableData parameter to specify which tables should be included in the bacpac. There's unfortunately no way to just specify which tables should be excluded. =^/
SqlPackage.exe documentation is available here: https://msdn.microsoft.com/en-us/hh550080(v=vs.103).aspx
Neither of the other answers worked for me, what did work was closing and restarting SSMS. This sounds like a silly suggestion, but I'd previously been running some large queries which must've caused memory issues.

How to get powershell to read a SQL Server error log

I need your help with PowerShell today. I have a SQL Server instance (on a server named VMDEV-APP11) configured as a Central Management Server (CMS) in which I have registered all my Dev/Test/Prod SQL instances and I want to use PowerShell to read the SQL Server error logs from all my servers. I have a query which retrieves all my SQL Server instances but when I pipe the output of this into a call to ReadErrorLog, I get an error.
This is the code that retrieves my list of the SQL Server instances which are registered on my CMS (note that I exclude my SQL Server 2000 instances):
Set-Location D:\MSSQL11.MSSQLSERVER\CMS
# Define functions to query SQL Server and write data to a SQL table
. ./invoke-sqlcmd2.ps1
. ./write-datatable.ps1
Invoke-sqlcmd2 -ServerInstance "VMDEV-APP11" -Database dba -Query "select s.server_name from msdb.dbo.sysmanagement_shared_registered_servers s, msdb.dbo.sysmanagement_shared_server_groups g where s.server_group_id = g.server_group_id and g.name not like '2000%'"
server_name
-----------
INF-SRV14
VMDEV-APP15
NEX-SRV48
...
And this is what I thought would work and the error I actually get:
Invoke-sqlcmd2 -ServerInstance "VMDEV-APP11" -Database dba -Query "select s.server_name from msdb.dbo.sysmanagement_shared_registered_servers s, msdb.dbo.sysmanagement_shared_server_groups g where s.server_group_id = g.server_group_id and g.name not like '2000%'" | foreach-object { $_.server_name.ReadErrorLog() }
Error:
Method invocation failed because [System.String] does not contain a method named 'ReadErrorLog'.
At D:\MSSQL11.MSSQLSERVER\CMS\db_errorlog.ps1:38 char:284
+ ... reach-object { $_.server_name.ReadErrorLog() }
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
I suspect I need to convert the string returned by my query to another type of object (a server name perhaps?) in order to get the ReadErrorLog() call to work but I don't know how to do that.
Any suggestions?
Any help would be greatly appreciated.
Ken
You're trying to invoke the ReadErrorLog() method on a DataRow column value, which is a string.
What you need to do is something like this:
Import-Module sqlps -DisableNameChecking
Invoke-sqlcmd2 -ServerInstance "VMDEV-APP11" -Database dba -Query "select s.server_name from msdb.dbo.sysmanagement_shared_registered_servers s, msdb.dbo.sysmanagement_shared_server_groups g where s.server_group_id = g.server_group_id and g.name not like '2000%'" | `
foreach-object {
$server = $_.server_name
$logs = (get-item SQLSERVER:\sql\$server\default).ReadErrorLog()
# $logs is a DataTable so you can iterate the rows however you wish
}
This assuming all your servers are default instances, otherwise you may need to fiddle around a bit more to target specific instances.
The code I'm running on my SQL Central Management server is:
$logs = 0..6 | % { (get-item SQLSERVER:\sql\<servername>\default).ReadErrorLog($_) }
Originally, I got this to work by adding the service account that ran the PowerShell code to the local Administrators Windows group AND creating a SQL login with sysadmin privileges on the remote SQL server host. Not sursprisingly, my security officer had an issue with this. My initial attempts to reduce access resulted i the following error:
WARNING: Could not obtain SQL Server Service information. An attempt to connect
to WMI on 'NEX-SRV1' failed with the following error: SQL Server WMI provider
is not available on NEX-SRV1. --> Invalid namespace
After quite a bit of fooling around, I have what I think is the minimum security needed to read the SQL error logs. Perform the following grants on the remote server running the SQL Server database:
Local Windows Group
Add the service account to the "Distributed COM Users" group
WMIMgmt.msc
Add the service account to each of the following branches with all security options EXCEPT "Edit Security"
Root > cimv2
Root > cimv2 > ms_409
Root > Microsoft > SQLServer > ComputerManagement
SQL Server
Create a SQL login for the service account and add it to the "Security Admin" role.
After I had made these changes, I have the ability to monitor SQL Error logs from a central location without having to grant crazy levels of access to the service account.

How can I use invoke-sqlcmd without enabling named pipes?

I am using a script that loads the following SQL Server 2008 R2 powershell plugins
Add-PSSnapin SqlServerCmdletSnapin100
Add-PSSnapin SqlServerProviderSnapin100
I then user invoke-sql like this:
Invoke-Sqlcmd -Query "select * from table" -ServerInstance xyz -Database abc -username xxxxxx -password yyyyyyy
I am using method to run a number of upgrade scripts on our databases. I was quite happily using this in our dev\test environments but then we I tried it in production and it turns out we have a difference in server configurations. On our prod servers named pipes are disabled for security reasons (apparently worm attacks) and our DBA's don't want to enable.
This is the error I get and research says it is a named pipes problem - starts working when I enable them too.
INFO ERROR: Invoke-Sqlcmd : A connection was successfully
established with the server, but then an error occurred during the
login process. (provider: Shared Memory Provider, error: 0 - No
process is on the other end of the pipe.)
Does anyone know if there is some way to switch my script so that it does not require named pipes? Or is this the built in connection method for invoke-sqlcmd and I need to change tack (if so any suggestions).
Similar to Surreal's response to use LPC (local shared memory), for TCP/IP instead of named pipes you can also specify -ServerInstance tcp:foodb
This is an educated guess. But here goes:
I think you have to "override the default" by using the registry.
http://support.microsoft.com/kb/229929
Now, the easiest way to do this (IIRC) is to go through your
Control Panel / ODBC Data Source / System DSN.
Add a "Sql Server". (Not the native client ones).
The most important button is the "Client Configuration" where you can pick named-pipes or tcp/ip.
Try out the DSN method, and after completing the wizard, look at the registry entries under
HKEY_LOCAL_MACHINE\Software\Microsoft\MSSQLServer\Client\ConnectTo
.........
You might check out this:
http://sev17.com/2012/11/05/cloning-sql-servers-to-a-test-environment/
Look for this code.
sqlcmd -S myCMServerInstance -d msdb -Q $query -h -1 -W |
foreach { Set-ItemProperty -Path 'HKLM:SOFTWAREMicrosoftMSSQLServerClientConnectTo' -Name $($_ -replace 'TEST') -Value "DBMSSOCN,$_" }
}
You can change the connection method using prefixes to the instance name as for sqlcmd. With SQL Server 2012 and Powershell 4, this works for me:
Invoke-Sqlcmd -Query $sqlQuery -serverinstance "lpc:localhost" -Database "myDatabase"

Resources