[COM]透過IE來將資料放到Clipboard之中

[COM]透過IE來將資料放到Clipboard之中

同事問說在asp使用IE設定Clipboard資料,原本在Windows 2000上是OK的!

但是將程式搬到了Windows 2003後就不OK了!

程式如下,

function CopyToClipboard(content)
        Set objIE = CreateObject("InternetExplorer.Application")
        objIE.Visible = True
        objIE.Navigate("about:blank")
        objIE.document.parentwindow.clipboardData.SetData "text", content   
        objIE.Quit
        set objIE=nothing
end function

將程式搬到WinForm上試一下,程式如下,

Dim objIE = CreateObject("InternetExplorer.Application")
objIE.Navigate("about:blank")
objIE.Visible = True
objIE.document.parentwindow.clipboardData.SetData("text", "this is context")
objIE.Quit()
objIE = Nothing

Run了一下,發現會跳出「您是否要允許這個網頁存取「剪貼簿」」的訊息!

Alert

原來因為IE預設的設定是「提示」,所以改成「啟用」就不會再詢問了!

IEOptions

再來將程式包成Method,程式如下,

Sub CopyToClipboard(ByVal setValue As String)
    Dim objIE = CreateObject("InternetExplorer.Application")
    objIE.Navigate("about:blank")
    objIE.Visible = True
    objIE.Document.parentWindow.clipboardData.setData("text", setValue)
    objIE.Quit()
    objIE = Nothing
End Sub

結果卻發生「不正確的引數」錯誤。

NOTrim

所以用Reflector查看直接使用字串與使用變數的差別,

直接使用使用字串結果如下,

Dim objIE As Object = RuntimeHelpers.GetObjectValue(Interaction.CreateObject("InternetExplorer.Application", ""))
NewLateBinding.LateCall(objIE, Nothing, "Navigate", New Object() { "about:blank" }, Nothing, Nothing, Nothing, True)
NewLateBinding.LateSet(objIE, Nothing, "Visible", New Object() { True }, Nothing, Nothing)
NewLateBinding.LateCall(NewLateBinding.LateGet(NewLateBinding.LateGet(NewLateBinding.LateGet(objIE, Nothing, "document", New Object(0  - 1) {}, Nothing, Nothing, Nothing), Nothing, "parentwindow", New Object(0  - 1) {}, Nothing, Nothing, Nothing), Nothing, "clipboarddata", New Object(0  - 1) {}, Nothing, Nothing, Nothing), Nothing, "SetData", New Object() { "Text", "abc" }, Nothing, Nothing, Nothing, True)
NewLateBinding.LateCall(objIE, Nothing, "Quit", New Object(0  - 1) {}, Nothing, Nothing, Nothing, True)
objIE = Nothing

使用變數結果如下,

Dim objIE As Object = RuntimeHelpers.GetObjectValue(Interaction.CreateObject("InternetExplorer.Application", ""))
NewLateBinding.LateCall(objIE, Nothing, "Navigate", New Object() { "about:blank" }, Nothing, Nothing, Nothing, True)
NewLateBinding.LateSet(objIE, Nothing, "Visible", New Object() { True }, Nothing, Nothing)
Dim VB$t_array$S1 As Object() = New Object() { "Text", setValue }
Dim VB$t_array$S2 As Boolean() = New Boolean() { False, True }
NewLateBinding.LateCall(NewLateBinding.LateGet(NewLateBinding.LateGet(NewLateBinding.LateGet(objIE, Nothing, "document", New Object(0  - 1) {}, Nothing, Nothing, Nothing), Nothing, "parentwindow", New Object(0  - 1) {}, Nothing, Nothing, Nothing), Nothing, "clipboarddata", New Object(0  - 1) {}, Nothing, Nothing, Nothing), Nothing, "SetData", VB$t_array$S1, Nothing, Nothing, VB$t_array$S2, True)
If VB$t_array$S2(1) Then
    setValue = CStr(Conversions.ChangeType(RuntimeHelpers.GetObjectValue(VB$t_array$S1(1)), GetType(String)))
End If
NewLateBinding.LateCall(objIE, Nothing, "Quit", New Object(0  - 1) {}, Nothing, Nothing, Nothing, True)
objIE = Nothing

後面的參數是Nothing  VS. VB$t_array$S2,那變數也是字串型態呀~~ 為何會有差呢!?

所以就在呼叫中,再加入Trim(),結果就OK了!

Sub CopyToClipboard(ByVal setValue As String)
    Dim objIE = CreateObject("InternetExplorer.Application")
    objIE.Navigate("about:blank")
    objIE.Visible = True
    '變數請加入Trim,才不會有 不正確的引數。的錯誤
    objIE.Document.parentWindow.clipboardData.setData("text", setValue.Trim())
    objIE.Quit()
    objIE = Nothing
End Sub

用Reflector查看一下,沒出現VB$t_array$的東西了!

Dim objIE As Object = RuntimeHelpers.GetObjectValue(Interaction.CreateObject("InternetExplorer.Application", ""))
NewLateBinding.LateCall(objIE, Nothing, "Navigate", New Object() { "about:blank" }, Nothing, Nothing, Nothing, True)
NewLateBinding.LateSet(objIE, Nothing, "Visible", New Object() { True }, Nothing, Nothing)
NewLateBinding.LateCall(NewLateBinding.LateGet(NewLateBinding.LateGet(NewLateBinding.LateGet(objIE, Nothing, "Document", New Object(0  - 1) {}, Nothing, Nothing, Nothing), Nothing, "parentWindow", New Object(0  - 1) {}, Nothing, Nothing, Nothing), Nothing, "clipboardData", New Object(0  - 1) {}, Nothing, Nothing, Nothing), Nothing, "setData", New Object() { "text", setValue.Trim }, Nothing, Nothing, Nothing, True)
NewLateBinding.LateCall(objIE, Nothing, "Quit", New Object(0  - 1) {}, Nothing, Nothing, Nothing, True)
objIE = Nothing

 

C#篇

如果要在C#中使用LateBinding呼叫COM元件就比VB麻煩多了,因為要透過Reflection來處理,而且要注意物件的屬性名稱大小寫也有差別! 不過,不會發生像VB變數值還要加Tirm()才Work的問題! 程式如下,

/// <summary>
/// 透過IE來將資料放到Clipboard之中
/// </summary>
/// <param name="setValue"></param>
private void CopyToClipboard(string setValue)
{
    //請注意,大小寫有差哦!
    System.Type ieType = System.Type.GetTypeFromProgID("InternetExplorer.Application");
    object objIE = System.Activator.CreateInstance(ieType);
    ieType.InvokeMember("Visible", BindingFlags.SetProperty, null, objIE, new Object[] { true });
    ieType.InvokeMember("Navigate", BindingFlags.InvokeMethod, null, objIE, new Object[] { @"about:blank" });
    object doc = ieType.InvokeMember("Document", BindingFlags.GetProperty, null, objIE, new Object[] { });
    object parentWin = doc.GetType().InvokeMember("parentWindow", BindingFlags.GetProperty, null, doc, new Object[] { });
    object clipData = parentWin.GetType().InvokeMember("clipboardData", BindingFlags.GetProperty, null, parentWin, new Object[] { });
    clipData.GetType().InvokeMember("setData", BindingFlags.InvokeMethod, null, clipData, new Object[] { "text", setValue });
    ieType.InvokeMember("Quit", BindingFlags.InvokeMethod, null, objIE, new Object[] { });
}

範例程式:

Hi, 

亂馬客Blog已移到了 「亂馬客​ : Re:從零開始的軟體開發生活

請大家繼續支持 ^_^