How to find module for a cmdlet - powershell

Multiple times I've tried finding the right module to import into Powershell to get certain cmdlets, but I could not figure it out. Currently I'm looking for: Add-MailboxFolderPermission
I've tried the following which returns no results:
Find-Command -Name Add-MailboxFolderPermission
When I get the module name I want to install it using the Install-Module "module name" cmdlet.

Install the Exchange Management Tools from the Exchange installation media
The command will then be available as part of the Exchange module

from cmd cd to the installation media then run:
setup.exe /mode:install /role:mt /IAcceptExchangeServerLicenseTerms.
This will install the management tools.
Note: you may need some prerequisites, but if the installation fails it will generally tell you what it needs. IIS management tools come to mind.
The Exchange Management Shell (ESM) always uses PowerShell implicit remoting to build local proxy functions. They do this so they can enforce role based access control, but it also means it doesn't load like a typical module.
Aside from launching the shortcut there are a few ways to load the ESM :
. 'C:\Program Files\Microsoft\Exchange Server\V15\bin\RemoteExchange.ps1'
. "C:\Program Files\Microsoft\Exchange Server\V15\bin\CommonConnectFunctions.ps1"
. "C:\Program Files\Microsoft\Exchange Server\V15\bin\ConnectFunctions.ps1"
Connect-ExchangeServer -auto -AllowClobber
This is for Exchange 2013 I presume 16 & 19 are similar.
I prefer this approach, it's more native, and in my experience more reliable. If you dig through how the EMS shortcut launches it does exactly the same thing.
You can also add the snapin like below but again I don't usually do that. However, it will often be the answer given in the Internet:
add-pssnapin Microsoft.Exchange.Management.PowerShell.E2010
If you don't want to or can't install the management tools a 3rd approach is to use implicit remoting directly like:
$Session = New-PSSession -ConnectionUri "http://<serverName>/powershell" -ConfigurationName Microsoft.Exchange -Authentication Kerberos
Import-PSSession $Session
This is really cool, but the down side is the objects returned as string based objects. For interactive use this is usually ok but for scripting or any time you're relying on on a specific object structure it could be a problem.
One last thing: some cmdlets may not be available if the user account doesn't have RBAC access to them. If you are in the organizational management role group you generally don't have to worry. But if a specific cmdlet is missing even though you've loaded up the shell RBAC is the place to look.
Sorry if I over-killed it, Let me know how it goes.

Exchange was Microsoft's first product with PowerShell support so they did some strange things with how their distributed the module.
With that said, they have a modern approach now in beta:
https://learn.microsoft.com/en-us/powershell/exchange/exchange-online/exchange-online-powershell-v2/exchange-online-powershell-v2?view=exchange-ps
that contains new, improved commands for Exchange Online as well as contains a backwards compatibility version of all the old commands. This module can be installed from the standard, common, public PowerShell repository.

Related

How to remotely execute an remote script in PowerShell

First off: This is not a duplicate of How to remote execute an ELEVATED remote script in PowerShell.
My scenario is similar but different in a certain way. What I want to do is the following:
Invoke-Command -UseSSL -ComputerName "$COMPUTER" -FilePath \\script.example.com\secretshare$\install_test.ps1 -ArgumentList 'U'
As the called script performs an installation and manipulates firewall rules, it needs elevated privileges. Irritatingly the error I get is an access error on the share mentioned above.
When I use this suggestion where I use PowerShell DSC, which is run as SYSTEM, it works. But only on Servers running Windows Management Framwork 4.0. So obviously I need a solution for Windows Server 2008 (R2) systems.
I hope someone can point me to the right direction so I can update this question to help other admins aswell.

Is it possible to delete or overwrite cmdlets?

I'm working with DNS resource records in Powershell 5 using code that I inherited from the guy who was trying to do this before me. The cmdlet I am trying to use is Add-DnsServerResourceRecordA.
Part of his code has import-module certain folder\PowerShell\Modules\DnsServer. The weird thing is, it seems like as I was trying bits and pieces of the code earlier, I was able to use the add-DNSblah cmdlet. Now, after It ried running the whole script including the import-module, Powershell is saying that the cmdlet does not exist natively, and when I import the module and run it it is giving me Add-DnsServerResourceRecordA: Invalid Class.
It is my understanding that Add-DnsServerResourceRecordA should be included in my normal Powershell 5.0. Could that Import-Module have permanently damaged PS somehow? Why else would the cmdlet not show up, even in a Get-Command "dns"?
I'm pretty sure you will need the Remote Server Administration Tools (RSAT) installed to have these cmdlets available on a non-server Windows OS.
You can download them from this page: https://www.microsoft.com/en-gb/download/details.aspx?id=45520.
Not really sure why the Import-Module does not fail if the DNSServer module is not present on the system.
If RSAT are already installed, you can try to reinstall them.

There is no Get-GacAssembly cmdlet

Windows 8.1, PowerShell 4. I'm wanting to use PS to manage the GAC. I find lots of references to Get-GacAssembly for reading a list, getting detailed info, etc.
But running PS as administrator, and PS ISE, I get an error:
>
The term 'Get-GacAssembly' is not recognized as the name of a cmdlet
Do I need to CD to somewhere? How would I discover where to go to find the cmdlets?
The general answer to your question is that you must first install the module (by adding relevant files to Documents\Powershell\Modules or Windows\System32\WindowsPowershell\v1.0\Modules. Then, you should use Import-Module to load the cmdlets. Cmdlets in Windows\System32\WindowsPowershell\v1.0\Modules should be loaded by default. Script modules (e.g., modules that export functions) require at least RemoteSigned execution settings to run.

How can I include KB2670838 in an installer with InstallShield 2013?

I'm using InstallShield 2013 to make a Basic MSI installer for an application that requires Windows Platform Update KB2670838.
For .NET frameworks and other requirements, I select them in InstallShield in the Redistributables section. KB2670838 is not available.
If I download KB2670838 from Microsoft I get a .msu file. Can that be included in the installer somehow so that it automatically installs if needed? If not, is there a way to stop the install and tell the user that "KB2670838 is required but not installed. Get it here..."?
In InstallShield, you should typically deliver this sort of update as a prerequisite (Tools > Prerequisite Editor), or as a package included in a Suite (reference [SystemFolder]wusa.exe to install an .msu file). In both cases this keeps the redistributable installation logically separate from your package's installation, while providing your users a single installer experience.
Glytzhkof mentions several really good points about how to determine whether the update has been installed. You will want to incorporate these into your conditions (on the prerequisite or suite package), and also into detecting the update or lack thereof in your .msi package so it can abort if the required update has not been installed by the time the .msi is launched.
The Add/Remove programs list in the registry could help you get a rough idea of what's installed:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
It seems this doesn't provide a full list of what is installed though: http://social.technet.microsoft.com/Forums/windows/en-US/d913471a-d7fb-448d-869b-da9025dcc943/where-does-addremove-programs-get-its-information-from-in-the-registry?forum=w7itprogeneral
Another way may be to use the file information from the knowledge base article:
http://support.microsoft.com/kb/2670838/en (For More Information : File Information) and use WIX / MSI's AppSearch / LaunchCondition feature. That should do the trick, though I find the syntax a bit counterintuitive.
Another approach is to write a custom action and combine these two sources (add /remove entry and file info). Such a custom action will make no changes to the system, and is hence less problematic than other custom actions that cause rollback-problems. I find it easier to test and maintain a custom action in case there are further prerequisites that are needed at some point. This is a matter of taste though. I just find it easier to run a prerequisite script against a selection of files to test that it identifies them correctly and run through as expected than to keep running the MSI file for every test.
Here is a similar question with some pointers from superuser.com:
https://superuser.com/questions/521175/determine-if-windows-hotfix-has-been-applied
And another link to serverfault.com (system administration site). Nice approach using PowerShell which can certainly be migrated to a custom action:
https://serverfault.com/questions/312778/determine-if-user-has-hotfix-981889-installed
Even more serverfault.com stuff involving update.exe, WMI and a Powershell script to view all installed hotfixes:
https://serverfault.com/questions/263847/how-can-i-query-my-system-via-command-line-to-see-if-a-kb-patch-is-installed . Recommended read. Microsoft: http://technet.microsoft.com/en-us/library/hh849836.aspx
PSInfo appears to be able to show installed hotfixes: http://technet.microsoft.com/en-us/sysinternals/bb897550
#Glytzhkof Good point. So how do I get InstallShield to abort and give the user a nice message so they know what to do? – shoelzer 1 hour ago
I will just add a new answer then - too long to write in a comment.
Locate the file details you need to scan for under "For More
Information : File Information" in this kdb article:
http://support.microsoft.com/kb/2670838/en
Select a few files to scan for and add as file searches in Installshield (see below screenshot). You specify a property for each file (FILE1FOUND, FILE2FOUND, FILE3FOUND, etc...), and if the search matches the file details (version, size, date, etc...) the property is set to the full path of the file. Otherwise the property is undefined or set to a default value (screenshot shows predefined search, and not file search, but you get the idea).
Finally you add LaunchCondition entries for each file to ensure that all files you have selected to check are the correct version or higher. I guess this is in Prerequisites or similar - I can't recall. Open the compiled MSI and check that it looks like the LaunchConditon table.
For the record: (not part of above suggestion)
Personally I am in favor of coding a single script for complex logic like this to ensure the logic can be inspected as a whole and crucially tested as a whole outside the MSI file. It is also good to add comments to such code to explain what the script is checking, and why (helps corporate deployment). A script can be run through dozens of tests against the machine directly without recompiling the MSI. This can save a lot of time if the logic is complex. If you write a compiled dll you can show a message box and attach the visual studio debugger to the msiexec.exe process (client or server depending on what context your custom action is running in) and step-through the code whilst embedded in the MSI, but this seems out of scope for your scenario. Just want to mention it for other people who might read this. Also check Stefan Kruger's installsite.com for more information on complex setup debugging like this.
It is important to note that scripting is never generally recommended for scenarios where the script makes changes to the system - if there is a built-in MSI way to achieve the same result. The reason for this is that a script that makes changes to a machine will need a separate rollback-operation to be specified for it for the MSI to follow best practice. This can be a spectacular amount of work and complexity to get right. The above script would only check system conditions, so there is no need for rollback support.
Let me try and add a reference style answer since my other answer is a bit organic to say the least at this point - I will leave it in since it contains an MSI discussion. See MSI recommendation in the middle section below:
WMI:
wmic qfe where "HotfixID = 'KB973687'"
PowerShell: (just get-hotfix for full list)
get-hotfix | findstr "981889"
SystemInfo (remove arguments for list format):
systeminfo /fo csv
PSInfo (seems to not list everything on all machines, and may not run silently properly):
PSinfo -h
Registry (apparently not complete list of hotfixes):
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
For MSI custom action use, I would actually use a custom action that inspects file versions as explained in my other answer. Very reliable, and takes into account that the hotfix may be deprecated whilst the files are still up to date.
References:
Recommended: https://serverfault.com/questions/263847/how-can-i-query-my-system-via-command-line-to-see-if-a-kb-patch-is-installed
How do I get a list of installed updates and hotfixes?
SystemInfo: https://serverfault.com/questions/334552/how-to-check-that-a-known-windows-vulnerability-has-been-patched
http://windowsitpro.com/scripting/get-hotfix-information-quickly-wmic
https://serverfault.com/questions/69467/list-all-hotfixes-applied-to-windows-server
wmic in general: http://technet.microsoft.com/en-us/library/bb742610.aspx
Recommended: http://www.dedoimedo.com/computers/windows-wmic.html
http://www.techsupportalert.com/content/quick-and-easy-way-list-all-windows-updates-installed-your-system.htm
http://pario.no/2011/06/19/list-installed-windows-updates-using-wmic/
Had the same issue and solved it by adding a prerequisite of a PowerShell script and a batch file to execute it.
The pre.ps1 file looks something like this:
function TestConnection
{
Test-Connection -ComputerName "8.8.8.8" -Quiet
}
get-hotfix -id KB2670838
if(!$?){
#SourceURI = "https://download.microsoft.com/download/1/4/9/14936FE9-4D16-4019-A093-5E00182609EB/Windows6.1-KB2670838-x64.msu";
#$FileName = $SourceURI .Split('/')[-1]
#$BinPath = Join-Path $DownloadPath -ChildPath $FileName
Invoke-Webrequest -Uri $SourceURI -OutFile $BinPath
#Start-Process -FilePath $BinPath -ArgumentList "/q /norestart" -Wait -NoNewWindow
}
the pre.cmd file looks something like this:
#echo off
::set PS_FILE=%~dp0Prerequisite.ps1
set PS_FILE=%~dpn0.ps1
set PS_EXEC_PATH=%SystemRoot%\sysnative\WindowsPowerShell\v1.0\
set PS_EXEC_PATH=%SystemRoot%\System32\WindowsPowerShell\v1.0\
::set PS_EXEC_PATH=%SystemRoot%\SysWOW64\WindowsPowerShell\v1.0\
set PS_EXEC_PATH=
set PS_EXEC=%PS_EXEC_PATH%powershell.exe
echo %PS_EXEC%
echo %PS_FILE%
::%PS_EXEC% -file %PS_FILE% set-executionpolicy remotesigned
::%PS_EXEC% -NoProfile -ExecutionPolicy Bypass -Command "& '%PS_FILE%'"
::This is with admin rights
%PS_EXEC% -NoProfile -Command "& {Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""%PS_FILE%""' -Verb RunAs}"
::pause

Powershell snap-in for exchange 2007

Ive never used powershell before but it seems like the correct tool to use to read the number and size of mailboxes on our 2007 and 2010 exchange servers. I'm running Powershell on Windows 7 and NOT on the exchange server. The commands used in the examples i have found are not recognised.
From my initial reading it appears i need the Exchange snap in. However, i can't seem to find a download page or instructions for loading it into Powershell, or if it is even possible to access this data from a workstation other than the exchange server. I was wondering if some one could give me some feedback on my problem and point me in the right direction.
thanks.
I have gotten this to work on windows 7 64 bit with exchange 2007 64
I installed the exchange management console via the exchange server 2007 installation files
you don't need to establish a remote powershell session, you run the commands with a domain/network administrator privileged powershell on the workstation.
I'm trying to get just the powershell snapin as I don't need the whole console, but as of right now, with the whole console and powershell you can load the exchange management snapin to powershell and create mail-enabled user accounts.
after installing the exchange management console you can execute
add-pssnapin microsoft.exchange.management.powershell.admin
to load the exchange snapin and begin pulling exchange data.
on top of that you may need to start the service on the exchange server "microsoft exchange system attendant"
i guess you need to establish a powershell remote session to the exchange server and run your powershell cmdlets.
You can start with having a look at the help about remote powershell
PS C:\Windows\system32> help about_Remote
Once you establish a remote powershell session to the exchange server you can add the Exchange Management Shell snap-in from Windows PowerShell
Click Start, click Programs, and then click Windows PowerShell 1.0, Click Windows PowerShell, Type the following command:
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin
Use the chdir command to change to the Exchange Server\Bin directory. For example, type:
chdir "c:\program files\microsoft\exchange server\bin"
Type the following command:
.\Exchange.ps1
Once the exchange module is loaded you can start using the various cmdlets.
I had the same problems when I was first trying to get this work, and it was never clear to me what I needed to do.
I was very new to Powershell and was trying to run the add-pssnapin without first creating a new session.
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://EXCHANGE-SERVERNAME/PowerShell/ -Authentication Kerberos -Credential $myCred
Import-PSSession $Session
Where the -ConnectionUri points to your exchange server name and the $myCred holds your admin credentials to access the server.
This will import all modules you can use against MS Exchange.
Note1: you can narrow this down to improve the speed of the import by only selecting to import certain modules you will be using. Good if, for example, you know you will only use certain tools.
You can do this by adding -CommandName and list necessary aliases you want to import.
Note2: Good practice to remove the sessions after you are finished:
Remove-PSSession $Session