Problem creating distribution lists on exchange server 2010 via power shell

Posted on 2012-04-04
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

Office 365 Training for IT Pros

Learn how to provision tenants, synchronize on-premise Active Directory, implement Single Sign-On, customize Office deployment, and protect your organization with eDiscovery and DLP policies.  Only from Platform Scholar.

Question has a verified solution.

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

A list of top three free exchange EDB viewers that helps the user to extract a mailbox from an unmounted .edb file and get a clear preview of all emails & other items with just a single click on mailboxes.
This article will help to fix the below error for MS Exchange server 2010 I. Out Of office not working II. Certificate error "name on the security certificate is invalid or does not match the name of the site" III. Make Internal URLs and External…
In this video we show how to create an Address List in Exchange 2013. We show this process by using the Exchange Admin Center. Log into Exchange Admin Center.: First we need to log into the Exchange Admin Center. Navigate to the Organization >> Ad…
The video tutorial explains the basics of the Exchange server Database Availability groups. The components of this video include: 1. Automatic Failover 2. Failover Clustering 3. Active Manager
Suggested Courses

622 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