An Issue With A Function

This topic contains 6 replies, has 4 voices, and was last updated by  Chris 2 weeks, 4 days ago.

  • Author
    Posts
  • #92647

    Chris
    Participant

    Hi

    A former colleague created a module for the company that did various bits and pieces. He left the company a while back and no one else really knows PowerShell. I know some basic stuff but that is all.

    The issue is when attempting to run this function:

    Function Restore-CompanySoftDeletedMailboxes {
        
    
        [cmdletbinding(
        )]
    
        Param(
            $ModifyUsername=$false,
            
            $TenantId
        )
    
        Begin {
            365CmdletInit
        } #end Begin
    
        Process {
            
            # Get the onmicrosoft.com domain as a string
            $MsolDomains = Get-MsolDomain
    
            # This regex matches .onmicrosoft.com where  does not include a dot.
            $regex = '^[^.]*\.onmicrosoft\.com$'
            $Domain = $MsolDomains |
                Where-Object Name -Match $regex |
                Select-Object -ExpandProperty Name |
                Select-Object -First 1
    
            if (-not $Domain) {
                throw "No onmicrosoft.com domain found"
            }
    
            # Get all soft deleted mailboxes
            $Mailboxes = Get-Mailbox -SoftDeletedMailbox
    
            foreach ($mailbox in $Mailboxes) {
                
                $Alias = $mailbox.Alias
                Write-Verbose "[Restore-CompanySoftDeletedMailboxes] Found soft deleted mailbox: $Alias"
                
                if ($ModifyUsername) {
                    # Generate the new username - leaver_alias@domain.onmicrosoft.com
                    $Username = 'leaver_{0}@{1}' -F $Alias,$Domain
                    Write-Verbose "[Restore-CompanySoftDeletedMailboxes] New Username: $Username"
                } else {
                    # Generate the new username - alias@domain.onmicrosoft.com
                    $Username = '{0}@{1}' -F $Alias,$Domain
                    Write-Verbose "[Restore-CompanySoftDeletedMailboxes] New Username: $Username"
                } #end else
    
                # Restoring the deleted mailbox creates an In Cloud user account
                # Undo-SoftDeletedMailbox screws up badly if it has a bad password
                # So we start with a "safe" password (terrible to use the same for all mailboxes).
                # This should be changed later.
                $Password = "22fvghRff3
                34t23a!"
                $SecurePassword = (ConvertTo-SecureString -String $Password -AsPlainText -Force)
        
                Write-Verbose "[Restore-CompanySoftDeletedMailboxes] Undoing soft-delete..."
                Undo-SoftDeletedMailbox $mailbox.alias -WindowsLiveID $username -Password $SecurePassword
    
                
    
            } #end foreach ($mailbox in $Mailboxes)
    
            Write-Warning "You should change the passwords for all restored mailboxes immediately.  Set-CompanyLeaverMailbox will set a random password for you."
    
        } #end Process
    
    } #end Function Set-CompanyLeaver

    We get this error:

    Error on proxy command 'Undo-SoftDeletedMailbox -WindowsLiveID:'user@company.onmicrosoft.com' -Password:'System.Security.SecureString' -SoftDeletedObject:'user' -Confirm:$False' to server
    AM2PR07MB0804.eurprd07.prod.outlook.com: Server version 15.20.0464.0000, Proxy method PSWS:
    Cmdlet error with following error message:
    System.Management.Automation.ParentContainsErrorRecordException: Cannot process argument transformation on parameter 'Password'. Cannot convert the "System.Security.SecureString" value of type "System.String" to type
    "System.Security.SecureString"...
        + CategoryInfo          : NotSpecified: (:) [Undo-SoftDeletedMailbox], CmdletProxyException
        + FullyQualifiedErrorId : Microsoft.Exchange.Configuration.CmdletProxyException,Microsoft.Exchange.Management.RecipientTasks.UndoSoftDeletedMailbox
        + PSComputerName        : outlook.office365.com

    I'm not sure what is wrong with it, my Google search though admittedly brief didn't yield the answer I need.

    Any help would be greatly appreciated.

  • #92723

    Don Jones
    Keymaster

    That is not an "issue," that is a "problem." Magazines have issues.

    The problem is that you're passing a password as a plain-text string, and the command wants a SecureString (e.g., ConvertTo-SecureString).

    Reading tour code, $SecurePassword -should- be a SecureString, but that's where I'd start troubleshooting. Drop a breakpoint right after $SecurePassword is created, and then in debug mode pipe $SecurePassword to Get-Member to confirm the data type in the variable.

  • #92728

    Matt Bloomfield
    Participant

    Could be a problem with the line break in the password string. Get rid of line 56 and have the whole password on line 55.

    • #92780

      Chris
      Participant

      Line 56 was an error on my part while editing the code to post here.

      It took me a while because I didn't know how to use breakpoints and I stupidly kept trying to run it as a script but I managed to do as you suggested Don.

      $SecurePassword | Get-Member
      
      
         TypeName: System.Security.SecureString
      
      Name         MemberType Definition                                
      ----         ---------- ----------                                
      AppendChar   Method     void AppendChar(char c)                   
      Clear        Method     void Clear()                              
      Copy         Method     securestring Copy()                       
      Dispose      Method     void Dispose(), void IDisposable.Dispose()
      Equals       Method     bool Equals(System.Object obj)            
      GetHashCode  Method     int GetHashCode()                         
      GetType      Method     type GetType()                            
      InsertAt     Method     void InsertAt(int index, char c)          
      IsReadOnly   Method     bool IsReadOnly()                         
      MakeReadOnly Method     void MakeReadOnly()                       
      RemoveAt     Method     void RemoveAt(int index)                  
      SetAt        Method     void SetAt(int index, char c)             
      ToString     Method     string ToString()                         
      Length       Property   int Length {get;}                         
      

      I did also try making this amendment to the code:

                  $Password = ConvertTo-SecureString "22fvghRff334t23a!" -AsPlainText -Force
          
                  Write-Verbose "[Restore-CompanySoftDeletedMailboxes] Undoing soft-delete..."
                  Undo-SoftDeletedMailbox $mailbox.alias -WindowsLiveID $username -Password $Password

      But that didn't seem to work either. I'm just puzzled to why this did work and now it doesn't, we've just not needed to use it for a few months. I am truly out of my depth with this but I guess it's going to be a good learning experience.

  • #92729

    Don Jones
    Keymaster

    Oh, indeed – I'd assumed that was just a paste issue here in the forum, but if that's how the script is, then it's borking your code.

    • #92731

      JB Lewis
      Participant

      Don't you mean a "problem" Don?

  • #92732

    Don Jones
    Keymaster

    No, that'd be an issue. Like, when you sneeze "ISH-SHOOO!" while pressing Ctrl+V and you mess up the paste.

You must be logged in to reply to this topic.