我正在构建一个需要剪贴板功能的Winform应用程序,因此我需要调用user32.dll。现在,当我启动应用程序时,我收到以下错误System.UnauthorizedAccessException: 'Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))'
。
经过进一步调查后发现,当我尝试使用SetClipboardViewer()
注册clipBoardViewer时,我从user32.dll获得了invalid Handle
错误代码。
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Threading;
namespace NiceClip
{
public partial class MainForm : Form
{
[DllImport("User32.dll")]
protected static extern int SetClipboardViewer(int hWndNewViewer);
[DllImport("User32.dll")]
protected static extern int GetLastError();
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
IntPtr nextClipboardViewer;
NotifyIcon niceClipIcon;
Icon niceClipIconImage;
ContextMenu contextMenu = new ContextMenu();
bool reallyQuit = false;
bool isCopying = false;
public MainForm()
{
InitializeComponent();
nextClipboardViewer = (IntPtr)SetClipboardViewer((int)this.Handle);
if (this.clipboardHistoryList.Items.Count > 0)
this.clipboardHistoryList.SetSelected(0, true);
clipboardHistoryList.Select();
this.TopMost = true;
niceClipIconImage = Properties.Resources.clipboard;
niceClipIcon = new NotifyIcon
{
Icon = niceClipIconImage,
Visible = true
};
MenuItem quitMenuItem = new MenuItem("Quit");
MenuItem showFormItem = new MenuItem("NiceClip");
this.contextMenu.MenuItems.Add(showFormItem);
this.contextMenu.MenuItems.Add("-");
this.contextMenu.MenuItems.Add(quitMenuItem);
niceClipIcon.ContextMenu = contextMenu;
quitMenuItem.Click += QuitMenuItem_Click;
showFormItem.Click += ShowForm;
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
}
/// <summary>
/// Takes care of the external DLL calls to user32 to receive notification when
/// the clipboard is modified. Passes along notifications to any other process that
/// is subscribed to the event notification chain.
/// </summary>
protected override void WndProc(ref System.Windows.Forms.Message m)
{
const int WM_DRAWCLIPBOARD = 0x308;
const int WM_CHANGECBCHAIN = 0x030D;
int error = Marshal.GetLastWin32Error(); // Error is code 1400 (invalid window handle)
switch (m.Msg)
{
case WM_DRAWCLIPBOARD:
if (!isCopying)
AddClipBoardEntry();
break;
case WM_CHANGECBCHAIN:
if (m.WParam == nextClipboardViewer)
nextClipboardViewer = m.LParam;
else
SendMessage(nextClipboardViewer, m.Msg, m.WParam,
m.LParam);
break;
default:
base.WndProc(ref m);
break;
}
}
/// <summary>
/// Adds a clipboard history to the clipboard history list.
/// </summary>
private void AddClipBoardEntry()
{
if (Clipboard.ContainsText()) // FAILS HERE
{
string clipboardText = Clipboard.GetText();
if (!String.IsNullOrEmpty(clipboardText))
{
clipboardHistoryList.Items.Insert(0, clipboardText);
toolStripStatusLabel.Text = "Entry added in the clipboard history.";
deleteButton.Enabled = true;
}
}
else
{
toolStripStatusLabel.Text = "History entry was not added because it was null or empty";
}
}
第int error = Marshal.GetLastWin32Error();
行返回错误代码1400,窗口句柄无效,see this。
我已经确认线程公寓已正确设置
namespace NiceClip
{
static class Program
{
[STAThread] // Here
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
我也尝试使用GC.KeepAlive()
所以它不会收集表单或它的句柄,但我真的不明白为什么会这样。
当我调试应用程序时,我发现,在调用SetClipBoardViewer()
之前,表单句柄有一个值(我认为)是有效的,至少它不是null
或{{1}所以我不明白为什么句柄会被视为无效。
答案 0 :(得分:0)
我发现了错误(source code from GIT)。更改应用程序设置。
转到Properties
- &gt; Security
并更改为&#39;这是一个完全信任的应用程序&#39;。
更改后,应用程序启动没有问题,剪贴板功能正常工作。