none
vb.net to create multiple new user mailboxes with passwords, from csv, in exchange 2007 and 2010 RRS feed

  • Question

  • Hi,

    I'm looking to see if this can be automated using vb.net I could see around similar ideas been coded in c#

    Surely, same can be done with vb.net

    This is another article that talks in c#: http://social.technet.microsoft.com/Forums/en-US/exchange2010/thread/d22c53bb-14e5-4ec8-8199-577a6d388528

    Any ideas will be highly appreciated as I could not find adequate documentation or code snippet anywhere. TIA


    - thestriver

    Monday, January 7, 2013 7:07 PM

Answers

  • This issue was resolved after adding the system to trusted hosts and enabling basic auth for winrm.

    Now, I'm able to create user mailboxes, np.

    Thanks!


    - thestriver


    • Marked as answer by thestriver Monday, January 14, 2013 11:44 AM
    • Edited by thestriver Monday, January 14, 2013 11:45 AM
    Monday, January 14, 2013 11:44 AM

All replies

  • The only supported method of creating mailboxes in Exchange 2007, 2010 is to use the "new-mailbox" powershell cmdlet. You can automate using this cmdlet from managed code is you search the forum http://social.technet.microsoft.com/Search/en-US/exchange?query=%22new-mailbox%22%20&rq=meta:Search.MSForums.ForumID(ff2ca6ee-6f7c-4773-a5aa-0dfedf84cfcb)+site:microsoft.com&rn=Exchange+Previous+Versions+-+Development+Forum you'll find a few vb.net samples and discussions around the problems and solutions for this.

    The difference between 2007 and 2010 is that you need to use Remote Powershell in 2010 vs using the EMS Snapin in 2007.

    Cheers
    Glen

    Tuesday, January 8, 2013 5:52 AM
  • Thanks, Glen.

            Dim hostname As String
            hostname = "http://".ToString & TextBox3.Text.ToString
            Dim uri As New System.Uri(hostname)
            Dim connectionInfo As New WSManConnectionInfo(uri)
            connectionInfo.OpenTimeout = 100000
            connectionInfo.OperationTimeout = 10000
            Dim r As Runspace = RunspaceFactory.CreateRunspace(connectionInfo)
            r.Open()
            Dim p As Pipeline = r.CreatePipeline(TextBox2.Text)
            Dim output As Collection(Of PSObject)
            output = p.Invoke()
            For Each o As PSObject In output
                TextBox1.AppendText(o.ToString() + vbCrLf)
            Next

    While still testing the above code, got the following error message ===>>>

    System.Management.Automation.Remoting.PSRemotingTransportException was unhandled
      ErrorCode=-2144108485
      Message=Connecting to remote server failed with the following error message : The WS-Management service cannot process the request. The resource URI (http://schemas.microsoft.com/powershell/Microsoft.PowerShell) was not found in the WS-Management catalog. The catalog contains the metadata that describes resources, or logical endpoints. For more information, see the about_Remote_Troubleshooting Help topic.
      Source=System.Management.Automation
      TransportMessage=The WS-Management service cannot process the request. The resource URI is missing or it has an incorrect format. Check the documentation or use the following command for information on how to construct a resource URI: "winrm help uris".
      WasThrownFromThrowStatement=False
      StackTrace:
           at System.Management.Automation.Runspaces.AsyncResult.EndInvoke()
           at System.Management.Automation.Runspaces.Internal.RunspacePoolInternal.EndOpen(IAsyncResult asyncResult)
           at System.Management.Automation.Runspaces.Internal.RemoteRunspacePoolInternal.Open()
           at System.Management.Automation.Runspaces.RunspacePool.Open()
           at System.Management.Automation.RemoteRunspace.Open()
           at eswm.Form2.Button1_Click(Object sender, EventArgs e) in C:\Users\bthankap\documents\visual studio 2010\Projects\eswm\eswm\Form2.vb:line 16
           at System.Windows.Forms.Control.OnClick(EventArgs e)
           at System.Windows.Forms.Button.OnClick(EventArgs e)
           at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
           at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
           at System.Windows.Forms.Control.WndProc(Message& m)
           at System.Windows.Forms.ButtonBase.WndProc(Message& m)
           at System.Windows.Forms.Button.WndProc(Message& m)
           at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
           at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
           at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
           at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
           at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
           at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
           at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
           at System.Windows.Forms.Application.Run(ApplicationContext context)
           at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
           at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
           at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
           at eswm.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
           at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
           at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
           at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
           at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           at System.Threading.ThreadHelper.ThreadStart()
      InnerException:

    On button click, textbox1 will show the output of the cmdlet entered in textbox2. textbox3 will have the exchange server uri (I'm entering my uri as "ex10-ws.ocho.com/powershell?serializationLevel=Full")

    Is that uri format correct, for variable 'hostname'?


    - thestriver

    Tuesday, January 8, 2013 10:50 AM
  • What version of Exchange is running on the server your targeting ? Remote powers-hell will only work with Exchange 2010. Can you start a Remote powershell session on the machine your running the code on normal eg http://www.msexchange.org/blogs/walther/news/connecting-to-a-remote-exchange-2010-organization-using-remote-powershell-429.html

    Cheers
    Glen

    Wednesday, January 9, 2013 5:32 AM
  • Using Exchange 2010

    I was able to resolve the issue with the following subroutine, got from the web, tweeked it a bit as the original was giving errors with uri:

        Sub RunRemotePSScript(ByVal connectTo As String, ByVal user As String, ByVal password As String, ByVal script As String)
            Dim SHELL_URI As String = "http://schemas.microsoft.com/powershell/Microsoft.Exchange"
            Dim securePassword As System.Security.SecureString = New System.Security.SecureString()
            Dim c As Char
            For Each c In password.ToCharArray()
                securePassword.AppendChar(c)
            Next
            Dim creds As System.Management.Automation.PSCredential
            creds = New System.Management.Automation.PSCredential(user, securePassword)
            Dim uri As New System.Uri("http://" & connectTo & "/powershell?serializationLevel=Full")
            Dim connectionInfo As New WSManConnectionInfo(uri, SHELL_URI, creds)

            Dim myRunSpace As Runspace = RunspaceFactory.CreateRunspace(connectionInfo)
            Dim psresult As New System.Collections.ObjectModel.Collection(Of PSObject)
            myRunSpace.Open()

            Dim psh As PowerShell = PowerShell.Create()
            psh.Runspace = myRunSpace

            psh.AddScript(script)
            psresult = psh.Invoke()
            psh.Dispose()
            myRunSpace.Close()
        End Sub

    This takes arguments as well.

    Now, I need to check if this sub can be used to create mailboxes from csv. I'll keep updated on this...


    - thestriver

    Thursday, January 10, 2013 5:56 AM
  •     Sub RunRemotePSScript(ByVal connectTo As String, ByVal user As String, ByVal password As String, ByVal script As String)
            Dim SHELL_URI As String = "http://schemas.microsoft.com/powershell/Microsoft.Exchange"
            Dim securePassword As System.Security.SecureString = New System.Security.SecureString()
            Dim c As Char
            For Each c In password.ToCharArray()
                securePassword.AppendChar(c)
            Next
            Dim creds As System.Management.Automation.PSCredential
            creds = New System.Management.Automation.PSCredential(user, securePassword)
            Dim uri As New System.Uri("http://" & connectTo & "/powershell?serializationLevel=Full")
            Dim connectionInfo As New WSManConnectionInfo(uri, SHELL_URI, creds)

            Dim myRunSpace As Runspace = RunspaceFactory.CreateRunspace(connectionInfo)
            Dim psresult As New System.Collections.ObjectModel.Collection(Of PSObject)
            myRunSpace.Open()

            Dim psh As PowerShell = PowerShell.Create()
            psh.Runspace = myRunSpace

            psh.AddScript(script)
            psresult = psh.Invoke()
            psh.Dispose()
            myRunSpace.Close()
        End Sub

        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            Dim psFile As String = TextBox4.Text & " -CSVFile " & TextBox6.Text & " -ReportFile C:\PS\Report.csv"
            RunRemotePSScript(TextBox5.Text, TextBox3.Text, TextBox2.Text, psFile)
            TextBox1.Text = "Done!"
        End Sub

    What is wrong in the above code that I'm receiving the following exception:

    +        Thrown: "Mixed mode assembly is built against version 'v2.0.50727' of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information." (System.IO.FileLoadException)    Exception Message = "Mixed mode assembly is built against version 'v2.0.50727' of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information.", Exception Type = "System.IO.FileLoadException"    


    - thestriver

    Thursday, January 10, 2013 9:47 AM
  • Now no more exceptions after adding an app config file with following in it:

    <configuration><startup useLegacyV2RuntimeActivationPolicy="true"><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>

    However, the mailboxes still won't get created, this time no errors to report. Has anyone got any ideas. Thanks!


    - thestriver

    Thursday, January 10, 2013 10:09 AM
  • Here is the ps script: (runs fine if run from ps shell directly - ".\BulkAddRandom.ps1 -CSVFile c:\users.csv -ReportFile c:\report.csv")

    [CmdletBinding()]
    param(
        [Parameter(Position=0, Mandatory=$true)]
        [System.String]
        $CSVFile,
        [Parameter(Position=1, Mandatory=$false)]
        [System.String]
        $PasswordLength = 8,
        [Parameter(Position=2, Mandatory=$false)]
        [System.String]
        $NonAlphanumericCharacters = 0,
        [Parameter(Position=3, Mandatory=$true)]
        [System.String]
        $ReportFile
        )
        
    begin {
        Add-Type -AssemblyName System.Web
        $mailboxes = Import-Csv $CSVFile
        $props = $mailboxes | gm -MemberType NoteProperty | select -ExpandProperty Name
        $report = @()
    }

    process {
        foreach($mailbox in $mailboxes) {
            $i++
            Write-Progress -Activity "Creating Mailboxes..." -Status "Progress:" -PercentComplete ($i/$mailboxes.count*100)        
            $properties = @{}
            $props | %{
                $properties.add($_,$mailbox.$_)
            }
            $password = [System.Web.Security.Membership]::GeneratePassword($PasswordLength,$NonAlphanumericCharacters)
            $securepassword = ConvertTo-SecureString -AsPlainText $password -Force
            $properties.add("Password",$securepassword)

            if(New-Mailbox @properties) {
                $mailbox | Add-Member -MemberType NoteProperty -Name Password -Value $Password
                $report += $mailbox            
            }
            $properties.clear()
        }
    }

    end {
        $report | Export-Csv -Path $ReportFile -NoTypeInformation
    }


    - thestriver



    • Edited by thestriver Thursday, January 10, 2013 11:52 AM
    Thursday, January 10, 2013 11:49 AM
  • I tested using another simple ps script and it works fine.

    However, the above mailbox script doesn't work and gives following exception:

    System.Management.Automation.CommandNotFoundException was unhandled
      CommandName=New-Mailbox
      Message=The term 'New-Mailbox' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
      Source=System.Management.Automation
      WasThrownFromThrowStatement=False
      StackTrace:
           at System.Management.Automation.CommandDiscovery.LookupCommandInfo(String commandName, CommandOrigin commandOrigin)
           at System.Management.Automation.CommandDiscovery.LookupCommandProcessor(String commandName, CommandOrigin commandOrigin, Nullable`1 useLocalScope)
           at System.Management.Automation.CommandFactory._CreateCommand(String commandName, CommandOrigin commandOrigin, Nullable`1 useLocalScope)
           at System.Management.Automation.ExecutionContext.CreateCommand(String command)
           at System.Management.Automation.CommandNode.CreateCommandProcessor(Int32& index, ExecutionContext context)
           at System.Management.Automation.CommandNode.AddToPipeline(PipelineProcessor pipeline, ExecutionContext context)
           at System.Management.Automation.PipelineNode.Execute(Array input, Pipe outputPipe, ArrayList& resultList, ExecutionContext context)
           at System.Management.Automation.ParseTreeNode.Execute(Array input, Pipe outputPipe, ExecutionContext context)
           at System.Management.Automation.ifStatementNode.Execute(Array input, Pipe outputPipe, ArrayList& resultList, ExecutionContext context)
           at System.Management.Automation.StatementListNode.ExecuteStatement(ParseTreeNode statement, Array input, Pipe outputPipe, ArrayList& resultList, ExecutionContext context)
      InnerException:

    Any ideas?


    - thestriver

    Friday, January 11, 2013 6:12 AM
  • Thanks, Glen. I have changed he language of coding to c# as more examples were found on the net using c#

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Management.Automation;
    using System.Management.Automation.Host;
    using System.Management.Automation.Runspaces;
    using System.Collections.ObjectModel;
    using System.Diagnostics;
    using System.Security;

    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }

            private void Button1_Click_1(object sender, EventArgs e)
            {
               //Application.Exit=true;
            }

            private void Button2_Click(object sender, EventArgs e)
            {
                SecureString password = new SecureString();
                string str_password = TextBox2.Text;
                string username = TextBox3.Text;
                string liveIdconnectionUri = TextBox5.Text;
                foreach (char x in str_password)
                {
                    password.AppendChar(x);
                }
                PSCredential credential = new PSCredential(username, password);
                WSManConnectionInfo connectionInfo = new WSManConnectionInfo(new Uri(liveIdconnectionUri), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", credential);
                connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Basic;
                Runspace runspace = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(connectionInfo);
                runspace.Open();
                Pipeline pipeline = runspace.CreatePipeline();
                Command c = new Command("new-mailbox");
                c.Parameters.Add("Database", "Mailbox Database 1499472923");
                c.Parameters.Add("Name", "Tom" + " " + "Bun");
                c.Parameters.Add("Alias", "tbun");
                c.Parameters.Add("OrganizationalUnit", "Permanent");
                c.Parameters.Add("UserPrincipalName", "tbun@ocho.com");
                SecureString pwd = new SecureString();
                string p = "owlnmaster001";
                foreach (char z in p)
                {
                    pwd.AppendChar(z);
                }
                c.Parameters.Add("Password", pwd);
                bool rp = False;
                c.Parameters.Add(new CommandParameter("ResetPasswordOnNextLogon", rp));
                pipeline.Commands.Add(c);
                try
                {
                    pipeline.Invoke();
                    TextBox6.Text = "Done!";
                }
                finally
                {
                    pipeline.Dispose();
                    runspace.Dispose();
                    runspace = null;
                }
            }

            public bool False { get; set; }
        }
    }

    In the above code, I'm getting the following error:

    +        Thrown: "Invalid URI: The format of the URI could not be determined." (System.UriFormatException)    Exception Message = "Invalid URI: The format of the URI could not be determined.", Exception Type = "System.UriFormatException"    

    Please help!


    - thestriver


    • Edited by thestriver Monday, January 14, 2013 11:46 AM
    Monday, January 14, 2013 8:42 AM
  • The uri information was in incorrect format. Corrected that.

    However, now I'm getting the following error:

    ++++++

    +        Thrown: "Connecting to remote server failed with the following error message : The WinRM client cannot process the request. Unencrypted traffic is currently disabled in the client configuration. Change the client configuration and try the request again. For more information, see the about_Remote_Troubleshooting Help topic." (System.Management.Automation.Remoting.PSRemotingTransportException)    Exception Message = "Connecting to remote server failed with the following error message : The WinRM client cannot process the request. Unencrypted traffic is currently disabled in the client configuration. Change the client configuration and try the request again. For more information, see the about_Remote_Troubleshooting Help topic.", Exception Type = "System.Management.Automation.Remoting.PSRemotingTransportException"    

    ++++++

    +        Thrown: "Mixed mode assembly is built against version 'v2.0.50727' of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information." (System.IO.FileLoadException)    Exception Message = "Mixed mode assembly is built against version 'v2.0.50727' of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information.", Exception Type = "System.IO.FileLoadException"    


    - thestriver


    • Edited by thestriver Monday, January 14, 2013 9:04 AM
    Monday, January 14, 2013 9:03 AM
  • This issue was resolved after adding the system to trusted hosts and enabling basic auth for winrm.

    Now, I'm able to create user mailboxes, np.

    Thanks!


    - thestriver


    • Marked as answer by thestriver Monday, January 14, 2013 11:44 AM
    • Edited by thestriver Monday, January 14, 2013 11:45 AM
    Monday, January 14, 2013 11:44 AM