Slow PowerShell execution of Microsoft Exchange 2013 commands from c# - c#

I have the following code that executes an exchange cmdlet. It works fast with command that return some output but work slow if command has no output.
for example
Invoke("Get-Mailbox")
print following output:
Begin execution at 11:44:43
Finish execution at 11:44:51
Output :
Administrator
Discovery Search Mailbox
Artem Romanchik
Execution time was about 8 second(6 second for loading exchange snappin + 2 seconds for command execution)
Slow example is Invoke("Set-Mailbox -identity tema -MaxSendSize 10MB")
Begin execution at 11:53:34
Finish execution at 11:54:36
Output :
Now it was 62 seconds(2 seconds for command and 60 seconds of waiting for something)
How can I reduce execution time of second example?
Invoke method code:
public void Invoke(string command)
{
var config = RunspaceConfiguration.Create();
PSSnapInException warning;
config.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.Snapin", out warning);
using(var runspace = RunspaceFactory.CreateRunspace(config))
{
runspace.Open();
using(var _psInstance = new RunspaceInvoke(runspace))
{
var psCommand = new PSCommand();
Console.WriteLine(String.Format("Begin execution at {0}", DateTime.Now.ToLongTimeString()));
var result = _psInstance.Invoke(command);
Console.WriteLine(String.Format("Finish execution at {0}", DateTime.Now.ToLongTimeString()));
var output = "";
foreach (var line in result)
{
if (line == null)
continue;
output += "\n" + line.BaseObject.ToString();
}
Console.WriteLine(String.Format("Output: {0}", output));
runspace.Close();
}
}
}

Set-Mailbox will accept multiple identity parameters
From Get-Help Set-Mailbox:
Identity:
The Identity parameter specifies the mailbox.
This parameter accepts the following values:
•Alias
Example: JPhillips
•Canonical DN
Example: Atlanta.Corp.Contoso.Com/Users/JPhillips
•Display Name
Example: Jeff Phillips
•Distinguished Name (DN)
Example: CN=JPhillips,CN=Users,DC=Atlanta,DC=Corp,DC=contoso,DC=com
•Domain\Account
Example: Atlanta\JPhillips
•GUID
Example: fb456636-fe7d-4d58-9d15-5af57d0354c2
•Immutable ID
Example: fb456636-fe7d-4d58-9d15-5af57d0354c2#contoso.com
•Legacy Exchange DN
Example: /o=Contoso/ou=AdministrativeGroup/cn=Recipients/cn=JPhillips
•SMTP Address
Example: Jeff.Phillips#contoso.com
•User Principal Name
Example: JPhillips#contoso.com
It's taking so long because it's having to search all the mailboxes looking for any of those properties in every mailbox that match the identity string you've given it.
You can speed that up by first doing a Get-Mailbox using a filter that specifies exactly which property you're using for identity. If it doesn't find the mailbox, don't try to do the set.
Beyond that, I think you'd be much better off switching to using implicit remoting instead of loading the snap in. It's much faster to set up a PS Session connection to one of the management sessions on the Exchange server and then use Invoke-Command to run the Exchange cmdlets in that session. It also eliminates the need to have the Exchange management tools installed where you're running the script and keep them updated every time you add a service pack or RU to your Exchange servers.

Related

Executing elevated powershell scripts from C# in .NET Core 3.0

I'm calling a self-elevating powershell script from C# code. The Script resets DNS Settings.
The script works fine when called from unelevated powershell, but takes no effect when called from C# code with no exceptions thrown.
My Execution policy is temporarily set on unrestricted and I'm running Visual Studio as Admin.
Does anyone know what's wrong?
The C#:
class Program
{
static void Main(string[] args)
{
var pathToScript = #"C:\Temp\test.ps1";
Execute(pathToScript);
Console.ReadKey();
}
public static void Execute(string command)
{
using (var ps = PowerShell.Create())
{
var results = ps.AddScript(command).Invoke();
foreach (var result in results)
{
Console.WriteLine(result.ToString());
}
}
}
}
The script:
# Get the ID and security principal of the current user account
$myWindowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent();
$myWindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($myWindowsID);
# Get the security principal for the administrator role
$adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator;
# Check to see if we are currently running as an administrator
if ($myWindowsPrincipal.IsInRole($adminRole))
{
# We are running as an administrator, so change the title and background colour to indicate this
$Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)";
$Host.UI.RawUI.BackgroundColor = "DarkBlue";
Clear-Host;
}
else {
# We are not running as an administrator, so relaunch as administrator
# Create a new process object that starts PowerShell
$newProcess = New-Object System.Diagnostics.ProcessStartInfo "PowerShell";
# Specify the current script path and name as a parameter with added scope and support for scripts with spaces in it's path
$newProcess.Arguments = "& '" + $script:MyInvocation.MyCommand.Path + "'"
# Indicate that the process should be elevated
$newProcess.Verb = "runas";
# Start the new process
[System.Diagnostics.Process]::Start($newProcess);
# Exit from the current, unelevated, process
Exit;
}
# Run your code that needs to be elevated here...
Set-DnsClientServerAddress -InterfaceIndex 9 -ResetServerAddresses
As you've just determined yourself, the primary problem was that script execution was disabled on your system, necessitating (at least) a process-level change of PowerShell's execution policy, as the following C# code demonstrates, which calls
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass before invoking the script file (*.ps1):
For an alternative approach that uses the initial session state to set the per-process execution policy, see this answer.
The approach below can in principle be used to persistently change the execution policy for the current user, namely by replacing .AddParameter("Scope", "Process") with .AddParameter("Scope", "CurrentUser")
Caveat: When using a PowerShell (Core) 7+ SDK, persistent changes to the local machine's policy (.AddParameter("Scope", "LocalMachine")) - which require running with elevation (as admin) - are seen by that SDK project only; see this answer for details.
Caveat: If the current user's / machine's execution policy is controlled by a GPO (Group Policy Object), it can NOT be overridden programmatically - neither per process, nor persistently (except via GPO changes).
class Program
{
static void Main(string[] args)
{
var pathToScript = #"C:\Temp\test.ps1";
Execute(pathToScript);
Console.ReadKey();
}
public static void Execute(string command)
{
using (var ps = PowerShell.Create())
{
// Make sure that script execution is enabled at least for
// the current process.
// For extra safety, you could try to save and restore
// the policy previously in effect after executing your script.
ps.AddCommand("Set-ExecutionPolicy")
.AddParameter("Scope", "Process")
.AddParameter("ExecutionPolicy", "Bypass")
.Invoke();
// Now invoke the script and print its success output.
// Note: Use .AddCommand() (rather than .AddScript()) even
// for script *files*.
// .AddScript() is meant for *strings
// containing PowerShell statements*.
var results = ps.AddCommand(command).Invoke();
foreach (var result in results)
{
Console.WriteLine(result.ToString());
}
// Also report non-terminating errors, if any.
foreach (var error in ps.Streams.Error)
{
Console.Error.WriteLine("ERROR: " + error.ToString());
}
}
}
}
Note that the code also reports any non-terminating errors that the script may have reported, via stderr (the standard error output stream).
Without the Set-ExecutionPolicy call, if the execution policy didn't permit (unsigned) script execution, PowerShell would report a non-terminating error via its error stream (.Streams.Error) rather than throw an exception.
If you had checked .Streams.Error to begin with, you would have discovered the specific cause of your problem sooner.
Therefore:
When using the PowerShell SDK, in addition to relying on / catching exceptions, you must examine .Streams.Error to determine if (at least formally less severe) errors occurred.
Potential issues with your PowerShell script:
You're not waiting for the elevated process to terminate before returning from your PowerShell script.
You're not capturing the elevated process' output, which you'd have to via the .RedirectStandardInput and .RedirectStandardError properties of the System.Diagnostics.ProcessStartInfo instance, and then make your script output the results.
See this answer for how to do that.
The following, streamlined version of your code addresses the first point, and invokes the powershell.exe CLI via -ExecutionPolicy Bypass too.
If you're using the Windows PowerShell SDK, this shouldn't be necessary (because the execution policy was already changed in the C# code), but it could be if you're using the PowerShell [Core] SDK, given that the two PowerShell editions have separate execution-policy settings.
# Check to see if we are currently running as an administrator
$isElevated = & { net session *>$null; $LASTEXITCODE -eq 0 }
if ($isElevated)
{
# We are running as an administrator, so change the title and background color to indicate this
$Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)"
$Host.UI.RawUI.BackgroundColor = "DarkBlue"
Clear-Host
}
else {
# We are not running as an administrator, so relaunch as administrator
# Create a new process object that starts PowerShell
$psi = New-Object System.Diagnostics.ProcessStartInfo 'powershell.exe'
# Specify the current script path and name as a parameter with and support for scripts with spaces in its path
$psi.Arguments = '-ExecutionPolicy Bypass -File "{0}"' -f
$script:MyInvocation.MyCommand.Path
# Indicate that the process should be elevated.
$psi.Verb = 'RunAs'
# !! For .Verb to be honored, .UseShellExecute must be $true
# !! In .NET Framework, .UseShellExecute *defaults* to $true,
# !! but no longer in .NET Core.
$psi.UseShellExecute = $true
# Start the new process, wait for it to terminate, then
# exit from the current, unelevated process, passing the exit code through.
exit $(
try { ([System.Diagnostics.Process]::Start($psi).WaitForExit()) } catch { Throw }
)
}
# Run your code that needs to be elevated here...
Set-DnsClientServerAddress -InterfaceIndex 9 -ResetServerAddresses

Get users who did not login to exchange server for the past 120 days using powershell script in C#

I have an web application that needs to connect to Exchange server and get list of users who did not login to the mailbox in the last 120 days.
This needs to be done using powershell script in C#.
The code uses powershell script to find the users who have not logged in to exchange server in 120 days. When trying to use the script mentioned in the code it returns count as 0 but there are many users who have not logged in the past 120 days.
Below the current code.
using System;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Security;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Collections.ObjectModel;
using System.DirectoryServices;
namespace Exchange
{
public partial class NoLoginLast120Days : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string serverAddress = "my server address", runasPassword = "serverpassword", runasUsername = "server username";
// Prepare the credentials that will be used when connecting
// to the server. More info on the user to use on the notes
// below this code snippet.
SecureString ssRunasPassword = new SecureString();
foreach (char x in runasPassword)
ssRunasPassword.AppendChar(x);
PSCredential credentials = new PSCredential(runasUsername, ssRunasPassword);
// Prepare the connection
var connInfo = new WSManConnectionInfo(
new Uri("https://" + serverAddress + "/PowerShell"),
"http://schemas.microsoft.com/powershell/Microsoft.Exchange",
credentials);
connInfo.AuthenticationMechanism = AuthenticationMechanism.Basic;
connInfo.SkipCACheck = true;
connInfo.SkipCNCheck = true;
// Create the runspace where the command will be executed
var runspace = RunspaceFactory.CreateRunspace(connInfo);
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
Command getStatistics = new Command("Get-MailboxStatistics");
getStatistics.Parameters.Add("Filter", "$_.Lastlogontime -lt (get-date).AddDays(-1000)");
ps.Commands.Add(getStatistics);
Collection<PSObject> commandResults = ps.Invoke();
runspace.Close();
runspace.Dispose();
}
}
}
Update:
I tried getStatistics.Parameters.Add("Filter", "Lastlogontime $null"); for getting results which had lastlogontime as null, it was successful.
I was able to process the commandResults.
I even tried the below for getting users with lastlogontime as not null, so I can filter the desired results using C# but it did not work out.
getStatistics.Parameters.Add("Filter", "Lastlogontime -ne $null");
Also the users count is huge that I get System.OutOfMemoryException if I try without any filters.
If there is a way to get users who have not logged in for the past 120 days using powershell script in C# it will be really helpful as I am stuck with this for a long time.
Update
Below code works in powershell. It will be really helpful to know how to use this in C#.
Get-MailboxStatistics -Server <servername> | where {$_.LastLogonTime -lt (get-date).AddDays(-120)} | ft displayName, lastlogontime
Without knowing your environment its not easy to answer. But I think the issue is a miss understanding from the timestamps you are using. So before you can use it, you need to understand the difference between Last-Logon-Timestamp and Last-Logon AD attribute:
Last-Logon-Timestamp Attribute
This is the time that the user last logged into the domain. Whenever a user logs on, the value of this attribute is read from the DC. If the value is older [ current_time - msDS-LogonTimeSyncInterval ], the value is updated. The initial update after the raise of the domain functional level is calculated as 14 days minus random percentage of 5 days. So with the default settings in place the lastLogontimeStamp will be 9-14 days behind the current date (as mentioned by Microsoft here).
Last-Logon Attribute
The last time the user logged on. This value is stored as a large integer that represents the number of 100 nanosecond intervals since January 1, 1601 (UTC). A value of zero means that the last logon time is unknown. This attribute is not replicated and is maintained separately on each domain controller in the domain. To get an accurate value for the user's last logon in the domain, the Last-Logon attribute for the user must be retrieved from every domain controller in the domain. Keep noted that your "solution" might pick different domain controller here and therefore will get different results!
This should explain your issue and why you see some "strange" results as using the Last-Logon-Timestamp is more a random value ...

What are the minimum IIS AppPool users permissions required for executing hosted Powershell via a WSManConnectionInfo WinRM 'loopback' session in C#?

I have a web service running some hosted Powershell. There is authentication at the front-end which passes credentials down to some impersonation in C#.
The application runs as the default IIS AppPool user. More or less everything ends up impersonated.
This works perfectly - although I had to tweak the .NET 'alwaysFlowImpersonationPolicy' setting as I discovered here:
Invoking Powershell via C# in a web application - issues with app pool identity
In an answer to the question above, it was also suggested I could use WinRM as an alternative method for executing the Powershell, which I didn't choose to do at the time.
For a bunch of different reasons I would like to experiment with doing away with the C# impersonation and move all of the permission elevation to WinRM. I am led to believe this is possible, although I am happy to acknowledge that it isn’t...
If I do something like this:
PSCredential psc = new PSCredential(user, password);
WSManConnectionInfo connectionInfo = new WSManConnectionInfo(new Uri("https://ahostname:5986/wsman"), "http://schemas.microsoft.com/powershell/Microsoft.PowerShell", psc);
connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Kerberos;
connectionInfo.SkipCNCheck = true;
connectionInfo.SkipCACheck = true;
using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
{
connectionInfo.EnableNetworkAccess = true;
using (PowerShell powershell = PowerShell.Create())
{
string existingScript = #"C:\Users\Administrator\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1";
string scriptFileName = Path.GetFileName(existingScript);
string scriptText = ". " + existingScript + "; " + command;
if (command_logging == true)
{
string logMessage = "Running command via PSH wrapper: " + scriptText;
Tools.logToFile(logMessage);
}
powershell.AddScript(scriptText);
Collection<PSObject> results = new Collection<PSObject>();
try
{
results = powershell.Invoke();
}
catch (Exception ex)
{
results.Add(new PSObject((object)ex.Message));
}
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject obj in results)
{
stringBuilder.AppendLine(obj.ToString());
}
string rawReturnValue = stringBuilder.ToString();
string returnValue = rawReturnValue.Replace(System.Environment.NewLine, "");
returnValue.Trim();
powershell.Dispose();
return returnValue;
}
I get a weird set of behaviour:
If my AppPool runs under the default credentials (ApplicationPoolIdentity), 99% of Powershell functions will not return anything meaningful.
The PSObject 'results' object in the snippet above returns 0. No error at all, it's almost as if it is not executing.
Some functions, 'Get-Process' for example, will return fine.
I thought perhaps my methodology may not transfer to using WSManConnectionInfo (i.e. dot sourcing the profile etc), however if I force the app to run under an administrator account, everything works perfectly (so much so I can swap my new and old Powershell 'wrapper' methods out seamlessly, running a bunch of other tests...)
The two 'default' cmdlets i tested:
'Get-Module'. This is in Microsoft.PowerShell.Core, works under the administrator account but does not work under ApplicationPoolIdentity.
'Get-Process'. Microsoft.PowerShell.Management, works under both ApplicationPoolIdentity and the administrator account.
I then wrapped 'Get-Process' in a test function, put it in my $profile and tried to call that. This works when the AppPool is running under the administrator account but not under the ApplicationPoolIdentity.
Almost certainly a permissions issue? Could someone please point me in the right direction?

The term 'New-CsOnlineSession' is not recognized as the name of a cmdlet

I am trying to run a power shell script from the c#.
When running the power shell script only, it runs successfully. But , while trying to run the same script from the c# . I get the error "The term 'New-CsOnlineSession' is not recognized as the name of a cmdlet"
Here is the code:
public static void GetLyncUsers(string userName, string password)
{
using (PowerShell powerShellInstance = PowerShell.Create())
{
var script = string.Format("$Username =\"{0}\"\n" +
"$Password =\"{1}\"\n" +
"$secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force\n" +
"$cred = new-Object System.Management.Automation.PSCredential ($Username , $secpasswd)\n" +
"$CSSession = New-CsOnlineSession -Credential $cred\n" +
"Import-PSSession $CSSession -AllowClobber\n" +
"Get-CsOnlineUser", userName, password);
// use "AddScript" to add the contents of a script file to the end of the execution pipeline.
// use "AddCommand" to add individual commands/cmdlets to the end of the execution pipeline.
powerShellInstance.AddScript(script);
// use "AddParameter" to add a single parameter to the last command/script on the pipeline.
// invoke execution on the pipeline (collecting output)
Collection<PSObject> psOutput = powerShellInstance.Invoke();
// check the other output streams (for example, the error stream)
if (powerShellInstance.Streams.Error.Count > 0)
{
// I am getting this error
//The term 'New-CsOnlineSession' is not recognized as the name of a cmdlet
}
}
Is there anything i am missing? I am new to powershell in general.
Solution:
using (PowerShell powerShellInstance = PowerShell.Create())
{
// Import-Module lynconlineconnector
powershellInstance.Commands
.AddCommand("Import-Module")
.AddArgument("lynconlineconnector");
// rest of your code ....
Why?
When running an interactive session in powershell v3 and higher, the host traps CommandNotFound, and searches every module in all the known locations. If it finds the command, it automatically loads the module, and proceeds normally.
When running same script in C#, the CommandNotFound exception isn't trapped, and hence you get the error.
Related Question(s):
PowerShell - How to Import-Module in a Runspace
#PSTip Cmdlet Discovery and Module auto-loading
I ran into the same problem. You have to install the Lync/Skype For Business Online Connector as described on Technet
The setup program copies the Skype for Business Online Connector
module (and the New-CsOnlineSession cmdlet) to your local computer.

Problem with credential chaining sequence in Windows and .NET

Problem Summary
When run in batch mode, my user identity is lost but (like a really good cliffhanger) not until the very last moment.
Problem Details
I have a PowerShell script running on WinXpSp3 that runs a script block (via Invoke-Command) on a remote machine as a particular test user (via -Session parameter) in the background (via -AsJob parameter). The session is created with this:
New-PSSession -computername $myServer -credential $myCredential
The script block performs a number of actions, culminating in running the NUnit test framework. The C# code under test records the "myTestUser" username (via Environment.UserName) so the credentials provided by PowerShell are properly received that far. This is further confirmed by Process Explorer: examining properties of nunit-console running the batch tests shows it is owned by myTestUser.
The test includes accessing a Sql Server 2008 R2 database; the connection string is set via a new SqlConnection(connectionString) call. The connection string is set up for Windows Authentication and uses this form:
Data Source=<my_db_server_name>;Initial Catalog=<my_db_name>;Integrated Security=True;Persist Security Info=True
Even though I have conclusively pushed the myTestUser credentials all the way to the C# code under test, the DB access attempt is not seeing these credentials, resulting in this error: Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'
Some supplemental info:
I have confirmed that the test user (myTestUser) has DB permissions and the NUnit test is capable of accessing the DB: When I run the NUnit test manually (via NUnit GUI) logged in as myTestUser, the test works properly and SqlProfiler clearly shows this activity with myTestUser appearing in the NTUserName column.
The same error occurs if I run locally rather than on a remote machine.
The same error occurs if I run as myself on my local machine (i.e. omitting the -credential parameter).
Question
How can I rescue myTestUser from the brink of doom and get him DB access?
2011.05.16 Update
Here is a simplified example exhibiting the same problem.
First, my test program DBFetchVersion that prints the name of the current user and the results of a simple query:
class Program
{
const string connString = ...your connection string here... ;
const string query = "SELECT getdate() [Date], substring(##version,1,charindex('-',##version)-1) +convert(varchar(100),SERVERPROPERTY('edition'))+ ' ' +convert(varchar(100),SERVERPROPERTY('productlevel')) [SQL Server Version], ##servicename [Service Name], ##servername [Server Host], db_name() [Database], user_name() [User], host_name() [Client]";
static void Main(string[] args)
{
DataView dataView;
using (var connection = new SqlConnection(connString))
{
Console.WriteLine("user = " + Environment.UserName);
using (var dataAdapter = new SqlDataAdapter(query, connection))
{
var dataSet = new DataSet();
try
{
connection.Open();
dataAdapter.SelectCommand.CommandType = CommandType.Text;
dataAdapter.Fill(dataSet, query);
}
finally { if (connection.State == ConnectionState.Open) connection.Close(); }
dataView = dataSet.Tables[0].DefaultView;
}
foreach (var item in dataView.Table.Rows[0].ItemArray)
Console.WriteLine(item);
}
}
}
And here is the Powershell script that calls the above program.
$scriptBlock = {
& "...path to my executable...\DBFetchVersion\bin\Debug\DBFetchVersion.exe"
}
$serverName = ... my server name ...
$username = "testuser"
$password = ... my user password ...
$adjPwd = $password | ConvertTo-SecureString -asPlainText -Force
$testCred = (New-Object System.Management.Automation.PSCredential($username,$adjPwd))
$mySession = New-PSSession -computername $serverName -credential $testCred
# Test Scenarios:
Invoke-Command $scriptBlock
#Invoke-Command $scriptBlock -computername $serverName
#Invoke-Command $scriptBlock -computername $serverName -credential $testCred
#Invoke-Command $scriptBlock -Session $mySession
In the list of four test scenarios at the end, the uncommented one works, printing my user name and the results of the query.
DBFetchVersion still reports I am the user with the second line, but the DB connection fails with the " Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON' " error.
The remaining two lines report the "testuser" user name, but both report the same login failure for the DB connection.
What this isolated example tells me is not that I think there is anything buggy about Powershell, .NET, or my code, but there is something with the authentication mechanism that I do not yet understand, since specifying another computer or a session both involve a path that should, in some sense, have stronger protection.
2011.08.03 Update - Eureka!
Well, Matt was correct in identifying the double-hop issue as the culprit and CredSSP authentication as the solution. Unfortunately, as I quickly found out, CredSSP requires Windows 7, so I went about setting up a couple VMs as a sandbox. CredSSP, however, was not one to easily relinquish its secrets (at least to me) as I detailed in this post on ServerFault: Cannot get CredSSP authentication to work in PowerShell
I finally was able to get CredSSP authentication to work so I could then come back to the problem I posed here in this thread. As a test, I used these 3 script blocks plugged into the PowerShell script I provided above:
$scriptBlockA = {
Write-Host ("hello, world: {0}, {1}" -f $env:USERNAME, (hostname))
}
# Simple DB test, but requires SqlServer installed!
$scriptBlockB = {
if (! (Get-PSSnapin | ? { $_.name -eq "SqlServerCmdletSnapin100" } ) )
{ Add-PSSnapin SqlServerCmdletSnapin100; }
Invoke-Sqlcmd -Query "SELECT getdate() as [Now]" -ServerInstance CinDevDB5
}
# Indirect DB test; requires .NET but not SqlServer,
# plus DBFetchVersion in home dir for targeted user.
$scriptBlockC = {
& ".\DBFetchVersion.exe"
}
Block A worked with or without CredSSP, since there is no double-hop. Blocks B and C would only work with CredSSP because they both attempt to access a remote database. QED.
Initially i read this and thought of the "double hop" issue, but the supplemental info maybe me question that though.
When you run it locally (as yourself or the testuser) what commands do you use? this:
& "...path to my executable...\DBFetchVersion\bin\Debug\DBFetchVersion.exe"
also does this work from your local machine (as either yourself or the user):
Add-PSSnapin SqlServerCmdletSnapin100;
Invoke-Sqlcmd -Query "SELECT getdate()" -ServerInstance Server
Also what OS are you using? If it is Windows 2008 and the issue is double hop you may be able to us CredSSP to avoid it.

Categories