简体   繁体   English

STAThread 丢失,但它在那里

[英]STAThread missing, but it is there

Here is the error message that I am recieving when I try to open an OpenFileDialog in my program:这是我尝试在程序中打开 OpenFileDialog 时收到的错误消息:

"Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process." “在进行 OLE 调用之前,当前线程必须设置为单线程单元 (STA) 模式。确保您的 Main 函数上标记了 STAThreadAttribute。仅当调试器附加到进程时才会引发此异常。”

The problem with this error message is that my Main method DOES have the STAThread attribute attached to it.此错误消息的问题在于我的 Main 方法确实附加了 STAThread 属性。 I am at a loss as to how to handle this.我不知道如何处理这个问题。 How can I add something if it is already there.如果它已经存在,我该如何添加。 Doubling it up is not a good option, and I tried erasing it, building the app, adding it and building it again with no success.将它加倍不是一个好的选择,我尝试删除它,构建应用程序,添加它并再次构建它,但没有成功。 I just don't understand.我就是不明白。

private void btnOldFind_Click(object sender, EventArgs e)
{
     openFileDialog1.Multiselect = false;
     openFileDialog1.FileName = "";
     openFileDialog1.ShowHelp = false;
     openFileDialog1.AutoUpgradeEnabled = true;
     openFileDialog1.InitialDirectory = @"C:\";
     openFileDialog1.Filter = "Microsoft Installer (*.msi)|*.msi|All Files (*.*)|*.* ";
     openFileDialog1.FilterIndex = 1;
     openFileDialog1.RestoreDirectory = true;

     if (openFileDialog1.ShowDialog() == DialogResult.OK)
     {
         textBoxOldInstallation.Text = openFileDialog1.FileName;
     }
}

and the main method is:主要方法是:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

And no threading is done explicitly.并且没有明确地完成线程。 Just a pretty basic program to be honest.老实说,这只是一个非常基本的程序。

EDIT2::编辑2::

Here is the complete error message including call stack这是完整的错误消息,包括调用堆栈

System.Threading.ThreadStateException was unhandled Message="Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process." System.Threading.ThreadStateException was unhandled Message="当前线程必须设置为单线程单元 (STA) 模式,然后才能进行 OLE 调用。确保您的 Main 函数上标记了 STAThreadAttribute。仅当调试器处于运行状态时才会引发此异常附加到过程中。” Source="System.Windows.Forms" StackTrace: at System.Windows.Forms.FileDialog.RunDialog(IntPtr hWndOwner) at System.Windows.Forms.CommonDialog.ShowDialog(IWin32Window owner) at System.Windows.Forms.CommonDialog.ShowDialog() at MSI_Comparison_GUI.Form1.btnOldFind_Click(Object sender, EventArgs e) in c:\\tfs\\DocuWare .NET\\DocuWare NewGen\\src\\Tools\\MSI_Comparison\\MSI_Comparison_GUI\\Form1.cs:line 70 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.Debu Source="System.Windows.Forms" StackTrace: at System.Windows.Forms.FileDialog.RunDialog(IntPtr hWndOwner) at System.Windows.Forms.CommonDialog.ShowDialog(IWin32Window owner) at System.Windows.Forms.CommonDialog.ShowDialog( ) 在 MSI_Comparison_GUI.Form1.btnOldFind_Click(Object sender, EventArgs e) in c:\\tfs\\DocuWare .NET\\DocuWare NewGen\\src\\Tools\\MSI_Comparison\\MSI_Comparison_GUI\\Form1.cs:line 70 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.Debu ggableCallback(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(Int32 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(Form mainForm) at MSI_Comparison_GUI.Program.Main() in c:\\tfs\\DocuWare .NET\\DocuWare NewGen\\src\\Tools\\MSI_Comparison\\MSI_Comparison_GUI\\Program.cs:line 18 at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.T ggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 在 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 在 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageL (Int32 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(Form mainForm) at MSI_Comparison_GUI.Program.Main() in c:\\tfs\\DocuWare .NET\\DocuWare NewGen\\src\\Tools\\MSI_Comparison\\MSI_Comparison_GUI\\Program.cs:line 18 at System. AppDomain._nExecuteAssembly(Assembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.T hreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() InnerException: hreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() InnerException:

It might be that you are facing the following problem reported on Connect 1 :您可能遇到了 Connect 1上报告的以下问题:

.vshost.exe forces wrong threading model used when debugging a .exe if a .dll of the same name exists in same bin directory 如果同名的 .dll 存在于同一 bin 目录中,.vshost.exe 会强制在调试 .exe 时使用错误的线程模型

According to that issue it happens that the hosting process of Visual Studio, ie the myprogram.vshost.exe enforces the wrong apartment state when you have both a myprogram.exe and a myprogram.dll file in your output folder.根据该问题,当您的输出文件夹中有myprogram.exemyprogram.dll文件时,Visual Studio 的托管进程,即 myprogram.vshost.exe 会强制执行错误的单元状态。

The problem might be specific to some older version of Visual Studio (2005), and I haven't been able to reproduce it using VS 2010.该问题可能特定于某些较旧版本的 Visual Studio (2005),我无法使用 VS 2010 重现它。

The obvious workaround would be to change the name of the dll or to move the dll to another folder.显而易见的解决方法是更改​​ dll 的名称或将 dll 移动到另一个文件夹。

The situation might have come up because you changed the output type of your project from class libary to Windows application.出现这种情况可能是因为您将项目的输出类型从类库更改为 Windows 应用程序。

1 It is unclear whether this problem is confirmed by Microsoft or not, it just says that the problem is outside the responsibility of the VS product team. 1不清楚这个问题是否得到了微软的确认,只是说这个问题不在VS产品团队的责任范围内。

You've got an impossible stack trace.你有一个不可能的堆栈跟踪。 It is clear that threading is not the cause of the problem, everything is running on the main thread and the [STAThread] attribute on your Main method is setting the apartment state.很明显,线程不是问题的原因,一切都在主线程上运行,并且 Main 方法上的 [STAThread] 属性正在设置单元状态。 The stack trace shows that it indeed the entrypoint.堆栈跟踪显示它确实是入口点。

Well, bad news, some kind of add-on is farking with your main thread.好吧,坏消息,某种附加组件正在与您的主线程发生冲突。 Doing something nasty like calling CoUninitialize too many times.做一些讨厌的事情,比如多次调用 CoUninitialize。 I've had this happen to me once, took me a month to find it.我曾经遇到过这种情况,我花了一个月才找到它。 Start diagnosing this with Project + Properties, Debug tab, tick "Enable unmanaged code debugging".使用 Project + Properties,Debug 选项卡开始诊断,勾选“Enable unmanaged code debugging”。 That lets you see what DLLs are getting loaded into your program, it is shown in the Output window.这让您可以看到哪些 DLL 被加载到您的程序中,它显示在“输出”窗口中。

The first lead is when the dialog displays okay the first time but fails the second time.第一个线索是当对话框一次显示正常但第二次失败时。 Then you've got some kind of shell extension handler that wormed its way into your program.然后你就有了某种外壳扩展处理程序,它蠕虫进入你的程序。 Use SysInternals' AutoRuns utility and disable any shell extension handler that wasn't made by Microsoft.使用 SysInternals 的 AutoRuns 实用程序并禁用任何非 Microsoft 制作的外壳扩展处理程序。

It gets harder when the dialog fails right away.当对话立即失败时,它会变得更难。 Then use Debug + Windows + Modules and go through the list of DLLs.然后使用 Debug + Windows + Modules 并查看 DLL 列表。 Pay attention to where they came from, shown in the Path column.注意它们来自哪里,显示在路径列中。 Distrust anything the doesn't quack like a .NET or Microsoft DLL.不信任任何不像 .NET 或 Microsoft DLL 那样嘎嘎叫的东西。 Especially not having a Symbol File when you enabled the Microsoft Symbol Server is a lead.尤其是当您启用 Microsoft 符号服务器时没有符号文件是一个主要因素。 A good way to make some headway with this is to compare that list to one you see on another machine that doesn't have this problem.取得进展的一个好方法是将该列表与您在另一台没有此问题的机器上看到的列表进行比较。

I do have a war-story about this.我确实有一个关于这个的战争故事。 My COM code was crashing on hundreds of machines, all I had to go by was a minidump.我的 COM 代码在数百台机器上崩溃,我所要做的只是一个小型转储。 Took me a month to discover the source, an open source project named ffdshow.我花了一个月的时间才发现源代码,一个名为 ffdshow 的开源项目。 Very widely distributed, using different names as well.分布非常广泛,也使用不同的名称。 It had a bug, calling CoUnitialize two times too many.它有一个错误,多次调用 CoUnitialize。 The bug was present in releases for two years but got fixed about a year and a half ago.该错误在发行版中存在了两年,但在大约一年半前得到修复。 Very hard to diagnose, I didn't get close to it until I started looking at old releases.很难诊断,我没有得到接近它,直到我开始寻找老版本。 If you do see ffdshow in your Modules window then you're close :)如果您确实在“模块”窗口中看到了 ffdshow,那么您就接近了 :)

Good luck, let us know the evil-doer.祝你好运,让我们认识邪恶的人。

Can't say without code.没有代码就不能说。 If a console app, add the following before you call the method:如果是控制台应用程序,请在调用该方法之前添加以下内容:

Console.Write(System.Threading.Thread.CurrentThread.ApartmentState);

otherwise,除此以外,

MessageBox.Show(System.Threading.Thread.CurrentThread.ApartmentState);

and see what the threading apartment state REALLY is.并查看线程单元状态真正是什么。

Try setting breakpoints at the main procedure, the point where the dialogbox is created, and where it is used.尝试在主过程、创建对话框的位置以及使用它的位置设置断点。 Then look at what thread(s) you actually are in. Also, check what the value of Thread.CurrentThread.GetApartmentState() is at those points.然后查看您实际所在的线程。另外,检查Thread.CurrentThread.GetApartmentState()在这些点的值。

t.SetApartmentState(ApartmentState.STA);

The above line of code worked for me.上面的代码行对我有用。 once try it.一旦尝试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM