- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这是我的源代码:
extern crate user32;
extern crate kernel32;
use std::io::prelude::*;
use std::net::TcpStream;
use std::ptr;
fn main() {
let mut message = get_data();
loop {
if message != get_data() {
let mut client = TcpStream::connect("127.0.0.1:8080").unwrap();
message = get_data();
println!("{}", message);
let _ = client.write(message.as_bytes());
println!("Sent!");
}
}
}
fn get_data() -> String {
let value: String;
unsafe {
let open = user32::OpenClipboard(ptr::null_mut());
if open == 0 {
println!("{}", kernel32::GetLastError());
user32::CloseClipboard();
return "NULL".to_string()
}
let var = user32::GetClipboardData(13 as u32);
if var.is_null() {
println!("{}", kernel32::GetLastError());
user32::CloseClipboard();
return "NULL".to_string()
}
let data = kernel32::GlobalLock(var) as *mut u16;
let len = rust_strlen16(data);
let raws = std::slice::from_raw_parts(data, len);
value = String::from_utf16_lossy(raws);
kernel32::GlobalUnlock(var);
user32::CloseClipboard();
}
value
}
#[inline(always)] // used from clipboard-win, not mine
unsafe fn rust_strlen16(buff_p: *mut u16) -> usize {
let mut i: isize = 0;
while *buff_p.offset(i) != 0 {
i += 1;
}
return i as usize
}
当我在 main
的第 1 行初始化 message
时,一切都很好,但是当我开始复制文本时,事情开始变得有点奇怪。
从 get_data()
中的 OpenClipboard
函数,我从 GetLastError
得到的错误要么是 6(ERROR_INVALID_HANDLE
) 或 5 (ERROR_ACCESS_DENIED
),原因不明。
在 GetClipboardData
函数中,我始终会从 GetLastError
中获取错误代码 1418 (ERROR_CLIPBOARD_NOT_OPEN
)。您可能会认为我会因为从 OpenClipboard
获取错误代码 6 或 5 而得到此错误,但是它不会打印 1418,因为它不能在函数中走那么远,对吧?我可能是错的,但这就是我的看法。
您还应该注意的是,在循环中比较 message
时会出现这些错误,但是 if
语句仍然继续并且消息被分配了实际复制的数据,这里是一些示例输出。
1418 // this is when message and get_data() are being checked
println!("{}", result); // this is the actual copied data which is message
Sent! // sent!
5
NULL
Sent!
println!("Got Connection");
Sent!
最佳答案
这是我对正在发生的事情的猜测:系统正在强行关闭您打开的剪贴板句柄。
据我所知,剪贴板是真正的全局共享资源,甚至是跨进程的。我无法追溯 OpenClipboard
函数出现的时间有多远,但根据 MSDN,它至少可以在 Windows 2000 上运行。如果它真的起源于 Windows 98/95 或更早版本,我不会感到惊讶。剪贴板是一个古老的概念!
但是,出现了一个概念性问题:如果一个程序打开剪贴板而忘记关闭它怎么办?然后你的整个系统将被阻止使用剪贴板,这将是非常糟糕的。我相信(没有证据)操作系统会跟踪您打开剪贴板的次数,并决定在您占用剪贴板时将其取回。
当您运行您的程序时,您可以看到它固定在 100% 的 CPU 上,因为您构建了一个大部分时间都打开剪贴板的繁忙循环。这足以触发简单的滥用启发式算法。添加 (::std::thread::sleep_ms(100)
) 到循环的末尾似乎让一切都表现得更好。
但是,您仍然偶尔会收到错误代码 5 (ERROR_ACCESS_DENIED
)。同样,我认为这是由剪贴板的全局共享性质引起的。某些其他 进程出于某种原因打开了剪贴板,您不能拥有它。正确的做法是处理无法始终立即访问资源的问题。
进行这些更改似乎可以使您的程序正常运行,但还有更多工作要做:
extern crate user32;
extern crate kernel32;
use std::ptr;
use std::marker::PhantomData;
fn main() {
let mut sequence_val = None;
loop {
let clip = match Clipboard::open() {
Err(WinApiError(ERROR_ACCESS_DENIED)) |
Err(WinApiError(ERROR_CLIPBOARD_NOT_OPEN)) => {
println!("Someone else is using the clipboard; continuing");
continue;
},
Err(e) => panic!("Unknown error while opening the clipboard: {:?}", e),
Ok(c) => c,
};
let next_sequence_val = Some(clip.sequence_number());
if sequence_val != next_sequence_val {
println!("Clipboard advanced from {:?} to {:?}", sequence_val, next_sequence_val);
sequence_val = next_sequence_val;
let all_formats: Result<Vec<_>, _> = clip.formats().collect();
println!("Available formats: {:?}", all_formats);
let message = clip.get_text().expect("Cannot read from clipboard");
match message {
Some(message) => println!("Got clipboard text: {}", message),
None => println!("Clipboard did not contain textual data"),
}
}
::std::thread::sleep_ms(250);
}
}
#[derive(Debug, Copy, Clone)]
struct WinApiError(u32);
const ERROR_ACCESS_DENIED: u32 = 0x5;
const ERROR_CLIPBOARD_NOT_OPEN: u32 = 0x58A;
impl WinApiError {
fn from_global() -> Result<(), WinApiError> {
let val = unsafe { kernel32::GetLastError() };
if val != 0 {
Err(WinApiError(val))
} else {
Ok(())
}
}
}
// PhantomData is used here to prevent creating the struct with
// `Clipboard`.
struct Clipboard {
marker: PhantomData<()>,
}
const CF_UNICODETEXT: u32 = 13;
impl Clipboard {
fn open() -> Result<Clipboard, WinApiError> {
unsafe {
user32::OpenClipboard(ptr::null_mut());
try!(WinApiError::from_global());
Ok(Clipboard { marker: PhantomData })
}
}
fn formats(&self) -> ClipboardFormats {
ClipboardFormats { clip: PhantomData, fmt: 0 }
}
fn sequence_number(&self) -> u32 {
unsafe { user32::GetClipboardSequenceNumber() }
}
fn get_text(&self) -> Result<Option<String>, WinApiError> {
for fmt in self.formats() {
let fmt = try!(fmt);
if fmt == CF_UNICODETEXT {
unsafe {
let var = user32::GetClipboardData(CF_UNICODETEXT);
try!(WinApiError::from_global());
// I don't believe this lock is actually
// needed. In searching around, it only seems to
// be used when you call `GlobalAlloc` and then
// set the clipboard with that data.
// If it's needed, consider making another RAII
// type to handle automatically unlocking.
let data = kernel32::GlobalLock(var) as *mut u16;
try!(WinApiError::from_global());
let len = rust_strlen16(data);
let raws = std::slice::from_raw_parts(data, len);
let value = String::from_utf16_lossy(raws);
kernel32::GlobalUnlock(var);
try!(WinApiError::from_global());
return Ok(Some(value));
}
}
}
Ok(None)
}
}
impl Drop for Clipboard {
fn drop(&mut self) {
unsafe {
// Ignore failure to close as we can't really do anything
// about it
user32::CloseClipboard();
let _ = WinApiError::from_global();
}
}
}
unsafe fn rust_strlen16(buff_p: *mut u16) -> usize {
let mut i = 0;
while *buff_p.offset(i) != 0 { i += 1 }
i as usize
}
struct ClipboardFormats<'a>{
// PhantomData is used here to prevent outliving the opened
// clipboard
clip: PhantomData<&'a Clipboard>,
fmt: u32,
}
impl<'a> Iterator for ClipboardFormats<'a> {
type Item = Result<u32, WinApiError>;
fn next(&mut self) -> Option<Self::Item> {
let next_fmt = unsafe { user32::EnumClipboardFormats(self.fmt) };
if next_fmt == 0 {
match WinApiError::from_global() {
Ok(_) => None,
Err(e) => Some(Err(e)),
}
} else {
self.fmt = next_fmt;
Some(Ok(next_fmt))
}
}
}
也就是说,我创建了一个便利类型 WinApiError
,它会自动检查 GetLastError
并将其绑定(bind)到 Rust 标准 Result
类型中。这与 try!
一起广泛使用。
我引入了一个 Clipboard
结构来拥有一个类型来实现 Drop
。这确保了我们将始终在使用完剪贴板后将其关闭。您甚至可能想要添加一个 close
方法,如果您想提前关闭它,它会变得非常明显和容易:
fn close(self) {
// Automatically dropped as it goes out of scope.
}
为了稍微提高性能,我使用了 GetClipboardSequenceNumber
,它返回剪贴板的整数时间戳。这允许进行更轻量级的检查以了解剪贴板是否已更改,而不是每次都创建一个 String
。它还会阻止您使用神奇的 "NULL"
字符串。您可能仍想跟踪最后一个字符串,以了解用户是否再次复制了相同的文本。
从剪贴板中检索数据时,您应该遍历所有可用格式并在您关心的第一个上采取行动。虽然您只关心 UCS-2 格式,但我在尝试调试时添加了它,所以我想我会保留它。
有比 sleep 更好的解决方案,我还没有实现。 AddClipboardFormatListener
可以在剪贴板更改时通知消息循环。这可能是正确的解决方案,但确实需要您创建一个窗口(即使它仅用于消息)。
关于winapi - 从 2 个 winapi 调用返回不一致的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34572755/
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
在编码时,我问了自己这个问题: 这样更快吗: if(false) return true; else return false; 比这个? if(false) return true; return
如何在逻辑条件下进行“返回”? 在这样的情况下这会很有用 checkConfig() || return false; var iNeedThis=doSomething() || return fa
这是我的正则表达式 demo 如问题所述: 如果第一个数字是 1 则返回 1 但如果是 145 则返回 145 但如果是 133 则返回 133 样本数据a: K'8134567 K'81345678
在代码高尔夫问答部分查看谜题和答案时,我遇到了 this solution返回 1 的最长和最晦涩的方法 引用答案, int foo(void) { return! 0; } int bar(
我想在下面返回 JSON。 { "name": "jackie" } postman 给我错误。说明 Unexpected 'n' 这里是 Spring Boot 的新手。 1日龄。有没有正确的方法来
只要“is”返回 True,“==”不应该返回 True 吗? In [101]: np.NAN is np.nan is np.NaN Out[101]: True In [102]: np.NAN
我需要获取所有在 6 号或 7 号房间或根本不在任何房间的学生的详细信息。如果他们在其他房间,简单地说,我不希望有那个记录。 我的架构是: students(roll_no, name,class,.
我有一个表单,我将它发送到 php 以通过 ajax 插入到 mysql 数据库中。一切顺利,php 返回 "true" 值,但在 ajax 中它显示 false 消息。 在这里你可以查看php代码:
我在 Kotlin 中遇到了一个非常奇怪的无法解释的值比较问题,以下代码打印 假 data class Foo ( val a: Byte ) fun main() { val NUM
请注意,这并非特定于 Protractor。问题在于 Angular 2 的内置 Testability service Protractor 碰巧使用。 Protractor 调用 Testabil
在调试窗口中,以下表达式均返回 1。 Application.WorksheetFunction.CountA(Cells(4 + (i - 1) * rows_per_record, 28) & "
我在本地使用 jsonplaceholder ( http://jsonplaceholder.typicode.com/)。我正在通过 extjs rest 代理测试我的 GET 和 POST 调用
这是 Postman 为成功调用我的页面而提供的(修改后的)代码段。 var client = new RestClient("http://sub.example.com/wp-json/wp/v2
这个问题在这里已经有了答案: What to do with mysqli problems? Errors like mysqli_fetch_array(): Argument #1 must
我想我对 C 命令行参数有点生疏。我查看了我的一些旧代码,但无论这个版本是什么,都会出现段错误。 运行方式是 ./foo -n num(其中 num 是用户在命令行中输入的数字) 但不知何故它不起作用
我已经编写了一个类来处理命名管道连接,如果我创建了一个实例,关闭它,然后尝试创建另一个实例,调用 CreateFile() 返回 INVALID_HANDLE_VALUE,并且 GetLastErro
即使 is_writable() 返回 true,我也无法写入文件。当然,该文件存在并且显然是可读的。这是代码: $file = "data"; echo file_get_contents($fil
下面代码中的变量 $response 为 NULL,尽管它应该是 SOAP 请求的值。 (潮汐列表)。当我调用 $client->__getLastResponse() 时,我从 SOAP 服务获得了
我一直在网上的不同论坛上搜索答案,但似乎没有与我的情况相符的... 我正在使用 Windows 7,VS2010。 我有一个使用定时器来调用任务栏刷新功能的应用程序。在该任务栏函数中包含对 LoadI
我是一名优秀的程序员,十分优秀!