locked
Setting retention dates using Powershell fails RRS feed

  • Question

  • I'm facing a strange behavior regarding DateTime conversion when using the Set-Mailbox command to set retention settings on a client, having german culture settings. In my use case, this is done in a .NET exe using the classes from System.Management.Automation. The issue can be reproduced on a "regular" shell.

    After creating an Exchange Online powershell connection, run the following commands for a user, that has RetentionHoldEnabled set to false:

    $dtStart = New-Object System.DateTime -ArgumentList 2025,12,29,0,0,0

    $dtEnd = New-Object System.DateTime -ArgumentList 2025,12,31,0,0,0

    Set-Mailbox -Identity <user> -RetentionHoldEnabled $true -StartDateForRetentionHold $dtStart -EndDateForRetentionHold $dtEnd

    When regional settings of the computer are set to "United States", the command runs fine. When set to "Germany", you'll get the following error:

    Error on proxy command 'Set-Mailbox -Identity:'...' -RetentionHoldEnabled:$True -StartDateForRetentionHold:'29.12.2025 00:00:00' 

    -EndDateForRetentionHold:'31.12.2025 00:00:00' -Confirm:$False -Force:$True' to server <...>.<...>.prod.outlook.com: Server version 15.01.1075.0000, Proxy method PSWS: 

    Cmdlet error with following error message:

    System.Management.Automation.ParentContainsErrorRecordException: Cannot process argument transformation on parameter 'StartDateForRetentionHold'. Cannot convert value "29.12.2025 00:00:00" 

    to type "System.DateTime". Error: "String was not recognized as a valid DateTime."..

        + CategoryInfo          : NotSpecified: (:) [Set-Mailbox], CmdletProxyException

        + FullyQualifiedErrorId : Microsoft.Exchange.Configuration.CmdletProxyException,Microsoft.Exchange.Management.RecipientTasks.SetMailbox

        + PSComputerName        : outlook.office365.com

    As you can see, the command send to the server converts the DateTimes (dtStart/dtEnd) to string using the german culture. The remote machine then fails to parse the string back to a valid DateTime.

    If you try to execute Set-Mailbox and pass the Datetime directly as string in the format yyyy-mm-dd it fails with the same error:

    Set-Mailbox -Identity <Identity> -RetentionHoldEnabled $true -StartDateForRetentionHold "2025-12-29" -EndDateForRetentionHold "2025-12-31"

    Error on proxy command 'Set-Mailbox -Identity:'<...>' -RetentionHoldEnabled:$True -StartDateForRetentionHold:'29.12.2025 00:00:00' 

    -EndDateForRetentionHold:'31.12.2025 00:00:00' -Confirm:$False -Force:$True' to server <...>.<...>.prod.outlook.com: Server version 15.01.1075.0000, Proxy method PSWS: 

    Cmdlet error with following error message:

    System.Management.Automation.ParentContainsErrorRecordException: Cannot process argument transformation on parameter 'StartDateForRetentionHold'. Cannot convert value "29.12.2025 00:00:00" 

    to type "System.DateTime". Error: "String was not recognized as a valid DateTime."..

        + CategoryInfo          : NotSpecified: (:) [Set-Mailbox], CmdletProxyException

        + FullyQualifiedErrorId : Microsoft.Exchange.Configuration.CmdletProxyException,Microsoft.Exchange.Management.RecipientTasks.SetMailbox

        + PSComputerName        : outlook.office365.com

    Things get strange when you do that operation in two steps

    $dtStart = New-Object System.DateTime -ArgumentList 2025,12,29,0,0,0

    $dtEnd = New-Object System.DateTime -ArgumentList 2025,12,31,0,0,0

    Set-Mailbox -Identity <user> -RetentionHoldEnabled $true

    Set-Mailbox -Identity <user> -StartDateForRetentionHold $dtStart -EndDateForRetentionHold $dtEnd

    This works (almost) fine no matter if region is set to United States or Germany. The drawback of this "workaround" is, that sometimes the second "Set-Mailbox" does not recognize, that RetentionHoldEnabled was enabled and then fails with an error message, stating that RetentionHoldEnabled must be enabled before start- and enddate can be set.

    The conversion error also occurs, when I try to set other properties along with start- and enddate (such as RetentionComment).

    Am I missing something or am I doing something wrong? (Just to clarify, I've a workaround but the behavior seems very strange to me)

    The client computer is btw. Windows 10 Enterprise 

    PSVersion                      5.1.14393.1066

    Friday, May 12, 2017 6:02 AM

Answers

  • As stated in my original post, I figured out, that setting the local culture to "en-us" works. Unfortunately the command is run in the context of a .NET service application. I'd like to avoid forcing the users to change the local settings. I've already tried to switch the culture of the thread to avoid the problem but due to the fact, that the application also spawns threads for parallel execution that I do not control (without major changes) that doesn't work in every case. However, I've a workaround and the confirmation, that it is a bug.

    Thanks everyone for your replies.

    • Marked as answer by Bill_Stewart Friday, July 7, 2017 6:23 PM
    Wednesday, May 17, 2017 11:19 AM

All replies

  • Hi Boerni,

    sounds like a server-side issue, where it converts datetime to string. By default, the client-side code only accepts the input and passes it along.

    On the other hand, maybe it has a serialization issues (that is: Has trouble sending the object to the server). Try running this:

    Get-Date | Export-Clixml datetime.xml
    Import-Clixml datetime.xml | gm

    Is the output a valid datetime object?

    Cheers,
    Fred


    There's no place like 127.0.0.1

    Friday, May 12, 2017 6:58 AM
  • Yes, this works fine and I get a valid DateTime.
    Friday, May 12, 2017 11:14 AM
  • Excellent. In that case your client side is doing just fine and the issue will probably be server-side (over which you don't have any control after all).

    Might be worth contacting support over.


    There's no place like 127.0.0.1

    Friday, May 12, 2017 12:18 PM
  • That is, what I was "afraid" of ;) Thanks a lot. I'll update this thread if I have news on the topic.

    Cheers,

    Stefan

    Friday, May 12, 2017 2:08 PM
  • Have you tried with:

    $dtStart = get-date -Day 29 -Month 12 -Year 2025 -Hour 00 -Minute 00 -Second 00 -Millisecond 00
    $dtEnd = get-date -Day 31 -Month 12 -Year 2025 -Hour 00 -Minute 00 -Second 00 -Millisecond 00

    If it still doesn't work, give this a try, too:

    $dtStart = $dtStart.tostring("MM-dd-yyyy")
    $dtEnd = $dtEnd.tostring("MM-dd-yyyy")

    Friday, May 12, 2017 2:16 PM
  • The issue is that the CmdLet converts the date locally.  If you set the local "culture" to "en-US" the command should work.  YOU can then set it back to the current culture.

    From what I remember the issue is a known bug.


    \_(ツ)_/


    • Edited by jrv Friday, May 12, 2017 4:02 PM
    Friday, May 12, 2017 4:02 PM
  • As an alternate you can try using a connection to a European O365 site and it will probable work.


    \_(ツ)_/

    Friday, May 12, 2017 4:05 PM
  • As stated in my original post, I figured out, that setting the local culture to "en-us" works. Unfortunately the command is run in the context of a .NET service application. I'd like to avoid forcing the users to change the local settings. I've already tried to switch the culture of the thread to avoid the problem but due to the fact, that the application also spawns threads for parallel execution that I do not control (without major changes) that doesn't work in every case. However, I've a workaround and the confirmation, that it is a bug.

    Thanks everyone for your replies.

    • Marked as answer by Bill_Stewart Friday, July 7, 2017 6:23 PM
    Wednesday, May 17, 2017 11:19 AM
  • You can temporarily change the culture in your script and it will only change it for that script.

    \_(ツ)_/

    Wednesday, May 17, 2017 12:50 PM