使用 Impersonation 打开 SQLconnection 时出现 TypeInitializationException
Posted
技术标签:
【中文标题】使用 Impersonation 打开 SQLconnection 时出现 TypeInitializationException【英文标题】:TypeInitializationException when opening SQLconnection with Impersonation 【发布时间】:2018-10-05 17:15:57 【问题描述】:我在 Windows 窗体应用程序中遇到 TypeInitializationException 问题,在使用模拟时打开 SQLconnection(当模拟删除一切正常时),我不知道如何解决该问题。
这里是 StackTrace:
v System.Data.SqlClient.SqlConnection..ctor()
v System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Initialize(IDataServices dataServices, Object connection)
v System.Data.Linq.DataContext.Init(Object connection, MappingSource mapping)
v System.Data.Linq.DataContext..ctor(String fileOrServerOrConnection)
v CallBackCvop.Persistance.UnitOfWork..ctor(String connectionString)
v CallBackCvop.MainForm.RefreshOrders()
v CallBackCvop.MainForm.BTN_Search_Click(Object sender, EventArgs e)
v System.Windows.Forms.Control.OnClick(EventArgs e)
v System.Windows.Forms.Button.OnClick(EventArgs e)
v System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
v System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
v System.Windows.Forms.Control.WndProc(Message& m)
v System.Windows.Forms.ButtonBase.WndProc(Message& m)
v System.Windows.Forms.Button.WndProc(Message& m)
v System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
v System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
v System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
v System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
v System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
v System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
v System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
v System.Windows.Forms.Application.Run(Form mainForm)
v CallBackCvop.Program.Main()
这是 innerException 的 StackTrace
v System.Diagnostics.FileVersionInfo.GetVersionInfo(String fileName)
v System.Configuration.ClientConfigPaths.SetNamesAndVersion(String applicationFilename, Assembly exeAssembly, Boolean isHttp)
v System.Configuration.ClientConfigPaths..ctor(String exePath, Boolean includeUserConfig)
v System.Configuration.ClientConfigPaths.GetPaths(String exePath, Boolean includeUserConfig)
v System.Configuration.ClientConfigurationHost.RequireCompleteInit(IInternalConfigRecord record)
v System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
v System.Configuration.BaseConfigurationRecord.GetSection(String configKey)
v System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(String sectionName)
v System.Data.SqlClient.SqlConnection..cctor()
这是我的模拟代码:
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public class Impersonation : IDisposable
private readonly SafeTokenHandle _handle;
private readonly WindowsImpersonationContext _context;
const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
public Impersonation(string domain, string username, string password)
var ok = LogonUser(username, domain, password,
LOGON32_LOGON_NEW_CREDENTIALS, 0, out this._handle);
if (!ok)
var errorCode = Marshal.GetLastWin32Error();
throw new ApplicationException(string.Format("Could not impersonate the elevated user. LogonUser returned error code 0.", errorCode));
this._context = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle());
public void Dispose()
this._context.Dispose();
this._handle.Dispose();
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
private SafeTokenHandle()
: base(true)
[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);
protected override bool ReleaseHandle()
return CloseHandle(handle);
问题是 - 我之前在不同的应用程序中使用过这个模拟代码并且一切正常。我很绝望,有救吗?谢谢。
这是连接字符串:
private readonly string _connectionString = "data source = xxx\\xxx; initial catalog = xxx; integrated security=True; MultipleActiveResultSets=True";
这里是开场白:
using (UnitOfWork frt = new UnitOfWork(_connectionString))
_outCalls.DownloadOutCalls(frt, _orders.ReturnSetOfNumbers());
UnitOfWork(在这里你会得到 TypeInitializationException):
public class UnitOfWork : IDisposable
....repositories...
private readonly DataContext _context;
public UnitOfWork(string connectionString)
_context = new DataContext(connectionString);
....repositories...
public void Dispose()
Dispose(true);
protected virtual void Dispose(bool disposing)
if (disposing)
if (_context != null)
_context.Dispose();
innerexception 是 FileNotFoundException,但它似乎引用了 .exe 本身 - 我不明白。
编辑 - 8.10.2018 我发现当 .exe 在我的桌面上但不在共享的 Intranet 驱动器上时,一切正常。但是被冒充的帐户与我的帐户具有相同的权利。 如前所述,我有一个不同的应用程序,它使用相同的模拟代码、相同的连接字符串,并且一切都在我的桌面和共享驱动器上运行。
编辑 - 8.10.2018 - 11:00 所以它被撞毁了...... System.Diagnostics.FileVersionInfo.GetVersionInfo(pathToExe),
我检查了模拟帐户的权限 - 一切正常, 我在没有假冒和我的帐户的情况下尝试了该应用程序 - 一切正常, 我尝试了模拟我的帐户的应用程序(应该可以) - 不工作【问题讨论】:
没有帮助? :( ... 【参考方案1】:所以... 一段时间后,想出了一个解决方法。 似乎出现了错误 --- System.Diagnostics.FileVersionInfo.GetVersionInfo(pathToExe) 所以将我的模拟调用从程序移到了工作单元。改成这样:
public class UnitOfWork : IDisposable
public IOrderRepository Orders get;
public ICallRepository OutCalls get;
public ILoginRepository Login get;
private readonly DataContext _context;
public UnitOfWork(string connectionString)
_context = new DataContext(new SqlConnection());
using (new Impersonation("domain", "user", "password"))
_context.Connection.ConnectionString = connectionString;
Orders = new OrderRepository(_context);
OutCalls = new CallRepository(_context);
Login = new LoginRepository(_context);
public void Dispose()
Dispose(true);
protected virtual void Dispose(bool disposing)
if (disposing)
if (_context != null)
_context.Dispose();
【讨论】:
以上是关于使用 Impersonation 打开 SQLconnection 时出现 TypeInitializationException的主要内容,如果未能解决你的问题,请参考以下文章
WCF:NetworkCredential 和 Impersonation 之间的关系
创建一个dynamics 365 CRM online plugin - plugin当中的Impersonation角色