C# \ Exchange 2010 PS1 Script - c#

I am trying to run a PS1 script using Exchange 2010 remote powershell and c#. I can connect and run the ps1 script but there are a few places in the script that use exchange cmdlets to update necessary user information. One cmdlet the script is using is update-recipient. The script runs fine until it trys to run this cmdlet and errors saying:
The term 'update-recipient' is not recognized as the name of a cmdlet, function, script file, or operable program.
Does anyone know if there are any restrictions on running cmdlets inside of PS1 scripts from c#?
Thanks

In order to run an Exchange 2010 powershell script from the command line, you need to load the Exchange components at the beginning of the powershell script. Add these 2 lines to your .ps1 file. Substitute your Exchange server's name for EXCHANGESERVER in the first line.
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://EXCHANGESERVER/PowerShell/ -Authentication Kerberos
Import-PSSession $Session

Try this sample code ( in know it works for Exchange 2010)
PSCredential credential = new PSCredential(#"domain\user", createPassword("Pass"));
WSManConnectionInfo connectionInfo = new WSManConnectionInfo(false, "exchange.ibm.com", 80, "/Powershell", "http://schemas.microsoft.com/powershell/Microsoft.Exchange", credential);
connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Default;
Runspace runspace = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(connectionInfo);
try
{
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
Command objCommand = new Command("");
objCommand.Parameters.Add("Identity", #"dom\user");
pipeline.Commands.Add(objCommand);
Collection<PSObject> results = pipeline.Invoke();
}
catch
{
}
finally
{
runspace.Close();
}

Or try this code for Exchange 2007 from MSFT
Runspace myRunspace = RunspaceFactory.CreateRunspace();
myRunspace.Open();
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);

Related

Why does powershell not recognize cmdlets in a script called by a windows service?

We have a windows service which runs as the local system account. It calls a PowerShell script and retrieves the output for further processing. It works like a charm under windows server 2016 but now needs to be moved to a windows server 2012 R2. On this machine, it does not recognize the azure specific cmdlets.
I tried to install the specific cmdlets via -Scope AllUsers. We also logged into the PowerShell directly as local system-user; it does recognize the cmdlets (e.g. Add-AzureRMAccount) correctly.
C#:
PowerShell psInstance = PowerShell.Create();
psInstance.AddScript(scriptBase + "getVMs.ps1");
var azureVMList = psInstance.Invoke();
getVMs.ps1:
$finalPassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential -ArgumentList $accountName, $finalPassword
$trash = Add-AzureRmAccount -Credential $psCred -TenantId $tenantID -ServicePrincipal`
We don't understand why the cmdlets are working fine under the same circumstances on server 2016 and if we run them directly as the user.
Any hint is appreciated
I suggest a workaround here, in your c# code, directly import the module which contains the cmdlet.
1.you can use this command to get the module file(I'm using az module, feel free to change to azureRm module):
(Get-Module -Name az.accounts).Path
then you can see the module file path, in my side, it's "C:\Program Files\WindowsPowerShell\Modules\Az.Accounts\1.5.2\Az.Accounts".
2.in your c# code:
InitialSessionState initial = InitialSessionState.CreateDefault();
initial.ImportPSModule(new string[] {"the full path of Az.Accounts.psd1, if it does not work, try full path of Az.Accounts.psm1"} );
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.AddScript(scriptBase + "getVMs.ps1");
var azureVMList = psInstance.Invoke();

Cannot import AzureAD module in C#

Has any one met this issue before? I plan to use C# to call AzureAD cmdlets. But I tried many ways to import the module, like:
InitialSessionState initialState = InitialSessionState.CreateDefault();
initialState.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Bypass;
initialState.AuthorizationManager = new System.Management.Automation.AuthorizationManager("O365");
initialState.LanguageMode = System.Management.Automation.PSLanguageMode.FullLanguage;
initialState.ImportPSModule(new string[] {"AzureAD" });
Runspace runspace = RunspaceFactory.CreateRunspace(initialState);
Or
pipeline.Commands.AddScript("Import-Module -Name AzureAD -Force; Get-Module");
var modules = pipeline.Invoke();
Or
pipeline.Commands.AddScript("Import-Module");
pipeline.Commands[0].Parameters.Add("Name", "AzureAD");
var modules = pipeline.Invoke()
No one can import the module. Even I use the full path "C:\Program Files\WindowsPowerShell\Modules\AzureAD\2.0.0.131\AzureAD.psd1". I have used cmdlet "Install-Module AzureAD -Force" to install the AzureAD module in my server. There is no error when I call the import-module in C#, but when I trying to use AzureAD cmdlet like 'Connect-AzureAD' I will get the error message:
The 'Connect-AzureAD' command was found in the module 'AzureAD', but the module could not be loaded.
I have tried both the 2 System.Management.Automation.dll, the issue is the same. I tried powershell 4.0, 5.0.
Any one has any ideas, please? Thanks very much.
By the way, the 1st version Azure AD module MSOnline works fine.
I enabled the -Verbose log in the import-module AzureAD cmdlet, then I checked the VERBOSE output in PowerShell.Streams.Verbose, I found there are just one record:
Loading module from path 'C:\Program Files (x86)\WindowsPowerShell\Modules\AzureAD\2.0.0.131\AzureAD.psd1'.
But it should have tens of verbose output as it does in powershell command prompt:
Thanks
-Justin
I also can repro it on my side. I resolved it by uncheck Prefer 32-bit the platform target, more detail please refer to the screenshot.
As I install the AzureADPreview module, C# code I used for test:
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript("Import-Module AzureADPreview -Force;");
pipeline.Commands.AddScript("Connect-AzureAD");
var result = pipeline.Invoke();

"The term 'New-Mailbox' is not recognized" error given from c# application

I have an application on a Windows 2012 server running Exchange 2010. Code is below:
string scriptpath = #"c:\scripts\emailtooltest.ps1";
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();
RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
Pipeline pipeline = runspace.CreatePipeline();
Command execPS = new Command(scriptpath);
pipeline.Commands.Add(execPS);
var results = pipeline.Invoke();
Console.Read();
I can execute manually when executing as administrator, but when attempting to execute through the application this exception is returned: "The term 'New-Mailbox' is not recognized as the name of a cmdlet, function, script file, or operable program." I think this is a permissions issue, and I everything I've researched seems to reference snapins, but those seem to be exclusive to Exchange 2007. Am I confused? Any ideas?

Import-Module won't work when launched from .net

I'm trying to run a powershell script within my C# web application.
When i run the following in powershell, it works fine.
Import-Module 'C:\\Program Files\\Microsoft Dynamics NAV\\80\\Service\\NavAdminTool.ps1'
Get-NAVTenant -ServerInstance DynamicsHost
But when i'm running it using my web application, it tells me
The term 'Get-NAVTenant -ServerInstance DynamicsHost' 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.
Here is my c# code:
InitialSessionState initial = InitialSessionState.CreateDefault();
initial.ImportPSModule(new string[] { "C:\\Program Files\\Microsoft Dynamics NAV\\80\\Service\\NavAdminTool.ps1" });
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.Commands.AddCommand("Get-NAVTenant -ServerInstance DynamicsHost");
foreach (PSObject result in ps.Invoke())
{
Console.WriteLine(result.ToString());
}
Can someone point me in the right direction??
UPDATE:
Using runspace.SessionStateProxy.PSVariable.GetValue("Error") i could see the following error:
Cannot bind argument to parameter 'Name' because it is null.
Cannot bind argument to parameter 'Path' because it is null.
Cannot find path 'HKLM:\SOFTWARE\Microsoft\Microsoft Dynamics NAV\80\Service' because it does not exist.
A command that prompts the user failed because the host program or the command type does not support user interaction. Try a host program that supports user interaction, such as the Windows PowerShell Console or Windows PowerShell ISE, and remove prompt-related commands from command types that do not support user interaction, such as Windows PowerShell workflows.
A command that prompts the user failed because the host program or the command type does not support user interaction. Try a host program that supports user interaction, such as the Windows PowerShell Console or Windows PowerShell ISE, and remove prompt-related commands from command types that do not support user interaction, such as Windows PowerShell workflows.
A command that prompts the user failed because the host program or the command type does not support user interaction. Try a host program that supports user interaction, such as the Windows PowerShell Console or Windows PowerShell ISE, and remove prompt-related commands from command types that do not support user interaction, such as Windows PowerShell workflows.
The error message suggests that your entire command string is interpreted as the name of a (non-existent) cmdlet. According to the documentation the AddCommand() method expects the name of a cmdlet, while parameters should be added via AddParameter().
Try changing this:
ps.Commands.AddCommand("Get-NAVTenant -ServerInstance DynamicsHost");
into this:
ps.Commands.AddCommand("Get-NAVTenant");
ps.Commands.AddParameter("-ServerInstance", "DynamicsHost");
or this:
ps.AddCommand("Get-NAVTenant");
ps.AddParameter("-ServerInstance", "DynamicsHost");
I can verify the following code works, posted from above: the following code will return the DatabaseServer name of the specified Dynamics NAV service tier
InitialSessionState initial = InitialSessionState.CreateDefault();
initial.ImportPSModule(new string[] { "C:\\Program Files\\Microsoft Dynamics NAV\\80\\Service\\NavAdminTool.ps1" });
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.Commands.AddCommand("Get-NAVTenant");
ps.Commands.AddParameter("-ServerInstance", "objectupgrade");
foreach (PSObject result in ps.Invoke())
{
Console.WriteLine(result.Properties["DatabaseServer"].Value);
}
Console.Read();
Console.ReadKey();
A better and a much quicker method is to use the Microsoft.Dynamics.Nav.Management snap-in directly. Significant performance improvement can be seen by using this method. Please see following code found here: Why does PowerShell class not load a snapin
var config = RunspaceConfiguration.Create();
PSSnapInException warning;
config.AddPSSnapIn("Microsoft.Dynamics.Nav.Management", out warning);
using (Runspace runspace = RunspaceFactory.CreateRunspace(config))
{
runspace.Open();
using (var ps = PowerShell.Create())
{
ps.Runspace = runspace;
ps.AddCommand("Get-NAVTenant");
ps.AddParameter("ServerInstance", "ObjectUpgrade");
Collection<PSObject> results = ps.Invoke();
foreach (PSObject obj in results)
{
Console.WriteLine(obj.Properties["DatabaseServer"].Value);
}
Console.Read();
Console.ReadKey();
}
}
It turned out to be that the developer web server could't handle the request. Switching to IIS as developer server solved the problem. Now both of watto's examples works.

Right runspace for psexec in script call from c#

I am writing a short c# program which execute a powershell script test.ps1. The code is the following :
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(scriptText);
pipeline.Commands.Add("Out-String");
Collection<psobject> results = pipeline.Invoke();
runspace.Close();
there is a psexec in the test.ps1 but when I run the c# program I get : "psexec is not recognize as a cmdlet ...", but when I launch my script in powershell it works. Something wrong with the runspace ? (I have tried also psexec.exe and c:\windows\system32\psexec.exe)
When you download PStools you extract some files. Put those files in C:\Windows\System32 AND in C:\Windows\Systemwow64.

Categories

Resources