Difference between AddPSSnapin() vs RunspaceFactory.CreateRunspace( WSManConnectionInfo)? - powershell

I need to connect to an Exchange 2010 server using C# and Powershell. The Exchange 2007 Docs want me to add a snap in
RunspaceConfiguration rsConfig = RunspaceConfiguration.Create();
PSSnapInException snapInException = null;
PSSnapInInfo info = rsConfig.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.Admin", out snapInException);
Runspace myRunSpace = RunspaceFactory.CreateRunspace(rsConfig);
myRunSpace.Open(rsConfig);
Other samples on the net want me to use WSMan like this
WSManConnectionInfo connectionInfo = new WSManConnectionInfo(false, "ExchangeServer.ibm.com", 80, "/Powershell", "http://schemas.microsoft.com/powershell/Microsoft.Exchange", credential);
So my questions are:
What is the effective difference between these techniques?
Are they interchangeable?

In Exchange 2007 you used a management snapin in a local runspace to run the cmdlets. All the changes were made under your credentials.
In Exchange 2010 that changed. Maintenance is done through a remote session provided by the Exchange server. The actual changes are done by the Exchange server on your behalf using a proxy account, and Exchange determines whether you're authorized to make those changes according to the RBAC roles you belong to. The changes are logged in the Admin Audit log.
There is a snapin for Exchange 2010, but using it by adding it into a local session is not supported by MS, and not all of the cmdlets work properly in that environment. Most cmdlets do work, but it bypasses RBAC, and and any changes made in that environment do not get logged to the Admin Audit Log.

Your first example is simply instantiating a new Runspace on the local system, which does not use WS-MAN. The second portion is leveraging the WS-MAN service, which requires that you configure it on all of the systems you'll be connecting to ahead of time.
To be honest, if you don't need to use WS-MAN to connect to a remote system, I would just avoid it and use the Exchange team's recommended practice. WS-MAN is (read: can be) fairly simple to set up and use, but it adds a layer of complexity that may simply be unnecessary, and cause additional troubleshooting headaches.

Related

Running BitsTransfer from Local Service account

I am working on making some scripts to make my job a little bit easier.
One of the things i need is too download some files to use. I first used powershell with the command Invoke-WebRequest.
It is working really well, however it dont run on windows 7 computeres, as they have powershell 2. As i have about as many windows 7 pc's as win 10 i need to find another way.
I found that Start-BitsTransfer is a good way that should work on most computeres. My problem now is, that when using the script via my remote support session it runs the script on the local service account, and then BitsTransfer wont run and gives me an error. (0x800704DD)
Is there a way to get around that problem, or any command that can be used on both win 7 and 10 and run from the local service account?
You should update PowerShell as gms0ulman states, but if you are not the person who is in charge of this decision, you have to take other steps.
This error code...
0x800704DD
The error message ERROR_NOT_LOGGED_ON, occurs because the System Event Notification Service (SENS) is not receiving user logon notifications. BITS (version 2.0 and up) depends on logon notifications from Service Control Manager, which in turn depends on the SENS service. Ensure that the SENS service is started and running correctly.
By default, BITS runs under the LocalSystem account. To modify, stop or restart BITS, you must be logged on as an administrator. In your situation, when you log on a regular account and start the PS in elevated privilege, the BITS doesn’t run under regular user account. To resolve it, you may need to configure the log on user for BITS. Please visit the following link to configure how a service is started.
Configure How a Service is Started
Services are often run with default settings — for example, a service
may be disabled automatically at startup. However, you can use the
Services snap-in to change the default settings for a service. This is
useful if you are troubleshooting service failures or if you need to
change the security account under which a service runs. Membership in
Account Operators or Domain Admins, Enterprise Admins, or equivalent,
is the minimum required to complete this procedure. Review the details
in "Additional considerations" in this topic.
https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc755249(v=ws.10)
I also agree that you should not continue supporting PowerShell 2.0. Ideally, ditch Windows 7 (it's way too old now), if you can't do that, upgrade PowerShell, if you can't do that, find a new job, if you can't do that, then I guess bring on the workarounds!
postanote's answer covers the BITS angle.
The other thing you can do is just use the .Net framework's underlying libraries, which is exactly what Invoke-RestMethod and Invoke-WebRequest do (those cmdlets were introduced in PowerShell 3.0, but the guts of them were around much longer).
try {
$wc = New-Object -TypeName System.Net.WebClient
$wc.DownloadFile($url, $path)
finally {
$wc.Dispose()
}
Most people don't bother disposing IDisposable objects in PowerShell so you'll see a lot of shorthand around like this:
(New-Object Net.WebClient).DownloadFile($url, $path)
Which is probably fine if your script's process isn't going to be around for a while, but it's good to keep in mind in case you incorporate this into something of a larger scale.

Remote execute Power Shell scripts to collect data

I am looking to collect data snapshot on a random interval from various machines in our network that we don't own, but may get access to install an agent to collect these data.
These machines are either in a domain or work-group and kind of data i get are based on the role they play and information they have. The machines are "Windows Server 2003" and above and I do not want to install anything on those machines before i get started, so thought I can use the PowerShell scripts that I can remote invoke form my server and pass the script it has to run to return the data.
I was wondering if this is possible to do that with the PowerShell scripts and as this is supposed to run in a secure environment, is there any major security implications with this approach. i.e. do I need to do anything on the client machines that can make them vulnerable to security threats.
BTW these machines are not exposed to internet and are behind a firewall.
I would appreciate if you point me to any other alternatives that can be useful for my analysis.
Regards
Kiran

Determine MS Exchange server role via WMI and Perl

We are working on a project that will require us to determine the exact role of an Exchange server through WMI, using Perl. It looks as if there was a WMI namespace for Exchange that was deprecated some time ago (possibly with 2003?). Is there a way to query through WMI to determine the role of an individual server for Exchange 2007/2010/2013?
No, WMI is not supported in versions of Exchange starting with Exchange 2007. Per Development technologies for earlier versions of Exchange, the Exchange Management Shell is the recommended replacement for WMI -"Exchange Management Shell commands that work with versions of Exchange starting with Exchange 2007 replace the WMI providers in Exchange 2003. Because Exchange Management Shell commands that enable you to control Exchange servers, storage groups, databases, and users are easier to use than the corresponding WMI providers and objects, you can easily migrate your applications to Exchange Management Shell commands." Hope that helps!

How to find out the Exchange server name from within standard PowerShell (not EMS)?

Let's say I would like to check some user mailbox properties from within PowerShell. I can run the script in Exchange Management Shell but the problem is that I have no guarantee that the end user will be running the script directly on Exchange or a machine with any Exchange tools. So, I can tell the end user to just run the script in the PowerShell (not EMS) and encode importing pssesion into the script.
However, here comes the main problem of mine, I cannot hard-code the server name into the script (it will be used in many different environments) and I would like to avoid asking the end user to provide the Exchange Server name for the pssesion.
Is there any way to obtain the Exchange Server name automatically with just vanilla PowerShell (no EMS, etc.)? The script will be ran by users with domain admin privileges, most likely there will be no Outlook on the machines (so no MAPI profiles configuration), if that is of any help.
I'm not sure how portable this is (it works on my E2K7 setup, but your mileage may vary)...
You can look in AD to get a list of exchange servers by doing something like the following:
$exchangeServers = [ADSI]"LDAP://contoso.com/CN=Exchange Servers,OU=Microsoft Exchange Security Groups,DC=contoso,DC=com"
$exchangeServers.Member
In my environment, this lists all of the exchange server computer accounts, plus a few other groups, but it's a starting point.

PowerShell Remoting to many servers across domains

I am DBA. I am trying to write bunch of scripts that I could execute from one central server. Ideal would be to send all the scripts from central server to say 50+ servers across multiple win domains (for databases management purposes).
The problem I am running into is - security. Seems like PowerShell Remoting is the way to go. But when I send a script to another server, I get 'not digitally signed' error.
I could 'self sign'. But that cert if only trusted on local machine. So that option is out.
Maybe Certificate Authority is a way to go. Or adding trusted hosts. I just have no clue on this one, so if you know any blog posts or how to do this - it would be big help.
Well, it's a security risk, but there's always the possibility of setting the execution policy to RemoteSigned, keeping a local repository on each server and calling those as needed via PS-Remoting. I don't like that idea one bit though.
If you are doing remote execution, you will need to sign your scripts. A detailed step by step can be found here. It even covers deploying the cert via GPO so that it's domain trusted.
I would use PowerShell remoting. This would allow you to run it as remote commands instead of remote scripts. If you catch the bottom of this SimpleTalk article, after "Persistent Sessions". It shows the option of executing a set of commands against each server instead of the script. This should prevent having to deal with the remote signed issue and provide a little more control.
The only thing to deal with on remote sessions is your credentials. I have not tried this on multiple domains but a few stand-alone servers.