1

I have a Powershell script I want to run by C# as another user.

Here is the code to call the ps script from the current session :

using (PowerShell PowerShellInstance = PowerShell.Create())
{
    PowerShellInstance.AddScript(RemoveUser);
    PowerShellInstance.AddParameter("GID", GID);
    try
    {
        PowerShellInstance.Invoke();
        return true;
    }
    catch (Exception e)
    {
        Debug.WriteLine(e.StackTrace);
    }
    return false;
}

This code works perfectly. But now I want to execute it as another user. I saw a lot of code sample talking about a WSManConnectionInfo so I tried this piece of code found in another question :

var password = new SecureString();
Array.ForEach("myStup1dPa$$w0rd".ToCharArray(), password.AppendChar);
PSCredential credential = new PSCredential("anotherUser", password);
WSManConnectionInfo connectionInfo = new WSManConnectionInfo() { Credential = credential };

using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
{
    runspace.Open();
    using (PowerShell PowerShellInstance = PowerShell.Create())
    {
        PowerShellInstance.Runspace = runspace;
        PowerShellInstance.AddScript(RemoveUser);
        PowerShellInstance.AddParameter("GID", GID);
        try
        {
            PowerShellInstance.Invoke();
            return true;
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.StackTrace);
        }
        return false;
    }
}

But at the moment I add a WSManConnectionInfo, I get a "PSRemotingTransportException" saying that Connecting to remote server localhost failed. It seems normal because There isn't anything waiting for a connection to my localhost and I don't want to add one. The runspace works when I implement it like that :

using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
    runspace.Open();
    using (PowerShell PowerShellInstance = PowerShell.Create())
    {
        PowerShellInstance.Runspace = runspace;
        PowerShellInstance.AddScript(RemoveUser);
        PowerShellInstance.AddParameter("GID", GID);
        try
        {
            PowerShellInstance.Invoke();
            return true;
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.StackTrace);
        }
        return false;
    }
}

It seems that there isn't any remote connection implemented, even if we are in localhost. So can I just add some credentials for another user to execute this code and avoid the remote connection ?

Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
M. Ozn
  • 1,018
  • 1
  • 19
  • 42
  • why do you want to run it as another user? I often run commands within PowerShell as another user. would that suit your case? – Guenther Schmitz Jan 29 '18 at 17:29
  • It could if I can pass it throught C# to avoid prompt.In fact we have a normal user account and a duplicated one with the admin rights. For a couple of PS scripts, the application have to execute it as an admin user, so another account (for example : normal account : 12aaa, admin account : 12aaa-admin) – M. Ozn Jan 29 '18 at 17:46
  • What's the content of the powershell script you're running? Must the whole script run as the other user or are there only particular commands? I'm wondering if you could push the credentials inside the powershell script and pass them in, say, the `-Credentials` parameter of relevant cmdlets. – veefu Jan 30 '18 at 01:19
  • It only contains a RemoveADUser command. In this case the whole script can be running as another user. Can I ask and store the password for example at the beginning of the C# script and pass it to all my Powershell scripts without prompting anything for the user with the -Credentials ? – M. Ozn Jan 30 '18 at 06:54

1 Answers1

1

You can store a credential variable in an XML file using the following:

$credential = Get-Credential
$credential | Export-Clixml -Path C:\path\to\credential.xml

Execute this with the normal account. Only the normal account will be able to load the credential using the following command:

$credential = Import-Clixml -Path C:\path\to\credential.xml

Once loaded you can execute the Cmdlet like

Remove-ADUser -Identity GlenJohn -Credential $credential -Confirm:$false

If another user tries to import the file the following error is shown:

Import-Clixml : Key not valid for use in specified state.

I recommend you watch the video https://www.youtube.com/watch?v=Ta2hQHVKauo which will give you an in-depth insight on storing credentials.

KR Guenther

Guenther Schmitz
  • 1,955
  • 1
  • 9
  • 23
  • Thanks for your answer. Instead of an xml file, can I ask for it at the beginning of my C# script then pass it through param to my Powershell Script ? The reason is that there will be a lot of different user for this application so I prefer to ask for the password at the beginning of the use and do not store it out of the application. The second reason is that our password have to be changed monthly so it not a must have to store it outside the application – M. Ozn Jan 30 '18 at 08:50
  • If you run `$credential = Get-Credential` in your script the user will be prompted to enter them. No need to ask them within C# and pass them to PowerShell IMHO. – Guenther Schmitz Jan 30 '18 at 08:58
  • The problem is my C# call multiples times several different Powershell scripts. It would be better if the user enter one and only one time his password instead of being prompted to re-enter it everytime a ps script is called – M. Ozn Jan 30 '18 at 09:20
  • 1
    have a look at this https://stackoverflow.com/questions/5592531/how-to-pass-an-argument-to-a-powershell-script – Guenther Schmitz Jan 30 '18 at 10:14