Automation

 View Only
Expand all | Collapse all

Trouble passing a function to be executed with Invoke-VMScript

LucD

LucDMar 24, 2014 06:49 AM

markvm2

markvm2Mar 24, 2014 07:00 AM

  • 1.  Trouble passing a function to be executed with Invoke-VMScript

    Posted Mar 24, 2014 02:54 AM

    I have the below function that I need to run on the remote VM through Invoke-VMScript with "remove-profile -days 0 - -computername localhost -profiles $profilename" this script removes a local profile, you can find out more about it here http://gallery.technet.microsoft.com/scriptcenter/Remove-Profile-787d9188

    Now I am having extreme difficultly figuring out how to drop the function with Invoke-VMScript so I can call the function. I usually do "Invoke-VMScript -VM $vmname2 -ScriptText "powershell.exe commands" and it works great, but I can't figure out how to drop a function to that powershell process to call the function. Any ideas? I do not want to do this with a ps1 file or remote share, I want this function to be available to the powershell process i start so I can call it. I have tried a bunch of different things like script blocks and invoke-command but they always break my entire script.

    To make it more clear - When i start a powershell process through Invoke-VMScript, I need this function to be there so I can call it. So once the powershell.exe process is running i can just have it execute "remove-profile -days 0 - -computername localhost -profiles $profilename"

    function remove-profile { [cmdletbinding(

            SupportsShouldProcess = $true,

            ConfirmImpact="High"

        )]

        param(

            [string[]]$computername="localhost",

            [validaterange(0,9999)][int]$days = 1,

            [string[]]$exceptions = $null,

            [string[]]$profiles = $null

        )

        #function to get profiles

        function Get-Profile {

            [cmdletbinding()]

            param(

                [string]$computername,

                [string[]]$exceptions = $null,

                [string[]]$profiles = $null

            )

            #function to convert array of strings into regex for paths to avoid

            function build-Regex {

                param([string[]]$items)

                $( foreach($item in $items){ "^$item$" } ) -join "|"

            }

            $date = get-date

            #test connection

            if(Test-Connection -ComputerName $computername -BufferSize 16 -count 2 -Quiet){

        

                #Check OS

                Try{

                    $opSys = Get-WmiObject Win32_OperatingSystem -computername $computername | select -ExpandProperty version

                }

                Catch{

                    Throw "Error: Could not obtain OS version WMI information from $computername"

                    Return

                }

                #Find XP profiles

                if ($opSys –like “5*”) {

                

                    #define property that we will use to test exceptions / profile regexs against

                    $property = "fullname"

            

                    #get all profiles on computer using file system

                    $allProfiles = Get-Childitem "\\$computername\c$\documents and settings\" -force | ?{$_.PSIsContainer}

                }

                #Find Vista + profiles

                if ($opSys –like “6*”) {

                

                    #define property that we will use to test exceptions / profile regexs against

                    $property = "localpath"

                

                    Try{

                        #get all profiles on computer using WMI

                        $allProfiles = get-wmiobject -computername $computername -class win32_userprofile | ?{ $_.localpath -like "C:\users\*" }

                    }

                    Catch{

                        Throw "Error gathering profile WMI information from $computername.  Be sure that WMI is functioning on this system and that it is running Windows Vista or Server 2008 or later"

                        Return

                    }

                }

                #if specified, filter for profiles

                if($profiles){

                    #build regex using provided profiles

                    $profileRegex = build-Regex $profiles

                    #test profiles against profiles regex

                    $allProfiles = $allProfiles | ?{ $(split-path $_.$property -leaf) -match $profileRegex }

                }

                #if specified, filter exceptions

                if($exceptions){

                    #build regex using provided exceptions

                    $exceptionsRegex = build-Regex $exceptions

                    #test profiles against exceptions regex

                    $allProfiles = $allProfiles | ?{ $(split-path $_.$property -leaf) -notmatch $exceptionsRegex }

                }

                #Return results

                $allProfiles

            }

            else{

                Throw "Could not connect to $computername"

                Return

            }

        }

        #Get date for profile last access comparison

        $date = get-date

        #Add standard accounts to exclude unless explicitly instructed not to

        if( -not $DontExcludeStandardAccounts ){

            $exceptions += "Administrator", "LocalService", "NetworkService", "All Users", "Default User"

        }

        #loop through provided computers

        foreach($computer in $computername){

        

            #get all the profiles for this computer

            $profilesToRemove = Get-Profile -computername $computer -exceptions $exceptions -profiles $profiles -ErrorAction stop

        

            #if none returned, throw an error and move on to the next computer

            if(-not $profilesToRemove){

                Write-Error "Error: No profiles returned on $computer"

                Continue

            }

            #Get-Profiles returns a directoryinfo object for XP, use this to determine OS.

            if($profilesToRemove[0] -isnot [System.IO.DirectoryInfo]){ $opsys = 6 }

            else{ $opsys = 5 }

            #loop through profiles

            foreach($profile in $profilesToRemove){

        

                #Define path and last access time for profile

                if($opsys -eq 6){

                    #Windows 7: convert localpath to remote path remote path.  Currently only handling profiles on C drive

                    $path = $profile.localpath.replace("C:","\\$computer\C$")

                    $lastAccess = ([WMI]'').ConvertToDateTime($profile.LastUseTime)

                }

                else{

                    #Windows XP: define path

                    $path = $profile.fullname

                    $lastAccess = $profile.lastWriteTime

                }

                #Confirm we can reach $path

                Try {

                    get-item $path -force -ErrorAction stop | out-null

                }

                Catch{

                    #if we couldnt get the item, display an error and move on to the next profile

                    Write-Error "Error: Could not get-item for $path"

                    Continue

                }

                #If the profile is older than the days specified, remove it

                if($lastAccess -lt $date.AddDays(-$days)){

            

                    #-confirm and -whatif support

                    if($pscmdlet.shouldprocess("$path last accessed $lastAccess")){

                    

                        #build results object

                        $tempResult = "" | Select ComputerName, Path, lastAccess, Status

                   

                        Try{

                            if($opsys -eq 6){

                                #Windows Vista+: remove the profile using WMI

                                $profile.delete()

                            }

                            else{

                                #Windows XP: remove the profile using file system

                                Remove-Item $path -force -confirm:$false -recurse

                            }

                            #Add properties to results object

                            $tempResult.ComputerName = $computer

                            $tempResult.Path = $path

                            $tempResult.LastAccess = $lastAccess

                            $tempResult.Status = "No error"

                        }

                        Catch{

                        

                            #add properties to results object

                            $tempResult.ComputerName = $computer

                            $tempResult.Path = $path

                            $tempResult.LastAccess = $lastAccess

                            $tempResult.Status = "Error removing profile"

                        

                            #WMI delete method or file removal failed.  Write an error, move on to the next profile

                            Write-Error "Error: Could not delete $path last accessed $lastAccess"

                            Continue

                        }

                    

                        #display result

                        $tempResult

                    }

                }

            }

        }

    }



  • 2.  RE: Trouble passing a function to be executed with Invoke-VMScript

    Posted Mar 24, 2014 05:50 AM