VBS Object required: '[string: ""]' - vbscript

I have the code
set WshShell = CreateObject("WScript.Shell")
Set ie = CreateObject("InternetExplorer.Application")
ie.Offline = True
ie.Navigate "about:blank"
ie.Height = 200
ie.Width = 425
ie.MenuBar = False
ie.StatusBar = False
ie.AddressBar = False
ie.Toolbar = False
ie.Visible = True
WshShell.Run "%windir%\notepad.exe"
WshShell.AppActivate "Notepad"
WScript.Sleep 3000
set a = WshShell.SendKeys("a") & Wscript.Sleep("100")
a
It does type "a" in notepad, but then it gives the error," Object Required: '[string: ""]' " and it will prevent any code after it from running.
If anyone knows how to fix this and prevent it in the future that would be great.

You're trying to assign something to a variable as an object that isn't an object (Set a = ...). Don't do that. Neither SendKeys() nor Sleep() return output, so there's no point in assigning that non-output anyway. Or in concatenating it (you're probably confusing the VBScript string concatenation operator & with the batch command chaining operator &).
Change this:
Set a = WshShell.SendKeys("a") & WScript.Sleep("100")
into this:
WshShell.SendKeys("a")
WScript.Sleep(100)
and the problem will disappear.
If you're trying to implement a procedure that you can invoke as a shorthand, that would be done e.g. like this:
Sub k
WshShell.SendKeys("a")
WScript.Sleep(100)
End Sub
k 'sends keystroke "a" and waits 100 ms
or like this, if you want it parametrized:
Sub k(keys)
WshShell.SendKeys(keys)
WScript.Sleep(100)
End Sub
k "b" 'sends keystroke "b" and waits 100 ms

Related

QTP-UFT-Weblist selection by sendkeys-How to keep control key pressed while selecting multiple values

Wsh.SendKeys "^"&a(i) is not holding the control down. Something like micCtrldown and micctrlup before and after sending the values would be helpful But not sure about the syntax
Set Wsh = CreateObject("Wscript.Shell")
a = Split(Datatable.Value("AssignedTerminal", dtlocalsheet),",")
b = ubound(a)
wait 3
Browser("P&D Routing -Estes").Page("P&D Routing Estes").WebList("addAssignedTerminal_Add").Click
Setting.WebPackage("ReplayType") = 2
Set WshShell = CreateObject("WScript.Shell")
WshShell.SendKeys "{DOWN}"
For i = 0 To b
Wsh.SendKeys "^"&a(i)
Next
Set WshShell = Nothing
Setting.WebPackage("ReplayType") = 1
Are we sure the SendKeys function supports the concatenated string you are sending it?
For i = 0 To b
Wsh.SendKeys "^"&a(i)
Next
Try to use a predefined string to send to SendKeys instead of building it inline.

how does objIE.Document.body.innertext work?

I'm trying to understand how the objIE.Document.body.innertext works. From what I've read, it's almost like CTRL+C, however, I'm trying to get it to work and something's missing. Here's the code:
Dim objIE
Dim strPrintText
Set objIE = CreateObject("InternetExplorer.Application")
objIE.Navigate "www.bing.com"
strPrintText = objIE.Document.body.innertext
msgbox(strPrintText)
You must wait until the browser is ready (and not use param list () when calling a Sub):
Dim objIE
Dim strPrintText
Set objIE = CreateObject("InternetExplorer.Application")
objIE.Navigate "www.bing.com"
Do Until objIE.readyState = 4 : Wscript.Sleep 10 : Loop
strPrintText = objIE.Document.body.innertext
msgbox strPrintText
Please cf this for background.
WRT param list () in Sub calls:
>> MsgBox "No param () when calling a Sub!", vbOkOnly
>>
>> MsgBox("No param () when calling a Sub!", vbOkOnly)
>>
Error Number: 1044
Error Description: Cannot use parentheses when calling a Sub
>>
>> MsgBox "Do you believe me now?", vbOkOnly
For theory/reason cf this; and reflect on the merit of "it works" when discussing rules of programming (or ethics: stealing works fine, as long you are not caught).

VBScript - Error 0x80041017 (null)

IMPORTANT UPDATE:
As Cheran S stated below, it's a good idea to avoid using "taskmgr" for this script. I'm not going to edit the code, as I feel it's best to maintain the original question as much as possible since doing so would partially invalidate & obfuscate Cheran's answer & comment.
A good alternative to "taskmgr" would be "CharMap" (for simple & fast testing).
Running Windows XP Professional (32-bit) and I've got this script that's throwing up this error:
Script: C:\test.vbs
Line: 40
Char: 3
Error: 0x80041017
Code: 80041017
Source: (null)
Here's the code:
Set objWshShell = Wscript.CreateObject("Wscript.Shell")
Set objWshNet = CreateObject("Wscript.Network")
strComputer = objWshNet.ComputerName
Set objWMIService = GetObject("winmgmts:" & _
"{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Dim arrWinTitle(2)
arrWinTitle(0) = "My Documents"
arrWinTitle(1) = "Control Panel"
Dim arrProcName(3)
arrProcName(0) = "'taskmgr.exe'"
arrProcName(1) = "'calc.exe'"
arrProcName(2) = "'notepad.exe'"
Sub srBlockWindow(strWinTitle, intWinTitle, strProcName, intProcName)
i = 0
Do While i = 0
If objWshShell.AppActivate(strWinTitle(intWinTitle)) Then
objWshShell.AppActivate(strWinTitle(intWinTitle))
Wscript.Sleep 100
objWshShell.SendKeys "%{F4}"
Wscript.Sleep 100
End If
If intWinTitle = 0 Then
intWinTitle = intWinTitle + 1
Else
intWinTitle = 0
End If
Wscript.Sleep 100
Set colProcesses = objWMIService.ExecQuery _
("SELECT * FROM Win32_Process WHERE NAME = " & strProcName(intProcName))
For Each objProcess In colProcesses
objProcess.Terminate()
Next
If intProcName >= 0 Then
intProcName = intProcName + 1
ElseIf intProcName >= 5 Then
intProcName = 0
End If
Set colProcesses = Nothing
Loop
End Sub
Call srBlockWindow(arrWinTitle, 0, arrProcName, 0)
I've reviewed this, but I believe my script doesn't have any issues with the quotes. For the sake of clarity, I'm getting the error at the start of the "For Each ..." string.
What's peculiar is that it will run fine the first time, but once it loops, that's when I get the error. So, it will close all the desired Windows/Applications, but once it goes through it's second iteration, I get the error. I've inserted "On Error Resume Next", but that doesn't resolve it (I will add it later, since it's required to resolve the conflict when the Window/Process Starts simultaneously with Close/End/Stop attempts made by the Script).
I think it's because I should be conditionally checking if the process exists; problem is, I'm not quite sure how to do that with this code (I've never been good with Collections). Anybody have suggestions on how to do it with this code specifically?
I reviewed this and tried to write a quick alternative script, but it didn't really work. Here's the code:
Set service = GetObject("winmgmts:")
Dim arrProcName(3)
arrProcName(0) = "'taskmgr.exe'"
arrProcName(1) = "'calc.exe'"
arrProcName(2) = "'notepad.exe'"
Sub srTest(strProc, intProc)
i = 0
Do While i = 0
For Each Process In Service.InstancesOf("Win32_Process")
If Process.Name = strProc(intProc) Then
Process.Name.Terminate
Process.Terminate
End If
Next
If intProc = 0 Then
intProc = intProc + 1
ElseIf intProc >= 3 Then
intProc = 0
End If
Loop
End Sub
Call srTest(arrProcName, 0)
As you can see, I tried both "Process.Terminate" & "Process.Name.Terminate", but neither yielded anything (not even an error). I further tested it with "Wscript.Echo Process.Name" & "Wscript.Echo strProc(intProc)", but neither of these worked too.
Now that I've failed at this alternative solution, I'm feeling that I'm wildly stabbing in the dark for solutions, so I'll defer these esoteric challenges to the community that is vastly superior to me.
There might be a few here who are reading this and wondering why I'm targeting My Documents, Control Panel, taskmgr.exe, calc.exe, & notepad.exe. Almost everybody reading this will probably be able to extrapolate on their own, but I'll make sure I'm clear on this for those who need it. I'm doing this because it makes it easier to test, since all of these can be accessed simply by using the "Run" shortcut (Windows Key + R) & then entering the following strings (one at a time, of course):
My Documents
Control
taskmgr
calc
notepad
You likely knew the keywords, but I just wanted to highlight why I'm using these specific ones (speed & simplicity).
I'll remove this if Cheran adds the final code to the answer posted
Final Solution:
Set objWshShell = Wscript.CreateObject("Wscript.Shell")
Set objWshNet = CreateObject("Wscript.Network")
strComputer = objWshNet.ComputerName
Set objWMIService = GetObject("winmgmts:" & _
"{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Dim arrWinTitle
arrWinTitle = Array("My Documents", "Control Panel")
Dim arrProcName
arrProcName = Array("'charmap.exe'", "'calc.exe'", "'notepad.exe'")
Sub srBlockWindow(strWinTitle, intWinTitle, strProcName, intProcName)
i = 0
Do While i = 0
On Error Resume Next
' In the Event of Conflict w/Initiation of Window or Process
If objWshShell.AppActivate(strWinTitle(intWinTitle)) Then
objWshShell.AppActivate(strWinTitle(intWinTitle))
Wscript.Sleep 100
objWshShell.SendKeys "%{F4}"
Wscript.Sleep 100
End If
intWinTitle = (intWinTitle + 1) Mod (UBound(strWinTitle) + 1)
Wscript.Sleep 100
Set colProcesses = objWMIService.ExecQuery _
("SELECT * FROM Win32_Process WHERE NAME = " & strProcName(intProcName))
For Each objProcess In colProcesses
objProcess.Terminate()
Next
intProcName = (intProcName + 1) Mod (UBound(strProcName) + 1)
Set colProcesses = Nothing
Loop
End Sub
Call srBlockWindow(arrWinTitle, 0, arrProcName, 0)
Here's a quick script I threw together to test it against:
Set objWshShell = Wscript.CreateObject("Wscript.Shell")
i = 0
Do While i = 0
objWshShell.Run "explorer.exe /e, C:\Documents and Settings\User\My Documents"
Wscript.Sleep 200
objWshShell.Run "CharMap.exe"
Wscript.Sleep 200
objWshShell.Run "Control.exe"
Wscript.Sleep 200
objWshShell.Run "calc.exe"
Wscript.Sleep 200
objWshShell.Run "notepad.exe"
Wscript.Sleep 200
Loop
BE CAREFUL! Adjust the timings so that you can end "Wscript.exe" without too many problems. Best to run both scripts simultaneously to see how it works.
Two big issues I found:
The main problem here is in the way you define your arrays. The number you specify in the array declaration is the largest array subscript. Since VBScript arrays are always indexed starting at 0, you actually need to specify one less than the number of elements in the array.
' This is wrong:
Dim arrWinTitle(2)
Dim arrProcName(3)
' Should be:
Dim arrWinTitle(1)
Dim arrProcName(2)
You could also use the Array function to initialize your array, assuming that you know beforehand how many elements are in it. In that case, you would just declare arrWinTitle as a Variant and not as an array:
Dim arrWinTitle
arrWinTitle = Array("My Documents", "Control Panel")
If you make that change and try to run the script, you'll still get a "Subscript out of range" error. That error is caused by this block:
If intProcName >= 0 Then
intProcName = intProcName + 1
ElseIf intProcName >= 5 Then
intProcName = 0
End If
First off, the maximum subscript should be 2 for strProcName, and not 5. Even then, this code won't work. It seems like what you're trying to do is loop through the elements of array, then start over back at 0. A better of doing this is with the Mod operator:
intProcName = (intProcName + 1) Mod (UBound(strProcName) + 1)
Notice also how I use the UBound function to avoid hard-coding the actual length of the array.
I won't spend too much time analyzing your second example, since it was just an attempt to make the first example work. I will note, however, that in your arrProcName array, the process names still have the single quotes around them, which is one reason why that script didn't work either.

How to create options dialog with VbScript?

I have a third party application that invokes a vsbscript file for certain operations. I would like to put up a user prompt with a choice of options, either a drop down list or checkbox or some such. However, all I can find is the input box option.
I don't think HTAs are an option in my case (unless there is a way to call them from a .vbs file?)
My other thought was some sort of ActiveX control, but I can't locate a built-in one that would be available by default on WindowsXP/Vista.
Anybody have any ideas on how I could accomplish this?
The simple answer is, you really can't. Tmdean's solution is the only way I can think of either. That said, you can spruce up the input box so it doesn't look horrible. Give this a run, I don't think it's an epic fail:
Dim bullet
Dim response
bullet = Chr(10) & " " & Chr(149) & " "
Do
response = InputBox("Please enter the number that corresponds to your selection:" & Chr(10) & bullet & "1.) Apple" & bullet & "2.) Bannana" & bullet & "3.) Pear" & Chr(10), "Select Thing")
If response = "" Then WScript.Quit 'Detect Cancel
If IsNumeric(response) Then Exit Do 'Detect value response.
MsgBox "You must enter a numeric value.", 48, "Invalid Entry"
Loop
MsgBox "The user chose :" & response, 64, "Yay!"
If you would like to use an hta for this it can be done like this.
The VBScript:
Set WshShell = CreateObject("WScript.Shell")
'Run the hta.
WshShell.Run "Test.hta", 1, true
'Display the results.
MsgBox "Return Value = " & getReturn
Set WshShell = Nothing
Function getReturn
'Read the registry entry created by the hta.
On Error Resume Next
Set WshShell = CreateObject("WScript.Shell")
getReturn = WshShell.RegRead("HKEY_CURRENT_USER\Volatile Environment\MsgResp")
If ERR.Number 0 Then
'If the value does not exist return -1
getReturn = -1
Else
'Otherwise return the value in the registry & delete the temperary entry.
WshShell.RegDelete "HKEY_CURRENT_USER\Volatile Environment\MsgResp"
End if
Set WshShell = Nothing
End Function
Then design the hta as desired, and include the following methods
'Call this when the OK button is clicked.
Sub OK_Click
For Each objradiobutton In Opt
If objradiobutton.Checked Then
WriteResponse objradiobutton.Value
End If
Next
window.Close
End Sub
'Call this when the Cancel button is clicked.
Sub Cancel_Click
WriteResponse("CANCEL")
window.Close
End Sub
'Write the response to the registry
Sub WriteResponse(strValue)
Set WshShell = CreateObject("WScript.Shell")
WshShell.RegWrite "HKEY_CURRENT_USER\Volatile Environment\MsgResp", strValue
Set WshShell = Nothing
End Sub
I used a group of radio buttons named "Opt" to make a choice, but you could use any controls you would like.
Because hta's cannot return values, this will create a temperary registry entry. If you are not comforatable messing with the registry, you could also write the result to a temperary text file.
This approach is nice because you can design the hta any way you like, rather than using the supplied inputbox and choosing numbers (thats so DOS).
This could also be nice if you expanded the hta to create itself based on arguments passed to it, like passing in a title, a message to display, an array of options, a set of buttons. That way you could use the same hta any time you needed to get input from the user.
You can use DialogLib to create forms with dropdowns and checkboxes. DialogLib is still in it's ealy stages, but is's allready quite usefull: http://www.soren.schimkat.dk/Blog/?p=189
Try WshShell.Popup. Depending upon your data that may work for you...
Otherwise you could investigate PowerShell.
One option is to script Internet Explorer. You can use VBScript to launch IE and load a local HTML file, and attach a VBScript sub to a form's submit button (or any other JavaScript events), which can then close the IE window as part of its execution.
You can launch an HTA from a VBScript.
Set shell = CreateObject("WScript.Shell")
shell.Run "Test.hta"
EDIT
Since you have full control of the VBScript, could you make the 3rd party VBScript simply call your HTA? You could put the UI and whatever processing code inside of the HTA.
As an example of #TmDean's suggestion, there's this class that I sometimes use which scripts IE (well, it scripted IE6; I haven't tried the more recent incarnations.)
class IEDisplay
'~ Based on original work by Tony Hinkle, tonyhinkle#yahoo.com
private TEMPORARY_FOLDER
private objShell
private objIE
private objFSO
private objFolder
private strName
private streamOut
private objDIV
private numHeight
private numWidth
private numTop
private numLeft
private sub Class_Initialize()
Dim strComputer
Dim objWMIService
Dim colItems
Dim objItem
Dim arrMonitors( 10, 1 )
Dim numMonitorCount
Set objShell = WScript.CreateObject("WScript.Shell")
Set objIE = CreateObject("InternetExplorer.Application")
strComputer = "."
Set objWMIService = GetObject( "winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery( "Select * from Win32_DesktopMonitor")
numMonitorCount = 0
For Each objItem in colItems
arrMonitors( numMonitorCount, 0 ) = objItem.ScreenHeight
arrMonitors( numMonitorCount, 1 ) = objItem.ScreenWidth
numMonitorCount = numMonitorCount + 1
Next
numHeight = arrMonitors( 0, 0 )
numWidth = arrMonitors( 0, 1 )
Set objFSO = CreateObject("Scripting.FileSystemObject")
TEMPORARY_FOLDER = 2
set objFolder = objFSO.GetSpecialFolder( TEMPORARY_FOLDER )
strName = objFSO.BuildPath( objFolder, objFSO.GetTempName ) & ".html"
WriteFileU strName, Join( Array( "<HTML><HEAD><TITLE>Information</TITLE></HEAD>", _
"<BODY SCROLL='NO'><CENTER><FONT FACE='arial black'> <HR COLOR='BLACK'>", _
"<DIV id='MakeMeAnObject'></DIV>", _
"<HR COLOR='BLACK'></FONT></CENTER></BODY></HTML>" ), vbCRLF ), WF_CREATE
numTop = 0
numLeft = 0
end sub
Sub Init( strPosition )
'NW, N, NE, W, CENTRE, E, SW, S, SE
Select Case strPosition
Case "NW"
numTop = 0
numLeft = 0
Case "N"
numTop = 0
numLeft = ( numWidth / 2 ) - 250
Case "NE"
numTop = 0
numLeft = numWidth - 500
Case "W"
numTop = ( numHeight / 2 ) - 55
numLeft = 0
Case "CENTRE"
numTop = ( numHeight / 2 ) - 55
numLeft = ( numWidth / 2 ) - 250
Case "E"
numTop = ( numHeight / 2 ) - 55
numLeft = numWidth - 500
Case "SW"
numTop = numHeight - 110
numLeft = 0
Case "S"
numTop = numHeight - 110
numLeft = ( numWidth / 2 ) - 250
Case "SE"
numTop = numHeight - 110
numLeft = numWidth - 500
Case Else
numTop = 0
numLeft = 0
End Select
SetupIE( strName )
Set objDIV = objIE.Document.All("MakeMeAnObject")
end sub
private sub Class_Terminate()
'Close IE and delete the file
objIE.Quit
'~ optionally you may want to get rid of the temp file
end sub
public sub Display( strMsg, numMillisec )
objDIV.InnerHTML = strMsg
WScript.Sleep numMillisec
end sub
Private Sub SetupIE(File2Load)
objIE.Navigate File2Load
objIE.ToolBar = False
objIE.StatusBar = False
objIE.Resizable = False
Do
Loop While objIE.Busy
objIE.Width = 500
objIE.Height = 110
objIE.Left = numLeft
objIE.Top = numTop
objIE.Visible = True
objShell.AppActivate("Microsoft Internet Explorer")
End Sub
end class
here is the missing (from the original posting) WriteFileU function
Const WF_APPEND = 1
Const WF_CREATE = 2
Const WF_FOR_APPENDING = 8
Const WF_FOR_WRITING = 2
Const WF_CREATE_NONEXISTING = True
Const CONST_READ = 1, CONST_WRITE = 2, CONST_APPEND = 8
Const AS_SYSTEMDEFAULT = -2, AS_UNICODE = -1, AS_ASCII = 0
Sub WriteFileU( sFilename, sContents, nMode )
Dim oStream
If nMode = WF_APPEND Then
Set oStream = oFSO.OpenTextFile( sFilename, WF_FOR_APPENDING, WF_CREATE_NONEXISTING, AS_UNICODE )
ElseIf nMode = WF_CREATE Then
Set oStream = oFSO.OpenTextFile( sFilename, WF_FOR_WRITING, WF_CREATE_NONEXISTING, AS_UNICODE )
Else
STOP
End If
oStream.Write sContents
oStream.Close
Set oStream = Nothing
End Sub
and then as an example of it's use
set i = new IEDisplay
a = array("NW", "N", "NE", "W", "CENTRE", "E", "SW","S","SE")
for each aa in a
i.init aa
i.display "Here in " & aa & " of screen", 1000
next
Now that's not immediately useful (especially are there are a pile of calls to my own utility routines in there) but it gives a framework. By modifying what HTML is stored, you could add support for listboxes etc.
I know this is eleven years too late, but it sounds like this would be more along the lines of what the original request would be looking for:
Sub CustomMsgBox(msg)
Dim ie, Style, FormExit
Set ie = CreateObject("InternetExplorer.Application")
ie.Navigate "about:blank"
While ie.ReadyState <> 4: WScript.Sleep 100: Wend
ie.Toolbar = False
ie.StatusBar = False
ie.Width = 450
ie.Height = 275
ie.document.body.innerHTML = "<title>Choose a Color</title><p class='msg'>Choose an option:</p>" & "<input type='radio' id='myRadio' name='colors' value='red'>Red</br><input type='radio' id='myRadio' name='colors' value='yellow'>Yellow</br><input type='radio' id='myRadio' name='colors' value='blue'>Blue"
Set Style = ie.document.CreateStyleSheet
Style.AddRule "p.msg", "font-family:calibri;font-weight:bold;"
ie.Visible = True
ie.Quit
End Sub
This code worked for me in an HTA file (that I opened from VBS using WScript.Shell Run). The trick was to get the data back to VBS which I accomplished by having HTA create an XML file that VBS read.
Sub CopySelect(sSrcId, sTargetId)
Dim oTarget: Set oTarget = document.getElementById(sTargetId)
Dim oSrc: Set oSrc = document.getElementById(sSrcId)
Dim j, n, o
oTarget.length = 0
For j = 0 to oSrc.length - 1
Set o = oSrc.options(j)
Set n = document.createElement("option")
n.text = o.text
n.value = o.value
oTarget.add n
Next
End Sub

Use clipboard from VBScript

I am looking for a method to place some text onto the clipboard with VBScript. The VBScript in question will be deployed as part of our login script. I would like to avoid using anything that isn't available on a clean Windows XP system.
Edit:
In answer to the questions about what this is for.
We wanted to encourage users inside our organization to use the file server to transfer documents instead of constantly sending attachments by email. One of the biggest barriers to this is that it isn't always obvious to people what the correct network path is to a file/folder. We developed a quick script, and attached it to the Windows context menu so that a user can right click on any file/folder, and get a URL that they can email to someone within our organization.
I want the URL displayed in the dialog box to also be placed onto the clipboard.
GetNetworkPath
Another solution I have found that isn't perfect in my opinion, but doesn't have the annoying security warnings is to use clip.exe from a w2k3 server.
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "cmd.exe /c echo hello world | clip", 0, TRUE
Example with a multiline string as per question below :
Link1
Dim string
String = "text here" &chr(13)& "more text here"
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "cmd.exe /c echo " & String & " | clip", 0, TRUE
Using Microsoft's clip.exe is the closest to having a clean Windows XP system solution. However you don't have to call CMD.EXE to host it in order to use it. You can call it directly and write to its input stream in your script code. Once you close the input stream clip.exe will write the contents straight to the clipboard.
Set WshShell = CreateObject("WScript.Shell")
Set oExec = WshShell.Exec("clip")
Set oIn = oExec.stdIn
oIn.WriteLine "Something One"
oIn.WriteLine "Something Two"
oIn.WriteLine "Something Three"
oIn.Close
If you need to wait for clip to be finished before your script can continue processing then add
' loop until we're finished working.
Do While oExec.Status = 0
WScript.Sleep 100
Loop
And don't forget to release your objects
Set oIn = Nothing
Set oExec = Nothing
The closest solution I have found so far is a method to use IE to get and set stuff on the clipboard. The problem with this solution is the user gets security warnings. I am tempted to move 'about:blank' to the local computer security zone so I don't get the warnings, but I am not sure what the security implications of that would be.
Set objIE = CreateObject("InternetExplorer.Application")
objIE.Navigate("about:blank")
objIE.document.parentwindow.clipboardData.SetData "text", "Hello This Is A Test"
objIE.Quit
http://www.microsoft.com/technet/scriptcenter/resources/qanda/dec04/hey1215.mspx
No security warnings, full let and get access:
'create a clipboard thing
Dim ClipBoard
Set Clipboard = New cClipBoard
ClipBoard.Clear
ClipBoard.Data = "Test"
Class cClipBoard
Private objHTML
Private Sub Class_Initialize
Set objHTML = CreateObject("htmlfile")
End Sub
Public Sub Clear()
objHTML.ParentWindow.ClipboardData.ClearData()
End Sub
Public Property Let Data(Value)
objHTML.ParentWindow.ClipboardData.SetData "Text" , Value
End Property
Public Property Get Data()
Data = objHTML.ParentWindow.ClipboardData.GetData("Text")
End Property
Private Sub Class_Terminate
Set objHTML = Nothing
End Sub
End Class
Example Usage.
' Create scripting object
Dim WShell, lRunUninstall
Set WShell = CreateObject("WScript.Shell")
WShell.sendkeys "^c"
WScript.Sleep 250
bWindowFound = WShell.AppActivate("Microsoft Excel")
WShell.sendkeys ClipBoard.Data
To avoid the security warnings associated with Internet Explorer and clipboard access, I would recommend you use the Word application object and its methods to put your data onto the clipboard. Of course you can only use this on a machine that has MS Word installed, but these days that's most of them. (*In spite of the fact that you asked for stuff on a 'clean' system :) *)
' Set what you want to put in the clipboard '
strMessage = "Imagine that, it works!"
' Declare an object for the word application '
Set objWord = CreateObject("Word.Application")
' Using the object '
With objWord
.Visible = False ' Don't show word '
.Documents.Add ' Create a document '
.Selection.TypeText strMessage ' Put text into it '
.Selection.WholeStory ' Select everything in the doc '
.Selection.Copy ' Copy contents to clipboard '
.Quit False ' Close Word, don't save '
End With
You can find detail on the MS Word application object and its methods here: http://msdn.microsoft.com/en-us/library/aa221371(office.11).aspx
Microsoft doesn't give a way for VBScript to directly access the clipboard. If you do a search for 'clipboard'on this site you'll see:
Although Visual Basic for Applications supports the Screen, Printer, App, Debug, Err, and Clipboard objects, VBScript supports only the Err object. Therefore, VBScript does not allow you to access such useful objects as the mouse pointer or the clipboard. You can, however, use the Err object to provide runtime error handling for your applications.
So using notepad indirectly is probably about the best you'll be able to do with just VBScript.
Here's another version of using the "clip" command, which avoids adding a carriage return, line feed to the end of the string:
strA= "some character string"
Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run "cmd /C echo . | set /p x=" & strA & "| c:\clip.exe", 2
s = "String: """ & strA & """ is on the clipboard."
Wscript.Echo s
I've only tested this in XP. clip.exe was downloaded from Link and placed in C:\.
I've found a way to copy multi line information to clipboard by vbscript/cmd.
Sequence:
with VBS generate the final "formatted string" that you need copy to clipboard
generate a (txt) file with the "formatted string"
use type command from cmd to paste information to clip by pipe
Example script:
Function CopyToClipboard( sInputString )
Dim oShell: Set oShell = CreateObject("WScript.Shell")
Dim sTempFolder: sTempFolder = oShell.ExpandEnvironmentStrings("%TEMP%")
Dim sFullFilePath: sFullFilePath = sTempFolder & "\" & "temp_file.txt"
Const iForWriting = 2, bCreateFile = True
Dim oFSO: Set oFSO = CreateObject("Scripting.FileSystemObject")
With oFSO.OpenTextFile(sFullFilePath, iForWriting, bCreateFile)
.Write sInputString
.Close
End With
Const iHideWindow = 0, bWaitOnReturnTrue = True
Dim sCommand: sCommand = "CMD /C TYPE " & sFullFilePath & "|CLIP"
oShell.Run sCommand, iHideWindow, bWaitOnReturnTrue
Set oShell = Nothing
Set oFSO = Nothing
End Function
Sub Main
Call CopyToClipboard( "Text1" & vbNewLine & "Text2" )
End Sub
Call Main
The easiest way is to use built-in mshta.exe functionality:
sText = "Text Content"
CreateObject("WScript.Shell").Run "mshta.exe ""javascript:clipboardData.setData('text','" & Replace(Replace(sText, "\", "\\"), "'", "\'") & "');close();""", 0, True
To put to clipboard a string containing double quote char ", use the below code:
sText = "Text Content and double quote "" char"
CreateObject("WScript.Shell").Run "mshta.exe ""javascript:clipboardData.setData('text','" & Replace(Replace(Replace(sText, "\", "\\"), """", """"""), "'", "\'") & "'.replace('""""',String.fromCharCode(34)));close();""", 0, True
Take a look at this post. It describes a hacky approach to read from the clipboard, but I imagine it could be adapted to also write to the clipboard as well, such as changing the Ctrl+V to Ctrl+A then Ctrl+C.
I devised another way to use IE and yet avoid security warnings...
By the way.. this function is in JavaScript.. but u can easily convert it to VBScript..
function CopyText(sTxt) {
var oIe = WScript.CreateObject('InternetExplorer.Application');
oIe.silent = true;
oIe.Navigate('about:blank');
while(oIe.ReadyState!=4) WScript.Sleep(20);
while(oIe.document.readyState!='complete') WSript.Sleep(20);
oIe.document.body.innerHTML = "<textarea id=txtArea wrap=off></textarea>";
var oTb = oIe.document.getElementById('txtArea');
oTb.value = sTxt;
oTb.select();
oTb = null;
oIe.ExecWB(12,0);
oIe.Quit();
oIe = null;
}
Here is Srikanth's method translated into vbs
function SetClipBoard(sTxt)
Set oIe = WScript.CreateObject("InternetExplorer.Application")
oIe.silent = true
oIe.Navigate("about:blank")
do while oIe.ReadyState <> 4
WScript.Sleep 20
loop
do while oIe.document.readyState <> "complete"
WScript.Sleep 20
loop
oIe.document.body.innerHTML = "<textarea id=txtArea wrap=off></textarea>"
set oTb = oIe.document.getElementById("txtArea")
oTb.value = sTxt
oTb.select
set oTb = nothing
oIe.ExecWB 12,0
oIe.Quit
Set oIe = nothing
End function
function GetClipBoard()
set oIe = WScript.CreateObject("InternetExplorer.Application")
oIe.silent = true
oIe.Navigate("about:blank")
do while oIe.ReadyState <> 4
WScript.Sleep 20
loop
do while oIe.document.readyState <> "complete"
WScript.Sleep 20
loop
oIe.document.body.innerHTML = "<textarea id=txtArea wrap=off></textarea>"
set oTb = oIe.document.getElementById("txtArea")
oTb.focus
oIe.ExecWB 13,0
GetClipBoard = oTb.value
oTb.select
set oTb = nothing
oIe.Quit
Set oIe = nothing
End function
In your Class ClipBoard, neither the Clear sub nor the Let Data sub work. I mean they have no effect on Windows Clipboard. Actually, and ironically so, the only sub that works is the one you have not included in your example, that is Get Data! (I have tested this code quite a few times.)
However, it's not your fault. I have tried to copy data to clipboard with ClipboardData.SetData and it's impossible. At least not by creating an "htmlfile" object. Maybe it works by creating an instance of "InternetExplorer.Application" as I have seen in a few cases, but I have not tried it. I hate creating application instances for such simple tasks!
Alkis
If it's just text can't you simply create a text file and read in the contents when you need it?
Another alternative and clearly a kludge, would be to use the SendKeys() method.
No security warnings and no carriage return at the end of line
' value to put in Clipboard
mavaleur = "YEAH"
' current Dir
path = WScript.ScriptFullName
GetPath = Left(path, InStrRev(path, "\"))
' Put the value in a file
Set objFSO=CreateObject("Scripting.FileSystemObject")
outFile=GetPath & "fichier.valeur"
Set objFile = objFSO.CreateTextFile(outFile,True)
objFile.Write mavaleur
objFile.Close
' Put the file in the Clipboard
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "cmd.exe /c clip < " & outFile, 0, TRUE
' Erase the file
Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.DeleteFile outFile

Resources