Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17


Problem creating distribution lists on exchange server 2010 via power shell

Posted on 2012-04-04
Medium Priority
Last Modified: 2012-04-16
Hi there,

we have an it management system running where we can put users into special groups. Eg. every user who uses Microsoft Word is in that group. Furthermore this tool has a kind of task server that can run tasks periodically.

The idea now is, that we would like to create distribution lists on the exchange server with the mentioned groups, like "All Word Users".

The task servers has some requirements that cannot easily be changed:

* The TaskServer can run multiple tasks threaded simultaneously
* The TaskServer is a windows service that runs under a domain account with local admin rights.
* The TaskServer-User has no authorization to do anything on the exchange server
* It is possible to impersonate a task to run with appropriate rights.

That's the prehistory so far. The solution looks as follows:

* I have created this task.
* I have installed the exchange power shell commandlets
* I have created a power shell command with runspace and pipeline
* I have impersonated the command with appropriate rights

The mean thing is now, that my code functions properly when

* I run the code without any service involved in a console application.
* It also runs as a windows service hosted in a console application.
* It does not run, when the service is hosted in a windows service (installutil etc.). I get the following error message:

Das Windows PowerShell-Snap-In Microsoft.Exchange.Management.PowerShell.E2010 kann aufgrund des folgenden Fehlers nicht geladen werden: Der Typeninitialisierer für "Microsoft.Exchange.Data.Directory.Globals" hat eine Ausnahme verursacht.
   bei System.Management.Automation.Runspaces.RunspaceConfigForSingleShell.LoadCustomPSSnapIn(PSSnapInInfo mshsnapinInfo)
   bei System.Management.Automation.Runspaces.RunspaceConfigForSingleShell.LoadPSSnapIn(PSSnapInInfo mshsnapinInfo)
   bei System.Management.Automation.Runspaces.RunspaceConfigForSingleShell.LoadPSSnapIn(PSSnapInInfo mshsnapinInfo, PSSnapInException& warning)
   bei System.Management.Automation.Runspaces.RunspaceConfigForSingleShell.DoAddPSSnapIn(String name, PSSnapInException& warning)
   bei System.Management.Automation.Runspaces.RunspaceConfiguration.AddPSSnapIn(String name, PSSnapInException& warning)
   bei mpc.Utilities.PowerShellCommand.AddSnapIn(String psSnapInName) in E:\Visual Studio

--> Short Translation: "The Windows PowerShell-SnapIn Microsoft.Exchange.... could not be loaded due to an error. The Type Initialization "Microsoft.Exchange.Data.Directory.Globals" has thrown an excetion at ...."

I have already checked a possible x86/x64 issue. Both the service as well as the task are compiled with "Any CPU".

Any idea would be more then welcomed.


Here is my sourcecode:

 Private Sub CreateExchangeDistributionList(ByVal name As String, ByVal organizationalUnit As String, ByVal samAccountName As String)

            '            ModuleLibrarySharedConfig.GetConfigValue(BindableConfiguration.StandardParameterNamesEnum.ImpersonationUserDomain),
            '            ModuleLibrarySharedConfig.GetConfigValue(BindableConfiguration.StandardParameterNamesEnum.ImpersonationUserPassword))

            Dim cmd As String = String.Format("New-DistributionGroup -Name ""{0}"" -OrganizationalUnit ""{1}"" -SamAccountName ""{2}"" -Type ""Distribution""",
            Dim ps As New PowerShellCommand


            If ps.HasError Then
                Throw New Exception(ps.GetLog)
            End If

        End Sub

Public Class PowerShellCommand

        ' //// EVENTS

        ' //// DEKLARATIONEN

        Private _log As String
        Private _hasErrors As Boolean

        Private ReadOnly _runspace As Runspace
        Private ReadOnly _pipeline As Pipeline

        ' //// PROPERTIES
        Public ReadOnly Property HasError As Boolean
                Return _hasErrors
            End Get
        End Property
        Public ReadOnly Property GetLog As String
                Return _log
            End Get
        End Property

        ' //// EVENTHANDLER

        ' //// METHODEN

        Public Sub AddSnapIn(ByVal psSnapInName As String)

            ' Exchange Snapin
            ' "Microsoft.Exchange.Management.PowerShell.E2010"

            Dim snapInWarning As New PSSnapInException
            Dim snapInInfo = _runspace.RunspaceConfiguration.AddPSSnapIn(psSnapInName, snapInWarning)
            snapInInfo.LogPipelineExecutionDetails = True

            If snapInWarning IsNot Nothing Then
                Throw New Exception("Power Shell SnapIn Warning", snapInWarning)
            End If

        End Sub
        Public Sub AddCommand(ByVal commandText As String)

            ' "New-DistributionGroup -Name ""Mail_Abwesenheitsplaner_U"" -OrganizationalUnit """" -SamAccountName ""Mail_Abwesenheitsplaner_U"" -Type ""Distribution"""
            _pipeline.Commands.Add(New Command(commandText, True))

        End Sub

        ' //// INIT

        Public Sub New()
            Dim runspaceConfig = RunspaceConfiguration.Create()
            _runspace = RunspaceFactory.CreateRunspace(runspaceConfig)
            _pipeline = _runspace.CreatePipeline

        End Sub

        ' //// ENUMS

        ' //// INLINE KLASSEN

        Public Sub Run()



                AddLogEntry("PowerShell - Execution started at " & Now.ToString)
                AddLogEntry("Current User: " & System.Environment.UserName)


                Dim out = _pipeline.Invoke()
                Dim builder As New System.Text.StringBuilder

                Dim info = _pipeline.PipelineStateInfo
                If (info.State <> PipelineState.Completed) Then
                    AddLogEntry("---PipelineState: " & info.State.ToString)
                End If

                If _pipeline.Error.Count > 0 Then
                End If

            Catch ex As Exception


            End Try

            If _hasErrors Then
            End If

        End Sub

        Private Sub ClearLog()
            _log = ""
            _hasErrors = False
        End Sub

        Private Sub AddLogEntry(ByVal entry As String)
            _log &= entry & Environment.NewLine
        End Sub

        Private Sub LogError(ByVal pipelineError As PipelineReader(Of Object))

            Dim x As Integer
            Dim log As New System.Text.StringBuilder

            If pipelineError.Count > 0 Then

                While Not pipelineError.EndOfPipeline
                    log.AppendFormat("---- Error from pipeline [{0}]", x)
                    Dim value = TryCast(pipelineError.Read(), PSObject)
                    If value IsNot Nothing Then
                        'get the ErrorRecord
                        Dim r = TryCast(value.BaseObject, ErrorRecord)
                        If r IsNot Nothing Then
                            'build whatever kind of message your want
                            log.AppendLine(Convert.ToString(r.InvocationInfo.MyCommand.Name) & " : " & Convert.ToString(r.Exception.Message))
                            log.AppendLine(String.Format("+ CategoryInfo: {0}", r.CategoryInfo))
                            log.AppendLine(String.Format("+ FullyQualifiedErrorId: {0}", r.FullyQualifiedErrorId))
                        End If
                    End If
                End While
            End If


        End Sub
        Private Sub LogError(ByVal ex As Exception)


            If ex.InnerException IsNot Nothing Then
            End If

        End Sub
        Private Sub LogError(ByVal err As String)

            _hasErrors = True

        End Sub

        Public Shared Sub FlushLogToEventLog(ByVal log As String)

            Dim sSource As String
            Dim sLog As String
            Dim sEvent As String
            Dim sMachine As String

            sSource = "PowerShell Log"
            sLog = "Application"
            sEvent = log
            sMachine = "."

            If Not EventLog.SourceExists(sSource, sMachine) Then
                EventLog.CreateEventSource(sSource, sLog, sMachine)
            End If

            Dim eLog As New EventLog(sLog, sMachine, sSource)
            eLog.WriteEntry(sEvent, EventLogEntryType.Error, 234, CType(3, Short))

        End Sub

    End Class

Open in new window

Question by:srexp
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
LVL 37

Expert Comment

by:Neil Russell
ID: 37806453
Your code for StartImpersonation(...) is all commented out. Is that just a typo in your posting??

Author Comment

ID: 37806491
That's a typo in my posting. This should not be commented out. The error occurs with impersonation to.

And as I said. The TaskServer User does not have rights to create lists on the exchange server. The code that gets executed in the three metioned scenarios is the same. Tow are working one not.

Here is the code I'm using for the impersonation:

Private Sub ImpersonateValidUser(ByVal userName As String, ByVal domain As String, ByVal password As String)
            ImpersonateValidUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE)
        End Sub
        Private Sub ImpersonateValidUser(ByVal userName As String, ByVal domain As String, ByVal password As String, ByVal provider As Integer)
            Dim tempWindowsIdentity As WindowsIdentity = Nothing
            Dim token As IntPtr = IntPtr.Zero
            Dim tokenDuplicate As IntPtr = IntPtr.Zero

                If RevertToSelf() Then
                    If LogonUser(userName, domain, password, provider, LOGON32_PROVIDER_DEFAULT, token) <> 0 Then
                        If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then
                            tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)
                            impersonationContext = tempWindowsIdentity.Impersonate()
                            Throw New Win32Exception(Marshal.GetLastWin32Error())
                        End If
                        Throw New Win32Exception(Marshal.GetLastWin32Error())
                    End If
                    Throw New Win32Exception(Marshal.GetLastWin32Error())
                End If
                If token <> IntPtr.Zero Then
                End If
                If tokenDuplicate <> IntPtr.Zero Then
                End If
            End Try
        End Sub

Open in new window


Accepted Solution

srexp earned 0 total points
ID: 37832867
I am using Remote Power Shell now to avoid this problem.

Author Closing Comment

ID: 37850309
Not solved. Workaround does work.

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Unified and professional email signatures help maintain a consistent company brand image to the outside world. This article shows how to create an email signature in Exchange Server 2010 using a transport rule and how to overcome native limitations …
If you troubleshoot Outlook for clients, you may want to know a bit more about the OST file before doing your next job. IMAP can cause a lot of drama if removed in the accounts without backing up.
To add imagery to an HTML email signature, you have two options available to you. You can either add a logo/image by embedding it directly into the signature or hosting it externally and linking to it. The vast majority of email clients display l…
This video demonstrates how to sync Microsoft Exchange Public Folders with smartphones using CodeTwo Exchange Sync and Exchange ActiveSync. To learn more about CodeTwo Exchange Sync and download the free trial, go to:…

722 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question