0

So I have a script to migrate users and I want to use that script in my application to make things faster and more simple. But there is some kind of problem, that I can't crack with current code.

Code runs to error in RunScript when I start Invoking pipeline.

Note Script itself works without a problem, when I run it in PowerShell ISE as administrator

Here is my code

public class Migration
{
    private static string scriptEmail = @"Add-PSSnapin Microsoft.SharePoint.Powershell
            $url = '{0}'
            $oldIdentity = '{1}'
            $newIdentity = '{2}'
            $email = '{3}'

            $user = Get-SPUser -web $url -Identity $oldIdentity
            Move-SPUser -IgnoreSID -Identity $user -NewAlias $newIdentity
            $newUser=Get-SPUser -Identity '$newIdentity' -Web $url
            Set-SPUser -Identity $newUser -Email $email
        ";

    private static string scriptNoEmail = @"Add-PSSnapin Microsoft.SharePoint.Powershell
            $url = '{0}'
            $oldIdentity = '{1}'
            $newIdentity = '{2}'

            $user = Get-SPUser -web $url -Identity $oldIdentity
            Move-SPUser -IgnoreSID -Identity $user -NewAlias $newIdentity
            $newUser=Get-SPUser -Identity '$newIdentity' -Web $url
        ";

    /// <summary>
    /// Starts user migration proccess
    /// </summary>
    /// <param name="users">Users to migrate in order (first will be main user)</param>
    /// <param name="email">User end email</param>
    /// <param name="url">Site URL</param>
    /// <returns>Did code excecute without errors</returns>
    public static bool Start(List<WorkUser> users, string email, string url)
    {
        try
        {
            for (int i = users.Count; i > 1; i--)
            {
                string script = string.Empty;
                if (email != string.Empty) // Kui on antud email ette (lisab etteantud emaili kasutajale)
                {
                    script = string.Format(scriptEmail, url, users[i - 1].Account, users[i - 2].Account, email);
                }
                else // Kui emaili pole ette antud (kasutaja andmed jäävad samaks)
                {
                    script = string.Format(scriptNoEmail, url, users[i - 1].Account, users[i - 2].Account);
                }
                Log.WriteToLog(string.Format("Running script | {0} |", script));
                RunScript(script);
                Log.WriteToLog(string.Format("Account \"{0}\" migrated to \"{1}\"", users[i - 1].Account, users[i - 2].Account));
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
            Log.WriteToLog(ex.ToString());
            return false;
        }
        return true;
        //string res = RunScript(script);
    }

    /// <summary>
    /// Runs and excecutes PowerShell script
    /// </summary>
    /// <param name="scriptText">PowerShell script to excecute</param>
    /// <returns>Result</returns>
    private static string RunScript(string scriptText)
    {
        // create Powershell runspace 
        using (Runspace runspace = RunspaceFactory.CreateRunspace())
        {
            // open it 
            runspace.Open();

            RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
            scriptInvoker.Invoke("Set-ExecutionPolicy Unrestricted");

            // create a pipeline and feed it the script text 
            Pipeline pipeline = runspace.CreatePipeline();
            pipeline.Commands.AddScript(scriptText);

            // add an extra command to transform the script output objects into nicely formatted strings 
            // remove this line to get the actual objects that the script returns. For example, the script 
            // "Get-Process" returns a collection of System.Diagnostics.Process instances. 
            pipeline.Commands.Add("Out-String");

            // execute the script 
            Collection<PSObject> results = pipeline.Invoke();

            // close the runspace 
            runspace.Close();

            // convert the script result into a single string 
            StringBuilder stringBuilder = new StringBuilder();
            foreach (PSObject obj in results)
            {
                stringBuilder.AppendLine(obj.ToString());
            }

            // return the results of the script that has 
            // now been converted to text 
            return stringBuilder.ToString();
        }
    }
}

Error, that I am getting is following:

    System.Management.Automation.ParameterBindingValidationException: Cannot validate argument on parameter 'Identity'. The argument is null. Provide a valid value for the argument, and then try running the command again. ---> System.Management.Automation.ValidationMetadataException: The argument is null. Provide a valid value for the argument, and then try running the command again.
   at System.Management.Automation.ValidateNotNullAttribute.Validate(Object arguments, EngineIntrinsics engineIntrinsics)
   at System.Management.Automation.ParameterBinderBase.BindParameter(CommandParameterInternal parameter, CompiledCommandParameter parameterMetadata, ParameterBindingFlags flags)
   --- End of inner exception stack trace ---
   at System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input)
   at UserMigrationTool.Code.Migration.RunScript(String scriptText) in c:\TauriVS\BCS.Sharepoint.Products.2013\UserMigrationTool\Code\Migration.cs:line 98
   at UserMigrationTool.Code.Migration.Start(List`1 users, String email, String url) in c:\TauriVS\BCS.Sharepoint.Products.2013\UserMigrationTool\Code\Migration.cs:line 63
2
  • Is there any reason not to use plain PowerShell scripting using either SharePoint Management Shell or Windows PowerShell ISE?
    – Benny Skogberg
    Commented Mar 7, 2017 at 13:09
  • I try to use it this way, since there are loads of users that I need to migrate and they don't have anything unique in common that I could automate this process. But if I could call plain PowerShell from C#, that would be helpful as well. Plus tehere might be need to migrate up to 4 users at the time (SharePoint has 4 user accounts that should be one)
    – Taurib
    Commented Mar 7, 2017 at 13:20

1 Answer 1

0

Make sure that the assigned value of Identity parameter is matched "DomainName\Username" at all similar statements use that like

Get-SPUser -web $url -Identity $oldIdentity

Also, it's preferred to assign parameter like this

pipeline.Parameters.Add("Identity", oldIdentity);
1
  • Referring to pipeline.Parameters.Add("Identity", oldIdentity);, how do you create line $user = Get-SPUser -web $url -Identity $oldIdentity in that case?
    – Taurib
    Commented Mar 8, 2017 at 10:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.