Restoring SSRS / PowerBI Reporting Server encryption key using Powershell - powershell

I have the following Powershell code to restore an Encryption key on a Power BI Report Server instance:
$encKeyPath = "C:\Test\enc.snk"
$encKeyPass = Read-Host 'Enter password for key:' -AsSecureString
Restore-RsEncryptionKey -ComputerName "localhost" -Password $encKeyPass -KeyPath $encKeyPath -ReportServerInstance PBIRS -ReportServerVersion SQLServer2016
When I run this I get the error:
Get-WmiObject : Invalid namespace "root\Microsoft\SqlServer\ReportServer\RS_PBIRS\v13\Admin"
At C:\Users\MyUser\Documents\WindowsPowerShell\Modules\ReportingServicesTools\ReportingServicesTools\Functions\Utilities\New-Rs
ConfigurationSettingObject.ps1:100 char:19
+ $wmiObjects = Get-WmiObject #getWmiObjectParameters
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-WmiObject], ManagementException
+ FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
I have tried also tried with the -ReportServerInstance and -ReportServerVersion parameters but get the same error message. I have also tried my local computer name for the -ComputerName parameter rather than localhost but still had no luck.
The error seems to refer to an error in the actual module itself rather than my code. Can anyone suggest where I am going wrong?
Environment
Power BI Report Server version: 1.8.7450.37410 (May 2020)
Instance name: PBIRS
Report Manager URL: http://localhost/reports
Service URL: http://localhost/reportserver
ReportServer database is on a SQL Server 2016 instance (the database name is PowerBIReportServer)
EDIT:
Using the two answers so far, I have found the following:
Restore-RsEncryptionKey -ComputerName "localhost" -Password $encKeyPass -KeyPath $encKeyPath -ReportServerInstance PBIRS -ReportServerVersion SQLServer2016
Throws
Invalid namespace "root\Microsoft\SqlServer\ReportServer\RS_PBIRS\v13\Admin"
and changing the -ReportServerVersion:
Restore-RsEncryptionKey -ComputerName "localhost" -Password $encKeyPass -KeyPath $encKeyPath -ReportServerInstance PBIRS -ReportServerVersion SQLServer2017
Throws
Invalid namespace "root\Microsoft\SqlServer\ReportServer\RS_PBIRS\v14\Admin"
(note the difference in versions)
running
Get-WmiObject -Namespace "Root/Microsoft/SqlServer/ReportServer/RS_PBIRS" -Class __Namespace | Select-Object -Property Name | Sort Name
outputs:
Name
----
V15
which makes sense as to why the two different -ReportServerVersion arguments throw an error.
this page suggests
+--------------------+---------+
| SQL Server Release | Version |
+--------------------+---------+
| SQL Server 2012 | 11 |
| SQL Server 2014 | 12 |
| SQL Server 2016 | 13 |
| SQL Server 2017 | 14 |
| SQL Server 2019 | 15 |
+--------------------+---------+
but changing -ReportServerVersion to SQLServer2019 returns:
Restore-RSEncryptionKey : Cannot process argument transformation on parameter 'ReportServerVersion'. Cannot convert value
"SQLServer2019" to type "Microsoft.ReportingServicesTools.SqlServerVersion". Error: "Unable to match the identifier name
SQLServer2019 to a valid enumerator name. Specify one of the following enumerator names and try again:
SQLServer2012, SQLServer2014, SQLServer2016, SQLServer2017, SQLServervNext"
At line:3 char:143
From here then I suppose the question is:
How do I get the module to run v15 OR how do I get version 13 of the module / namespace?

The error is being thrown from the module, but it appears to be as a result of the data we're putting into the module. Let's dive into the code to see what's happening.
I found the source code of the module here. These lines towards the bottom (85 through 102) stuck out to me:
$getWmiObjectParameters = #{
ErrorAction = "Stop"
Namespace = "root\Microsoft\SqlServer\ReportServer\RS_$ReportServerInstance\v$($ReportServerVersion.Value__)\Admin"
Class = "MSReportServer_ConfigurationSetting"
}
# code snipped
$wmiObjects = Get-WmiObject #getWmiObjectParameters
Looking back at your error, the first line is noting "invalid namespace". If anything looks immediately off in "root\Microsoft\SqlServer\ReportServer\RS_PBIRS\v13\Admin" or your values for $ReportServerInstance or $($ReportServerVersion.Value__) then I'd change those.
If those look okay to you, I'd suggest you manually search through the available WMI namespaces on the target machine. First, we want to return all the child namespaces of root.
PS C:\windows\system32> Get-WmiObject -Namespace "Root" -Class __Namespace | Select-Object -Property Name | Sort Name
Name
----
Appv
cimv2
Hardware
HyperVCluster
Microsoft
WMI
Now that we have those, we can continue searching down the path that the module is expecting. We know from the module code, it's expecting to hit "Microsoft" in the namespace/path next so add that to the namespace we're searching child namespaces for:
PS C:\windows\system32> Get-WmiObject -Namespace "Root\Microsoft" -Class __Namespace | Select-Object -Property Name | Sort Name
Name
----
HomeNet
PolicyPlatform
protectionManagement
SecurityClient
Uev
Windows
I think if you continue down that line of logic, you'll run into the spot where the module is expecting a child WMI namespace, but the target machine lacks it.
Hope this was helpful and good luck!
****Update:
To answer the new question 'How do I get the module to run v15 OR how do I get version 13 of the module / namespace?'
The example use of the cmdlet shows use of the 2-digit report server version so I'd have you try this:
Restore-RsEncryptionKey -ComputerName "localhost" -Password $encKeyPass -KeyPath $encKeyPath -ReportServerInstance PBIRS -ReportServerVersion '15'
If that returns the same error, try Connect-RsReportServer. Module documentation notes it will set/update the parameter ReportServerVersion
.PARAMETER ReportServerVersion
Specify the version of the SQL Server Reporting Services Instance.
Use the "Connect-RsReportServer" function to set/update a default value.

To troubleshoot problems with the -ReportServerVersion parameter in the ReportingServicesTools module, resulting in namespace errors, you can use the following three quick steps:
Determine the SQL server versions your server supports (replace PBIRS by your actual ReportServerInstance, if different):
Get-WmiObject -Namespace "root\Microsoft\SqlServer\ReportServer\RS_PBIRS" -Class __Namespace | Select-Object -ExpandProperty Name
Example output:
V15
Display the current version to name mappings in ReportingServicesTools:
[enum]::GetValues([Microsoft.ReportingServicesTools.SqlServerVersion]) | % {[PSCustomObject]#{Name = $_;Version = $_.value__}}
Example output:
Name Version
---- -------
SQLServer2012 11
SQLServer2014 12
SQLServer2016 13
SQLServer2017 14
SQLServervNext 15
Map your supported server version to the corresponding name in the ReportingServicesTools module and use this name to pass it to the -ReportServerVersion parameter or pass the integer directly (after stripping the v).

Related

Fetching values from Net Use command using powershell

I am trying to get network mapped drives using below commands.
Get-WmiObject -Class Win32_MappedLogicalDisk | %{$_.Name}
Get-WmiObject -Class Win32_MappedLogicalDisk | %{$_.ProviderName}
This works in some system however does not in other systems(may be powershell version issue) So I thought of using net use command. However, I am unable to fetch the values or not sure how to get the values displays when i type 'net use'
when I type net use I get status, Local, Remote and Network column. I tried to use the below command to get the field values.
net use | select local.
but I get blank or nothing
Used below command.
net use | select local.
Need to get Local and Remote values from net use command.
See this for parsing legacy console output ---
How to Convert Text Output of a Legacy Console Application to PowerShell Objects
Yet, along with what LotPings gave you already. Your query could be a duplicate of this ...
Equivalent of net use (to list computer's connections) in powershell?
... and it's accepted answer
# For the mapped logical drive you can use WMI class Win32_MappedLogicalDisk :
Get-WmiObject Win32_MappedLogicalDisk
# Here is another way with Win32_LogicalDisk :
PS C:\> Get-WmiObject -Query "Select * From Win32_LogicalDisk Where DriveType = 4"
DeviceID : V:
DriveType : 4
ProviderName : \\jpbdellf1\c$
FreeSpace :
Size :
VolumeName :
# Edited
# You are right, you can get what you need with Win32_NetworkConnection :
Get-WmiObject Win32_NetworkConnection
LocalName RemoteName ConnectionState Status
--------- ---------- --------------- ------
\\jpbasusf1\temp Connected OK
# On Seven or W2K8 be careful to call this with the same user that run the NET USE because it's a session information.
How about using get-psdrive (the root header actually matches the displayroot property)?
get-psdrive | where displayroot -like '\\*'
Name Used (GB) Free (GB) Provider Root
---- --------- --------- -------- ----
Y 91.84 7.82 FileSystem \\server....
Depending on the PowerShell versions available you might encounter similar problems with
Get-SmbMapping which wraps the CimClass: ROOT/Microsoft/Windows/SMB:MSFT_SmbMapping.
But has otherwise an output resembling net use.
To process the real net use output and convert to an object with properties,
you may use:
$SmbMapping = (net use) -like '* \\*' | ForEach-Object {
$Status,$Local,$Remote,$Null = $_ -split ' +',4
[PSCustomObject]#{
Status = $Status
Local = $Local
Remote = $Remote
}
}
This works at least in my German locale Win10.
(Not sure about different status messages in other locales.)

Getting Azure VM OS name using PowerShell

I have been trying to get the VM OS name from Microsoft Azure using PowerShell.
I think I am very close to the solution but I don't know where I'm going wrong.
This is the command that I am using to get the VM details:
Get-AzureRmVM -ResourceGroupName TEST -Name VF-Test1 | Select OsType
The answer I get is just blank.
When running the following command:
Get-AzureRmVM -ResourceGroupName TEST -Name VF-Test1
I get all the details that belong to that VM.
The osType property lives inside $_.StorageProfile.osDisk
Get-AzureRmVM -ResourceGroupName TEST -Name VMNAME |
Format-Table Name, #{l='osType';e={$_.StorageProfile.osDisk.osType}}
Name osType
------ ------
VMNAME Windows
Use https://resources.azure.com to explore the object representation when in doubt, or pipe to Show-Object, like i did below.
You can get resource groups' VMs by Get-AzureRmVM and classic VMs by Get-AzureVM. Both of the returning values of the two cmdlets contain OS type properties but in different paths.
For the cmdlet Get-AzureRmVM, the OS type property path is $vm.StorageProfile.OsDisk.OsType
For the cmdlet Get-AzureVM, the OS type property path is $vm.VM.OSVirtualHardDisk.OS
There exists a sample code about fetching Azure VM OS Type here: https://gallery.technet.microsoft.com/How-to-retrieve-Azure-5a3d3751
Get-AzVM -name SERVERNAME | select name, #{n="OS";E={$_.StorageProfile.OsDisk.OsType}}, #{n="Offer";E={$_.StorageProfile.ImageReference.offer}} , #{n="SKU";E={$_.StorageProfile.ImageReference.sku}}, #{n="Publisher";E={$_.StorageProfile.ImageReference.Publisher}}
RESULT:

Unable to remote to a machine running Powershell 5.0

I've come across a strange error when trying to use Invoke-Command or Enter-PSSession when the destination is running WMF 5.0 (April Preview or August pre-Release).
I haven't been able to find any reference to this on Google so I suspect it's a local/network configuration issue but I'm unsure how to track it down.
The account in question has Local Administrator permissions on both machines (Domain Group is added on both) and I can locally run any and all commands on the destination. Remote access in the opposite direction results in the same error (also running 5.0.10514).
--- Output sanitized of identifiable information and formatting adjusted to wrap better ---
# user#HOST | [2015-09-09 Wed 08:18]
C:\Windows>invoke-command -computer test {$psversiontable.psversion}
Major Minor Build Revision PSComputerName
----- ----- ----- -------- --------------
4 0 -1 -1 test
# user#HOST | [2015-09-09 Wed 08:18]
C:\Windows>enter-pssession -computer test
[test]: PS C:\Users\user\Documents> exit
# user#HOST | [2015-09-09 Wed 08:19]
C:\Windows>invoke-command -computer test {$psversiontable.psversion}
Major Minor Build Revision PSComputerName
----- ----- ----- -------- --------------
5 0 10514 6 test
# user#HOST | [2015-09-09 Wed 08:37]
C:\Windows>enter-pssession -computer test
enter-pssession : The term 'Measure-Object' is not recognized as the name of a cmdlet,
function, script file, or operable program. Check the spelling of the name, or if a path
was included, verify that the path is correct and try again.
At line:1 char:1
+ enter-pssession -computer test
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Measure-Object:String) [Enter-PSSession],
CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
# user#HOST | [2015-09-09 Wed 08:38]
C:\Windows>
Are you running your powershell session with elevated privileges (eventhough it's an Administrator accout)?
Is it working if you use a FQDN instead of the simple name? It's a known issue in some of the builds if you're using a simple name for the target.
There might be some restrictions on the commands available, if the endpoint is restricted somehow. The Measure-Object is one of the required methods needed to run in the session when using enter-pssession. This might be your issue; though hard to guess without details of your setup.
Some details on restricting commands and locking down methods in remoting:
https://www.petri.com/powershell-remoting-restricting-user-commands
There are some more details about delegated administration and proxy functions:
http://blogs.technet.com/b/heyscriptingguy/archive/2014/04/03/use-delegated-administration-and-proxy-functions.aspx
If your target is a container, you might need to configure it properly:
https://www.petri.com/managing-windows-server-containers-with-powershell-managing-containers
Hope this helps you debugging and get remoting up working:)
I ran into this problem too. In my case, using the FQDN of the server didn't fix the problem.
Someone posted about a problem caused by the PSModulePath variable.
RDP to the remote server and check the current value of $env:PSModulePath
If the path includes UNCs replace them with the name of a mapped drive (e.g. replace \myserver\public\docs with z:\docs, where z is mapped to \myserver\public)
This worked for me

Need Script to find server activation status

We have an environment with different domains and forests with and without trusts.
I need to manage the license for these with out KMS.
I want to find out the servers which are running without activated or with Grace period.
I have been trying with differnt scripts from WMIC and Powershell. But, not able to generate with clear and clean.
Below are the scripts tried. I need assistance on this.
From WMIC:
WMIC /Output:#D:\output.txt /node:#D:\serverslist.txt PATH SoftwareLicensingProduct WHERE "ProductKeyID like '%-%' AND Description like '%Windows%'" get LicenseStatus
From Powershell:
PS C:\Windows\system32> Get-CimInstance -ClassName SoftwareLicensingProduct |where PartialProductKey |select PScomputername,LicenseStatus
I need help to generate a table with computer name/IP and license status.
Thanks in advance.
Here you go, I just made a few tweaks.
For one, your code returns the LicenseStatus as a number...which is OK, but to get some real wow-factor, I consulted this chart from MSDN on what the numbers mean, and used that with a Switch Statement, within a Calulated Property to replace the number with the human-meaningful license status, giving us logic like this:
select Pscomputername,Name,#{Name='LicenseStatus';Exp={
switch ($_.LicenseStatus)
{
0 {'Unlicensed'}
1 {'licensed'}
2 {'OOBGrace'}
3 {'OOTGrace'}
4 {'NonGenuineGrace'}
5 {'Notification'}
6 {'ExtendedGrace'}
Default {'Undetected'}
}
#EndofCalulatedProperty
}}
This gives us full code, like this, and also extracts the name of the product as well. You can run this against multiple systems by just adding their names to the -ComputerName property:
Get-CimInstance -ClassName SoftwareLicensingProduct -computerName localhost,dc01,windows10 |
where PartialProductKey | select Pscomputername,Name,#{Name='LicenseStatus';Exp={
switch ($_.LicenseStatus)
{
0 {'Unlicensed'}
1 {'licensed'}
2 {'OOBGrace'}
3 {'OOTGrace'}
4 {'NonGenuineGrace'}
5 {'Notification'}
6 {'ExtendedGrace'}
Default {'Undetected'}
}
#EndOfCaltulatedProperty
}}
This gives you results like this:
PSComputerName Name LicenseStatus
-------------- ---- -------------
localhost Office 15, OfficeProPlusVL_MAK edition licensed
localhost Windows(R), ServerDatacenter edition licensed
dc01 Windows(R), ServerStandard edition licensed
Windows10 Windows(R), ServerStandard edition licensed
you may also try
$activation = (Get-CimInstance -ClassName SoftwareLicensingProduct | where ApplicationId -EQ 55c92734-d682-4d71-983e-d6ec3f16059f | where PartialProductKey).LicenseStatus
Get-CimInstance -ClassName SoftwareLicensingProduct |
where PartialProductKey |
select Name, ApplicationId, LicenseStatus

Powershell to return the value only for Cluster Resource

I am trying to evaluate a value from a powershell command for a SQL Agent setting on a clustered server using powershell. I am very new to Powershell but we want to set up a monitor to make sure that all of our Windows Server 2008 r2 clusters have this setting correct.
I did find the setting in question by using the following at a PS prompt...
cluster resource 'SQL Server Agent' /prop : RestartAction
The issue is I would like it to return just the number (either 1 or 1(0x1) would be fine) under the Value column in the following output.
Listing properties for 'SQL Server Agent':
T Resource Name Value
-- -------------------- ------------------------------ -----------------------
D SQL Server Agent RestartAction 1 (0x1)
Because this will be a monitor I need to be able to evaluate if the Value is = 1 or not and then report when it isn't. If I could get the powershell to just return the simple value I can do the rest of setting up the monitor in T-SQL.
I have been scouring the internet trying to find an answer but everything has to do with cmdlets and functions and all I want is the windows server value to be returned. Maybe it is not really that simple but I wanted to check before going down a long scripting venture.
I appreciate any help, thanks!!
Can you use the FailoverClusters module?
(Get-ClusterResource -Cluster Cluster1 -Name 'SQL Server Agent').RestartAction
If not, string parse it:
PS> $clus = cluster /cluster:cluster1 resource 'SQL Server Agent' /prop:RestartAction
PS> $clus[10]
D SQL Server Agent RestartAction 1 (0x1)
PS> $clus[10] -replace '^.+\((.+)\)$','$1'
0x1
You can use WMI if you can't load the failoverclusters module and there's no need to parse:
gwmi -ComputerName cluster1 -Authentication PacketPrivacy -Namespace "root\mscluster" -Class MSCluster_Resource -Filter "name LIKE 'SQL Server Agent%'" |
select -ExpandProperty RestartAction