【问题标题】:Problem only in Vista (.net): call unmanaged dll(Shell32.dll, function: SHEmptyRecycleBin) from thread仅在 Vista (.net) 中的问题:从线程调用非托管 dll(Shell32.dll,函数:SHEmptyRecycleBin)
【发布时间】:2009-05-27 06:18:40
【问题描述】:

********平台:在Vista(终极版或家庭/高级版)中不起作用,其他操作系统(xp,windows7)它起作用*************

我正在线程中使用 c++.net(或 c#.net)清空回收站。当我直接(没有线程)这样做时,它可以工作。但如果线程使用它不会。请看下面的代码sn-p:

namespace EmptyRecycleBin_C{
enum RecycleFlags
{
  SHERB_NOCONFIRMATION = 0x00000001,
  SHERB_NOPROGRESSUI = 0x00000002,
  SHERB_NOSOUND = 0x00000004
};
public ref class Form1 : public System::Windows::Forms::Form{

[DllImport("Shell32.dll",CharSet=CharSet::Unicode)]
static System::UInt32 SHEmptyRecycleBin(IntPtr hwnd, String^ pszRootPath, RecycleFlags dwFlags);

private: void button1_Click(System::Object^  sender, System::EventArgs^  e)
{
  Thread^ th = gcnew System::Threading::Thread(gcnew ThreadStart(this, &Form1::doEmpty));
  th->Start();
  //this->doEmpty(); // this line works just fine
}

private: void doEmpty()
{
  try{
        SHEmptyRecycleBin(IntPtr::Zero, String::Empty, RecycleFlags::SHERB_NOCONFIRMATION);
     }catch(Exception^ ex)
     {Diagnostics::Debug::Write(ex->Message);}
}
};
}

这里有什么问题...?

【问题讨论】:

  • 你能分享一些关于它是如何不工作的细节(异常细节和类似的)吗?
  • 它不会抛出任何异常,而是返回一个负值。成功时(在没有任何线程的情况下调用)返回 0。在调用 SHEmptyRecycleBin 后还设置 [DllImport("kernel32.dll", SetLastError=true, ...)] 尝试使用 System.Console.WriteLine(Marshal. GetLastWin32Error()) 显示“操作成功完成”虽然回收站没有清空。
  • 返回错误码?负值?号码是多少?更好的是:假设负数实际上是一个无符号的 32 位值,然后将其转换为十六进制。然后用谷歌搜索十六进制错误代码(例如 80004005)

标签: .net multithreading dll pinvoke unmanaged


【解决方案1】:

可能是因为您创建的线程在默认安全上下文中执行,而不是在主线程的安全上下文中执行?

请参阅the doc on ExecutionContext 以获取提示。您可以在线程上设置 ExecutionContext 并重试。

【讨论】:

  • 我敢打赌这是权限问题。 Vista UAC 可能会成为阻碍。 Windows 7 对某些任务进行自动提升,因此可以解释为什么它可以在 7 而不是 Vista 上运行。
  • Chesso,链接处理 FileDialogPermission。这种情况需要什么权限(上面的代码)。如果您可以提供代码 sn-p 如何执行此操作,那将非常有帮助。
【解决方案2】:

您是否从您的线程中调用了 CoInitialize?

它返回什么错误代码?

【讨论】:

    【解决方案3】:

    Shell 函数仅适用于 STA 线程,而 .NET 线程默认为 MTA。您可以将线程设置为使用单单元线程:

    th->SetApartmentState(ApartmentState::STA);
    th->Start();
    

    【讨论】:

      【解决方案4】:

      我不知道为什么会这样,但是您尝试过其他线程方法吗?比如 BackgroundWorker 组件或 ThreadPool.QueueUserWorkItem?错误是否仍然发生?

      【讨论】:

        猜你喜欢
        • 2014-08-18
        • 2011-12-27
        • 2016-02-09
        • 1970-01-01
        • 2013-01-10
        • 1970-01-01
        • 2015-04-07
        • 2011-09-24
        相关资源
        最近更新 更多