0

I'm developing a Console application that must read from a PS1 file and execute the command from a Form. My runs very well when I have to call simple function PS1

I have this scrip1 that :

 =======================================================================
 Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

#Function to copy user permissions
Function Copy-UserPermissions($SourceUserID, $TargetUserID, [Microsoft.SharePoint.SPSecurableObject]$Object)
{
 #Determine the given Object type and Get URL of it
    Switch($Object.GetType().FullName)
 {
  "Microsoft.SharePoint.SPWeb"  { $ObjectType = "Site" ; $ObjectURL = $Object.URL; $web = $Object }
  "Microsoft.SharePoint.SPListItem"
  {
   if($Object.Folder -ne $null)
   {
     $ObjectType = "Folder" ; $ObjectURL = "$($Object.Web.Url)/$($Object.Url)"; $web = $Object.Web
   }
   else
   {
    $ObjectType = "List Item"; $ObjectURL = "$($Object.Web.Url)/$($Object.Url)" ; $web = $Object.Web
   }
  }
  #Microsoft.SharePoint.SPList, Microsoft.SharePoint.SPDocumentLibrary, Microsoft.SharePoint.SPPictureLibrary,etc
  default { $ObjectType = "List/Library"; $ObjectURL = "$($Object.ParentWeb.Url)/$($Object.RootFolder.URL)"; $web = $Object.ParentWeb }
 }

 #Get Source and Target Users
 $SourceUser = $Web.EnsureUser($SourceUserID)
 $TargetUser = $Web.EnsureUser($TargetUserID)

 #Get Permissions of the Source user on given object - Such as: Web, List, Folder, ListItem
 $SourcePermissions = $Object.GetUserEffectivePermissionInfo($SourceUser)

 #Iterate through each permission and get the details
 foreach($SourceRoleAssignment in $SourcePermissions.RoleAssignments)
 {
  #Get all permission levels assigned to User account directly or via SharePOint Group
  $SourceUserPermissions=@()
        foreach ($SourceRoleDefinition in $SourceRoleAssignment.RoleDefinitionBindings)
        {
   #Exclude "Limited Accesses"
   if($SourceRoleDefinition.Name -ne "Limited Access")
   {
          $SourceUserPermissions += $SourceRoleDefinition.Name
   }
        }

  #Check Source Permissions granted directly or through SharePoint Group
  if($SourceUserPermissions)
  {
   if($SourceRoleAssignment.Member -is [Microsoft.SharePoint.SPGroup])  
   {
    $SourcePermissionType = "'Member of SharePoint Group - " + $SourceRoleAssignment.Member.Name +"'"

    #Add Target User to the Source User's Group
    #Get the Group
    $Group = [Microsoft.SharePoint.SPGroup]$SourceRoleAssignment.Member

    #Check if user is already member of the group - If not, Add to group
    if( ($Group.Users | where {$_.UserLogin -eq $TargetUserID}) -eq $null )
    {
      #Add User to Group
      $Group.AddUser($TargetUser)
      #Write-Host Added to Group: $Group.Name
    }    
   }
   else
   {
    $SourcePermissionType = "Direct Permission"

    #Add Each Direct permission (such as "Full Control", "Contribute") to Target User
    foreach($NewRoleDefinition in $SourceUserPermissions)
    {   
      #Role assignment is a linkage between User object and Role Definition
      $NewRoleAssignment = New-Object Microsoft.SharePoint.SPRoleAssignment($TargetUser)
      $NewRoleAssignment.RoleDefinitionBindings.Add($web.RoleDefinitions[$NewRoleDefinition])

      $object.RoleAssignments.Add($NewRoleAssignment)
      $object.Update()    
    }     
   }
   $SourceUserPermissions = $SourceUserPermissions -join ";" 
   Write-Host "***$($ObjectType) Permissions Copied: $($SourceUserPermissions) at $($ObjectURL) via $($SourcePermissionType)***"
  }  
 }
}

Function Clone-SPUser($SourceUserID, $TargetUserID, $WebAppURL)
{
 ###Check Whether the Source Users is a Farm Administrator ###
 Write-host "Scanning Farm Administrators Group..."
   #Get the SharePoint Central Administration site
   $AdminWebApp = Get-SPwebapplication -includecentraladministration | where {$_.IsAdministrationWebApplication}
    $AdminSite = Get-SPWeb $AdminWebApp.Url
    $AdminGroupName = $AdminSite.AssociatedOwnerGroup
    $FarmAdminGroup = $AdminSite.SiteGroups[$AdminGroupName]

 #enumerate in farm adminidtrators groups
    foreach ($user in $FarmAdminGroup.users)
    {
     if($User.LoginName.Endswith($SourceUserID,1)) #1 to Ignore Case
     {
       #Add the target user to Farm Administrator Group
    $FarmAdminGroup.AddUser($TargetUserID,"",$TargetUserID , "")
    Write-Host "***Added to Farm Administrators Group!***"
     }    
    }

 ### Check Web Application User Policies ###
 Write-host "Scanning Web Application Policies..."
  $WebApp = Get-SPWebApplication $WebAppURL  

  foreach ($Policy in $WebApp.Policies)
  {
      #Check if the search users is member of the group
     if($Policy.UserName.EndsWith($SourceUserID,1))
       {
       #Write-Host $Policy.UserName
    $PolicyRoles=@()
       foreach($Role in $Policy.PolicyRoleBindings)
       {
        $PolicyRoles+= $Role
       }
   }
  }
  #Add Each Policy found
  if($PolicyRoles)
  {
   $WebAppPolicy = $WebApp.Policies.Add($TargetUserID, $TargetUserID)
   foreach($Policy in $PolicyRoles)
   {
    $WebAppPolicy.PolicyRoleBindings.Add($Policy)
   }
   $WebApp.Update()
   Write-host "***Added to Web application Policies!***"
  }

 ### Drill down to Site Collections, Webs, Lists & Libraries, Folders and List items ###
 #Get all Site collections of given web app
 $SiteCollections = Get-SPSite -WebApplication $WebAppURL -Limit All

 #Convert UserID Into Claims format - If WebApp is claims based! Domain\User to i:0#.w|Domain\User
    if( (Get-SPWebApplication $WebAppURL).UseClaimsAuthentication)
    {
        $SourceUserID = (New-SPClaimsPrincipal -identity $SourceUserID -identitytype 1).ToEncodedString()
  $TargetUserID = (New-SPClaimsPrincipal -identity $TargetUserID -identitytype 1).ToEncodedString()
    }

 #Loop through all site collections
    foreach($Site in $SiteCollections)
    {
  #Prepare the Target user
  $TargetUser = $Site.RootWeb.EnsureUser($TargetUserID)

     Write-host "Scanning Site Collection Administrators Group for:" $site.Url
  ###Check Whether the User is a Site Collection Administrator
     foreach($SiteCollAdmin in $Site.RootWeb.SiteAdministrators)
        {
      if($SiteCollAdmin.LoginName.EndsWith($SourceUserID,1))
      {
          #Make the user as Site collection Admin
           $TargetUser.IsSiteAdmin = $true
           $TargetUser.Update()
       Write-host "***Added to Site Collection Admin Group***"
      }    
    }

  #Get all webs
  $WebsCollection = $Site.AllWebs
  #Loop throuh each Site (web)
  foreach($Web in $WebsCollection)
  {
       if($Web.HasUniqueRoleAssignments -eq $True)
             {
     Write-host "Scanning Site:" $Web.Url

     #Call the function to Copy Permissions to TargetUser
     Copy-UserPermissions $SourceUserID $TargetUserID $Web   
    }

    #Check Lists with Unique Permissions
    Write-host "Scanning Lists on $($web.url)..."
    foreach($List in $web.Lists)
    {
              if($List.HasUniqueRoleAssignments -eq $True -and ($List.Hidden -eq $false))
                 {
      #Call the function to Copy Permissions to TargetUser
      Copy-UserPermissions $SourceUserID $TargetUserID $List
     }

     #Check Folders with Unique Permissions
     $UniqueFolders = $List.Folders | where { $_.HasUniqueRoleAssignments -eq $True }                   
                    #Get Folder permissions
                    foreach($folder in $UniqueFolders)
        {
      #Call the function to Copy Permissions to TargetUser
                                                Copy-UserPermissions $SourceUserID $TargetUserID $folder     
                    }

     #Check List Items with Unique Permissions
     $UniqueItems = $List.Items | where { $_.HasUniqueRoleAssignments -eq $True }
                    #Get Item level permissions
                    foreach($item in $UniqueItems)
        {
      #Call the function to Copy Permissions to TargetUser
      Copy-UserPermissions $SourceUserID $TargetUserID $Item 
                    }
    }
  }
 }
 Write-Host "Permission are copied successfully!"

}
#Define variables for processing
$WebAppURL = "http://sp2010devid/sites/EsercioWeekend/"

#Provide input for source and Target user Ids
$SourceUser ="virtualsp\admnistrator"
$TargetUser ="virtualsp\b.ferreirarocha"

#Call the function to clone user access rights
Clone-SPUser $SourceUser $TargetUser $WebAppURL
==========================================================================

And the most important part of my C# Code that runs the script:

using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace HowToRunPowerShell
{
    public partial class FormPowerShellSample : Form
    {
        // Represents the kind of drag drop formats we want to receive
        private const string dragDropFormat = "FileDrop";

        public FormPowerShellSample()
        {
            InitializeComponent();
        }

        private void buttonRunScript_Click(object sender, EventArgs e)
        {
            try
            {
                textBoxOutput.Clear();
                textBoxOutput.Text = RunScript(textBoxScript.Text);
            }
            catch (Exception error)
            {
                textBoxOutput.Text += String.Format("\r\nError in script : {0}\r\n", error.Message);
            }
        }

        /// <summary>
        /// Runs the given powershell script and returns the script output.
        /// </summary>
        /// <param name="scriptText">the powershell script text to run</param>
        /// <returns>output of the script</returns>
        private string RunScript(string scriptText)
        {
            // create Powershell runspace
            Runspace runspace = RunspaceFactory.CreateRunspace();


            PSSnapInException snapInError;
            runspace.RunspaceConfiguration.AddPSSnapIn("Microsoft.SharePoint.PowerShell", out snapInError);
            // open it
            runspace.Open();

            // 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 stringBuilder.ToString();
        }

        #region Drag-drop handling events
        private void FormPowerShellSample_DragDrop(object sender, DragEventArgs e)
        {
            // is it the correct type of data?
            if (e.Data.GetDataPresent(dragDropFormat))
            {
                // dragging files onto the window yields an array of pathnames
                string[] files = (string[])e.Data.GetData(dragDropFormat);

                if (files.Length > 0)
                {
                    // just read the first file
                    using (StreamReader sr = new StreamReader(files[0]))
                    {
                        // and plunk the contents in the textbox
                        textBoxScript.Text = sr.ReadToEnd();
                    }
                }
            }
        }

        private void FormPowerShellSample_DragEnter(object sender, DragEventArgs e)
        {
            // only accept the dropped data if it has the correct format
            e.Effect = e.Data.GetDataPresent(dragDropFormat) ? DragDropEffects.Link : DragDropEffects.None;
        }
        #endregion
    }
}

but when I try to run the script it return me the the following exception :

“Cannot Invoke this function because the current host does not implement it”

I found this post link and it Seems it Someone has found the same isseus and solve it with this procedure but i'm completely ignorant on PowerSehll.

Community
  • 1
  • 1
hello B
  • 891
  • 5
  • 18
  • 41

2 Answers2

1

To run arbitrary PowerShell scripts from .net code, you need to implement a host.

Here are my blog posts on the subject: http://powershellstation.com/category/writing-a-host/

Since you have the script in question, you can simply eliminate the parts of it which require a host. You have most of the write-host calls commented out. Try commenting out the rest.

Other things that cause problems are prompting for input and using -confirm.

Community
  • 1
  • 1
Mike Shepard
  • 17,466
  • 6
  • 51
  • 69
  • hi , thanks.. One more question. I'm trying to run a Sharepoint PS1. but I have some problems with SP Object . My code is the same of this. https://msdn.microsoft.com/en-us/library/ee706594(v=vs.85).aspx – hello B Mar 25 '15 at 09:24
1
 private static void Main(string[] args)
        {
            // Display the welcome message.
            Console.Title = "PowerShell Console Host Sample Application";
            ConsoleColor oldFg = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("    Windows PowerShell Console Host Application Sample");
            Console.WriteLine("    ==================================================");
            Console.WriteLine(string.Empty);
            Console.WriteLine("This is an example of a simple interactive console host uses ");
            Console.WriteLine("the Windows PowerShell engine to interpret commands.");
            Console.WriteLine("Type 'exit' to exit.");
            Console.WriteLine(string.Empty);
            Console.ForegroundColor = oldFg;

            // Create the listener and run it. This method never returns.
            PSListenerConsoleSample listener = new PSListenerConsoleSample();
            listener.Run();
        }

        /// <summary>
        /// Initializes a new instance of the PSListenerConsoleSample class.
        /// </summary>
        public PSListenerConsoleSample()
        {
            // Create the host and runspace instances for this interpreter. 
            // Note that this application does not support console files so 
            // only the default snap-ins will be available.
            this.myHost = new MyHost(this);
            this.myRunSpace = RunspaceFactory.CreateRunspace(this.myHost);
            this.myRunSpace.Open();

            // Create a PowerShell object to run the commands used to create 
            // $profile and load the profiles.
            lock (this.instanceLock)
            {
                this.currentPowerShell = PowerShell.Create();
            }

            try
            {

                this.currentPowerShell.AddScript("Add-PSSnapin Microsoft.Sharepoint.Powershell");
                this.currentPowerShell.AddScript(@"C:\Users\Administrator\Desktop\Untitled1.ps1");

                this.currentPowerShell.Runspace = this.myRunSpace;

                PSCommand[] profileCommands = Microsoft.Samples.PowerShell.Host.HostUtilities.GetProfileCommands("SampleHost06");
                foreach (PSCommand command in profileCommands)
                {
                    this.currentPowerShell.Commands = command;
                    this.currentPowerShell.Invoke();
                }
            }
            finally
            {
                // Dispose the PowerShell object and set currentPowerShell 
                // to null. It is locked because currentPowerShell may be 
                // accessed by the ctrl-C handler.
                lock (this.instanceLock)
                {
                    this.currentPowerShell.Dispose();
                    this.currentPowerShell = null;
                }
            }
        }

        /// <summary>

POWERSHELL PS1

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
function Get-SPUserEffectivePermissions(
    [object[]]$users, 
    [Microsoft.SharePoint.SPSecurableObject]$InputObject) {

    begin { }
    process {
        $so = $InputObject
        if ($so -eq $null) { $so = $_ }


    if ($so -isnot [Microsoft.SharePoint.SPSecurableObject]) {
        throw "A valid SPWeb, SPList, or SPListItem must be provided."
    }

    foreach ($user in $users) {
        # Set the users login name
        $loginName = $user
        if ($user -is [Microsoft.SharePoint.SPUser] -or $user -is [PSCustomObject]) {
            $loginName = $user.LoginName
        }
        if ($loginName -eq $null) {
            throw "The provided user is null or empty. Specify a valid SPUser object or login name."
        }

        # Get the users permission details.
        $permInfo = $so.GetUserEffectivePermissionInfo($loginName)

        # Determine the URL to the securable object being evaluated
        $resource = $null
        if ($so -is [Microsoft.SharePoint.SPWeb]) {
            $resource = $so.Url
        } elseif ($so -is [Microsoft.SharePoint.SPList]) {
            $resource = $so.ParentWeb.Site.MakeFullUrl($so.RootFolder.ServerRelativeUrl)
        } elseif ($so -is [Microsoft.SharePoint.SPListItem]) {
            $resource = $so.ParentList.ParentWeb.Site.MakeFullUrl($so.Url)
        }

        # Get the role assignments and iterate through them
        $roleAssignments = $permInfo.RoleAssignments
        if ($roleAssignments.Count -gt 0) {
            foreach ($roleAssignment in $roleAssignments) {
                $member = $roleAssignment.Member

                # Build a string array of all the permission level names
                $permName = @()
                foreach ($definition in $roleAssignment.RoleDefinitionBindings) {
                    $permName += $definition.Name
                }

                # Determine how the users permissions were assigned
                $assignment = "Direct Assignment"
                if ($member -is [Microsoft.SharePoint.SPGroup]) {
                    $assignment = $member.Name
                } else {
                    if ($member.IsDomainGroup -and ($member.LoginName -ne $loginName)) {
                        $assignment = $member.LoginName
                    }
                }

                # Create a hash table with all the data
                $hash = @{
                    Resource = $resource
                    "Resource Type" = $so.GetType().Name
                    User = $loginName
                    Permission = $permName -join ", "
                    "Granted By" = $assignment
                }

                # Convert the hash to an object and output to the pipeline
                New-Object PSObject -Property $hash
            }
        }
    }
}
end {}

}

Get-SPSite -Limit All | Get-SPWeb | Get-SPUserEffectivePermissions "virtualsp\administrator" | Export-Csv -NoTypeInformation -Path c:\perms.csv

enter image description here

hello B
  • 891
  • 5
  • 18
  • 41